Merge from Chromium at DEPS revision 225410
This commit was generated by merge_to_master.py.
Change-Id: Ifa1539ca216abb163295ee7a77f81bb67f52e178
diff --git a/chrome/VERSION b/chrome/VERSION
index 1bea54d..e470924 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
-MAJOR=31
+MAJOR=32
MINOR=0
-BUILD=1637
+BUILD=1653
PATCH=0
diff --git a/chrome/android/java/res/drawable-xhdpi/infobar_protected_media_identifier.png b/chrome/android/java/res/drawable-xhdpi/infobar_protected_media_identifier.png
new file mode 100644
index 0000000..2751b3c
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/infobar_protected_media_identifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable/infobar_protected_media_identifier.png b/chrome/android/java/res/drawable/infobar_protected_media_identifier.png
new file mode 100644
index 0000000..c3d87d4
--- /dev/null
+++ b/chrome/android/java/res/drawable/infobar_protected_media_identifier.png
Binary files differ
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ForeignSessionHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ForeignSessionHelper.java
index 4faf66b..33a6e57 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ForeignSessionHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ForeignSessionHelper.java
@@ -37,13 +37,23 @@
* Represents synced foreign session.
*/
public static class ForeignSession {
+ // Please keep in sync with synced_session.h
+ public static final int DEVICE_TYPE_UNSET = 0;
+ public static final int DEVICE_TYPE_WIN = 1;
+ public static final int DEVICE_TYPE_MACOSX = 2;
+ public static final int DEVICE_TYPE_LINUX = 3;
+ public static final int DEVICE_TYPE_CHROMEOS = 4;
+ public static final int DEVICE_TYPE_OTHER = 5;
+ public static final int DEVICE_TYPE_PHONE = 6;
+ public static final int DEVICE_TYPE_TABLET = 7;
+
public final String tag;
public final String name;
- public final String deviceType;
+ public final int deviceType;
public final long modifiedTime;
public final List<ForeignSessionWindow> windows = new ArrayList<ForeignSessionWindow>();
- private ForeignSession(String tag, String name, String deviceType, long modifiedTime) {
+ private ForeignSession(String tag, String name, int deviceType, long modifiedTime) {
this.tag = tag;
this.name = name;
this.deviceType = deviceType;
@@ -85,7 +95,7 @@
@CalledByNative
private static ForeignSession pushSession(
- List<ForeignSession> sessions, String tag, String name, String deviceType,
+ List<ForeignSession> sessions, String tag, String name, int deviceType,
long modifiedTime) {
ForeignSession session = new ForeignSession(tag, name, deviceType, modifiedTime);
sessions.add(session);
@@ -186,6 +196,15 @@
}
/**
+ * Get the given session collapsed or uncollapsed state in preferences.
+ * @param session Session to fetch collapsed state.
+ * @return {@code True} if the session is collapsed, false if expanded.
+ */
+ public boolean getForeignSessionCollapsed(ForeignSession session) {
+ return nativeGetForeignSessionCollapsed(mNativeForeignSessionHelper, session.tag);
+ }
+
+ /**
* Remove Foreign session to display. Note that it will be reappear on the next sync.
*
* This is mainly for when user wants to delete very old session that won't be used or syned in
@@ -207,6 +226,8 @@
int nativeForeignSessionHelper, String sessionTag, int tabId);
private static native void nativeSetForeignSessionCollapsed(
int nativeForeignSessionHelper, String sessionTag, boolean isCollapsed);
+ private static native boolean nativeGetForeignSessionCollapsed(
+ int nativeForeignSessionHelper, String sessionTag);
private static native void nativeDeleteForeignSession(
int nativeForeignSessionHelper, String sessionTag);
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
index 15acd0b..4a61723 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -7,7 +7,9 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.os.Bundle;
import android.text.TextUtils;
+import android.util.Base64;
import android.util.Log;
import org.chromium.base.CalledByNative;
@@ -19,8 +21,9 @@
* This is a helper class to create shortcuts on the Android home screen.
*/
public class ShortcutHelper {
- public static final String EXTRA_ID = "webapp_id";
- public static final String EXTRA_URL = "webapp_url";
+ public static final String EXTRA_ID = "org.chromium.chrome.browser.webapp_id";
+ public static final String EXTRA_MAC = "org.chromium.chrome.browser.webapp_mac";
+ public static final String EXTRA_URL = "org.chromium.chrome.browser.webapp_url";
private static String sFullScreenAction;
@@ -65,6 +68,13 @@
shortcutIntent.setAction(sFullScreenAction);
shortcutIntent.putExtra(EXTRA_URL, url);
shortcutIntent.putExtra(EXTRA_ID, UUID.randomUUID().toString());
+
+ // The only reason we convert to a String here is because Android inexplicably eats a
+ // byte[] when adding the shortcut -- the Bundle received by the launched Activity even
+ // lacks the key for the extra.
+ byte[] mac = WebappAuthenticator.getMacForUrl(context, url);
+ String encodedMac = Base64.encodeToString(mac, Base64.DEFAULT);
+ shortcutIntent.putExtra(EXTRA_MAC, encodedMac);
} else {
// Add the shortcut as a launcher icon to open in the browser Activity.
shortcutIntent = BookmarkUtils.createShortcutIntent(context, url);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/UrlUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/UrlUtilities.java
index 8f16003..f8b93ee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/UrlUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/UrlUtilities.java
@@ -112,21 +112,35 @@
/**
* Builds a String that strips down the URL to the its scheme, host, and port.
* @param uri URI to break down.
- * @return Stripped-down String containing the essential bits of the URL, or null if we fail
- * to strip it down.
+ * @param showScheme Whether or not to show the scheme. If the URL can't be parsed, this value
+ * is ignored.
+ * @return Stripped-down String containing the essential bits of the URL, or the original URL if
+ * it fails to parse it.
*/
- public static String getOriginForDisplay(URI uri) {
+ public static String getOriginForDisplay(URI uri, boolean showScheme) {
String scheme = uri.getScheme();
String host = uri.getHost();
int port = uri.getPort();
- if (TextUtils.isEmpty(scheme) || TextUtils.isEmpty(host)) return null;
- if (port == -1 || (port == 80 && "http".equals(scheme))
- || (port == 443 && "https".equals(scheme))) {
- return scheme + "://" + host;
+ String displayUrl;
+ if (TextUtils.isEmpty(scheme) || TextUtils.isEmpty(host)) {
+ displayUrl = uri.toString();
} else {
- return scheme + "://" + host + ":" + port;
+ if (showScheme) {
+ scheme += "://";
+ } else {
+ scheme = "";
+ }
+
+ if (port == -1 || (port == 80 && "http".equals(scheme))
+ || (port == 443 && "https".equals(scheme))) {
+ displayUrl = scheme + host;
+ } else {
+ displayUrl = scheme + host + ":" + port;
+ }
}
+
+ return displayUrl;
}
/**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WebappAuthenticator.java b/chrome/android/java/src/org/chromium/chrome/browser/WebappAuthenticator.java
new file mode 100644
index 0000000..8a3f4f2
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/WebappAuthenticator.java
@@ -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.
+
+package org.chromium.chrome.browser;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Authenticate the source of Intents to launch web apps (see e.g. {@link #FullScreenActivity}).
+ *
+ * Chrome does not keep a store of valid URLs for installed web apps (because it cannot know when
+ * any have been uninstalled). Therefore, upon installation, it tells the Launcher a message
+ * authentication code (MAC) along with the URL for the web app, and then Chrome can verify the MAC
+ * when starting e.g. {@link #FullScreenActivity}. Chrome can thus distinguish between legitimate,
+ * installed web apps and arbitrary other URLs.
+ */
+public class WebappAuthenticator {
+ private static final String TAG = "WebappAuthenticator";
+ private static final String MAC_ALGORITHM_NAME = "HmacSHA256";
+ private static final String MAC_KEY_BASENAME = "webapp-authenticator";
+ private static final int MAC_KEY_BYTE_COUNT = 32;
+ private static final Object sLock = new Object();
+
+ private static FutureTask<SecretKey> sMacKeyGenerator;
+ private static SecretKey sKey = null;
+
+ /**
+ * @see #getMacForUrl
+ *
+ * @param url The URL to validate.
+ * @param mac The bytes of a previously-calculated MAC.
+ *
+ * @return true if the MAC is a valid MAC for the URL, false otherwise.
+ */
+ public static boolean isUrlValid(Context context, String url, byte[] mac) {
+ byte[] goodMac = getMacForUrl(context, url);
+ if (goodMac == null) {
+ return false;
+ }
+ return constantTimeAreArraysEqual(goodMac, mac);
+ }
+
+ /**
+ * @see #isUrlValid
+ *
+ * @param url A URL for which to calculate a MAC.
+ *
+ * @return The bytes of a MAC for the URL, or null if a secure MAC was not available.
+ */
+ public static byte[] getMacForUrl(Context context, String url) {
+ Mac mac = getMac(context);
+ if (mac == null) {
+ return null;
+ }
+ return mac.doFinal(url.getBytes());
+ }
+
+ // TODO(palmer): Put this method, and as much of this class as possible, in a utility class.
+ private static boolean constantTimeAreArraysEqual(byte[] a, byte[] b) {
+ if (a.length != b.length) {
+ return false;
+ }
+
+ int result = 0;
+ for (int i = 0; i < a.length; i++) {
+ result |= a[i] ^ b[i];
+ }
+ return result == 0;
+ }
+
+ private static SecretKey readKeyFromFile(
+ Context context, String basename, String algorithmName) {
+ FileInputStream input = null;
+ File file = context.getFileStreamPath(basename);
+ try {
+ if (file.length() != MAC_KEY_BYTE_COUNT) {
+ Log.w(TAG, "Could not read key from '" + file + "': invalid file contents");
+ return null;
+ }
+
+ byte[] keyBytes = new byte[MAC_KEY_BYTE_COUNT];
+ input = new FileInputStream(file);
+ if (MAC_KEY_BYTE_COUNT != input.read(keyBytes)) {
+ return null;
+ }
+
+ try {
+ return new SecretKeySpec(keyBytes, algorithmName);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Could not read key from '" + file + "': " + e);
+ return null;
+ } finally {
+ try {
+ if (input != null) {
+ input.close();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Could not close key input stream '" + file + "': " + e);
+ }
+ }
+ }
+
+ private static boolean writeKeyToFile(Context context, String basename, SecretKey key) {
+ File file = context.getFileStreamPath(basename);
+ byte[] keyBytes = key.getEncoded();
+ if (MAC_KEY_BYTE_COUNT != keyBytes.length) {
+ Log.e(TAG, "writeKeyToFile got key encoded bytes length " + keyBytes.length +
+ "; expected " + MAC_KEY_BYTE_COUNT);
+ return false;
+ }
+
+ try {
+ FileOutputStream output = new FileOutputStream(file);
+ output.write(keyBytes);
+ output.close();
+ return true;
+ } catch (Exception e) {
+ Log.e(TAG, "Could not write key to '" + file + "': " + e);
+ return false;
+ }
+ }
+
+ private static SecretKey getKey(Context context) {
+ synchronized (sLock) {
+ if (sKey == null) {
+ SecretKey key = readKeyFromFile(context, MAC_KEY_BASENAME, MAC_ALGORITHM_NAME);
+ if (key != null) {
+ sKey = key;
+ return sKey;
+ }
+
+ triggerMacKeyGeneration();
+ try {
+ sKey = sMacKeyGenerator.get();
+ sMacKeyGenerator = null;
+ if (!writeKeyToFile(context, MAC_KEY_BASENAME, sKey)) {
+ sKey = null;
+ return null;
+ }
+ return sKey;
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return sKey;
+ }
+ }
+
+ /**
+ * Generates the authentication encryption key in a background thread (if necessary).
+ */
+ private static void triggerMacKeyGeneration() {
+ synchronized (sLock) {
+ if (sKey != null || sMacKeyGenerator != null) {
+ return;
+ }
+
+ sMacKeyGenerator = new FutureTask<SecretKey>(new Callable<SecretKey>() {
+ @Override
+ public SecretKey call() throws Exception {
+ KeyGenerator generator = KeyGenerator.getInstance(MAC_ALGORITHM_NAME);
+ SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+
+ // Versions of SecureRandom from Android <= 4.3 do not seed themselves as
+ // securely as possible. This workaround should suffice until the fixed version
+ // is deployed to all users. getRandomBytes, which reads from /dev/urandom,
+ // which is as good as the platform can get.
+ //
+ // TODO(palmer): Consider getting rid of this once the updated platform has
+ // shipped to everyone. Alternately, leave this in as a defense against other
+ // bugs in SecureRandom.
+ byte[] seed = getRandomBytes(MAC_KEY_BYTE_COUNT);
+ if (seed == null) {
+ return null;
+ }
+ random.setSeed(seed);
+ generator.init(MAC_KEY_BYTE_COUNT * 8, random);
+ return generator.generateKey();
+ }
+ });
+ AsyncTask.THREAD_POOL_EXECUTOR.execute(sMacKeyGenerator);
+ }
+ }
+
+ private static byte[] getRandomBytes(int count) {
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream("/dev/urandom");
+ byte[] bytes = new byte[count];
+ if (bytes.length != fis.read(bytes)) {
+ return null;
+ }
+ return bytes;
+ } catch (Throwable t) {
+ // This causes the ultimate caller, i.e. getMac, to fail.
+ return null;
+ } finally {
+ try {
+ if (fis != null) {
+ fis.close();
+ }
+ } catch (IOException e) {
+ // Nothing we can do.
+ }
+ }
+ }
+
+ /**
+ * @return A Mac, or null if it is not possible to instantiate one.
+ */
+ private static Mac getMac(Context context) {
+ try {
+ SecretKey key = getKey(context);
+ if (key == null) {
+ // getKey should have invoked triggerMacKeyGeneration, which should have set the
+ // random seed and generated a key from it. If not, there is a problem with the
+ // random number generator, and we must not claim that authentication can work.
+ return null;
+ }
+ Mac mac = Mac.getInstance(MAC_ALGORITHM_NAME);
+ mac.init(key);
+ return mac;
+ } catch (GeneralSecurityException e) {
+ Log.w(TAG, "Error in creating MAC instance", e);
+ return null;
+ }
+ }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java
index e7696d5..8213ad3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java
@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.autofill;
+import com.google.common.annotations.VisibleForTesting;
+
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.ui.WindowAndroid;
@@ -14,7 +16,8 @@
*/
@JNINamespace("autofill")
public class AutofillDialogControllerAndroid {
- private static AutofillDialogFactory mDialogFactory;
+ private static AutofillDialogFactory sDialogFactory;
+ private static boolean sAllowInsecureDialogsForTesting = false;
private int mNativeDelegate; // could be 0 after onDestroy().
private AutofillDialog mDialog;
@@ -96,7 +99,12 @@
* @param factory An instance of the AutofillDialogFactory that will handle requests.
*/
public static void setDialogFactory(AutofillDialogFactory factory) {
- mDialogFactory = factory;
+ sDialogFactory = factory;
+ }
+
+ @VisibleForTesting
+ public static void allowInsecureDialogsForTesting() {
+ sAllowInsecureDialogsForTesting = true;
}
private AutofillDialogControllerAndroid(
@@ -111,7 +119,7 @@
final String merchantDomain) {
mNativeDelegate = nativeAutofillDialogControllerAndroid;
- if (mDialogFactory == null) {
+ if (sDialogFactory == null) {
nativeDialogCancel(mNativeDelegate);
return;
}
@@ -134,7 +142,7 @@
}
};
- mDialog = mDialogFactory.createDialog(
+ mDialog = sDialogFactory.createDialog(
delegate,
windowAndroid,
requestFullBillingAddress, requestShippingAddress,
@@ -171,6 +179,14 @@
}
@CalledByNative
+ private static boolean isDialogAllowed(boolean requestsCreditCardInformation,
+ boolean isTransmissionSecure, boolean isInvokedFromTheSameOrigin) {
+ if (!requestsCreditCardInformation) return true;
+ if (isTransmissionSecure && isInvokedFromTheSameOrigin) return true;
+ return sAllowInsecureDialogsForTesting;
+ }
+
+ @CalledByNative
private void onDestroy() {
if (mNativeDelegate == 0) return;
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
index fc82dd1..21065b6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
@@ -27,7 +27,7 @@
private int mNativeFaviconHelper;
/**
- * Callback interface for getting the result from getFaviconImageForURL method.
+ * Callback interface for getting the result from getLocalFaviconImageForURL method.
*/
public interface FaviconImageCallback {
/**
@@ -54,17 +54,9 @@
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.
+ * Get Favicon bitmap for the requested arguments. Retrieves favicons only for pages the user
+ * has visited on the current device.
* @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.
@@ -72,19 +64,35 @@
* @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.
+ * @return True if GetLocalFaviconImageForURL is successfully called.
*/
- public boolean getFaviconImageForURL(
+ public boolean getLocalFaviconImageForURL(
Profile profile, String pageUrl, int iconTypes,
int desiredSizeInDip, FaviconImageCallback faviconImageCallback) {
assert mNativeFaviconHelper != 0;
- return nativeGetFaviconImageForURL(mNativeFaviconHelper, profile, pageUrl, iconTypes,
+ return nativeGetLocalFaviconImageForURL(mNativeFaviconHelper, profile, pageUrl, iconTypes,
desiredSizeInDip, faviconImageCallback);
}
+ /**
+ * Get 16x16 Favicon bitmap for the requested arguments. Only retrives favicons in synced
+ * session storage. (e.g. favicons synced from other devices). TODO (apiccion) provide a way
+ * to obtain higher resolution favicons.
+ * @param profile Profile used for the FaviconService construction.
+ * @param pageUrl The target Page URL to get the favicon.
+ *
+ * @return 16x16 favicon Bitmap corresponding to the pageUrl.
+ */
+ public Bitmap getSyncedFaviconImageForURL(Profile profile, String pageUrl) {
+ assert mNativeFaviconHelper != 0;
+ return nativeGetSyncedFaviconImageForURL(mNativeFaviconHelper, profile, pageUrl);
+ }
+
private static native int nativeInit();
private static native void nativeDestroy(int nativeFaviconHelper);
- private static native boolean nativeGetFaviconImageForURL(int nativeFaviconHelper,
+ private static native boolean nativeGetLocalFaviconImageForURL(int nativeFaviconHelper,
Profile profile, String pageUrl, int iconTypes, int desiredSizeInDip,
FaviconImageCallback faviconImageCallback);
+ private static native Bitmap nativeGetSyncedFaviconImageForURL(int nativeFaviconHelper,
+ Profile profile, String pageUrl);
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AndroidProfileOAuth2TokenServiceHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AndroidProfileOAuth2TokenServiceHelper.java
index 7e0582d..09d73a1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AndroidProfileOAuth2TokenServiceHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AndroidProfileOAuth2TokenServiceHelper.java
@@ -51,6 +51,16 @@
}
/**
+ * Called by native to list the accounts with OAuth2 refresh tokens.
+ */
+ @CalledByNative
+ public static String[] getAccounts(Context context) {
+ AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(context);
+ java.util.List<String> accountNames = accountManagerHelper.getGoogleAccountNames();
+ return accountNames.toArray(new String[accountNames.size()]);
+ }
+
+ /**
* Called by native to retrieve OAuth2 tokens.
*
* @param username The native username (full address).
@@ -136,6 +146,14 @@
}
/**
+ * Called by native to check wether the account has an OAuth2 refresh token.
+ */
+ @CalledByNative
+ public static boolean hasOAuth2RefreshToken(Context context, String accountName) {
+ return AccountManagerHelper.get(context).hasAccountForName(accountName);
+ }
+
+ /**
* Called by native to invalidate an OAuth2 token.
*/
@CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
index 0876130..965f58d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -136,17 +136,16 @@
return;
}
- if (mPassive) {
- // The account has policy management, but the user should be asked before signing-in
- // to an account with management enabled. Don't show the policy dialog since this is a
- // passive interaction (e.g. auto signing-in), and just don't auto-signin in this case.
+ if (mSignInActivity.isDestroyed()) {
+ // The activity is no longer running, cancel sign in.
cancelSignIn();
return;
}
- if (mSignInActivity.isDestroyed()) {
- // The activity is no longer running, cancel sign in.
- cancelSignIn();
+ if (mPassive) {
+ // If this is a passive interaction (e.g. auto signin) then don't show the confirmation
+ // dialog.
+ nativeFetchPolicyBeforeSignIn(mNativeSigninManagerAndroid);
return;
}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/UrlUtilitiesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/UrlUtilitiesTest.java
index 00b899f..7ee5b80 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/UrlUtilitiesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/UrlUtilitiesTest.java
@@ -89,20 +89,34 @@
@Feature({"Webapps"})
public void testGetOriginForDisplay() {
URI uri;
+
uri = URI.create("http://chopped.com/is/awesome");
- assertEquals("http://chopped.com", UrlUtilities.getOriginForDisplay(uri));
+ assertEquals("http://chopped.com", UrlUtilities.getOriginForDisplay(uri, true));
+ assertEquals("chopped.com", UrlUtilities.getOriginForDisplay(uri, false));
+
uri = URI.create("http://lopped.com");
- assertEquals("http://lopped.com", UrlUtilities.getOriginForDisplay(uri));
+ assertEquals("http://lopped.com", UrlUtilities.getOriginForDisplay(uri, true));
+ assertEquals("lopped.com", UrlUtilities.getOriginForDisplay(uri, false));
+
uri = URI.create("http://dropped.com?things");
- assertEquals("http://dropped.com", UrlUtilities.getOriginForDisplay(uri));
+ assertEquals("http://dropped.com", UrlUtilities.getOriginForDisplay(uri, true));
+ assertEquals("dropped.com", UrlUtilities.getOriginForDisplay(uri, false));
+
uri = URI.create("http://dfalcant@stopped.com:1234");
- assertEquals("http://stopped.com:1234", UrlUtilities.getOriginForDisplay(uri));
+ assertEquals("http://stopped.com:1234", UrlUtilities.getOriginForDisplay(uri, true));
+ assertEquals("stopped.com:1234", UrlUtilities.getOriginForDisplay(uri, false));
+
uri = URI.create("http://dfalcant:secret@stopped.com:9999");
- assertEquals("http://stopped.com:9999", UrlUtilities.getOriginForDisplay(uri));
+ assertEquals("http://stopped.com:9999", UrlUtilities.getOriginForDisplay(uri, true));
+ assertEquals("stopped.com:9999", UrlUtilities.getOriginForDisplay(uri, false));
+
uri = URI.create("chrome://settings:443");
- assertEquals("chrome://settings:443", UrlUtilities.getOriginForDisplay(uri));
+ assertEquals("chrome://settings:443", UrlUtilities.getOriginForDisplay(uri, true));
+ assertEquals("settings:443", UrlUtilities.getOriginForDisplay(uri, false));
+
uri = URI.create("about:blank");
- assertEquals(null, UrlUtilities.getOriginForDisplay(uri));
+ assertEquals("about:blank", UrlUtilities.getOriginForDisplay(uri, true));
+ assertEquals("about:blank", UrlUtilities.getOriginForDisplay(uri, false));
}
}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/WebappAuthenticatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/WebappAuthenticatorTest.java
new file mode 100644
index 0000000..2d075f1
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/WebappAuthenticatorTest.java
@@ -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.
+
+package org.chromium.chrome.browser;
+
+import android.content.Context;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class WebappAuthenticatorTest extends InstrumentationTestCase {
+ @SmallTest
+ public void testAuthentication() {
+ Context context = getInstrumentation().getTargetContext();
+ String url = "http://www.example.org/hello.html";
+ byte[] mac = WebappAuthenticator.getMacForUrl(context, url);
+ assertNotNull(mac);
+ assertTrue(WebappAuthenticator.isUrlValid(context, url, mac));
+ assertFalse(WebappAuthenticator.isUrlValid(context, url + "?goats=true", mac));
+ mac[4] += 1;
+ assertFalse(WebappAuthenticator.isUrlValid(context, url, mac));
+ }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerTest.java
index 06945de..ec58b3e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerTest.java
@@ -145,6 +145,7 @@
public void setUp() throws Exception {
super.setUp();
clearAppData();
+ AutofillDialogControllerAndroid.allowInsecureDialogsForTesting();
}
@MediumTest
diff --git a/chrome/app/breakpad_field_trial_win.cc b/chrome/app/breakpad_field_trial_win.cc
deleted file mode 100644
index 5293879..0000000
--- a/chrome/app/breakpad_field_trial_win.cc
+++ /dev/null
@@ -1,58 +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/app/breakpad_field_trial_win.h"
-
-#include "base/lazy_instance.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "breakpad/src/client/windows/common/ipc_protocol.h"
-#include "chrome/app/breakpad_win.h"
-#include "chrome/common/child_process_logging.h"
-
-// Sets the breakpad experiment chunks for crash reporting. |chunks| is an
-// array of C strings of size |chunk_size| containing the values to set, where
-// each entry may contain multiple experiment tuples, with the total number of
-// experiments indicated by |experiments_chunks|.
-// Note that this is suffixed with "3" due to parameter changes that were made
-// to the predecessor functions. If the signature changes again, use a new name.
-extern "C" void __declspec(dllexport) __cdecl SetExperimentList3(
- const wchar_t** chunks,
- size_t chunks_size,
- size_t experiments_count) {
- // Make sure the offset was initialized before storing the data.
- if (breakpad_win::g_experiment_chunks_offset == 0)
- return;
-
- // Store up to |kMaxReportedVariationChunks| chunks.
- const size_t number_of_chunks_to_report =
- std::min(chunks_size, kMaxReportedVariationChunks);
- for (size_t i = 0; i < number_of_chunks_to_report; ++i) {
- const size_t entry_index = breakpad_win::g_experiment_chunks_offset + i;
- (*breakpad_win::g_custom_entries)[entry_index].set_value(chunks[i]);
- }
-
- // Make note of the total number of experiments, which may be greater than
- // what was able to fit in |kMaxReportedVariationChunks|. This is useful when
- // correlating stability with the number of experiments running
- // simultaneously.
- base::wcslcpy(
- (*breakpad_win::g_custom_entries)[
- breakpad_win::g_num_of_experiments_offset].value,
- base::StringPrintf(
- L"%d", static_cast<int>(experiments_count)).c_str(),
- google_breakpad::CustomInfoEntry::kValueMaxLength);
-}
-
-namespace testing {
-
-void SetExperimentChunks(const std::vector<string16>& chunks,
- size_t experiments_count) {
- std::vector<const wchar_t*> cstrings;
- StringVectorToCStringVector(chunks, &cstrings);
- ::SetExperimentList3(&cstrings[0], cstrings.size(), experiments_count);
-}
-
-} // namespace testing
diff --git a/chrome/app/breakpad_field_trial_win.h b/chrome/app/breakpad_field_trial_win.h
deleted file mode 100644
index e74ab86..0000000
--- a/chrome/app/breakpad_field_trial_win.h
+++ /dev/null
@@ -1,22 +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_APP_BREAKPAD_FIELD_TRIAL_WIN_H_
-#define CHROME_APP_BREAKPAD_FIELD_TRIAL_WIN_H_
-
-#include <vector>
-
-#include "base/strings/string16.h"
-
-namespace testing {
-
-// Sets the breakpad experiment chunks for testing. |chunks| is the list of
-// values to set, where each entry may contain multiple experiment tuples, with
-// the total number of experiments indicated by |experiments_chunks|.
-void SetExperimentChunks(const std::vector<string16>& chunks,
- size_t experiments_count);
-
-} // namespace testing
-
-#endif // CHROME_APP_BREAKPAD_FIELD_TRIAL_WIN_H_
diff --git a/chrome/app/breakpad_linux.cc b/chrome/app/breakpad_linux.cc
index 198b237..a4ebd28 100644
--- a/chrome/app/breakpad_linux.cc
+++ b/chrome/app/breakpad_linux.cc
@@ -1264,26 +1264,6 @@
writer.Flush();
}
- if (*child_process_logging::g_num_variations) {
- writer.AddPairString("num-experiments",
- child_process_logging::g_num_variations);
- writer.AddBoundary();
- writer.Flush();
- }
-
- unsigned variation_chunks_len =
- my_strlen(child_process_logging::g_variation_chunks);
- if (variation_chunks_len) {
- static const char variation_msg[] = "experiment-chunk-";
- static const unsigned kMaxVariationsLen =
- kMaxReportedVariationChunks * kMaxVariationChunkSize;
- writer.AddPairDataInChunks(variation_msg, sizeof(variation_msg) - 1,
- child_process_logging::g_variation_chunks,
- std::min(variation_chunks_len, kMaxVariationsLen),
- kMaxVariationChunkSize,
- true /* Strip whitespace since variation chunks are padded. */);
- }
-
if (info.oom_size) {
char oom_size_str[kUint64StringSize];
const unsigned oom_size_len = my_uint64_len(info.oom_size);
diff --git a/chrome/app/breakpad_unittest_win.cc b/chrome/app/breakpad_unittest_win.cc
deleted file mode 100644
index 3dca060..0000000
--- a/chrome/app/breakpad_unittest_win.cc
+++ /dev/null
@@ -1,83 +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 <vector>
-
-#include "base/strings/stringprintf.h"
-#include "breakpad/src/client/windows/common/ipc_protocol.h"
-#include "chrome/app/breakpad_field_trial_win.h"
-#include "chrome/app/breakpad_win.h"
-#include "chrome/common/child_process_logging.h"
-#include "chrome/common/metrics/variations/variations_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using breakpad_win::g_custom_entries;
-using breakpad_win::g_experiment_chunks_offset;
-using breakpad_win::g_num_of_experiments_offset;
-
-class ChromeAppBreakpadTest : public testing::Test {
- public:
- ChromeAppBreakpadTest() {
- testing::InitCustomInfoEntries();
- }
-
- protected:
- typedef std::vector<string16> Experiments;
- void ValidateExperimentChunks(const Experiments& experiments) {
- std::vector<string16> chunks;
- chrome_variations::GenerateVariationChunks(experiments, &chunks);
- testing::SetExperimentChunks(chunks, experiments.size());
- EXPECT_STREQ(base::StringPrintf(L"%d", experiments.size()).c_str(),
- (*g_custom_entries)[g_num_of_experiments_offset].value);
- // We make a copy of the array that we empty as we find the experiments.
- Experiments experiments_left(experiments);
- for (int i = 0; i < kMaxReportedVariationChunks; ++i) {
- const google_breakpad::CustomInfoEntry& entry =
- (*g_custom_entries)[g_experiment_chunks_offset + i];
- EXPECT_STREQ(base::StringPrintf(L"experiment-chunk-%i", i + 1).c_str(),
- entry.name);
- // An empty value should only appear when |experiments_left| is empty.
- if (wcslen(entry.value) == 0)
- EXPECT_TRUE(experiments_left.empty());
- if (experiments_left.empty()) {
- // All other slots should be empty.
- EXPECT_STREQ(L"", entry.value);
- } else {
- // We can't guarantee the order, so we must search for them all.
- Experiments::const_iterator experiment = experiments_left.begin();
- while (experiment != experiments_left.end()) {
- if (wcsstr(entry.value, experiment->c_str())) {
- experiment = experiments_left.erase(experiment);
- } else {
- ++experiment;
- }
- }
- }
- }
- EXPECT_TRUE(experiments_left.empty());
- }
-
- private:
- static const wchar_t* kNumExperiments;
- static const size_t kNumExperimentsSize;
-};
-
-const wchar_t* ChromeAppBreakpadTest::kNumExperiments = L"num-experiments";
-const size_t ChromeAppBreakpadTest::kNumExperimentsSize =
- wcslen(ChromeAppBreakpadTest::kNumExperiments);
-
-TEST_F(ChromeAppBreakpadTest, ExperimentList) {
- Experiments experiments;
- experiments.push_back(L"ABCDE-12345");
- ValidateExperimentChunks(experiments);
-
- experiments.push_back(L"There-You Are");
- ValidateExperimentChunks(experiments);
-
- experiments.push_back(L"Peter-Sellers");
- ValidateExperimentChunks(experiments);
-
- experiments.push_back(L"Eat me-Drink me");
- ValidateExperimentChunks(experiments);
-}
diff --git a/chrome/app/breakpad_win.cc b/chrome/app/breakpad_win.cc
index 80ccd01..6f83def 100644
--- a/chrome/app/breakpad_win.cc
+++ b/chrome/app/breakpad_win.cc
@@ -31,7 +31,6 @@
#include "base/win/registry.h"
#include "base/win/win_util.h"
#include "breakpad/src/client/windows/handler/exception_handler.h"
-#include "chrome/app/breakpad_field_trial_win.h"
#include "chrome/app/hard_error_handler_win.h"
#include "chrome/common/child_process_logging.h"
#include "chrome/common/chrome_constants.h"
@@ -54,16 +53,12 @@
// is way too too fragile. See
// https://code.google.com/p/chromium/issues/detail?id=137062.
std::vector<google_breakpad::CustomInfoEntry>* g_custom_entries = NULL;
-size_t g_num_of_experiments_offset = 0;
-size_t g_experiment_chunks_offset = 0;
bool g_deferred_crash_uploads = false;
} // namespace breakpad_win
using breakpad_win::g_custom_entries;
using breakpad_win::g_deferred_crash_uploads;
-using breakpad_win::g_experiment_chunks_offset;
-using breakpad_win::g_num_of_experiments_offset;
namespace {
@@ -426,21 +421,6 @@
if (use_crash_service)
SetBreakpadDumpPath();
- g_num_of_experiments_offset = g_custom_entries->size();
- g_custom_entries->push_back(
- google_breakpad::CustomInfoEntry(L"num-experiments", L"N/A"));
-
- g_experiment_chunks_offset = g_custom_entries->size();
- // We depend on this in UpdateExperiments...
- DCHECK_NE(0UL, g_experiment_chunks_offset);
- // And the test code depends on this.
- DCHECK_EQ(g_num_of_experiments_offset + 1, g_experiment_chunks_offset);
- // one-based index for the name suffix.
- for (int i = 1; i <= kMaxReportedVariationChunks; ++i) {
- g_custom_entries->push_back(google_breakpad::CustomInfoEntry(
- base::StringPrintf(L"experiment-chunk-%i", i).c_str(), L""));
- }
-
// Create space for dynamic ad-hoc keys. The names and values are set using
// the API defined in base/debug/crash_logging.h.
g_dynamic_keys_offset = g_custom_entries->size();
@@ -925,11 +905,3 @@
void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) {
previous_filter = SetUnhandledExceptionFilter(filter);
}
-
-void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings,
- std::vector<const wchar_t*>* cstrings) {
- cstrings->clear();
- cstrings->reserve(wstrings.size());
- for (size_t i = 0; i < wstrings.size(); ++i)
- cstrings->push_back(wstrings[i].c_str());
-}
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index 0ca3d07..04715f3 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -138,6 +138,7 @@
#define IDC_FIND 37000
#define IDC_FIND_NEXT 37001
#define IDC_FIND_PREVIOUS 37002
+#define IDC_FIND_MENU 37100
// Zoom
#define IDC_ZOOM_MENU 38000
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index e890295..aa0c845 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -559,6 +559,9 @@
<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_ILLEGAL_USERNAME" desc="Error text shown in supervised user creation dialog when suggested name contains illegal characters (e.g. html tags).">
+ Whoops, illegal symbols in name!
+ </message>
<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>
@@ -613,7 +616,7 @@
This is taking much longer than it should.
</message>
<message name="IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE" desc="Text for notifications showing that this user is locally managed">
- This user is supervised by <ph name="MANAGER_EMAIL">$1<ex>user@example.com</ex></ph>. Usage and history from this user can be reviewed by the manager on chrome.com.
+ Usage and history of this user can be reviewed by the manager (<ph name="MANAGER_EMAIL">$1<ex>user@example.com</ex></ph>) on chrome.com.
</message>
<message name="IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING" desc="Warning text that is shown on login screen trying to sign in as a supervised user that has expired token">
This supervised user may have been deleted or disabled by the manager. Please contact the manager if you would like to continue signing in as this user.
@@ -1164,6 +1167,9 @@
<message name="IDS_IMAGE_SCREEN_PROFILE_LOADING_PHOTO" desc="The title of the loading stub for Google profile image on image selection screen. Please keep in sync with IDS_OPTIONS_CHANGE_PICTURE_PROFILE_LOADING_PHOTO.">
* Google Profile photo (loading)
</message>
+ <message name="IDS_IMAGE_SCREEN_SYNCING_PREFERENCES" desc="The message displayed on the image screen while user preferences are syncing.">
+ Syncing your preferences
+ </message>
<message name="IDS_OPTIONS_SETTINGS_INTERNET_TAB_WIFI" desc="In settings Internet options, the title for the wifi tab.">
Wi-Fi
</message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index ea437af..01cf01a 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -277,12 +277,6 @@
<message name="IDS_BACKGROUND_CRASHED_EXTENSION_BALLOON_MESSAGE" desc="The contents of the balloon that is displayed when an extension crashes">
<ph name="APP_NAME">$1<ex>Extension</ex></ph> has crashed. Click this balloon to reload the extension.
</message>
- <message name="IDS_BACKGROUND_MISBEHAVING_APP_BALLOON_MESSAGE" desc="The contents of the balloon that is displayed when a background force-installed app crashes multiple times">
- Managed app <ph name="APP_NAME">$1<ex>Background App</ex></ph> installed by enterprise policy is misbehaving. Please contact your administrator.
- </message>
- <message name="IDS_BACKGROUND_MISBEHAVING_EXTENSION_BALLOON_MESSAGE" desc="The contents of the balloon that is displayed when an extension installed by enterprise policy crashes repeatedly">
- Managed extension <ph name="APP_NAME">$1<ex>Extension</ex></ph> installed by enterprise policy is misbehaving. Please contact your administrator.
- </message>
<if expr="pp_ifdef('use_titlecase')">
<message name="IDS_BACKGROUND_APP_NOT_INSTALLED" desc="In Title Case: Label displayed in the status icon context menu when a profile does not have any background apps running.">
No Background Apps Running
@@ -4052,10 +4046,65 @@
<message name="IDS_EXTENSION_PROMPT_OAUTH_PERMISSIONS_HEADER" desc="A line of explanatory text that precedes all GAIA account permissions that an extension might request. This is shown when an app requests permissions which are optional.">
On your <ph name="ACCOUNT_EMAIL">$1<ex>user@example.com</ex></ph> account, it could:
</message>
- <message name="IDS_EXTENSION_PROMPT_RETAINED_FILES" desc="A line of explanatory text that precedes the list of files the app has permanent access to, showing how the number of files. This is shown when an app has persistent access to files.">
- It has permanent access to <ph name="NUMBER_OF_FILES">$1<ex>5</ex></ph> files.
+ <message name="IDS_EXTENSION_PROMPT_RETAINED_FILES_DEFAULT" desc="A line of explanatory text that precedes the list of files the app has permanent access to, showing how the number of files. This is shown when an app has persistent access to files. This is necessary for every language. This is the default for all the numbers NOT covered by special cases (singular, dual/two, few, many) some languages need. For CJK, Vietnamese, Turkish and Kannada, this is the only string necessary. For languages with singular-plural distinction, this is the generic plural. For Lithuanian, NUMBER_OF_FILES is 11 .. 19.">
+ It has permanent access to <ph name="NUMBER_OF_FILES">#<ex>5</ex></ph> files.
</message>
+ <if expr="lang not in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr', 'kn']">
+ <message name="IDS_EXTENSION_PROMPT_RETAINED_FILE_SINGULAR" desc="A line of explanatory text that precedes the list of files the app has permanent access to, showing how the number of files. This is shown when an app has persistent access to files. NUMBER_OF_FILES is one or one-like numbers : 1 (many European and most Indian languages), 1 and 0 (French, Brazilian Portuguese and Hindi), 1,21,31, .. (Russian, Ukrainian, Croatian, Serbian, Latvian, Lithuanian), or 1, 101, 201, .. (Slovenian). Do NOT translate this for CJK, Vietnamese, Turkish and Kannada">
+ It has permanent access to <ph name="NUMBER_OF_FILES">#<ex>1</ex></ph> file.
+ </message>
+ </if>
+ <if expr="lang in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr', 'kn']">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_RETAINED_FILE_SINGULAR" desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ar', 'ro', 'lv']">
+ <message name="IDS_EXTENSION_PROMPT_RETAINED_FILES_ZERO" desc="A line of explanatory text that precedes the list of files the app has permanent access to, showing how the number of files. This is shown when an app has persistent access to files. NUMBER_OF_FILES is 0 (Arabic, Latvian) or 0, 2..19, 101..119, ... (Romanian). For other languages, do NOT translate.">
+ It has permanent access to <ph name="NUMBER_OF_FILES">#<ex>0</ex></ph> files.
+ </message>
+ </if>
+ <if expr="lang not in ['ar', 'ro', 'lv']">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_RETAINED_FILES_ZERO" desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ga', 'sl', 'ar']">
+ <message name="IDS_EXTENSION_PROMPT_RETAINED_FILES_TWO" desc="A line of explanatory text that precedes the list of files the app has permanent access to, showing how the number of files. This is shown when an app has persistent access to files. NUMBER_OF_FILES is two or two-like/dual numbers : 2 (Arabic and Irish) or 2, 102, 202 ... (Slovenian). For other languages, do NOT translated.">
+ It has permanent access to <ph name="NUMBER_OF_FILES">#<ex>2</ex></ph> files.
+ </message>
+ </if>
+ <if expr="lang not in ['ga', 'sl', 'ar']">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_RETAINED_FILES_TWO" desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message name="IDS_EXTENSION_PROMPT_RETAINED_FILES_FEW" desc="A line of explanatory text that precedes the list of files the app has permanent access to, showing how the number of files. This is shown when an app has persistent access to files. NUMBER_OF_FILES is few or few-like numbers in Arabic, Russian, Polish, Croatian, Serbian, Ukrainian, Czech, Slovak, Slovenian, Latvian. For other languages, do NOT translate.">
+ It has permanent access to <ph name="NUMBER_OF_FILES">#<ex>3</ex></ph> files.
+ </message>
+ </if>
+ <if expr="lang not in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_RETAINED_FILES_FEW" desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang == 'ar'">
+ <message name="IDS_EXTENSION_PROMPT_RETAINED_FILES_MANY" desc="A line of explanatory text that precedes the list of files the app has permanent access to, showing how the number of files. This is shown when an app has persistent access to files. NUMBER_OF_FILES is 11 through 99 in Arabic. For all other languages, do NOT translate.">
+ It has permanent access to <ph name="NUMBER_OF_FILES">#<ex>23</ex></ph> files.
+ </message>
+ </if>
+ <if expr="lang != 'ar'">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_RETAINED_FILES_MANY" desc="">
+ NA
+ </message>
+ </if>
+
<if expr="is_android">
<message name="IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS" desc="Mobile: Permission string for full access to the device and all websites.">
Access all data on your device and the websites you visit
@@ -4078,9 +4127,64 @@
<message name="IDS_EXTENSION_PROMPT_WARNING_3_HOSTS" desc="Permission string for access to data on three websites.">
Access your data on <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and <ph name="WEBSITE_3">$3<ex>news.ycombinator.com</ex></ph>
</message>
- <message name="IDS_EXTENSION_PROMPT_WARNING_HOSTS" desc="Permission string for access to data on four or more websites.">
- Access your data on <ph name="NUMBER_OF_OTHER_WEBSITES">$1<ex>5</ex></ph> website(s)
+ <message name="IDS_EXTENSION_PROMPT_WARNING_HOSTS_DEFAULT" desc="Permission string for access to data on four or more websites. This is necessary for every language. This is the default for all the numbers NOT covered by special cases (singular, dual/two, few, many) some languages need. For CJK, Vietnamese, Turkish and Kannada, this is the only string necessary. For languages with singular-plural distinction, this is the generic plural. For Lithuanian, NUMBER_OF_WEBSITES is 11 .. 19.">
+ Access your data on <ph name="NUMBER_OF_WEBSITES">#<ex>5</ex></ph> websites
</message>
+
+ <if expr="lang not in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr', 'kn']">
+ <message name="IDS_EXTENSION_PROMPT_WARNING_HOST_SINGULAR" desc="Permission string for access to data on four or more websites. NUMBER_OF_WEBSITES is one or one-like numbers : 1 (many European and most Indian languages), 1 and 0 (French, Brazilian Portuguese and Hindi), 1,21,31, .. (Russian, Ukrainian, Croatian, Serbian, Latvian, Lithuanian), or 1, 101, 201, .. (Slovenian). Do NOT translate this for CJK, Vietnamese, Turkish and Kannada">
+ Access your data on <ph name="NUMBER_OF_WEBSITES">#<ex>1</ex></ph> websites
+ </message>
+ </if>
+ <if expr="lang in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr', 'kn']">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_WARNING_HOST_SINGULAR" desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ar', 'ro', 'lv']">
+ <message name="IDS_EXTENSION_PROMPT_WARNING_HOSTS_ZERO" desc="Permission string for access to data on four or more websites. NUMBER_OF_WEBSITES is 0 (Arabic, Latvian) or 0, 2..19, 101..119, ... (Romanian). For other languages, do NOT translate.">
+ Access your data on <ph name="NUMBER_OF_WEBSITES">#<ex>0</ex></ph> websites
+ </message>
+ </if>
+ <if expr="lang not in ['ar', 'ro', 'lv']">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_WARNING_HOSTS_ZERO" desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ga', 'sl', 'ar']">
+ <message name="IDS_EXTENSION_PROMPT_WARNING_HOSTS_TWO" desc="Permission string for access to data on four or more websites. NUMBER_OF_WEBSITES is two or two-like/dual numbers : 2 (Arabic and Irish) or 2, 102, 202 ... (Slovenian). For other languages, do NOT translated.">
+ Access your data on <ph name="NUMBER_OF_WEBSITES">#<ex>2</ex></ph> websites
+ </message>
+ </if>
+ <if expr="lang not in ['ga', 'sl', 'ar']">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_WARNING_HOSTS_TWO" desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message name="IDS_EXTENSION_PROMPT_WARNING_HOSTS_FEW" desc="Permission string for access to data on four or more websites. NUMBER_OF_WEBSITES is few or few-like numbers in Arabic, Russian, Polish, Croatian, Serbian, Ukrainian, Czech, Slovak, Slovenian, Latvian. For other languages, do NOT translate.">
+ Access your data on <ph name="NUMBER_OF_WEBSITES">#<ex>3</ex></ph> websites
+ </message>
+ </if>
+ <if expr="lang not in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_WARNING_HOSTS_FEW" desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang == 'ar'">
+ <message name="IDS_EXTENSION_PROMPT_WARNING_HOSTS_MANY" desc="Permission string for access to data on four or more websites. NUMBER_OF_WEBSITES is 11 through 99 in Arabic. For all other languages, do NOT translate.">
+ Access your data on <ph name="NUMBER_OF_WEBSITES">#<ex>23</ex></ph> websites
+ </message>
+ </if>
+ <if expr="lang != 'ar'">
+ <message translateable="false" name="IDS_EXTENSION_PROMPT_WARNING_HOSTS_MANY" desc="">
+ NA
+ </message>
+ </if>
<message name="IDS_EXTENSION_PROMPT_WARNING_HOST_LIST" desc="Permission string (heading) for a list of websites.">
Access your data on the following websites:
</message>
@@ -4163,13 +4267,13 @@
Change your wallpaper
</message>
<message name="IDS_EXTENSION_PROMPT_WARNING_FILE_SYSTEM_DIRECTORY" desc="Permission string for read access to directories and their contents.">
- Read folders that you open, and all files and folders within.
+ Read folders that you open in the application
</message>
<message name="IDS_EXTENSION_PROMPT_WARNING_FILE_SYSTEM_WRITE" desc="Permission string for write access to the file system.">
- Write to files that you open in the application.
+ Write to files that you open in the application
</message>
<message name="IDS_EXTENSION_PROMPT_WARNING_FILE_SYSTEM_WRITE_DIRECTORY" desc="Permission string for write access to directories and their contents.">
- Write to files and folders that you open, and all files and folders within.
+ Write to files and folders that you open in the application
</message>
<message name="IDS_EXTENSION_PROMPT_WARNING_MEDIA_GALLERIES_READ_WRITE" desc="Permission string for access to read and write to all of the user's media galleries.">
Access and change photos, music, and other media from your computer.
@@ -4341,6 +4445,9 @@
<message name="IDS_EXTENSION_INSTALL_DEPENDENCY_NOT_SHARED_MODULE" desc="Error displayed during installation of an extension which tries to imports resources from an extension which is not a shared module.">
Unable to import extension with ID "<ph name="IMPORT_ID">$1<ex>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</ex></ph>" because it is not a shared module.
</message>
+ <message name="IDS_EXTENSION_INSTALL_KIOSK_MODE_ONLY" desc="Error displayed during installation of an app with 'kiosk_only' attribute but user is not in ChromeOS kiosk mode.">
+ App with 'kiosk_only' manifest attribute must be installed in ChromeOS kiosk mode.
+ </message>
<message name="IDS_EXTENSION_OVERLAPPING_WEB_EXTENT" desc="Error message when a user tries to install an app with a web extent that overlaps another installed app.">
Could not add application because it conflicts with "<ph name="APP_NAME">$1<ex>Google Mail</ex></ph>".
</message>
@@ -4477,7 +4584,7 @@
<!-- Directory access confirmation dialog -->
<message name="IDS_EXTENSIONS_DIRECTORY_CONFIRMATION_DIALOG_TITLE" desc="Text of the title of the directory access confirmation dialog.">
- Confirm access
+ Confirm Access
</message>
<message name="IDS_EXTENSIONS_DIRECTORY_CONFIRMATION_DIALOG_MESSAGE_READ_ONLY" desc="Text of the message of the directory access confirmation dialog if the app does not have write access.">
The folder you selected contains sensitive files. Are you sure you want to grant "$1" permanent read access to this folder?
@@ -5465,17 +5572,17 @@
<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_DISABLE_DEVICE_DISCOVERY_NAME" desc="Title of the disable 'disable device discovery' flag.">
+ <message name="IDS_FLAGS_DISABLE_DEVICE_DISCOVERY_NAME" desc="Title of the 'disable device discovery' flag.">
Disable Device Discovery
</message>
- <message name="IDS_FLAGS_DISABLE_DEVICE_DISCOVERY_DESCRIPTION" desc="Description for 'disable device discovery' flag.">
+ <message name="IDS_FLAGS_DISABLE_DEVICE_DISCOVERY_DESCRIPTION" desc="Description of the 'disable device discovery' flag.">
Disable device discovery on local network.
</message>
- <message name="IDS_FLAGS_DISABLE_DEVICE_DISCOVERY_NOTIFICATIONS_NAME" desc="Title of the disable 'disable device discovery notificatios' flag.">
- Disable Device Discovery Notifications
+ <message name="IDS_FLAGS_DEVICE_DISCOVERY_NOTIFICATIONS_NAME" desc="Title of the 'device discovery notificatios' flag.">
+ Device Discovery Notifications
</message>
- <message name="IDS_FLAGS_DISABLE_DEVICE_DISCOVERY_NOTIFICATIONS_DESCRIPTION" desc="Description for 'disable device discovery notifications' flag.">
- Disable device discovery notifications on local network.
+ <message name="IDS_FLAGS_DEVICE_DISCOVERY_NOTIFICATIONS_DESCRIPTION" desc="Description of the 'device discovery notifications' flag.">
+ Device discovery notifications on local network.
</message>
<message name="IDS_FLAGS_TOUCH_OPTIMIZED_UI_NAME" desc="Title of the touch-optimized UI flag." >
Touch Optimized UI
@@ -5733,6 +5840,12 @@
<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_INSTANT_EXTENDED_CACHEABLE_NTP" desc="Title for the flag to enable the cacheable New Tab page for Instant extended.">
+ Cacheable New Tab page for Instant Extended.
+ </message>
+ <message name="IDS_FLAGS_ENABLE_INSTANT_EXTENDED_CACHEABLE_NTP_DESCRIPTION" desc="Description for the flag to enable the cacheable New Tab page for Instant extended.">
+ Use the cacheable New Tab page for Instant Extended.
+ </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>
@@ -6081,6 +6194,12 @@
Enable appropriate responses to canPlayType() for key systems that return the empty string by default.
</message>
<if expr="is_android">
+ <message name="IDS_FLAGS_DISABLE_INFOBAR_FOR_PROTECTED_MEDIA_IDENTIFIER_NAME" desc="Title for the flag to disable infobar popup for protected media identifier.">
+ Disable infobar popup for protected media.
+ </message>
+ <message name="IDS_FLAGS_DISABLE_INFOBAR_FOR_PROTECTED_MEDIA_IDENTIFIER_DESCRIPTION" desc="Description for the flag to disable infobar popup for protected media identifier.">
+ Disable infobar popup by default when accessing the protected media identifier.
+ </message>
<message name="IDS_FLAGS_MEDIADRM_ENABLE_NON_COMPOSITING_NAME" desc="Title for the flag to enable non-conmpositing decoding in MediaDrm for encrypted content.">
Enable non-compositing decoding.
</message>
@@ -6161,6 +6280,12 @@
<message name="IDS_FLAGS_ENABLE_MEMORY_MONITOR_DESCRIPTION" desc="Title for the flag to enable advanced gestures.">
Enables visual memory monitor in status area.
</message>
+ <message name="IDS_FLAGS_ENABLE_MULTI_PROFILE_SHELF_NAME" desc="Title for the multi profile shelf functionality flag.">
+ Enable multi profile shelf functionality
+ </message>
+ <message name="IDS_FLAGS_ENABLE_MULTI_PROFILE_SHELF_DESCRIPTION" desc="Title for the multi profile shelf functionality flag.">
+ Enable multi profile shelf functionality
+ </message>
<message name="IDS_FLAGS_ASH_AUDIO_DEVICE_MENU_NAME" desc="Title for a flag for audio switching.">
Audio input/output menu
</message>
@@ -6392,6 +6517,12 @@
<message name="IDS_FLAGS_ENABLE_SAML_SIGNIN_DESCRIPTION" desc="Description for the flag to enable SAML signin support.">
Enables SAML signin support for ChromeOS login.
</message>
+ <message name="IDS_FLAGS_ENABLE_MULTI_PROFILES_NAME" desc="Name for the flag to enable multi-profile support.">
+ Enable multiprofiles mode.
+ </message>
+ <message name="IDS_FLAGS_ENABLE_MULTI_PROFILES_DESCRIPTION" desc="Description for the flag to enable multi-profile support.">
+ This is an unsupported experimental mode, currently limited for testing purposes to devices enrolled on google.com, and with an @google.com account as the primary user. Features may break or change significantly.
+ </message>
</if>
<message name="IDS_FLAGS_FULL_HISTORY_SYNC_NAME" desc="Name of the flag to disable full history sync.">
Disable full history sync
@@ -6485,6 +6616,18 @@
<message name="IDS_FLAGS_IMPL_SIDE_PAINTING_DESCRIPTION" desc="Description of about:flags option for impl-side painting.">
If enabled, painting is done on a separate thread instead of the main thread.
</message>
+ <message name="IDS_FLAGS_DEADLINE_SCHEDULING_NAME" desc="Name of about:flags option for deadline scheduling.">
+ Deadline scheduling.
+ </message>
+ <message name="IDS_FLAGS_DEADLINE_SCHEDULING_DESCRIPTION" desc="Description of about:flags option for deadline scheduling.">
+ If enabled, latency in the Renderer may improve if the various stages of rendering are fast enough to beat a deadline. Requires threaded compositing.
+ </message>
+ <message name="IDS_FLAGS_UI_DEADLINE_SCHEDULING_NAME" desc="Name of about:flags option for UI deadline scheduling.">
+ UI deadline scheduling.
+ </message>
+ <message name="IDS_FLAGS_UI_DEADLINE_SCHEDULING_DESCRIPTION" desc="Description of about:flags option for UI deadline scheduling.">
+ If enabled, latency in the Browser may improve if the various stages of rendering are fast enough to beat a deadline. Requires threaded compositiing.
+ </message>
<message name="IDS_FLAGS_LCD_TEXT_NAME" desc="Name of about:flags option for LCD text.">
LCD text antialiasing
</message>
@@ -6950,6 +7093,9 @@
<message name="IDS_ABOUT_SYS_TABLE_TITLE" desc="Title of a table that contains system details">
Details
</message>
+ <message name="IDS_ABOUT_SYS_LOG_FILE_TABLE_TITLE" desc="Title of a table that contains details from an uploaded log">
+ Details: <ph name="FILE_NAME">$1<ex>Log.txt</ex></ph>
+ </message>
<message name="IDS_ABOUT_SYS_EXPAND_ALL" desc="name of a button that shows (expands) all system details">
Expand all...
</message>
@@ -6962,6 +7108,9 @@
<message name="IDS_ABOUT_SYS_COLLAPSE" desc="name of a button that hides (collapses) specific system details">
Collapse...
</message>
+ <message name="IDS_ABOUT_SYS_PARSE_ERROR" desc="error message displayed if parsing of custom uploaded log fails">
+ Unable to parse file: <ph name="FILE_NAME">$1<ex>Log.txt</ex></ph>
+ </message>
<!-- chrome://mobilesetup strings -->
<message name="IDS_MOBILE_SETUP_TITLE" desc="ChromeOS mobile device activation page title">
@@ -7378,6 +7527,12 @@
<message name="IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON" desc="Button text for the 'Save Password' infobar's 'Never remember for this site' option">
Never for this site
</message>
+ <message name="IDS_PASSWORD_MANAGER_BLACKLIST_DROP_DOWN" desc="Text for the 'Save Password' bubble's 'Never remember passwords for this site' option">
+ Never remember passwords for this site
+ </message>
+ <message name="IDS_PASSWORD_MANAGER_CANCEL_DROP_DOWN" desc="Text for the 'Save Password' bubble's 'Nope' option">
+ Nope
+ </message>
</if>
<if expr="is_android">
<message name="IDS_PASSWORD_MANAGER_SAVE_BUTTON" desc="Mobile: Button text for the 'Save Password' infobar's 'Remember password' option">
@@ -7623,7 +7778,7 @@
<!-- Managed User Avatar Menu -->
<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_EMAIL">$1<ex>Jane.Doe@gmail.com</ex></ph>. Usage and history from this user can be reviewed by the manager on chrome.com.
+ Usage and history of this user can be reviewed by the manager (<ph name="CUSTODIAN_EMAIL">$1<ex>Jane.Doe@gmail.com</ex></ph>) on chrome.com.
</message>
<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
@@ -8017,6 +8172,33 @@
Send Feedback
</message>
+ <!-- settings reset bubble messages -->
+ <message name="IDS_RESETTING" desc="Text for the button, once the user clicked to reset settings.">
+ Resetting...
+ </message>
+ <message name="IDS_NO_THANKS" desc="Text for the button the user clicks to refuse settings reset.">
+ No thanks
+ </message>
+ <if expr="pp_ifdef('use_titlecase')">
+ <message name="IDS_RESET_SETTINGS_MENU_ITEM" desc="In Title Case: Text for the Chrome menu option replacing Update required.">
+ Reset Altered <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> Settings
+ </message>
+ </if>
+ <if expr="not pp_ifdef('use_titlecase')">
+ <message name="IDS_RESET_SETTINGS_MENU_ITEM" desc="Text for the Chrome menu option replacing Update required.">
+ Reset altered <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> settings
+ </message>
+ </if>
+ <message name="IDS_RESET_BUBBLE_TITLE" desc="Text for the title of the settings reset bubble view.">
+ Reset altered <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> settings?
+ </message>
+ <message name="IDS_RESET_BUBBLE_TEXT" desc="Text for the settings reset bubble view full description.">
+ <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> detected that your browser settings may have been changed without your knowledge. Would you like to reset them to their original defaults?
+ </message>
+ <message name="IDS_REPORT_BUBBLE_TEXT" desc="Text for the settings reset bubble reporting checkbox.">
+ Help make Google Chrome better by reporting the current settings
+ </message>
+
<!-- Upgrade bubble messages -->
<message name="IDS_REINSTALL_APP" desc="Text for the button the user clicks to reinstall the app.">
Reinstall <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph>
@@ -9996,7 +10178,7 @@
Save and protect my details with Google Wallet.
</message>
<message name="IDS_AUTOFILL_DIALOG_SAVE_IN_WALLET_TOOLTIP" desc="Tooltip text that explains how Google Wallet integration works.">
- Google Wallet generates a new credit card number for each transaction, so the merchant never sees your personal card number.
+ A Google Wallet Virtual Card will be used for this transacation. A Virtual Card is a new card number so the seller never sees your real credit card number.
</message>
<message name="IDS_AUTOFILL_DIALOG_COMPLETE_WITHOUT_WALLET" desc="An error notification shown to users when Google Wallet is found to be unavailable.">
Oops, <ph name="WALLET_ERROR">$1<ex>Google Wallet is unavailable at this time.</ex></ph> You can complete this transaction without Google Wallet.
@@ -10017,7 +10199,7 @@
Could not save data to Wallet.
</message>
<message name="IDS_AUTOFILL_DIALOG_CHOOSE_DIFFERENT_WALLET_INSTRUMENT" desc="Text asking the user to choose a different payment method or address when using wallet.">
- We need more information to complete your purchase.
+ More information is needed to complete this purchase.
</message>
<!--- Autofill dialog: Wallet interstitials -->
@@ -10028,10 +10210,7 @@
Generating Google Wallet Virtual Card...
</message>
<message name="IDS_AUTOFILL_DIALOG_CARD_GENERATION_DONE" desc="Text the user sees after the wallet servers respond with a generated card number.">
- Your Google Wallet Virtual Card is ready.
- </message>
- <message name="IDS_AUTOFILL_DIALOG_CARD_GENERATION_OK_BUTTON" desc="Text for the button users have to press to proceed past the wallet card generation text.">
- Okay, got it
+ Your Virtual Card is ready.
</message>
<!--- Autofill dialog: Wallet error messages -->
@@ -10039,13 +10218,13 @@
There's something wrong with your Google Wallet account [12].
</message>
<message name="IDS_AUTOFILL_WALLET_BUYER_COUNTRY_NOT_SUPPORTED" desc="Text explaining that the user's Wallet Buyer Legal Address has a country which is unsupported. The text inside the |bars| is link text.">
- Unfortunately, Google Wallet can only be used at this merchant by buyers with a US address. If you are a US resident, |change your home address| or pay without Google Wallet.
+ Unfortunately, Google Wallet can only be used at this merchant by buyers with a US address. If you are a US resident, please |change your home address with Wallet| or pay without using Google Wallet.
</message>
<message name="IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS" desc="Text explaining that Google Wallet failed/pending Know Your Customer (KYC) check. The text inside the |bars| is link text.">
We were unable to verify your account information. |Fix this problem|
</message>
<message name="IDS_AUTOFILL_WALLET_UNSUPPORTED_MERCHANT" desc="Text explaining that the merchant is blacklisted for Google Wallet Chrome Payments due to compliance violation.">
- Google Wallet is not supported for this merchant.
+ Google Wallet is not supported with this merchant.
</message>
<message name="IDS_AUTOFILL_WALLET_SERVICE_UNAVAILABLE_ERROR" desc="Text explaining that Wallet is currently unavailable.">
Google Wallet is currently unavailable [61].
@@ -10062,7 +10241,7 @@
Email address
</message>
<message name="IDS_AUTOFILL_DIALOG_SECTION_CC" desc="Label for the credit card section of the autofill dialog.">
- Card information
+ Card details
</message>
<message name="IDS_AUTOFILL_DIALOG_SECTION_BILLING" desc="Label for the billing details (credit card + address) section of the autofill dialog.">
Billing details
@@ -10128,28 +10307,28 @@
Google Wallet requires at least a first and last name.
</message>
<message name="IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_EMAIL_ADDRESS" desc="Message displayed to user when email address validation fails.">
- Not a valid email address
+ Invalid email address. Please check and try again.
</message>
<message name="IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_CREDIT_CARD_NUMBER" desc="Message displayed to user when credit card number validation fails.">
- Not a valid credit card number
+ Invalid card number. Please check and try again.
</message>
<message name="IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_CREDIT_CARD_SECURITY_CODE" desc="Message displayed to user when credit card security code validation fails.">
- Not a valid credit card security code
+ Invalid CVC code. Please check and try again.
</message>
<message name="IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_DATE" desc="Message displayed to user when credit card expiration date validation fails.">
- Card is expired
+ The card is expired. Please check the date or enter a new card.
</message>
<message name="IDS_AUTOFILL_DIALOG_VALIDATION_CREDIT_CARD_NOT_SUPPORTED_BY_WALLET" desc="Message displayed to user when user entered a credit card number that is not supported by Google Wallet.">
- Card type is not supported by Wallet
+ This type of card is not supported by Google Wallet. Please select a different card.
</message>
<message name="IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_ZIP_CODE" desc="Message displayed to user when ZIP code (postal code) validation fails.">
- Not a valid ZIP code
+ Invalid ZIP code. Please check and try again.
</message>
<message name="IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_REGION" desc="Message displayed to user when the region (US state) validation fails.">
- Not a valid state
+ Invalid state. Please check and try again.
</message>
<message name="IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_PHONE_NUMBER" desc="Message displayed to user when phone number validation fails.">
- Not a valid phone number
+ Invalid phone number. Please check and try again.
</message>
<message name="IDS_AUTOFILL_DIALOG_VALIDATION_MISSING_VALUE" desc="Message displayed to user when one of the required fields is left empty.">
Field is required
@@ -10163,7 +10342,7 @@
Your card has been protected with the Google Wallet Virtual Card (<ph name="FRONTING_CREDIT_CARD">|$1|<ex>Visa - 1234</ex></ph>) and this number will appear on your receipt. This purchase will still be charged to your <ph name="BACKING_CREDIT_CARD">|$2|<ex>Visa - 5678</ex></ph>.
</message>
<message name="IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_LINK" desc="The text of a link at the bottom of the autofill dialog bubble that sends users to a Google Wallet billing/card management page.">
- Manage Saved Cards
+ Manage credit cards
</message>
<message name="IDS_APPEARANCE_GROUP_NAME" desc="The title of the appearance group">
@@ -10217,7 +10396,7 @@
</if>
<if expr="not is_android">
<message name="IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_DISABLED_LABEL" desc="The label of the cloud print setup button when it hasn't been set up yet.">
- <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph> lets you access this computer's printers from anywhere. Click to enable.
+ <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph> lets you access this computer's printers from anywhere.
</message>
</if>
<message name="IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_DISABLED_BUTTON" desc="The label of the cloud connector configure button when it hasn't been set up yet.">
@@ -10980,22 +11159,6 @@
Add more apps
</message>
- <!-- Offline page -->
- <if expr="pp_ifdef('chromeos')">
- <message name="IDS_SITE_OFFLINE_LOAD_HEADLINE" desc="Offline Page HTML headline for a site.">
- This page is not available offline.
- </message>
- <message name="IDS_APP_OFFLINE_LOAD_HEADLINE" desc="Offline Page HTML headline for an app.">
- This app is not available offline.
- </message>
- <message name="IDS_OFFLINE_LOAD_DESCRIPTION" desc="Description for the offline page.">
- Please reconnect to a network.
- </message>
- <message name="IDS_OFFLINE_NETWORK_SETTINGS">
- Network settings
- </message>
- </if>
-
<!-- Multi-profile -->
<message name="IDS_PROFILES_OPTIONS_GROUP_NAME" desc="The name of the sync group in the options dialog.">
Users
@@ -11026,9 +11189,16 @@
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>
+ <if expr="not pp_ifdef('chromeos')">
+ <message name="IDS_PROFILES_CREATE_NEW_PROFILE_LINK" desc="Link in the avatar menu bubble view to create a new profile.">
+ New user
+ </message>
+ </if>
+ <if expr="pp_ifdef('chromeos')">
+ <message name="IDS_PROFILES_CREATE_NEW_PROFILE_LINK" desc="Link in the avatar menu bubble view to create a new profile.">
+ Sign in another account
+ </message>
+ </if>
<message name="IDS_PROFILES_MANAGE_PROFILES_BUTTON" desc="Button in the avatar menu bubble view to manage profiles.">
Manage
</message>
@@ -11047,15 +11217,18 @@
<message name="IDS_PROFILES_EDIT_PROFILE_LINK" desc="Link in the avatar menu bubble to edit a profile.">
edit
</message>
- <message name="IDS_PROFILES_PROFILE_USERS_BUTTON" desc="Button in the avatar menu bubble view for switching users.">
+ <message name="IDS_PROFILES_ADD_PERSON_BUTTON" desc="Button in the avatar menu bubble view for creating a new user.">
Add person
</message>
- <message name="IDS_PROFILES_PROFILE_GUEST_BUTTON" desc="Button in the avatar menu bubble view for guest browsing.">
+ <message name="IDS_PROFILES_GUEST_BUTTON" desc="Button in the avatar menu bubble view for guest browsing.">
Browse as guest
</message>
- <message name="IDS_PROFILES_PROFILE_EXIT_GUEST_BUTTON" desc="Button in the avatar menu bubble view for guest browsing.">
+ <message name="IDS_PROFILES_EXIT_GUEST_BUTTON" desc="Button in the avatar menu bubble view to end guest browsing.">
End guest session
</message>
+ <message name="IDS_PROFILES_ALL_PEOPLE_BUTTON" desc="Button in the avatar menu bubble view for launching the user manager.">
+ View all people
+ </message>
<message name="IDS_PROFILES_PROFILE_ADD_ACCOUNT_BUTTON" desc="Button in the avatar menu bubble view used to add an account to a profile.">
Add account for <ph name="PROFILE_NAME">$1<ex>John</ex></ph>
</message>
@@ -11180,6 +11353,12 @@
This account is already being used on this computer.
</message>
</if>
+ <if expr="pp_ifdef('chromeos')">
+ <message name="IDS_MULTI_PROFILES_WARNING" desc="A notification message when user signs into a multiprofile session for the first time.">
+ You have enabled multiprofiles, an unsupported experimental mode in Chrome OS. Features may change or break.
+ </message>
+ </if>
+
<!-- SafeBrowsing -->
<message name="IDS_SAFE_BROWSING_MALWARE_TITLE" desc="SafeBrowsing Malware HTML title">
Malware Detected!
@@ -13386,6 +13565,9 @@
Quit <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>
</message>
<!-- File menu -->
+ <message name="IDS_NEW_MAC" desc="The Mac menu item for creating a new file in the file menu.">
+ New
+ </message>
<message name="IDS_NEW_TAB_MAC" desc="The Mac menu item for opening a new tab in the file menu.">
New Tab
</message>
@@ -13821,6 +14003,22 @@
New camera and microphone settings will take effect after reloading the page.
</message>
+ <!-- Proteced media identifier permission infobar -->
+ <if expr="is_android">
+ <message name="IDS_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_QUESTION" desc="Question asked on the infobar whenever URL wants to access protected media identifier. It shows the origin of the URL.">
+ @<ph name="URL">$1<ex>https://www.youtube.com</ex></ph> needs to uniquely identify your device to play premium content.
+ </message>
+ <message name="IDS_PROTECTED_MEDIA_IDENTIFIER_ALLOW_BUTTON" desc="A button in the protected media identifier infobar for allowing access to a protected media identifier for a given origin.">
+ Allow
+ </message>
+ <message name="IDS_PROTECTED_MEDIA_IDENTIFIER_DENY_BUTTON" desc="A button in the protected media identifier infobar for denying access to a protected media identifier for a given origin.">
+ Deny
+ </message>
+ <message name="IDS_PROTECTED_MEDIA_IDENTIFIER_SETTINGS_LINK" desc="Link on in the protected media identifier infobar to open up its settings page.">
+ Settings
+ </message>
+ </if>
+
<message name="IDS_SAVE_PASSWORD" desc="The status text that is used as tooltip text for the save password icon and as status text of the save password bubble when a password can be saved.">
Would you like to save this password?
</message>
@@ -14302,7 +14500,7 @@
</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"><a target="_blank" href="https://www.chrome.com/manage"></ph>www.chrome.com/manage<ph name="END_LINK"></a><ex></a></ex></ph>.
+ Settings and browsing history for this supervised user may still be visible by the manager at <ph name="BEGIN_LINK"><a target="_blank" href="https://www.chrome.com/manage"></ph>www.chrome.com/manage<ph name="END_LINK"></a><ex></a></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)
@@ -14381,6 +14579,9 @@
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_MANAGED_USER_LEARN_EVEN_MORE_LABEL" desc="Label for the link within the 'Learn more' dialog for the supervised user feature, which links to a Help Center article giving even more information about the feature.">
+ Learn even more
+ </message>
<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>
@@ -14709,16 +14910,16 @@
<!-- Media Galleries. -->
<message name="IDS_MEDIA_GALLERIES_DIALOG_HEADER" desc="Header for media gallery permissions dialog.">
- Access Settings
+ Media-File Permissions for "<ph name="EXTENSION">$1<ex>Photo Editor</ex></ph>"
</message>
<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.
+ "<ph name="EXTENSION">$1<ex>PhotoEditor</ex></ph>" can read and write images, video, and sound files in the checked 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.
+ "<ph name="EXTENSION">$1<ex>PhotoEditor</ex></ph>" can read images, video, and sound files in the checked locations.
</message>
<message name="IDS_MEDIA_GALLERIES_DIALOG_SUBTEXT_WRITE_ONLY" desc="Explanatory text for the media gallery access permission. Indicates than the specified (by name) extension has write-only access to the listed folders.">
- <ph name="EXTENSION">$1<ex>PhotoEditor</ex></ph> can change media in these locations.
+ "<ph name="EXTENSION">$1<ex>PhotoEditor</ex></ph>" can write images, video, and sound files in the checked 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
@@ -15093,9 +15294,15 @@
New printer on your network
</message>
<message name="IDS_LOCAL_DISOCVERY_NOTIFICATION_CONTENTS_PRINTER" desc="Contents of notification for a new printer showing up on your network">
- Add <ph name="PRINTER_NAME">$1</ph> to Cloud Print so you can print from anywhere.
+ Add the printer to <ph name="PRODUCT_NAME">$1<ex>Google Cloud Print</ex></ph> so you can print from anywhere.
</message>
- <message name="IDS_LOCAL_DISOCVERY_NOTIFICATION_DISPLAY_SOURCE_PRINTER" desc="Display name for notification for a new printer showing up on your network">
+ <message name="IDS_LOCAL_DISOCVERY_NOTIFICATION_TITLE_PRINTER_MULTIPLE" desc="Title of notification for a new printer showing up on your network">
+ New printers on your network
+ </message>
+ <message name="IDS_LOCAL_DISOCVERY_NOTIFICATION_CONTENTS_PRINTER_MULTIPLE" desc="Contents of notification for a new printer showing up on your network">
+ Add the printers to <ph name="PRODUCT_NAME">$1<ex>Google Cloud Print</ex></ph> so you can print from anywhere.
+ </message>
+ <message name="IDS_LOCAL_DISOCVERY_PRODUCT_NAME_PRINTER" desc="Display name for notification for a new printer showing up on your network">
Google Cloud Print
</message>
<message name="IDS_LOCAL_DISOCVERY_NOTIFICATION_BUTTON_PRINTER" desc="Message on registration button for printer">
@@ -15105,7 +15312,7 @@
Devices
</message>
<message name="IDS_LOCAL_DISCOVERY_REGISTER_CONFIRMATION" desc="Confirmation for registering a printer to Google Cloud Print">
- The following devices can be added to your account from your local network:
+ Do you wish to register the printer <ph name="PRINTER_NAME">$1</ph> to Google Cloud Print?
</message>
<message name="IDS_LOCAL_DISCOVERY_REGISTER_USER" desc="Label for user picker in registration dialog">
User:
@@ -15164,6 +15371,31 @@
<message name="IDS_LOCAL_DISCOVERY_CLOUD_DEVICES_LOGIN" desc="Text on login button for local discovery page">
sign in
</message>
+ <message name="IDS_LOCAL_DISCOVERY_DEVICES_PAGE_BUTTON" desc="Text on button to take user to devices page">
+ Manage
+ </message>
+ <message name="IDS_LOCAL_DISCOVERY_AVAILABLE_DEVICES" desc="Title for 'available devices' section in devices page">
+ New devices
+ </message>
+ <message name="IDS_LOCAL_DISCOVERY_MY_DEVICES" desc="Title for 'my devices' section in devices page">
+ My devices
+ </message>
+ <message name="IDS_LOCAL_DISCOVERY_CLOUD_PRINT_CONNECTOR_DISABLED_LABEL" desc="In local discovery page: The label of the cloud print setup button when it hasn't been set up yet.">
+ You can add classic printers connected to your computer to <ph name="CLOUD_PRINT_NAME">$1<ex>Google Cloud Print</ex></ph>.
+ </message>
+ <message name="IDS_LOCAL_DISCOVERY_CONNECTOR_SECTION" desc="In local discovery page: Title of cloud print connector section.">
+ Classic printers
+ </message>
+ <message name="IDS_LOCAL_DISCOVERY_NOTIFICATIONS_ENABLE_CHECKBOX_LABEL" desc="Label for notificatiosn-enable checkbox">
+ Show notifications when new printers are detected on the network
+ </message>
+ <message name="IDS_LOCAL_DISCOVERY_NOTIFICATIONS_DISABLE_BUTTON_LABEL" desc="Label for button disabling local device notifications">
+ Don't show this again
+ </message>
+ <!-- People search strings -->
+ <message name="IDS_PEOPLE_SEARCH_ACTION_EMAIL_TOOLTIP" desc="Tooltip text for sending an email to the person in the result">
+ E-mail this person
+ </message>
</messages>
<structures fallback_to_english="true">
diff --git a/chrome/app/nibs/ContentBlockedSavePassword.xib b/chrome/app/nibs/ContentBlockedSavePassword.xib
index 7c863a7..246e6e6 100644
--- a/chrome/app/nibs/ContentBlockedSavePassword.xib
+++ b/chrome/app/nibs/ContentBlockedSavePassword.xib
@@ -2,7 +2,7 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
- <string key="IBDocument.SystemVersion">12E3067</string>
+ <string key="IBDocument.SystemVersion">12F37</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
@@ -17,6 +17,10 @@
<string>NSButtonCell</string>
<string>NSCustomObject</string>
<string>NSCustomView</string>
+ <string>NSMenu</string>
+ <string>NSMenuItem</string>
+ <string>NSPopUpButton</string>
+ <string>NSPopUpButtonCell</string>
<string>NSTextField</string>
<string>NSTextFieldCell</string>
<string>NSView</string>
@@ -60,25 +64,97 @@
<int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSButton" id="31268199">
+ <object class="NSPopUpButton" id="565504492">
<reference key="NSNextResponder" ref="301729179"/>
<int key="NSvFlags">268</int>
- <string key="NSFrame">{{57, 103}, {123, 28}}</string>
+ <string key="NSFrame">{{180, 106}, {16, 22}}</string>
<reference key="NSSuperview" ref="301729179"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="825590456"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
- <object class="NSButtonCell" key="NSCell" id="932040963">
- <int key="NSCellFlags">67108864</int>
- <int key="NSCellFlags2">134348800</int>
- <string key="NSContents">^IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON</string>
+ <object class="NSPopUpButtonCell" key="NSCell" id="666181329">
+ <int key="NSCellFlags">67108928</int>
+ <int key="NSCellFlags2">133120</int>
<object class="NSFont" key="NSSupport" id="26">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">11</double>
<int key="NSfFlags">3100</int>
</object>
<string key="NSCellIdentifier">_NS:9</string>
+ <reference key="NSControlView" ref="565504492"/>
+ <int key="NSButtonFlags">103301120</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">400</int>
+ <int key="NSPeriodicInterval">75</int>
+ <object class="NSMenuItem" key="NSMenuItem" id="340982779">
+ <reference key="NSMenu" ref="860319963"/>
+ <string key="NSTitle">^IDS_PASSWORD_MANAGER_CANCEL_DROP_DOWN</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <int key="NSState">1</int>
+ <object class="NSCustomResource" key="NSOnImage" id="451765153">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSMenuCheckmark</string>
+ </object>
+ <object class="NSCustomResource" key="NSMixedImage" id="467001193">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSMenuMixedState</string>
+ </object>
+ <string key="NSAction">_popUpItemAction:</string>
+ <reference key="NSTarget" ref="666181329"/>
+ </object>
+ <bool key="NSMenuItemRespectAlignment">YES</bool>
+ <object class="NSMenu" key="NSMenu" id="860319963">
+ <string key="NSTitle">OtherViews</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="340982779"/>
+ <object class="NSMenuItem" id="786233053">
+ <reference key="NSMenu" ref="860319963"/>
+ <string key="NSTitle">^IDS_PASSWORD_MANAGER_BLACKLIST_DROP_DOWN</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="451765153"/>
+ <reference key="NSMixedImage" ref="467001193"/>
+ <string key="NSAction">_popUpItemAction:</string>
+ <reference key="NSTarget" ref="666181329"/>
+ </object>
+ </object>
+ <bool key="NSMenuExcludeMarkColumn">YES</bool>
+ <object class="NSFont" key="NSMenuFont" id="761092028">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">13</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ </object>
+ <int key="NSSelectedIndex">-1</int>
+ <int key="NSPreferredEdge">1</int>
+ <bool key="NSUsesItemFromMenu">YES</bool>
+ <bool key="NSAltersState">YES</bool>
+ <int key="NSArrowPosition">1</int>
+ </object>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ </object>
+ <object class="NSButton" id="31268199">
+ <reference key="NSNextResponder" ref="301729179"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{139, 103}, {63, 28}}</string>
+ <reference key="NSSuperview" ref="301729179"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="565504492"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="932040963">
+ <int key="NSCellFlags">67108864</int>
+ <int key="NSCellFlags2">16908288</int>
+ <string key="NSContents">^IDS_PASSWORD_MANAGER_CANCEL_DROP_DOWN</string>
+ <reference key="NSSupport" ref="26"/>
+ <string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="31268199"/>
<int key="NSButtonFlags">-2038284288</int>
<int key="NSButtonFlags2">129</int>
@@ -92,7 +168,7 @@
<object class="NSButton" id="825590456">
<reference key="NSNextResponder" ref="301729179"/>
<int key="NSvFlags">268</int>
- <string key="NSFrame">{{178, 103}, {123, 28}}</string>
+ <string key="NSFrame">{{197, 103}, {104, 28}}</string>
<reference key="NSSuperview" ref="301729179"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="913795455"/>
@@ -100,7 +176,7 @@
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="339708150">
<int key="NSCellFlags">67108864</int>
- <int key="NSCellFlags2">134348800</int>
+ <int key="NSCellFlags2">131072</int>
<string key="NSContents">^IDS_PASSWORD_MANAGER_SAVE_BUTTON</string>
<reference key="NSSupport" ref="26"/>
<string key="NSCellIdentifier">_NS:9</string>
@@ -161,11 +237,7 @@
<int key="NSCellFlags">67108864</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Box</string>
- <object class="NSFont" key="NSSupport">
- <string key="NSName">LucidaGrande</string>
- <double key="NSSize">13</double>
- <int key="NSfFlags">1044</int>
- </object>
+ <reference key="NSSupport" ref="761092028"/>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
@@ -225,7 +297,7 @@
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">12</double>
- <int key="NSfFlags">4883</int>
+ <int key="NSfFlags">16</int>
</object>
<string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="744075081"/>
@@ -320,22 +392,6 @@
<int key="connectionID">61</int>
</object>
<object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">blacklistPasswordButton_</string>
- <reference key="source" ref="1001"/>
- <reference key="destination" ref="31268199"/>
- </object>
- <int key="connectionID">62</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">blacklistBubble:</string>
- <reference key="source" ref="1001"/>
- <reference key="destination" ref="31268199"/>
- </object>
- <int key="connectionID">63</int>
- </object>
- <object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">saveBubble:</string>
<reference key="source" ref="1001"/>
@@ -361,6 +417,54 @@
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
+ <string key="label">blacklistPasswordButton_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="565504492"/>
+ </object>
+ <int key="connectionID">106</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">closeBubble:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="31268199"/>
+ </object>
+ <int key="connectionID">122</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">doneButton_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="31268199"/>
+ </object>
+ <int key="connectionID">123</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">blacklistBubble:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="565504492"/>
+ </object>
+ <int key="connectionID">124</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">blacklistBubble:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="786233053"/>
+ </object>
+ <int key="connectionID">126</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">closeBubble:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="340982779"/>
+ </object>
+ <int key="connectionID">127</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="1005"/>
<reference key="destination" ref="1001"/>
@@ -469,6 +573,7 @@
<reference ref="266815090"/>
<reference ref="825590456"/>
<reference ref="31268199"/>
+ <reference ref="565504492"/>
</object>
<reference key="parent" ref="1006"/>
</object>
@@ -547,6 +652,44 @@
<reference key="object" ref="614462829"/>
<reference key="parent" ref="744075081"/>
</object>
+ <object class="IBObjectRecord">
+ <int key="objectID">81</int>
+ <reference key="object" ref="565504492"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="666181329"/>
+ </object>
+ <reference key="parent" ref="301729179"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">82</int>
+ <reference key="object" ref="666181329"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="860319963"/>
+ </object>
+ <reference key="parent" ref="565504492"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">83</int>
+ <reference key="object" ref="860319963"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="786233053"/>
+ <reference ref="340982779"/>
+ </object>
+ <reference key="parent" ref="666181329"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">86</int>
+ <reference key="object" ref="786233053"/>
+ <reference key="parent" ref="860319963"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">84</int>
+ <reference key="object" ref="340982779"/>
+ <reference key="parent" ref="860319963"/>
+ </object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -577,6 +720,11 @@
<string>72.CustomClassName</string>
<string>72.IBPluginDependency</string>
<string>8.IBPluginDependency</string>
+ <string>81.IBPluginDependency</string>
+ <string>82.IBPluginDependency</string>
+ <string>83.IBPluginDependency</string>
+ <string>84.IBPluginDependency</string>
+ <string>86.IBPluginDependency</string>
</object>
<object class="NSArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -604,6 +752,11 @@
<string>HyperlinkButtonCell</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
</object>
<object class="NSMutableDictionary" key="unlocalizedProperties">
@@ -618,7 +771,7 @@
<reference key="dict.values" ref="0"/>
</object>
<nil key="sourceID"/>
- <int key="maxID">74</int>
+ <int key="maxID">127</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -672,6 +825,7 @@
<string>load:</string>
<string>manageBlocking:</string>
<string>mediaMenuChanged:</string>
+ <string>noActionBubble:</string>
<string>saveBubble:</string>
<string>showMoreInfo:</string>
</object>
@@ -686,6 +840,7 @@
<string>id</string>
<string>id</string>
<string>id</string>
+ <string>id</string>
</object>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
@@ -699,6 +854,7 @@
<string>load:</string>
<string>manageBlocking:</string>
<string>mediaMenuChanged:</string>
+ <string>noActionBubble:</string>
<string>saveBubble:</string>
<string>showMoreInfo:</string>
</object>
@@ -733,6 +889,10 @@
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo">
+ <string key="name">noActionBubble:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo">
<string key="name">saveBubble:</string>
<string key="candidateClassName">id</string>
</object>
@@ -754,6 +914,7 @@
<string>loadButton_</string>
<string>manageButton_</string>
<string>mediaMenusContainer_</string>
+ <string>noActionButton_</string>
<string>savePasswordButton_</string>
<string>titleLabel_</string>
</object>
@@ -768,6 +929,7 @@
<string>NSButton</string>
<string>NSView</string>
<string>NSButton</string>
+ <string>NSButton</string>
<string>NSTextField</string>
</object>
</object>
@@ -783,6 +945,7 @@
<string>loadButton_</string>
<string>manageButton_</string>
<string>mediaMenusContainer_</string>
+ <string>noActionButton_</string>
<string>savePasswordButton_</string>
<string>titleLabel_</string>
</object>
@@ -821,6 +984,10 @@
<string key="candidateClassName">NSView</string>
</object>
<object class="IBToOneOutletInfo">
+ <string key="name">noActionButton_</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
<string key="name">savePasswordButton_</string>
<string key="candidateClassName">NSButton</string>
</object>
@@ -1006,5 +1173,18 @@
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSMenuCheckmark</string>
+ <string>NSMenuMixedState</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>{11, 11}</string>
+ <string>{10, 3}</string>
+ </object>
+ </object>
</data>
</archive>
diff --git a/chrome/app/nibs/MainMenu.xib b/chrome/app/nibs/MainMenu.xib
index c46aec9..1aba13d 100644
--- a/chrome/app/nibs/MainMenu.xib
+++ b/chrome/app/nibs/MainMenu.xib
@@ -68,6 +68,7 @@
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="353210768"/>
<reference key="NSMixedImage" ref="549394948"/>
+ <int key="NSTag">40018</int>
</object>
<object class="NSMenuItem" id="304266470">
<reference key="NSMenu" ref="110575045"/>
@@ -529,6 +530,7 @@
<reference key="NSOnImage" ref="353210768"/>
<reference key="NSMixedImage" ref="549394948"/>
<string key="NSAction">submenuAction:</string>
+ <int key="NSTag">37100</int>
<object class="NSMenu" key="NSSubmenu" id="963351320">
<string key="NSTitle">^IDS_EDIT_FIND_SUBMENU_MAC</string>
<object class="NSMutableArray" key="NSMenuItems">
@@ -612,6 +614,7 @@
<reference key="NSOnImage" ref="353210768"/>
<reference key="NSMixedImage" ref="549394948"/>
<string key="NSAction">submenuAction:</string>
+ <int key="NSTag">41005</int>
<object class="NSMenu" key="NSSubmenu" id="769623530">
<string key="NSTitle">^IDS_EDIT_SPELLING_GRAMMAR_MAC</string>
<object class="NSMutableArray" key="NSMenuItems">
@@ -661,6 +664,7 @@
<reference key="NSOnImage" ref="353210768"/>
<reference key="NSMixedImage" ref="549394948"/>
<string key="NSAction">submenuAction:</string>
+ <int key="NSTag">50158</int>
<object class="NSMenu" key="NSSubmenu" id="84147574">
<string key="NSTitle">^IDS_SPEECH_MAC</string>
<object class="NSMutableArray" key="NSMenuItems">
diff --git a/chrome/app/policy/policy_templates.json b/chrome/app/policy/policy_templates.json
index 59aa304..c65023a 100644
--- a/chrome/app/policy/policy_templates.json
+++ b/chrome/app/policy/policy_templates.json
@@ -118,7 +118,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: 243
+# For your editing convenience: highest ID currently used: 244
#
# Placeholders:
# The following placeholder strings are automatically substituted:
@@ -2747,6 +2747,56 @@
If the policy is left not set the user can choose whether he wants to be asked for password to unlock the device or not.''',
},
{
+ 'name': 'ChromeOsMultiProfileUserBehavior',
+ 'type': 'string-enum',
+ 'schema': {
+ 'type': 'string',
+ 'enum': [
+ 'unrestricted',
+ 'primary-only',
+ 'not-allowed',
+ ],
+ },
+ 'items': [
+ {
+ 'name': 'MultiProfileUserBehaviorUnrestricted',
+ 'value': 'unrestricted',
+ 'caption': '''Allow enterprise user to be both primary and secondary (Default behavior)''',
+ },
+ {
+ 'name': 'MultiProfileUserBehaviorMustBePrimary',
+ 'value': 'primary-only',
+ 'caption': '''Allow enterprise user to be primary multiprofile user only''',
+ },
+ {
+ 'name': 'MultiProfileUserBehaviorNotAllowed',
+ 'value': 'not-allowed',
+ 'caption': '''Do not allow enterprise user to be part of multiprofile (primary or secondary)''',
+ },
+ ],
+ 'supported_on': ['chrome_os:31-'],
+ 'features': {
+ 'dynamic_refresh': True,
+ 'per_profile': True,
+ },
+ 'example_value': 'unrestricted',
+ 'id': 244,
+ 'caption': '''Control the user behavior in a multiprofile session''',
+ 'desc': '''Control the user behavior in a multiprofile session on <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> devices.
+
+ If this policy is set to 'MultiProfileUserBehaviorUnrestricted', the user can be either primary or secondary user in a multiprofile session.
+
+ If this policy is set to 'MultiProfileUserBehaviorMustBePrimary', the user can only be the primary user in a multiprofile session.
+
+ If this policy is set to 'MultiProfileUserBehaviorNotAllowed', the user cannot be part of a multiprofile session.
+
+ If you set this setting, users cannot change or override it.
+
+ If the setting is changed while the user is signed into a multiprofile session, all users in the session will be checked against their cooresponding settings. The session will be closed if any one of the users is no longer allowed to be in the session.
+
+ If the policy is left not set, the default value 'MultiProfileUserBehaviorUnrestricted' will be used.''',
+ },
+ {
'name': 'InstantEnabled',
'type': 'main',
'schema': { 'type': 'boolean' },
diff --git a/chrome/app/theme/chromium/app_list_128.png b/chrome/app/theme/chromium/app_list_128.png
index 17916f4..e525514 100644
--- a/chrome/app/theme/chromium/app_list_128.png
+++ b/chrome/app/theme/chromium/app_list_128.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
deleted file mode 100644
index 3de14dd..0000000
--- a/chrome/app/theme/default_100_percent/common/audio_equalizer_column.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/cloudprint.png b/chrome/app/theme/default_100_percent/common/cloudprint.png
index 98c0de0..0155c63 100644
--- a/chrome/app/theme/default_100_percent/common/cloudprint.png
+++ b/chrome/app/theme/default_100_percent/common/cloudprint.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/credit_card_cvc_hint.png b/chrome/app/theme/default_100_percent/common/credit_card_cvc_hint.png
index b177ae0..951ade9 100644
--- a/chrome/app/theme/default_100_percent/common/credit_card_cvc_hint.png
+++ b/chrome/app/theme/default_100_percent/common/credit_card_cvc_hint.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/credit_card_cvc_hint_amex.png b/chrome/app/theme/default_100_percent/common/credit_card_cvc_hint_amex.png
index 91b3685..22e11d3 100644
--- a/chrome/app/theme/default_100_percent/common/credit_card_cvc_hint_amex.png
+++ b/chrome/app/theme/default_100_percent/common/credit_card_cvc_hint_amex.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/help_16.png b/chrome/app/theme/default_100_percent/common/help_16.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/help_16.png
rename to chrome/app/theme/default_100_percent/common/help_16.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/icon_add_user.png b/chrome/app/theme/default_100_percent/common/icon_add_user.png
index 4a953d8..c1a83ec 100644
--- a/chrome/app/theme/default_100_percent/common/icon_add_user.png
+++ b/chrome/app/theme/default_100_percent/common/icon_add_user.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/icon_add_user_white.png b/chrome/app/theme/default_100_percent/common/icon_add_user_white.png
index 6b1b213..da53c59 100644
--- a/chrome/app/theme/default_100_percent/common/icon_add_user_white.png
+++ b/chrome/app/theme/default_100_percent/common/icon_add_user_white.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/icon_browse_as_guest.png b/chrome/app/theme/default_100_percent/common/icon_browse_as_guest.png
index 9ee934d..c319af3 100644
--- a/chrome/app/theme/default_100_percent/common/icon_browse_as_guest.png
+++ b/chrome/app/theme/default_100_percent/common/icon_browse_as_guest.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/icon_browse_as_guest_white.png b/chrome/app/theme/default_100_percent/common/icon_browse_as_guest_white.png
index c373055..9fd7b79 100644
--- a/chrome/app/theme/default_100_percent/common/icon_browse_as_guest_white.png
+++ b/chrome/app/theme/default_100_percent/common/icon_browse_as_guest_white.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/icon_locked.png b/chrome/app/theme/default_100_percent/common/icon_locked.png
index d31fcad..1c06959 100644
--- a/chrome/app/theme/default_100_percent/common/icon_locked.png
+++ b/chrome/app/theme/default_100_percent/common/icon_locked.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_protected_media_identifier.png b/chrome/app/theme/default_100_percent/common/infobar_protected_media_identifier.png
new file mode 100644
index 0000000..c3d87d4
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/infobar_protected_media_identifier.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/mail.png b/chrome/app/theme/default_100_percent/common/mail.png
new file mode 100644
index 0000000..712e1a9
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/mail.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/mail_hover.png b/chrome/app/theme/default_100_percent/common/mail_hover.png
new file mode 100644
index 0000000..72bfabd
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/mail_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/mail_pressed.png b/chrome/app/theme/default_100_percent/common/mail_pressed.png
new file mode 100644
index 0000000..49ca510
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/mail_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_border_bottom.png b/chrome/app/theme/default_100_percent/common/omnibox_border_bottom.png
index f3adecb..59672c7 100644
--- a/chrome/app/theme/default_100_percent/common/omnibox_border_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/omnibox_border_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_border_top.png b/chrome/app/theme/default_100_percent/common/omnibox_border_top.png
index 0f8d37c..285ed7b 100644
--- a/chrome/app/theme/default_100_percent/common/omnibox_border_top.png
+++ b/chrome/app/theme/default_100_percent/common/omnibox_border_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_popup_border_bottom.png b/chrome/app/theme/default_100_percent/common/omnibox_popup_border_bottom.png
index c296870..feca814 100644
--- a/chrome/app/theme/default_100_percent/common/omnibox_popup_border_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/omnibox_popup_border_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_popup_border_top.png b/chrome/app/theme/default_100_percent/common/omnibox_popup_border_top.png
index 4eb2bfe..a9eede2 100644
--- a/chrome/app/theme/default_100_percent/common/omnibox_popup_border_top.png
+++ b/chrome/app/theme/default_100_percent/common/omnibox_popup_border_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/save_password.png b/chrome/app/theme/default_100_percent/common/save_password.png
index 368127e..63829ef 100644
--- a/chrome/app/theme/default_100_percent/common/save_password.png
+++ b/chrome/app/theme/default_100_percent/common/save_password.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/supervised_user_placeholder.png b/chrome/app/theme/default_100_percent/common/supervised_user_placeholder.png
index decfcba..7a03286 100644
--- a/chrome/app/theme/default_100_percent/common/supervised_user_placeholder.png
+++ b/chrome/app/theme/default_100_percent/common/supervised_user_placeholder.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/tab_audio_indicator.png b/chrome/app/theme/default_100_percent/common/tab_audio_indicator.png
new file mode 100644
index 0000000..423e930
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/tab_audio_indicator.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/notification_alert.png b/chrome/app/theme/default_100_percent/cros/notification_alert.png
new file mode 100644
index 0000000..f96cc72
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/cros/notification_alert.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
index df0ba11..d644e40 100644
--- a/chrome/app/theme/default_100_percent/cros/technical_error.png
+++ b/chrome/app/theme/default_100_percent/cros/technical_error.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_protected_media_identifier.png b/chrome/app/theme/default_100_percent/infobar_protected_media_identifier.png
new file mode 100644
index 0000000..c3d87d4
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/infobar_protected_media_identifier.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
deleted file mode 100644
index 480acb9..0000000
--- a/chrome/app/theme/default_200_percent/common/audio_equalizer_column.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_tools_badge_aura.png b/chrome/app/theme/default_200_percent/common/browser_tools_badge_aura.png
index 1078549..78fd405 100644
--- a/chrome/app/theme/default_200_percent/common/browser_tools_badge_aura.png
+++ b/chrome/app/theme/default_200_percent/common/browser_tools_badge_aura.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_tools_normal_aura.png b/chrome/app/theme/default_200_percent/common/browser_tools_normal_aura.png
index 3a91696..136fc68 100644
--- a/chrome/app/theme/default_200_percent/common/browser_tools_normal_aura.png
+++ b/chrome/app/theme/default_200_percent/common/browser_tools_normal_aura.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/cloudprint.png b/chrome/app/theme/default_200_percent/common/cloudprint.png
index 01c8e88..e90bd60 100644
--- a/chrome/app/theme/default_200_percent/common/cloudprint.png
+++ b/chrome/app/theme/default_200_percent/common/cloudprint.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/credit_card_cvc_hint.png b/chrome/app/theme/default_200_percent/common/credit_card_cvc_hint.png
index 715743a..be64e42 100644
--- a/chrome/app/theme/default_200_percent/common/credit_card_cvc_hint.png
+++ b/chrome/app/theme/default_200_percent/common/credit_card_cvc_hint.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/credit_card_cvc_hint_amex.png b/chrome/app/theme/default_200_percent/common/credit_card_cvc_hint_amex.png
index da4d32b..39b3bdf 100644
--- a/chrome/app/theme/default_200_percent/common/credit_card_cvc_hint_amex.png
+++ b/chrome/app/theme/default_200_percent/common/credit_card_cvc_hint_amex.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/icon_add_user.png b/chrome/app/theme/default_200_percent/common/icon_add_user.png
index 315cd46..07efcfb 100644
--- a/chrome/app/theme/default_200_percent/common/icon_add_user.png
+++ b/chrome/app/theme/default_200_percent/common/icon_add_user.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/icon_add_user_white.png b/chrome/app/theme/default_200_percent/common/icon_add_user_white.png
index 61fa23f..094d649 100644
--- a/chrome/app/theme/default_200_percent/common/icon_add_user_white.png
+++ b/chrome/app/theme/default_200_percent/common/icon_add_user_white.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/icon_browse_as_guest.png b/chrome/app/theme/default_200_percent/common/icon_browse_as_guest.png
index 063146e..007a8d6 100644
--- a/chrome/app/theme/default_200_percent/common/icon_browse_as_guest.png
+++ b/chrome/app/theme/default_200_percent/common/icon_browse_as_guest.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/icon_browse_as_guest_white.png b/chrome/app/theme/default_200_percent/common/icon_browse_as_guest_white.png
index 01ff992..ab8eeb1 100644
--- a/chrome/app/theme/default_200_percent/common/icon_browse_as_guest_white.png
+++ b/chrome/app/theme/default_200_percent/common/icon_browse_as_guest_white.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/icon_locked.png b/chrome/app/theme/default_200_percent/common/icon_locked.png
index 5e28a83..da64b5c 100644
--- a/chrome/app/theme/default_200_percent/common/icon_locked.png
+++ b/chrome/app/theme/default_200_percent/common/icon_locked.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_protected_media_identifier.png b/chrome/app/theme/default_200_percent/common/infobar_protected_media_identifier.png
new file mode 100644
index 0000000..2751b3c
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/infobar_protected_media_identifier.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/mail.png b/chrome/app/theme/default_200_percent/common/mail.png
new file mode 100644
index 0000000..286d6db
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/mail.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/mail_hover.png b/chrome/app/theme/default_200_percent/common/mail_hover.png
new file mode 100644
index 0000000..08cf55a
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/mail_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/mail_pressed.png b/chrome/app/theme/default_200_percent/common/mail_pressed.png
new file mode 100644
index 0000000..6a37960
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/mail_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_border_bottom.png b/chrome/app/theme/default_200_percent/common/omnibox_border_bottom.png
index 6a47906..7c710c4 100644
--- a/chrome/app/theme/default_200_percent/common/omnibox_border_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/omnibox_border_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_border_top.png b/chrome/app/theme/default_200_percent/common/omnibox_border_top.png
index a31d29a..e84763c 100644
--- a/chrome/app/theme/default_200_percent/common/omnibox_border_top.png
+++ b/chrome/app/theme/default_200_percent/common/omnibox_border_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_popup_border_bottom.png b/chrome/app/theme/default_200_percent/common/omnibox_popup_border_bottom.png
index ee844f7..528a40c 100644
--- a/chrome/app/theme/default_200_percent/common/omnibox_popup_border_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/omnibox_popup_border_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_popup_border_top.png b/chrome/app/theme/default_200_percent/common/omnibox_popup_border_top.png
index e937b3c..0fd3ef4 100644
--- a/chrome/app/theme/default_200_percent/common/omnibox_popup_border_top.png
+++ b/chrome/app/theme/default_200_percent/common/omnibox_popup_border_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/save_password.png b/chrome/app/theme/default_200_percent/common/save_password.png
index 31341dd..9e192fe 100644
--- a/chrome/app/theme/default_200_percent/common/save_password.png
+++ b/chrome/app/theme/default_200_percent/common/save_password.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/supervised_user_placeholder.png b/chrome/app/theme/default_200_percent/common/supervised_user_placeholder.png
index 05ff4b9..d0036dc 100644
--- a/chrome/app/theme/default_200_percent/common/supervised_user_placeholder.png
+++ b/chrome/app/theme/default_200_percent/common/supervised_user_placeholder.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/tab_audio_indicator.png b/chrome/app/theme/default_200_percent/common/tab_audio_indicator.png
new file mode 100644
index 0000000..65670d8
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/tab_audio_indicator.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/notification_alert.png b/chrome/app/theme/default_200_percent/cros/notification_alert.png
new file mode 100644
index 0000000..112014d
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/cros/notification_alert.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_protected_media_identifier.png b/chrome/app/theme/default_200_percent/infobar_protected_media_identifier.png
new file mode 100644
index 0000000..2751b3c
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/infobar_protected_media_identifier.png
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 216bb94..475ab3a 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -68,7 +68,6 @@
<structure type="chrome_scaled_image" name="IDR_APP_WINDOW_MINIMIZE_H" file="win/app_window_minimize_hover.png" />
<structure type="chrome_scaled_image" name="IDR_APP_WINDOW_MINIMIZE_P" file="win/app_window_minimize_active.png" />
</if>
- <structure type="chrome_scaled_image" name="IDR_AUDIO_EQUALIZER_COLUMN" file="common/audio_equalizer_column.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_DIALOG_MENU_BUTTON" file="common/autofill_dialog_menu_button_normal.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_DIALOG_MENU_BUTTON_P" file="common/autofill_dialog_menu_button_pressed.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_DIALOG_MENU_BUTTON_H" file="common/autofill_dialog_menu_button_hover.png" />
@@ -234,6 +233,9 @@
<structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_BACKGROUND_32" file="download_progress_background32.png" />
<structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_FOREGROUND_16" file="download_progress_foreground16.png" />
<structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_FOREGROUND_32" file="download_progress_foreground32.png" />
+ <if expr="is_android">
+ <structure type="chrome_scaled_image" name="IDR_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_ICON" file="infobar_protected_media_identifier.png" />
+ </if>
<if expr="pp_ifdef('chromeos')">
<structure type="chrome_scaled_image" name="IDR_ENROLL_FAILURE" file="enroll_failure.png" />
<structure type="chrome_scaled_image" name="IDR_ENROLL_SUCCESS" file="enroll_success.png" />
@@ -323,9 +325,7 @@
<structure type="chrome_scaled_image" name="IDR_FULLSCREEN_MENU_BUTTON" file="fullscreen_menu_button.png" />
<structure type="chrome_scaled_image" name="IDR_GEOLOCATION_INFOBAR_ICON" file="infobar_geolocation.png" />
<structure type="chrome_scaled_image" name="IDR_GUEST_ICON" file="common/guest_icon.png" />
- <if expr="pp_ifdef('chromeos')">
- <structure type="chrome_scaled_image" name="IDR_HELP_MENU" file="help_16.png" />
- </if>
+ <structure type="chrome_scaled_image" name="IDR_HELP_MENU" file="common/help_16.png" />
<structure type="chrome_scaled_image" name="IDR_HISTORY_FAVICON" file="common/favicon_history.png" />
<if expr="not pp_ifdef('toolkit_views') and not is_macosx and not is_ios">
<structure type="chrome_scaled_image" name="IDR_HOME" file="home.png" />
@@ -342,15 +342,20 @@
<structure type="chrome_scaled_image" name="IDR_HOME_P" file="common/browser_home_pressed.png" />
</if>
<if expr="not is_android and not is_ios">
- <structure type="chrome_scaled_image" name="IDR_ICON_ADD_USER24" file="icon_add_user24.png" />
- <structure type="chrome_scaled_image" name="IDR_ICON_ADD_USER_WHITE" file="icon_add_user_white.png" />
- <structure type="chrome_scaled_image" name="IDR_ICON_GUEST_WHITE" file="icon_guest_white.png" />
+ <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_ADD_USER" file="common/icon_add_user.png" />
+ <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_ADD_USER_WHITE" file="common/icon_add_user_white.png" />
+ <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_BROWSE_GUEST" file="common/icon_browse_as_guest.png" />
+ <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_BROWSE_GUEST_WHITE" file="common/icon_browse_as_guest_white.png" />
+ <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_LOCKED" file="common/icon_locked.png" />
</if>
<if expr="not is_android and not is_ios and not pp_ifdef('chromeos')">
<!-- TODO(noms): Remove this once local profile avatars are migrated -->
<structure type="chrome_scaled_image" name="IDR_USER_MANAGER_DEFAULT_AVATAR" file="avatar_user_color.png" />
</if>
<if expr="pp_ifdef('chromeos')">
+ <structure type="chrome_scaled_image" name="IDR_ICON_ADD_USER24" file="icon_add_user24.png" />
+ <structure type="chrome_scaled_image" name="IDR_ICON_ADD_USER_WHITE" file="icon_add_user_white.png" />
+ <structure type="chrome_scaled_image" name="IDR_ICON_GUEST_WHITE" file="icon_guest_white.png" />
<structure type="chrome_scaled_image" name="IDR_ICON_POWER24" file="icon_power24.png" />
<structure type="chrome_scaled_image" name="IDR_ICON_POWER_WHITE" file="icon_power_white.png" />
</if>
@@ -504,6 +509,7 @@
</if>
<structure type="chrome_scaled_image" name="IDR_NEWTAB_WEBSTORE_THUMBNAIL" file="ntp_webstore_thumb.png" />
<if expr="pp_ifdef('chromeos')">
+ <structure type="chrome_scaled_image" name="IDR_NOTIFICATION_ALERT" file="cros/notification_alert.png" />
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_PERIPHERAL_BATTERY_LOW" file="cros/notification_peripheral_battery_low.png" />
</if>
<if expr="is_win or is_linux">
@@ -805,6 +811,7 @@
<structure type="chrome_scaled_image" name="IDR_CLOSE_1_H" file="common/close_1_hover.png" />
<structure type="chrome_scaled_image" name="IDR_CLOSE_1_MASK" file="common/close_1_mask.png" />
<structure type="chrome_scaled_image" name="IDR_CLOSE_1_P" file="common/close_1_pressed.png" />
+ <structure type="chrome_scaled_image" name="IDR_TAB_AUDIO_INDICATOR" file="common/tab_audio_indicator.png" />
<structure type="chrome_scaled_image" name="IDR_TAB_DROP_DOWN" file="tab_drop_down.png" />
<structure type="chrome_scaled_image" name="IDR_TAB_DROP_UP" file="tab_drop_up.png" />
<if expr="not pp_ifdef('toolkit_views') and not is_macosx and not is_ios">
@@ -976,6 +983,10 @@
<structure type="chrome_scaled_image" name="IDR_ZOOM_MINUS" file="zoom_minus.png" />
<structure type="chrome_scaled_image" name="IDR_ZOOM_PLUS" file="zoom_plus.png" />
<structure type="chrome_scaled_image" name="IDR_ZOOM_NORMAL" file="zoom_reset.png" />
+ <!-- People search images -->
+ <structure type="chrome_scaled_image" name="IDR_PEOPLE_SEARCH_ACTION_EMAIL" file="common/mail.png" />
+ <structure type="chrome_scaled_image" name="IDR_PEOPLE_SEARCH_ACTION_EMAIL_HOVER" file="common/mail_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_PEOPLE_SEARCH_ACTION_EMAIL_PRESSED" file="common/mail_pressed.png" />
</structures>
</release>
</grit>
diff --git a/chrome/app/theme/touch_100_percent/common/browser_tools_normal_aura.png b/chrome/app/theme/touch_100_percent/common/browser_tools_normal_aura.png
index 73ad5cb..02bd8f3 100644
--- a/chrome/app/theme/touch_100_percent/common/browser_tools_normal_aura.png
+++ b/chrome/app/theme/touch_100_percent/common/browser_tools_normal_aura.png
Binary files differ
diff --git a/chrome/app/theme/touch_140_percent/common/browser_tools_normal_aura.png b/chrome/app/theme/touch_140_percent/common/browser_tools_normal_aura.png
index 9bdd7a0..429d99a 100644
--- a/chrome/app/theme/touch_140_percent/common/browser_tools_normal_aura.png
+++ b/chrome/app/theme/touch_140_percent/common/browser_tools_normal_aura.png
Binary files differ
diff --git a/chrome/app/theme/touch_180_percent/common/browser_tools_normal_aura.png b/chrome/app/theme/touch_180_percent/common/browser_tools_normal_aura.png
index 973567b..6878bf2 100644
--- a/chrome/app/theme/touch_180_percent/common/browser_tools_normal_aura.png
+++ b/chrome/app/theme/touch_180_percent/common/browser_tools_normal_aura.png
Binary files differ
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index ccf9b10..4a53a33 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -29,6 +29,8 @@
#include "media/base/media_switches.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_switches.h"
+#include "ui/compositor/compositor_switches.h"
+#include "ui/events/event_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "ui/keyboard/keyboard_switches.h"
@@ -205,6 +207,22 @@
cc::switches::kDisableImplSidePainting, ""}
};
+const Experiment::Choice kDeadlineSchedulingChoices[] = {
+ { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
+ { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
+ switches::kEnableDeadlineScheduling, ""},
+ { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
+ switches::kDisableDeadlineScheduling, ""}
+};
+
+const Experiment::Choice kUIDeadlineSchedulingChoices[] = {
+ { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
+ { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
+ switches::kUIEnableDeadlineScheduling, ""},
+ { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
+ switches::kUIDisableDeadlineScheduling, ""}
+};
+
const Experiment::Choice kLCDTextChoices[] = {
{ IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
{ IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED, cc::switches::kEnableLCDText, ""},
@@ -263,6 +281,7 @@
switches::kUseSimpleCacheBackend, "on"}
};
+#if defined(USE_AURA)
const Experiment::Choice kTabCaptureUpscaleQualityChoices[] = {
{ IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
{ IDS_FLAGS_TAB_CAPTURE_SCALE_QUALITY_FAST,
@@ -282,6 +301,7 @@
{ IDS_FLAGS_TAB_CAPTURE_SCALE_QUALITY_BEST,
switches::kTabCaptureDownscaleQuality, "best" },
};
+#endif
const Experiment::Choice kMapImageChoices[] = {
{ IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
@@ -642,6 +662,13 @@
switches::kDisableInstantExtendedAPI)
},
{
+ "use-cacheable-new-tab-page",
+ IDS_FLAGS_ENABLE_INSTANT_EXTENDED_CACHEABLE_NTP,
+ IDS_FLAGS_ENABLE_INSTANT_EXTENDED_CACHEABLE_NTP_DESCRIPTION,
+ kOsMac | kOsWin | kOsCrOS,
+ SINGLE_VALUE_TYPE(switches::kUseCacheableNewTabPage)
+ },
+ {
"enable-local-first-load-ntp",
IDS_FLAGS_ENABLE_LOCAL_FIRST_LOAD_NTP,
IDS_FLAGS_ENABLE_LOCAL_FIRST_LOAD_NTP_DESCRIPTION,
@@ -701,7 +728,7 @@
IDS_FLAGS_ENABLE_OVERLAY_SCROLLBARS_DESCRIPTION,
// Uses the system preference on Mac (a different implementation).
// On Android, this is always enabled.
- kOsWin | kOsLinux | kOsCrOS,
+ kOsCrOS,
SINGLE_VALUE_TYPE(switches::kEnableOverlayScrollbars)
},
{
@@ -765,7 +792,7 @@
switches::kDisableAsyncDns)
},
{
- "disable-media-source",
+ "disable-webkit-media-source",
IDS_FLAGS_DISABLE_WEBKIT_MEDIA_SOURCE_NAME,
IDS_FLAGS_DISABLE_WEBKIT_MEDIA_SOURCE_DESCRIPTION,
kOsAll,
@@ -794,6 +821,13 @@
},
#if defined(OS_ANDROID)
{
+ "disable-infobar-for-protected-media-identifier",
+ IDS_FLAGS_DISABLE_INFOBAR_FOR_PROTECTED_MEDIA_IDENTIFIER_NAME,
+ IDS_FLAGS_DISABLE_INFOBAR_FOR_PROTECTED_MEDIA_IDENTIFIER_DESCRIPTION,
+ kOsAndroid,
+ SINGLE_VALUE_TYPE(switches::kDisableInfobarForProtectedMediaIdentifier)
+ },
+ {
"mediadrm-enable-non-compositing",
IDS_FLAGS_MEDIADRM_ENABLE_NON_COMPOSITING_NAME,
IDS_FLAGS_MEDIADRM_ENABLE_NON_COMPOSITING_DESCRIPTION,
@@ -1054,11 +1088,11 @@
SINGLE_VALUE_TYPE(switches::kDisableMinimizeOnSecondLauncherItemClick)
},
{
- "disable-overview-mode",
- IDS_FLAGS_DISABLE_OVERVIEW_MODE_NAME,
- IDS_FLAGS_DISABLE_OVERVIEW_MODE_DESCRIPTION,
+ "enable-overview-mode",
+ IDS_FLAGS_OVERVIEW_MODE_NAME,
+ IDS_FLAGS_OVERVIEW_MODE_DESCRIPTION,
kOsCrOS,
- SINGLE_VALUE_TYPE(ash::switches::kAshDisableOverviewMode)
+ SINGLE_VALUE_TYPE(ash::switches::kAshEnableOverviewMode)
},
{
"show-touch-hud",
@@ -1139,6 +1173,13 @@
kOsCrOS,
SINGLE_VALUE_TYPE(chromeos::switches::kEnableSamlSignin),
},
+ {
+ "enable-multi-profiles",
+ IDS_FLAGS_ENABLE_MULTI_PROFILES_NAME,
+ IDS_FLAGS_ENABLE_MULTI_PROFILES_DESCRIPTION,
+ kOsCrOS,
+ SINGLE_VALUE_TYPE(switches::kMultiProfiles),
+ },
#endif // defined(OS_CHROMEOS)
{
"views-textfield",
@@ -1217,6 +1258,14 @@
SINGLE_VALUE_TYPE(ash::switches::kAshEnableMemoryMonitor),
},
#endif
+#if defined(OS_CHROMEOS)
+ { "ash-enable-multi-profile-shelf",
+ IDS_FLAGS_ENABLE_MULTI_PROFILE_SHELF_NAME,
+ IDS_FLAGS_ENABLE_MULTI_PROFILE_SHELF_DESCRIPTION,
+ kOsCrOS,
+ SINGLE_VALUE_TYPE(ash::switches::kAshEnableMultiProfileShelfMenu),
+ },
+#endif
#endif
#if defined(OS_CHROMEOS)
{
@@ -1409,6 +1458,23 @@
MULTI_VALUE_TYPE(kImplSidePaintingChoices)
},
{
+ "deadline-scheduling",
+ IDS_FLAGS_DEADLINE_SCHEDULING_NAME,
+ IDS_FLAGS_DEADLINE_SCHEDULING_DESCRIPTION,
+ kOsMac | kOsWin | kOsLinux | kOsCrOS | kOsAndroid,
+ MULTI_VALUE_TYPE(kDeadlineSchedulingChoices)
+ },
+ {
+ "ui-deadline-scheduling",
+ IDS_FLAGS_UI_DEADLINE_SCHEDULING_NAME,
+ IDS_FLAGS_UI_DEADLINE_SCHEDULING_DESCRIPTION,
+#ifdef USE_AURA
+ kOsWin | kOsLinux |
+#endif
+ kOsCrOS,
+ MULTI_VALUE_TYPE(kUIDeadlineSchedulingChoices)
+ },
+ {
"lcd-text-aa",
IDS_FLAGS_LCD_TEXT_NAME,
IDS_FLAGS_LCD_TEXT_DESCRIPTION,
@@ -1534,11 +1600,12 @@
SINGLE_VALUE_TYPE(switches::kDisableDeviceDiscovery)
},
{
- "disable-device-discovery-notifications",
- IDS_FLAGS_DISABLE_DEVICE_DISCOVERY_NOTIFICATIONS_NAME,
- IDS_FLAGS_DISABLE_DEVICE_DISCOVERY_NOTIFICATIONS_DESCRIPTION,
+ "device-discovery-notifications",
+ IDS_FLAGS_DEVICE_DISCOVERY_NOTIFICATIONS_NAME,
+ IDS_FLAGS_DEVICE_DISCOVERY_NOTIFICATIONS_DESCRIPTION,
kOsWin | kOsLinux | kOsCrOS,
- SINGLE_VALUE_TYPE(switches::kDisableDeviceDiscoveryNotifications)
+ ENABLE_DISABLE_VALUE_TYPE(switches::kEnableDeviceDiscoveryNotifications,
+ switches::kDisableDeviceDiscoveryNotifications)
},
#endif // ENABLE_MDNS
#if defined(OS_MACOSX)
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index de7c939..5f23d8e 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -36,15 +36,15 @@
#include "chrome/browser/ui/android/autofill/autofill_dialog_result.h"
#include "chrome/browser/ui/android/autofill/autofill_popup_view_android.h"
#include "chrome/browser/ui/android/chrome_http_auth_handler.h"
-#include "chrome/browser/ui/android/infobar/confirm_infobar.h"
-#include "chrome/browser/ui/android/infobar/infobar_android.h"
-#include "chrome/browser/ui/android/infobar/infobar_container_android.h"
+#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h"
+#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/infobar_android.h"
+#include "chrome/browser/ui/android/infobars/infobar_container_android.h"
#include "chrome/browser/ui/android/javascript_app_modal_dialog_android.h"
#include "chrome/browser/ui/android/navigation_popup.h"
#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 "chrome/browser/ui/auto_login_infobar_delegate_android.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"
diff --git a/chrome/browser/android/chrome_startup_flags.cc b/chrome/browser/android/chrome_startup_flags.cc
index b789424..e6edaa2 100644
--- a/chrome/browser/android/chrome_startup_flags.cc
+++ b/chrome/browser/android/chrome_startup_flags.cc
@@ -9,6 +9,7 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
+#include "base/android/sys_utils.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "chrome/common/chrome_switches.h"
@@ -42,6 +43,8 @@
SetCommandLineSwitchASCII(
switches::kPrerenderFromOmnibox,
switches::kPrerenderFromOmniboxSwitchValueEnabled);
+ if (base::android::SysUtils::IsLowEndDevice())
+ SetCommandLineSwitch(switches::kDisableSyncFavicons);
#if defined(GOOGLE_TV)
SetCommandLineSwitch(switches::kPpapiInProcess);
#endif
diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.cc b/chrome/browser/android/chrome_web_contents_delegate_android.cc
index 0334acf..560a505 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.cc
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.cc
@@ -10,6 +10,8 @@
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/file_select_helper.h"
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
+#include "chrome/browser/media/protected_media_identifier_permission_context.h"
+#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_manager.h"
#include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
@@ -20,6 +22,7 @@
#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"
#include "content/public/common/file_chooser_params.h"
@@ -301,5 +304,20 @@
delete new_contents;
}
+void
+ChromeWebContentsDelegateAndroid::RequestProtectedMediaIdentifierPermission(
+ const WebContents* web_contents,
+ const GURL& frame_url,
+ const base::Callback<void(bool)>& callback) {
+ Profile* profile =
+ Profile::FromBrowserContext(web_contents->GetBrowserContext());
+ ProtectedMediaIdentifierPermissionContextFactory::GetForProfile(profile)->
+ RequestProtectedMediaIdentifierPermission(
+ web_contents->GetRenderProcessHost()->GetID(),
+ web_contents->GetRenderViewHost()->GetRoutingID(),
+ frame_url,
+ callback);
+}
+
} // 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 9c22997..06c84eb 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.h
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.h
@@ -71,6 +71,10 @@
const gfx::Rect& initial_pos,
bool user_gesture,
bool* was_blocked) OVERRIDE;
+ virtual void RequestProtectedMediaIdentifierPermission(
+ const content::WebContents* web_contents,
+ const GURL& frame_url,
+ const base::Callback<void(bool)>& callback) OVERRIDE;
private:
// NotificationObserver implementation.
diff --git a/chrome/browser/android/favicon_helper.cc b/chrome/browser/android/favicon_helper.cc
index 69de06c..eda5a4b 100644
--- a/chrome/browser/android/favicon_helper.cc
+++ b/chrome/browser/android/favicon_helper.cc
@@ -10,10 +10,17 @@
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/bind.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.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 "chrome/browser/sync/glue/session_model_associator.h"
+#include "chrome/browser/sync/glue/session_model_associator.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "jni/FaviconHelper_jni.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/android/java_bitmap.h"
@@ -22,29 +29,29 @@
using base::android::ScopedJavaLocalRef;
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
+using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF8ToJavaString;
-using base::android::MethodID;
namespace {
-void FaviconImageCallback(
- ScopedJavaGlobalRef<jobject>* java_favicon_image_callback,
+void OnLocalFaviconAvailable(
+ ScopedJavaGlobalRef<jobject>* j_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());
+ ScopedJavaLocalRef<jstring> j_icon_url =
+ ConvertUTF8ToJavaString(env, favicon_image_result.icon_url.spec());
SkBitmap favicon_bitmap = favicon_image_result.image.AsBitmap();
- ScopedJavaLocalRef<jobject> java_favicon_bitmap;
- if (!favicon_bitmap.isNull()) {
- java_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap);
- }
+ ScopedJavaLocalRef<jobject> j_favicon_bitmap;
+ if (!favicon_bitmap.isNull())
+ j_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());
+ // Call java side OnLocalFaviconAvailable method.
+ Java_FaviconImageCallback_onFaviconAvailable(env,
+ j_favicon_image_callback->obj(),
+ j_favicon_bitmap.obj(),
+ j_icon_url.obj());
}
} // namespace
@@ -61,11 +68,15 @@
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);
+jboolean FaviconHelper::GetLocalFaviconImageForURL(
+ JNIEnv* env,
+ jobject obj,
+ jobject j_profile,
+ jstring j_page_url,
+ jint j_icon_types,
+ jint j_desired_size_in_dip,
+ jobject j_favicon_image_callback) {
+ Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
DCHECK(profile);
if (!profile)
return false;
@@ -77,15 +88,17 @@
return false;
FaviconService::FaviconForURLParams params(
- profile, GURL(ConvertJavaStringToUTF16(env, page_url)),
- static_cast<int>(icon_types), static_cast<int>(desired_size_in_dip));
+ profile,
+ GURL(ConvertJavaStringToUTF16(env, j_page_url)),
+ static_cast<int>(j_icon_types),
+ static_cast<int>(j_desired_size_in_dip));
ScopedJavaGlobalRef<jobject>* j_scoped_favicon_callback =
new ScopedJavaGlobalRef<jobject>();
- j_scoped_favicon_callback->Reset(env, java_favicon_image_callback);
+ j_scoped_favicon_callback->Reset(env, j_favicon_image_callback);
FaviconService::FaviconImageCallback callback_runner = base::Bind(
- &FaviconImageCallback, base::Owned(j_scoped_favicon_callback));
+ &OnLocalFaviconAvailable, base::Owned(j_scoped_favicon_callback));
favicon_service->GetFaviconImageForURL(
params, callback_runner,
@@ -94,9 +107,42 @@
return true;
}
-FaviconHelper::~FaviconHelper() {
+ScopedJavaLocalRef<jobject> FaviconHelper::GetSyncedFaviconImageForURL(
+ JNIEnv* env,
+ jobject obj,
+ jobject jprofile,
+ jstring j_page_url) {
+ Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
+ DCHECK(profile);
+
+ std::string page_url = ConvertJavaStringToUTF8(env, j_page_url);
+
+ ProfileSyncService* sync_service =
+ ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
+ DCHECK(sync_service);
+
+ scoped_refptr<base::RefCountedMemory> favicon_png;
+ browser_sync::SessionModelAssociator* associator =
+ sync_service->GetSessionModelAssociator();
+ DCHECK(associator);
+
+ if (!associator->GetSyncedFaviconForPageURL(page_url, &favicon_png))
+ return ScopedJavaLocalRef<jobject>();
+
+ // Convert favicon_image_result to java objects.
+ gfx::Image favicon_image = gfx::Image::CreateFrom1xPNGBytes(
+ favicon_png->front(), favicon_png->size());
+ SkBitmap favicon_bitmap = favicon_image.AsBitmap();
+
+ ScopedJavaLocalRef<jobject> j_favicon_bitmap;
+ if (favicon_bitmap.isNull())
+ return ScopedJavaLocalRef<jobject>();
+
+ return gfx::ConvertToJavaBitmap(&favicon_bitmap);
}
+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
index a360995..fb86587 100644
--- a/chrome/browser/android/favicon_helper.h
+++ b/chrome/browser/android/favicon_helper.h
@@ -7,6 +7,7 @@
#include <jni.h>
+#include "base/android/scoped_java_ref.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/common/cancelable_task_tracker.h"
@@ -14,11 +15,20 @@
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);
+ jboolean GetLocalFaviconImageForURL(JNIEnv* env,
+ jobject obj,
+ jobject j_profile,
+ jstring j_page_url,
+ jint j_icon_types,
+ jint j_desired_size_in_dip,
+ jobject j_favicon_image_callback);
+ base::android::ScopedJavaLocalRef<jobject> GetSyncedFaviconImageForURL(
+ JNIEnv* env,
+ jobject obj,
+ jobject jprofile,
+ jstring j_page_url);
static bool RegisterFaviconHelper(JNIEnv* env);
+
private:
scoped_ptr<CancelableTaskTracker> cancelable_task_tracker_;
diff --git a/chrome/browser/android/foreign_session_helper.cc b/chrome/browser/android/foreign_session_helper.cc
index 0c8f0d9..fa7ff24 100644
--- a/chrome/browser/android/foreign_session_helper.cc
+++ b/chrome/browser/android/foreign_session_helper.cc
@@ -43,47 +43,84 @@
return service->GetSessionModelAssociator();
}
+bool ShouldSkipTab(const SessionTab& tab) {
+ if (tab.navigations.empty())
+ return true;
+
+ int selected_index = tab.current_navigation_index;
+ if (selected_index < 0 ||
+ selected_index >= static_cast<int>(tab.navigations.size()))
+ return true;
+
+ return false;
+}
+
+bool ShouldSkipWindow(const SessionWindow& window) {
+ for (std::vector<SessionTab*>::const_iterator tab_it = window.tabs.begin();
+ tab_it != window.tabs.end(); ++tab_it) {
+ const SessionTab &tab = **tab_it;
+ if (!ShouldSkipTab(tab))
+ return false;
+ }
+ return true;
+}
+
+bool ShouldSkipSession(const browser_sync::SyncedSession& session) {
+ for (SyncedSession::SyncedWindowMap::const_iterator it =
+ session.windows.begin(); it != session.windows.end(); ++it) {
+ const SessionWindow &window = *(it->second);
+ if (!ShouldSkipWindow(window))
+ return false;
+ }
+ return true;
+}
+
void CopyTabsToJava(
JNIEnv* env,
- const SessionWindow* window,
+ const SessionWindow& window,
ScopedJavaLocalRef<jobject>& j_window) {
- for (std::vector<SessionTab*>::const_iterator tab_it = window->tabs.begin();
- tab_it != window->tabs.end(); ++tab_it) {
+ for (std::vector<SessionTab*>::const_iterator tab_it = window.tabs.begin();
+ tab_it != window.tabs.end(); ++tab_it) {
const SessionTab &tab = **tab_it;
- if (tab.navigations.empty())
+ if (ShouldSkipTab(tab))
continue;
+ int selected_index = tab.current_navigation_index;
+ DCHECK(selected_index >= 0);
+ DCHECK(selected_index < static_cast<int>(tab.navigations.size()));
+
const ::sessions::SerializedNavigationEntry& current_navigation =
- tab.navigations.at(tab.current_navigation_index);
+ tab.navigations.at(selected_index);
GURL tab_url = current_navigation.virtual_url();
- if (tab_url.SchemeIs(chrome::kChromeNativeScheme) ||
- (tab_url.SchemeIs(chrome::kChromeUIScheme) &&
- tab_url.host() == chrome::kChromeUINewTabHost))
- continue;
Java_ForeignSessionHelper_pushTab(
env, j_window.obj(),
ConvertUTF8ToJavaString(env, tab_url.spec()).Release(),
ConvertUTF16ToJavaString(env, current_navigation.title()).Release(),
- tab.timestamp.ToInternalValue(), tab.tab_id.id());
+ tab.timestamp.ToJavaTime(),
+ tab.tab_id.id());
}
}
void CopyWindowsToJava(
JNIEnv* env,
- const SyncedSession* session,
+ const SyncedSession& session,
ScopedJavaLocalRef<jobject>& j_session) {
for (SyncedSession::SyncedWindowMap::const_iterator it =
- session->windows.begin(); it != session->windows.end(); ++it) {
- const SessionWindow* window = it->second;
+ session.windows.begin(); it != session.windows.end(); ++it) {
+ const SessionWindow &window = *(it->second);
+
+ if (ShouldSkipWindow(window))
+ continue;
ScopedJavaLocalRef<jobject> last_pushed_window;
last_pushed_window.Reset(
Java_ForeignSessionHelper_pushWindow(
- env, j_session.obj(), window->timestamp.ToInternalValue(),
- window->window_id.id()));
+ env, j_session.obj(),
+ window.timestamp.ToJavaTime(),
+ window.window_id.id()));
CopyTabsToJava(env, window, last_pushed_window);
}
@@ -101,7 +138,6 @@
: profile_(profile) {
ProfileSyncService* service = ProfileSyncServiceFactory::GetInstance()->
GetForProfile(profile);
-
registrar_.Add(this, chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
content::Source<ProfileSyncService>(service));
registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED,
@@ -178,22 +214,23 @@
// Note: we don't own the SyncedSessions themselves.
for (size_t i = 0; i < sessions.size(); ++i) {
- const browser_sync::SyncedSession* session = sessions[i];
+ const browser_sync::SyncedSession &session = *(sessions[i]);
+ if (ShouldSkipSession(session))
+ continue;
- const bool is_collapsed = collapsed_sessions->HasKey(session->session_tag);
+ const bool is_collapsed = collapsed_sessions->HasKey(session.session_tag);
if (is_collapsed)
- pref_collapsed_sessions->SetBoolean(session->session_tag, true);
+ pref_collapsed_sessions->SetBoolean(session.session_tag, true);
last_pushed_session.Reset(
Java_ForeignSessionHelper_pushSession(
env,
result,
- ConvertUTF8ToJavaString(env, session->session_tag).Release(),
- ConvertUTF8ToJavaString(env, session->session_name).Release(),
- ConvertUTF8ToJavaString(env,
- session->DeviceTypeAsString()).Release(),
- session->modified_time.ToInternalValue()));
+ ConvertUTF8ToJavaString(env, session.session_tag).Release(),
+ ConvertUTF8ToJavaString(env, session.session_name).Release(),
+ session.device_type,
+ session.modified_time.ToJavaTime()));
CopyWindowsToJava(env, session, last_pushed_session);
}
@@ -257,6 +294,14 @@
update.Get()->Remove(ConvertJavaStringToUTF8(env, session_tag), NULL);
}
+jboolean ForeignSessionHelper::GetForeignSessionCollapsed(JNIEnv* env,
+ jobject obj,
+ jstring session_tag) {
+ const DictionaryValue* dict = profile_->GetPrefs()->GetDictionary(
+ prefs::kNtpCollapsedForeignSessions);
+ return dict && dict->HasKey(ConvertJavaStringToUTF8(env, session_tag));
+}
+
void ForeignSessionHelper::DeleteForeignSession(JNIEnv* env, jobject obj,
jstring session_tag) {
SessionModelAssociator* associator = GetSessionModelAssociator(profile_);
diff --git a/chrome/browser/android/foreign_session_helper.h b/chrome/browser/android/foreign_session_helper.h
index 22c1025..0a08159 100644
--- a/chrome/browser/android/foreign_session_helper.h
+++ b/chrome/browser/android/foreign_session_helper.h
@@ -36,6 +36,9 @@
jobject obj,
jstring session_tag,
jboolean is_collapsed);
+ jboolean GetForeignSessionCollapsed(JNIEnv* env,
+ jobject obj,
+ jstring session_tag);
void DeleteForeignSession(JNIEnv* env, jobject obj, jstring session_tag);
// NotificationObserver implemenation
diff --git a/chrome/browser/android/provider/chrome_browser_provider.cc b/chrome/browser/android/provider/chrome_browser_provider.cc
index f319c66..2f82c13 100644
--- a/chrome/browser/android/provider/chrome_browser_provider.cc
+++ b/chrome/browser/android/provider/chrome_browser_provider.cc
@@ -39,6 +39,7 @@
#include "sql/statement.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/layout.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/favicon_size.h"
using base::android::AttachCurrentThread;
@@ -676,7 +677,7 @@
url,
chrome::FAVICON | chrome::TOUCH_ICON,
gfx::kFaviconSize),
- ui::GetMaxScaleFactor(),
+ ResourceBundle::GetSharedInstance().GetMaxScaleFactor(),
base::Bind(
&BookmarkIconFetchTask::OnFaviconRetrieved,
base::Unretained(this)),
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h
index 3393724..bc414b4 100644
--- a/chrome/browser/android/resource_id.h
+++ b/chrome/browser/android/resource_id.h
@@ -14,6 +14,8 @@
DEFINE_RESOURCE_ID(0, 0)
// InfoBar resources.
+DEFINE_RESOURCE_ID(IDR_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_ICON,
+ R.drawable.infobar_protected_media_identifier)
DEFINE_RESOURCE_ID(IDR_GEOLOCATION_INFOBAR_ICON, R.drawable.infobar_geolocation)
DEFINE_RESOURCE_ID(IDR_INFOBAR_ALT_NAV_URL, R.drawable.infobar_didyoumean)
DEFINE_RESOURCE_ID(IDR_INFOBAR_AUTOFILL, R.drawable.infobar_autofill)
diff --git a/chrome/browser/apps/web_view_browsertest.cc b/chrome/browser/apps/web_view_browsertest.cc
index 17c1d79..f905a11 100644
--- a/chrome/browser/apps/web_view_browsertest.cc
+++ b/chrome/browser/apps/web_view_browsertest.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/notification_service.h"
@@ -652,6 +653,13 @@
"web_view/shim");
}
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestOnEventProperty) {
+ TestHelper("testOnEventProperties",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestLoadProgressEvent) {
TestHelper("testLoadProgressEvent",
"DoneShimTest.PASSED",
@@ -849,6 +857,13 @@
"web_view/shim");
}
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestLoadAbortIllegalJavaScriptURL) {
+ TestHelper("testLoadAbortIllegalJavaScriptURL",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestReload) {
TestHelper("testReload",
"DoneShimTest.PASSED",
@@ -939,7 +954,13 @@
// This test makes sure we do not crash if app is closed while interstitial
// page is being shown in guest.
-IN_PROC_BROWSER_TEST_F(WebViewTest, InterstitialTeardown) {
+// Test flaky on windows; http://crbug.com/297014 .
+#if defined(OS_WIN)
+#define MAYBE_InterstitialTeardown DISABLED_InterstitialTeardown
+#else
+#define MAYBE_InterstitialTeardown InterstitialTeardown
+#endif
+IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_InterstitialTeardown) {
// Start a HTTPS server so we can load an interstitial page inside guest.
net::SpawnedTestServer::SSLOptions ssl_options;
ssl_options.server_certificate =
@@ -1492,7 +1513,6 @@
// Checks that window.screenX/screenY/screenLeft/screenTop works correctly for
// guests.
IN_PROC_BROWSER_TEST_F(WebViewTest, ScreenCoordinates) {
- ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
ASSERT_TRUE(RunPlatformAppTestWithArg(
"platform_apps/web_view/common", "screen_coordinates"))
<< message_;
@@ -1622,7 +1642,6 @@
#define MAYBE_ConsoleMessage ConsoleMessage
#endif
IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_ConsoleMessage) {
- ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
ASSERT_TRUE(RunPlatformAppTestWithArg(
"platform_apps/web_view/common", "console_messages"))
<< message_;
@@ -1693,6 +1712,18 @@
<< message_;
}
+// Tests overriding user agent.
+IN_PROC_BROWSER_TEST_F(WebViewTest, UserAgent) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+ ASSERT_TRUE(RunPlatformAppTestWithArg(
+ "platform_apps/web_view/common", "useragent")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, NoPermission) {
+ ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/nopermission"))
+ << message_;
+}
+
IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestAlertDialog) {
TestHelper("testAlertDialog",
"DoneDialogTest.PASSED",
diff --git a/chrome/browser/apps/web_view_interactive_browsertest.cc b/chrome/browser/apps/web_view_interactive_browsertest.cc
index ede2118..dd93988 100644
--- a/chrome/browser/apps/web_view_interactive_browsertest.cc
+++ b/chrome/browser/apps/web_view_interactive_browsertest.cc
@@ -142,12 +142,18 @@
}
}
+ enum TestServer {
+ NEEDS_TEST_SERVER,
+ NO_TEST_SERVER
+ };
+
scoped_ptr<ExtensionTestMessageListener> RunAppHelper(
const std::string& test_name,
const std::string& app_location,
+ TestServer test_server,
content::WebContents** embedder_web_contents) {
// For serving guest pages.
- if (!StartEmbeddedTestServer()) {
+ if ((test_server == NEEDS_TEST_SERVER) && !StartEmbeddedTestServer()) {
LOG(ERROR) << "FAILED TO START TEST SERVER.";
return scoped_ptr<ExtensionTestMessageListener>();
}
@@ -183,15 +189,19 @@
}
void TestHelper(const std::string& test_name,
- const std::string& app_location) {
+ const std::string& app_location,
+ TestServer test_server) {
content::WebContents* embedder_web_contents = NULL;
scoped_ptr<ExtensionTestMessageListener> done_listener(
- RunAppHelper(test_name, app_location, &embedder_web_contents));
+ RunAppHelper(
+ test_name, app_location, test_server, &embedder_web_contents));
ASSERT_TRUE(done_listener);
ASSERT_TRUE(done_listener->WaitUntilSatisfied());
}
+ void RunTest(const std::string& app_name) {
+ }
void SetupTest(const std::string& app_name,
const std::string& guest_url_spec) {
ASSERT_TRUE(StartEmbeddedTestServer());
@@ -497,18 +507,21 @@
// Tests that setting focus on the <webview> sets focus on the guest.
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusEvent) {
- TestHelper("testFocusEvent", "web_view/focus");
+ TestHelper("testFocusEvent", "web_view/focus", NO_TEST_SERVER);
}
// Tests that setting focus on the <webview> sets focus on the guest.
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_BlurEvent) {
- TestHelper("testBlurEvent", "web_view/focus");
+ TestHelper("testBlurEvent", "web_view/focus", NO_TEST_SERVER);
}
// Tests that guests receive edit commands and respond appropriately.
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommands) {
- SetupTest("web_view/edit_commands",
- "/extensions/platform_apps/web_view/edit_commands/guest.html");
+ ExtensionTestMessageListener guest_connected_listener("connected", false);
+ LoadAndLaunchPlatformApp("web_view/edit_commands");
+ // Wait until the guest process reports that it has established a message
+ // channel with the app.
+ ASSERT_TRUE(guest_connected_listener.WaitUntilSatisfied());
ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
GetPlatformAppWindow()));
@@ -543,44 +556,62 @@
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
NewWindow_NewWindowNameTakesPrecedence) {
- TestHelper("testNewWindowNameTakesPrecedence", "web_view/newwindow");
+ TestHelper("testNewWindowNameTakesPrecedence",
+ "web_view/newwindow",
+ NEEDS_TEST_SERVER);
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
NewWindow_WebViewNameTakesPrecedence) {
- TestHelper("testWebViewNameTakesPrecedence", "web_view/newwindow");
+ TestHelper("testWebViewNameTakesPrecedence",
+ "web_view/newwindow",
+ NEEDS_TEST_SERVER);
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_NoName) {
- TestHelper("testNoName", "web_view/newwindow");
+ TestHelper("testNoName",
+ "web_view/newwindow",
+ NEEDS_TEST_SERVER);
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_Redirect) {
- TestHelper("testNewWindowRedirect", "web_view/newwindow");
+ TestHelper("testNewWindowRedirect",
+ "web_view/newwindow",
+ NEEDS_TEST_SERVER);
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_Close) {
- TestHelper("testNewWindowClose", "web_view/newwindow");
+ TestHelper("testNewWindowClose",
+ "web_view/newwindow",
+ NEEDS_TEST_SERVER);
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_ExecuteScript) {
- TestHelper("testNewWindowExecuteScript", "web_view/newwindow");
+ TestHelper("testNewWindowExecuteScript",
+ "web_view/newwindow",
+ NEEDS_TEST_SERVER);
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_WebRequest) {
- TestHelper("testNewWindowWebRequest", "web_view/newwindow");
+ TestHelper("testNewWindowWebRequest",
+ "web_view/newwindow",
+ NEEDS_TEST_SERVER);
}
// A custom elements bug needs to be addressed to enable this test:
// See http://crbug.com/282477 for more information.
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
DISABLED_NewWindow_WebRequestCloseWindow) {
- TestHelper("testNewWindowWebRequestCloseWindow", "web_view/newwindow");
+ TestHelper("testNewWindowWebRequestCloseWindow",
+ "web_view/newwindow",
+ NEEDS_TEST_SERVER);
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
NewWindow_WebRequestRemoveElement) {
- TestHelper("testNewWindowWebRequestRemoveElement", "web_view/newwindow");
+ TestHelper("testNewWindowWebRequestRemoveElement",
+ "web_view/newwindow",
+ NEEDS_TEST_SERVER);
}
// Tests that Ctrl+Click/Cmd+Click on a link fires up the newwindow API.
@@ -591,6 +622,7 @@
scoped_ptr<ExtensionTestMessageListener> done_listener(
RunAppHelper("testNewWindowOpenInNewTab",
"web_view/newwindow",
+ NEEDS_TEST_SERVER,
&embedder_web_contents));
loaded_listener.WaitUntilSatisfied();
@@ -610,7 +642,6 @@
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, ExecuteCode) {
- ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
ASSERT_TRUE(RunPlatformAppTestWithArg(
"platform_apps/web_view/common", "execute_code")) << message_;
}
@@ -647,8 +678,10 @@
// Drag and drop inside a webview is currently only enabled for linux and mac,
// but the tests don't work on anything except chromeos for now. This is because
// of simulating mouse drag code's dependency on platforms.
+//
+// Disabled because of flake on CrOS: http://crbug.com/161112
#if defined(OS_CHROMEOS)
-IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DragDropWithinWebView) {
+IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_DragDropWithinWebView) {
SetupTest(
"web_view/dnd_within_webview",
"/extensions/platform_apps/web_view/dnd_within_webview/guest.html");
@@ -667,11 +700,10 @@
#endif // (defined(OS_CHROMEOS))
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation) {
- TestHelper("testNavigation", "web_view/navigation");
+ TestHelper("testNavigation", "web_view/navigation", NO_TEST_SERVER);
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation_BackForwardKeys) {
- ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
ExtensionTestMessageListener launched_listener("Launched", false);
LoadAndLaunchPlatformApp("web_view/navigation");
ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
@@ -706,16 +738,9 @@
ASSERT_TRUE(done_listener.WaitUntilSatisfied());
}
-// Fail at least once a day on Windows. See http://crbug.com/293445.
-#if defined(OS_WIN)
-#define MAYBE_PointerLock_PointerLockLostWithFocus \
- DISABLED_PointerLock_PointerLockLostWithFocus
-#else
-#define MAYBE_PointerLock_PointerLockLostWithFocus \
- PointerLock_PointerLockLostWithFocus
-#endif
-
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
- MAYBE_PointerLock_PointerLockLostWithFocus) {
- TestHelper("testPointerLockLostWithFocus", "web_view/pointerlock");
+ PointerLock_PointerLockLostWithFocus) {
+ TestHelper("testPointerLockLostWithFocus",
+ "web_view/pointerlock",
+ NO_TEST_SERVER);
}
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc
index 1f982e2..c2a5f74 100644
--- a/chrome/browser/autocomplete/search_provider.cc
+++ b/chrome/browser/autocomplete/search_provider.cc
@@ -639,6 +639,8 @@
if (minimal_changes)
return;
+ base::TimeTicks do_history_query_start_time(base::TimeTicks::Now());
+
keyword_history_results_.clear();
default_history_results_.clear();
@@ -646,10 +648,17 @@
input_.current_page_classification()))
return;
+ base::TimeTicks start_time(base::TimeTicks::Now());
HistoryService* const history_service =
HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
+ base::TimeTicks now(base::TimeTicks::Now());
+ UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.GetHistoryServiceTime",
+ now - start_time);
+ start_time = now;
history::URLDatabase* url_db = history_service ?
history_service->InMemoryDatabase() : NULL;
+ UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.InMemoryDatabaseTime",
+ base::TimeTicks::Now() - start_time);
if (!url_db)
return;
@@ -665,14 +674,20 @@
int num_matches = kMaxMatches * 5;
const TemplateURL* default_url = providers_.GetDefaultProviderURL();
if (default_url) {
+ start_time = base::TimeTicks::Now();
url_db->GetMostRecentKeywordSearchTerms(default_url->id(), input_.text(),
num_matches, &default_history_results_);
+ UMA_HISTOGRAM_TIMES(
+ "Omnibox.SearchProvider.GetMostRecentKeywordTermsDefaultProviderTime",
+ base::TimeTicks::Now() - start_time);
}
const TemplateURL* keyword_url = providers_.GetKeywordProviderURL();
if (keyword_url) {
url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(),
keyword_input_.text(), num_matches, &keyword_history_results_);
}
+ UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.DoHistoryQueryTime",
+ base::TimeTicks::Now() - do_history_query_start_time);
}
void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) {
@@ -977,6 +992,7 @@
void SearchProvider::ConvertResultsToAutocompleteMatches() {
// Convert all the results to matches and add them to a map, so we can keep
// the most relevant match for each result.
+ base::TimeTicks start_time(base::TimeTicks::Now());
MatchMap map;
const base::Time no_time;
int did_not_accept_keyword_suggestion =
@@ -1044,6 +1060,8 @@
// 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.
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Omnibox.SearchProvider.NumMatchesToSort", matches.size(), 1, 50, 20);
std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant);
matches_.clear();
@@ -1070,6 +1088,8 @@
matches_.push_back(*i);
}
+ UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.ConvertResultsTime",
+ base::TimeTicks::Now() - start_time);
}
bool SearchProvider::IsTopMatchNavigationInKeywordMode() const {
@@ -1115,6 +1135,7 @@
}
void SearchProvider::UpdateMatches() {
+ base::TimeTicks update_matches_start_time(base::TimeTicks::Now());
ConvertResultsToAutocompleteMatches();
// Check constraints that may be violated by suggested relevances.
@@ -1186,8 +1207,13 @@
DCHECK(HasValidDefaultMatch(omnibox_will_reorder_for_legal_default_match));
}
+ base::TimeTicks update_starred_start_time(base::TimeTicks::Now());
UpdateStarredStateOfMatches();
+ UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateStarredTime",
+ base::TimeTicks::Now() - update_starred_start_time);
UpdateDone();
+ UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateMatchesTime",
+ base::TimeTicks::Now() - update_matches_start_time);
}
void SearchProvider::AddNavigationResultsToMatches(
@@ -1210,6 +1236,7 @@
if (results.empty())
return;
+ base::TimeTicks start_time(base::TimeTicks::Now());
bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() ||
(input_.type() == AutocompleteInput::URL);
const string16& input_text =
@@ -1242,6 +1269,8 @@
false, std::string(), AutocompleteMatchType::SEARCH_HISTORY,
did_not_accept_suggestion, is_keyword, map);
}
+ UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime",
+ base::TimeTicks::Now() - start_time);
}
SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults(
diff --git a/chrome/browser/autocomplete/zero_suggest_provider.cc b/chrome/browser/autocomplete/zero_suggest_provider.cc
index 24b0291..4a09c4a 100644
--- a/chrome/browser/autocomplete/zero_suggest_provider.cc
+++ b/chrome/browser/autocomplete/zero_suggest_provider.cc
@@ -202,12 +202,19 @@
ProfileSyncService* service =
ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_);
browser_sync::SyncPrefs sync_prefs(prefs);
- // The user has needs to have Chrome Sync enabled (for permissions to
- // transmit their current URL) and be in the field trial.
+
+ // ZeroSuggest requires sending the current URL to the suggest provider, so we
+ // only want to enable it if the user is willing to have this data sent.
+ // Because tab sync involves sending the same data, we currently use
+ // "tab sync is enabled and tab sync data is unencrypted" as a proxy for
+ // "the user is OK with sending this data". We might someday want to change
+ // this to a standalone setting or part of some other explicit general opt-in.
if (!OmniboxFieldTrial::InZeroSuggestFieldTrial() ||
service == NULL ||
!service->IsSyncEnabledAndLoggedIn() ||
- !sync_prefs.HasKeepEverythingSynced()) {
+ !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()).Has(
+ syncer::PROXY_TABS) ||
+ service->GetEncryptedDataTypes().Has(syncer::SESSIONS)) {
return false;
}
return true;
diff --git a/chrome/browser/automation/automation_provider_json.cc b/chrome/browser/automation/automation_provider_json.cc
index 6684b48..fd6f12a 100644
--- a/chrome/browser/automation/automation_provider_json.cc
+++ b/chrome/browser/automation/automation_provider_json.cc
@@ -13,13 +13,10 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/automation_id.h"
#include "chrome/common/automation_messages.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/web_contents.h"
-using automation::Error;
-using automation::ErrorCode;
using content::WebContents;
AutomationJSONReply::AutomationJSONReply(AutomationProvider* provider,
@@ -44,19 +41,10 @@
}
void AutomationJSONReply::SendError(const std::string& error_message) {
- SendError(Error(error_message));
-}
-
-void AutomationJSONReply::SendErrorCode(ErrorCode code) {
- SendError(Error(code));
-}
-
-void AutomationJSONReply::SendError(const Error& error) {
DCHECK(message_) << "Resending reply for JSON automation request";
base::DictionaryValue dict;
- dict.SetString("error", error.message());
- dict.SetInteger("code", error.code());
+ dict.SetString("error", error_message);
std::string json;
base::JSONWriter::Write(&dict, &json);
@@ -69,32 +57,15 @@
DictionaryValue* args,
Browser** browser,
std::string* error) {
- if (args->HasKey("auto_id")) {
- AutomationId id;
- if (!GetAutomationIdFromJSONArgs(args, "auto_id", &id, error))
- return false;
- WebContents* tab;
- if (!automation_util::GetTabForId(id, &tab)) {
- *error = "'auto_id' does not refer to an open tab";
- return false;
- }
- Browser* container = automation_util::GetBrowserForTab(tab);
- if (!container) {
- *error = "tab does not belong to an open browser";
- return false;
- }
- *browser = container;
- } else {
- int browser_index;
- if (!args->GetInteger("windex", &browser_index)) {
- *error = "'windex' missing or invalid";
- return false;
- }
- *browser = automation_util::GetBrowserAt(browser_index);
- if (!*browser) {
- *error = "Cannot locate browser from given index";
- return false;
- }
+ int browser_index;
+ if (!args->GetInteger("windex", &browser_index)) {
+ *error = "'windex' missing or invalid";
+ return false;
+ }
+ *browser = automation_util::GetBrowserAt(browser_index);
+ if (!*browser) {
+ *error = "Cannot locate browser from given index";
+ return false;
}
return true;
}
@@ -103,29 +74,19 @@
DictionaryValue* args,
WebContents** tab,
std::string* error) {
- if (args->HasKey("auto_id")) {
- AutomationId id;
- if (!GetAutomationIdFromJSONArgs(args, "auto_id", &id, error))
- return false;
- if (!automation_util::GetTabForId(id, tab)) {
- *error = "'auto_id' does not refer to an open tab";
- return false;
- }
- } else {
- int browser_index, tab_index;
- if (!args->GetInteger("windex", &browser_index)) {
- *error = "'windex' missing or invalid";
- return false;
- }
- if (!args->GetInteger("tab_index", &tab_index)) {
- *error = "'tab_index' missing or invalid";
- return false;
- }
- *tab = automation_util::GetWebContentsAt(browser_index, tab_index);
- if (!*tab) {
- *error = "Cannot locate tab from given indices";
- return false;
- }
+ int browser_index, tab_index;
+ if (!args->GetInteger("windex", &browser_index)) {
+ *error = "'windex' missing or invalid";
+ return false;
+ }
+ if (!args->GetInteger("tab_index", &tab_index)) {
+ *error = "'tab_index' missing or invalid";
+ return false;
+ }
+ *tab = automation_util::GetWebContentsAt(browser_index, tab_index);
+ if (!*tab) {
+ *error = "Cannot locate tab from given indices";
+ return false;
}
return true;
}
@@ -139,40 +100,15 @@
GetTabFromJSONArgs(args, tab, error);
}
-bool GetAutomationIdFromJSONArgs(
- DictionaryValue* args,
- const std::string& key,
- AutomationId* id,
- std::string* error) {
- Value* id_value;
- if (!args->Get(key, &id_value)) {
- *error = base::StringPrintf("Missing parameter '%s'", key.c_str());
- return false;
- }
- return AutomationId::FromValue(id_value, id, error);
-}
-
bool GetRenderViewFromJSONArgs(
DictionaryValue* args,
Profile* profile,
content::RenderViewHost** rvh,
std::string* error) {
- Value* id_value;
- if (args->Get("auto_id", &id_value)) {
- AutomationId id;
- if (!AutomationId::FromValue(id_value, &id, error))
- return false;
- if (!automation_util::GetRenderViewForId(id, profile, rvh)) {
- *error = "ID does not correspond to an open view";
- return false;
- }
- } else {
- // If the render view id is not specified, check for browser/tab indices.
- WebContents* tab = NULL;
- if (!GetTabFromJSONArgs(args, &tab, error))
- return false;
- *rvh = tab->GetRenderViewHost();
- }
+ WebContents* tab = NULL;
+ if (!GetTabFromJSONArgs(args, &tab, error))
+ return false;
+ *rvh = tab->GetRenderViewHost();
return true;
}
diff --git a/chrome/browser/automation/automation_provider_json.h b/chrome/browser/automation/automation_provider_json.h
index c8817b2..428fa4d 100644
--- a/chrome/browser/automation/automation_provider_json.h
+++ b/chrome/browser/automation/automation_provider_json.h
@@ -12,7 +12,6 @@
#include "base/compiler_specific.h"
#include "chrome/common/automation_constants.h"
-class AutomationId;
class AutomationProvider;
class Browser;
class Profile;
@@ -53,13 +52,6 @@
// Send an error reply along with error message |error_message|.
void SendError(const std::string& error_message);
- // Send an error reply along with the specified error code and its
- // associated error message.
- void SendErrorCode(automation::ErrorCode code);
-
- // Send an automation error.
- void SendError(const automation::Error& error);
-
private:
AutomationProvider* provider_;
IPC::Message* message_;
@@ -90,14 +82,6 @@
content::WebContents** tab,
std::string* error) WARN_UNUSED_RESULT;
-// Gets an automation ID from the given value in the given dicitionary |args|.
-// Returns true on success and sets |id|. Otherwise, |error| will be set.
-bool GetAutomationIdFromJSONArgs(
- base::DictionaryValue* args,
- const std::string& key,
- AutomationId* id,
- std::string* error) WARN_UNUSED_RESULT;
-
// Gets the render view specified by the given dictionary |args|. |args|
// should contain a key 'view_id' which refers to an automation ID for the
// render view. Returns true on success and sets |rvh|. Otherwise, |error|
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index 34fc6ac..09e4380 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -1123,7 +1123,7 @@
if (dom_op_details->automation_id == automation_id_)
OnDomOperationCompleted(dom_op_details->json);
} else if (type == chrome::NOTIFICATION_APP_MODAL_DIALOG_SHOWN) {
- OnModalDialogShown();
+ OnJavascriptBlocked();
} else {
DCHECK_EQ(chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, type);
WebContents* web_contents = content::Source<WebContents>(source).ptr();
@@ -1166,14 +1166,6 @@
delete this;
}
-void DomOperationMessageSender::OnModalDialogShown() {
- if (automation_.get() && use_json_interface_) {
- AutomationJSONReply(automation_.get(), reply_message_.release())
- .SendErrorCode(automation::kBlockedByModalDialog);
- delete this;
- }
-}
-
void DomOperationMessageSender::OnJavascriptBlocked() {
if (automation_.get() && use_json_interface_) {
AutomationJSONReply(automation_.get(), reply_message_.release())
diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h
index a1ea47e..198389e 100644
--- a/chrome/browser/automation/automation_provider_observers.h
+++ b/chrome/browser/automation/automation_provider_observers.h
@@ -580,7 +580,6 @@
const content::NotificationDetails& details) OVERRIDE;
virtual void OnDomOperationCompleted(const std::string& json) = 0;
- virtual void OnModalDialogShown() = 0;
virtual void OnJavascriptBlocked() = 0;
private:
@@ -600,7 +599,6 @@
virtual ~DomOperationMessageSender();
virtual void OnDomOperationCompleted(const std::string& json) OVERRIDE;
- virtual void OnModalDialogShown() OVERRIDE;
virtual void OnJavascriptBlocked() OVERRIDE;
private:
diff --git a/chrome/browser/automation/automation_util.cc b/chrome/browser/automation/automation_util.cc
index 3313186..7b42e6c 100644
--- a/chrome/browser/automation/automation_util.cc
+++ b/chrome/browser/automation/automation_util.cc
@@ -29,7 +29,6 @@
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/automation_id.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
@@ -51,10 +50,6 @@
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
#endif
-#if defined(ENABLE_FULL_PRINTING)
-#include "chrome/browser/printing/print_preview_dialog_controller.h"
-#endif
-
using content::BrowserThread;
using content::RenderViewHost;
using content::WebContents;
@@ -469,182 +464,9 @@
bool SendErrorIfModalDialogActive(AutomationProvider* provider,
IPC::Message* message) {
bool active = AppModalDialogQueue::GetInstance()->HasActiveDialog();
- if (active) {
- AutomationJSONReply(provider, message).SendErrorCode(
- automation::kBlockedByModalDialog);
- }
+ if (active)
+ AutomationJSONReply(provider, message).SendError("Blocked by modal dialog");
return active;
}
-AutomationId GetIdForTab(const WebContents* tab) {
- const SessionTabHelper* session_tab_helper =
- SessionTabHelper::FromWebContents(tab);
- return AutomationId(AutomationId::kTypeTab,
- base::IntToString(session_tab_helper->session_id().id()));
-}
-
-AutomationId GetIdForExtensionView(
- const content::RenderViewHost* render_view_host) {
- AutomationId::Type type;
- WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host);
- switch (extensions::GetViewType(web_contents)) {
- case extensions::VIEW_TYPE_EXTENSION_POPUP:
- type = AutomationId::kTypeExtensionPopup;
- break;
- case extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE:
- type = AutomationId::kTypeExtensionBgPage;
- break;
- case extensions::VIEW_TYPE_EXTENSION_INFOBAR:
- type = AutomationId::kTypeExtensionInfobar;
- break;
- case extensions::VIEW_TYPE_APP_SHELL:
- type = AutomationId::kTypeAppShell;
- break;
- default:
- type = AutomationId::kTypeInvalid;
- break;
- }
- // Since these extension views do not permit navigation, using the
- // renderer process and view ID should suffice.
- std::string id = base::StringPrintf("%d|%d",
- render_view_host->GetRoutingID(),
- render_view_host->GetProcess()->GetID());
- return AutomationId(type, id);
-}
-
-AutomationId GetIdForExtension(const extensions::Extension* extension) {
- return AutomationId(AutomationId::kTypeExtension, extension->id());
-}
-
-bool GetTabForId(const AutomationId& id, WebContents** tab) {
- if (id.type() != AutomationId::kTypeTab)
- return false;
-
-#if defined(ENABLE_FULL_PRINTING)
- printing::PrintPreviewDialogController* preview_controller =
- printing::PrintPreviewDialogController::GetInstance();
-#endif
- for (chrome::BrowserIterator it; !it.done(); it.Next()) {
- Browser* browser = *it;
- for (int tab_index = 0;
- tab_index < browser->tab_strip_model()->count();
- ++tab_index) {
- WebContents* web_contents =
- browser->tab_strip_model()->GetWebContentsAt(tab_index);
- SessionTabHelper* session_tab_helper =
- SessionTabHelper::FromWebContents(web_contents);
- if (base::IntToString(
- session_tab_helper->session_id().id()) == id.id()) {
- *tab = web_contents;
- return true;
- }
-
-#if defined(ENABLE_FULL_PRINTING)
- if (preview_controller) {
- WebContents* print_preview_contents =
- preview_controller->GetPrintPreviewForContents(web_contents);
- if (print_preview_contents) {
- SessionTabHelper* preview_session_tab_helper =
- SessionTabHelper::FromWebContents(print_preview_contents);
- std::string preview_id = base::IntToString(
- preview_session_tab_helper->session_id().id());
- if (preview_id == id.id()) {
- *tab = print_preview_contents;
- return true;
- }
- }
- }
-#endif
- }
- }
- return false;
-}
-
-namespace {
-
-bool GetExtensionRenderViewForId(
- const AutomationId& id,
- Profile* profile,
- RenderViewHost** rvh) {
- ExtensionProcessManager* extension_mgr =
- extensions::ExtensionSystem::Get(profile)->process_manager();
- const ExtensionProcessManager::ViewSet view_set =
- extension_mgr->GetAllViews();
- for (ExtensionProcessManager::ViewSet::const_iterator iter = view_set.begin();
- iter != view_set.end(); ++iter) {
- content::RenderViewHost* host = *iter;
- AutomationId this_id = GetIdForExtensionView(host);
- if (id == this_id) {
- *rvh = host;
- return true;
- }
- }
- return false;
-}
-
-} // namespace
-
-bool GetRenderViewForId(
- const AutomationId& id,
- Profile* profile,
- RenderViewHost** rvh) {
- switch (id.type()) {
- case AutomationId::kTypeTab: {
- WebContents* tab;
- if (!GetTabForId(id, &tab))
- return false;
- *rvh = tab->GetRenderViewHost();
- break;
- }
- case AutomationId::kTypeExtensionPopup:
- case AutomationId::kTypeExtensionBgPage:
- case AutomationId::kTypeExtensionInfobar:
- case AutomationId::kTypeAppShell:
- if (!GetExtensionRenderViewForId(id, profile, rvh))
- return false;
- break;
- default:
- return false;
- }
- return true;
-}
-
-bool GetExtensionForId(
- const AutomationId& id,
- Profile* profile,
- const extensions::Extension** extension) {
- if (id.type() != AutomationId::kTypeExtension)
- return false;
- ExtensionService* service = extensions::ExtensionSystem::Get(profile)->
- extension_service();
- const extensions::Extension* installed_extension =
- service->GetInstalledExtension(id.id());
- if (installed_extension)
- *extension = installed_extension;
- return !!installed_extension;
-}
-
-bool DoesObjectWithIdExist(const AutomationId& id, Profile* profile) {
- switch (id.type()) {
- case AutomationId::kTypeTab: {
- WebContents* tab;
- return GetTabForId(id, &tab);
- }
- case AutomationId::kTypeExtensionPopup:
- case AutomationId::kTypeExtensionBgPage:
- case AutomationId::kTypeExtensionInfobar:
- case AutomationId::kTypeAppShell: {
- RenderViewHost* rvh;
- return GetExtensionRenderViewForId(id, profile, &rvh);
- }
- case AutomationId::kTypeExtension: {
- const extensions::Extension* extension;
- return GetExtensionForId(id, profile, &extension);
- }
- default:
- break;
- }
- return false;
-}
-
} // namespace automation_util
diff --git a/chrome/browser/automation/automation_util.h b/chrome/browser/automation/automation_util.h
index 79322e9..9252a89 100644
--- a/chrome/browser/automation/automation_util.h
+++ b/chrome/browser/automation/automation_util.h
@@ -9,7 +9,6 @@
#include "base/basictypes.h"
-class AutomationId;
class AutomationProvider;
class Browser;
class GURL;
@@ -94,32 +93,6 @@
bool SendErrorIfModalDialogActive(AutomationProvider* provider,
IPC::Message* message);
-// Returns a valid automation ID for the given tab.
-AutomationId GetIdForTab(const content::WebContents* tab);
-
-// Returns a valid automation ID for the extension view.
-AutomationId GetIdForExtensionView(
- const content::RenderViewHost* render_view_host);
-
-// Returns a valid automation ID for the extension.
-AutomationId GetIdForExtension(const extensions::Extension* extension);
-
-// Gets the tab for the given ID. Returns true on success.
-bool GetTabForId(const AutomationId& id, content::WebContents** tab);
-
-// Gets the render view for the given ID. Returns true on success.
-bool GetRenderViewForId(const AutomationId& id,
- Profile* profile,
- content::RenderViewHost** rvh);
-
-// Gets the extension for the given ID. Returns true on success.
-bool GetExtensionForId(const AutomationId& id,
- Profile* profile,
- const extensions::Extension** extension);
-
-// Returns whether the given ID refers to an actual automation entity.
-bool DoesObjectWithIdExist(const AutomationId& id, Profile* profile);
-
} // namespace automation_util
#endif // CHROME_BROWSER_AUTOMATION_AUTOMATION_UTIL_H_
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index 2eb3b0a..c42c266 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -108,7 +108,6 @@
#include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
#include "chrome/browser/ui/startup/startup_types.h"
#include "chrome/common/automation_constants.h"
-#include "chrome/common/automation_id.h"
#include "chrome/common/automation_messages.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
@@ -165,12 +164,6 @@
#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
#endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
-#if defined(ENABLE_FULL_PRINTING)
-#include "chrome/browser/printing/print_preview_dialog_controller.h"
-#endif
-
-using automation::Error;
-using automation::ErrorCode;
using automation_util::SendErrorIfModalDialogActive;
using content::BrowserChildProcessHostIterator;
using content::BrowserContext;
@@ -1647,12 +1640,8 @@
handler_map_["GetTabIds"] =
&TestingAutomationProvider::GetTabIds;
- handler_map_["GetViews"] =
- &TestingAutomationProvider::GetViews;
handler_map_["IsTabIdValid"] =
&TestingAutomationProvider::IsTabIdValid;
- handler_map_["DoesAutomationObjectExist"] =
- &TestingAutomationProvider::DoesAutomationObjectExist;
handler_map_["CloseTab"] =
&TestingAutomationProvider::CloseTabJSON;
handler_map_["SetViewBounds"] =
@@ -1685,8 +1674,6 @@
&TestingAutomationProvider::ActionOnSSLBlockingPage;
handler_map_["GetSecurityState"] =
&TestingAutomationProvider::GetSecurityState;
- handler_map_["GetChromeDriverAutomationVersion"] =
- &TestingAutomationProvider::GetChromeDriverAutomationVersion;
handler_map_["IsPageActionVisible"] =
&TestingAutomationProvider::IsPageActionVisible;
handler_map_["CreateNewAutomationProvider"] =
@@ -4198,11 +4185,11 @@
// Gets the active JavaScript modal dialog, or NULL if none.
JavaScriptAppModalDialog* GetActiveJavaScriptModalDialog(
- ErrorCode* error_code) {
+ std::string* error_msg) {
AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
if (!dialog_queue->HasActiveDialog() ||
!dialog_queue->active_dialog()->IsJavaScriptModalDialog()) {
- *error_code = automation::kNoJavaScriptModalDialogOpen;
+ *error_msg = "No JavaScriptModalDialog open";
return NULL;
}
return static_cast<JavaScriptAppModalDialog*>(dialog_queue->active_dialog());
@@ -4213,10 +4200,10 @@
void TestingAutomationProvider::GetAppModalDialogMessage(
DictionaryValue* args, IPC::Message* reply_message) {
AutomationJSONReply reply(this, reply_message);
- ErrorCode code;
- JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&code);
+ std::string error_msg;
+ JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&error_msg);
if (!dialog) {
- reply.SendErrorCode(code);
+ reply.SendError(error_msg);
return;
}
DictionaryValue result_dict;
@@ -4233,10 +4220,10 @@
return;
}
- ErrorCode code;
- JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&code);
+ std::string error_msg;
+ JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&error_msg);
if (!dialog) {
- reply.SendErrorCode(code);
+ reply.SendError(error_msg);
return;
}
if (accept) {
@@ -4740,8 +4727,7 @@
std::string error;
RenderViewHost* render_view;
if (!GetRenderViewFromJSONArgs(args, profile(), &render_view, &error)) {
- AutomationJSONReply(this, reply_message).SendError(
- Error(automation::kInvalidId, error));
+ AutomationJSONReply(this, reply_message).SendError(error);
return;
}
if (!args->GetString("frame_xpath", &frame_xpath)) {
@@ -5223,58 +5209,6 @@
AutomationJSONReply(this, reply_message).SendSuccess(&dict);
}
-void TestingAutomationProvider::GetViews(
- DictionaryValue* args, IPC::Message* reply_message) {
- ListValue* view_list = new ListValue();
-#if defined(ENABLE_FULL_PRINTING)
- printing::PrintPreviewDialogController* preview_controller =
- printing::PrintPreviewDialogController::GetInstance();
-#endif
- for (chrome::BrowserIterator it; !it.done(); it.Next()) {
- Browser* browser = *it;
- for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
- WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(i);
- DictionaryValue* dict = new DictionaryValue();
- AutomationId id = automation_util::GetIdForTab(contents);
- dict->Set("auto_id", id.ToValue());
- view_list->Append(dict);
-#if defined(ENABLE_FULL_PRINTING)
- if (preview_controller) {
- WebContents* preview_dialog =
- preview_controller->GetPrintPreviewForContents(contents);
- if (preview_dialog) {
- DictionaryValue* dict = new DictionaryValue();
- AutomationId id = automation_util::GetIdForTab(preview_dialog);
- dict->Set("auto_id", id.ToValue());
- view_list->Append(dict);
- }
- }
-#endif
- }
- }
-
- ExtensionProcessManager* extension_mgr =
- extensions::ExtensionSystem::Get(profile())->process_manager();
- const ExtensionProcessManager::ViewSet all_views =
- extension_mgr->GetAllViews();
- ExtensionProcessManager::ViewSet::const_iterator iter;
- for (iter = all_views.begin(); iter != all_views.end(); ++iter) {
- content::RenderViewHost* host = (*iter);
- AutomationId id = automation_util::GetIdForExtensionView(host);
- if (!id.is_valid())
- continue;
- const Extension* extension =
- extension_mgr->GetExtensionForRenderViewHost(host);
- DictionaryValue* dict = new DictionaryValue();
- dict->Set("auto_id", id.ToValue());
- dict->SetString("extension_id", extension->id());
- view_list->Append(dict);
- }
- DictionaryValue dict;
- dict.Set("views", view_list);
- AutomationJSONReply(this, reply_message).SendSuccess(&dict);
-}
-
void TestingAutomationProvider::IsTabIdValid(
DictionaryValue* args, IPC::Message* reply_message) {
AutomationJSONReply reply(this, reply_message);
@@ -5301,22 +5235,6 @@
reply.SendSuccess(&dict);
}
-void TestingAutomationProvider::DoesAutomationObjectExist(
- DictionaryValue* args, IPC::Message* reply_message) {
- AutomationJSONReply reply(this, reply_message);
- AutomationId id;
- std::string error_msg;
- if (!GetAutomationIdFromJSONArgs(args, "auto_id", &id, &error_msg)) {
- reply.SendError(error_msg);
- return;
- }
- DictionaryValue dict;
- dict.SetBoolean(
- "does_exist",
- automation_util::DoesObjectWithIdExist(id, profile()));
- reply.SendSuccess(&dict);
-}
-
void TestingAutomationProvider::CloseTabJSON(
DictionaryValue* args, IPC::Message* reply_message) {
Browser* browser;
@@ -5360,7 +5278,7 @@
Browser* browser;
std::string error;
if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
- reply.SendError(Error(automation::kInvalidId, error));
+ reply.SendError(error);
return;
}
BrowserWindow* browser_window = browser->window();
@@ -5377,8 +5295,7 @@
Browser* browser;
std::string error;
if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
- AutomationJSONReply(this, reply_message)
- .SendError(Error(automation::kInvalidId, error));
+ AutomationJSONReply(this, reply_message).SendError(error);
return;
}
@@ -5463,14 +5380,6 @@
reply.SendSuccess(&dict);
}
-void TestingAutomationProvider::GetChromeDriverAutomationVersion(
- DictionaryValue* args,
- IPC::Message* reply_message) {
- DictionaryValue reply_dict;
- reply_dict.SetInteger("version", automation::kChromeDriverAutomationVersion);
- AutomationJSONReply(this, reply_message).SendSuccess(&reply_dict);
-}
-
void TestingAutomationProvider::CreateNewAutomationProvider(
DictionaryValue* args,
IPC::Message* reply_message) {
diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h
index 989ace7..5129527 100644
--- a/chrome/browser/automation/testing_automation_provider.h
+++ b/chrome/browser/automation/testing_automation_provider.h
@@ -934,31 +934,12 @@
// output: { "ids": [213, 1] }
void GetTabIds(base::DictionaryValue* args, IPC::Message* reply_message);
- // Gets info about all open views. Each view ID is unique per session.
- // Example:
- // input: none
- // output: { "views": [
- // {
- // "auto_id": { "type": 0, "id": "awoein" },
- // "extension_id": "askjeoias3" // optional
- // }
- // ]
- // }
- void GetViews(base::DictionaryValue* args, IPC::Message* reply_message);
-
// Checks if the given tab ID refers to an open tab.
// Example:
// input: { "id": 41 }
// output: { "is_valid": false }
void IsTabIdValid(base::DictionaryValue* args, IPC::Message* reply_message);
- // Checks if the given automation ID refers to an actual object.
- // Example:
- // input: { "auto_id": { "type": 0, "id": "awoein" } }
- // output: { "does_exist": false }
- void DoesAutomationObjectExist(
- base::DictionaryValue* args, IPC::Message* reply_message);
-
// Closes the specified tab.
// The pair |windex| and |tab_index| or the single |auto_id| must be given
// to specify the tab.
@@ -1182,13 +1163,6 @@
void BringBrowserToFrontJSON(base::DictionaryValue* args,
IPC::Message* message);
- // Gets the version of ChromeDriver automation supported by this server.
- // Example:
- // input: none
- // output: { "version": 1 }
- void GetChromeDriverAutomationVersion(base::DictionaryValue* args,
- IPC::Message* message);
-
// Determines whether the extension page action is visible in the given tab.
// Example:
// input: { "auto_id": { "type": 0, "id": "awoein" },
diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc
index 8b308e2..9e2230f 100644
--- a/chrome/browser/background/background_contents_service.cc
+++ b/chrome/browser/background/background_contents_service.cc
@@ -12,6 +12,7 @@
#include "base/prefs/pref_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/background/background_contents_service_factory.h"
#include "chrome/browser/browser_process.h"
@@ -56,38 +57,22 @@
namespace {
-const char kCrashNotificationPrefix[] = "app.background.crashed.";
-const char kMisbehaveNotificationPrefix[] = "app.background.misbehaved.";
-
-// Number of recent crashes of a force-installed app/extension that will
-// trigger an 'App/Extension is misbehaving' balloon.
-const unsigned int kMisbehaveCrashCountThreshold = 5;
+const char kNotificationPrefix[] = "app.background.crashed.";
void CloseBalloon(const std::string& balloon_id) {
g_browser_process->notification_ui_manager()->
CancelById(balloon_id);
}
-// Closes the balloon with this id.
-void ScheduleCloseBalloon(const std::string& balloon_id) {
+// Closes the crash notification balloon for the app/extension with this id.
+void ScheduleCloseBalloon(const std::string& extension_id) {
if (!base::MessageLoop::current()) // For unit_tests
return;
base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&CloseBalloon, balloon_id));
+ FROM_HERE, base::Bind(&CloseBalloon, kNotificationPrefix + extension_id));
}
-// Closes the crash notification balloon for the app/extension with this id.
-void ScheduleCloseCrashBalloon(const std::string& extension_id) {
- ScheduleCloseBalloon(kCrashNotificationPrefix + extension_id);
-}
-
-// Closes all notification balloons relating to the app/extension with this id.
-void ScheduleCloseBalloons(const std::string& extension_id) {
- ScheduleCloseBalloon(kMisbehaveNotificationPrefix + extension_id);
- ScheduleCloseBalloon(kCrashNotificationPrefix + extension_id);
-}
-
-// Delegate for the 'app/extension has crashed' popup balloon. Restarts the
+// Delegate for the app/extension crash notification balloon. Restarts the
// app/extension when the balloon is clicked.
class CrashNotificationDelegate : public NotificationDelegate {
public:
@@ -129,15 +114,15 @@
ReloadExtension(copied_extension_id);
}
- // Closing the 'app/extension has crashed' balloon here should be OK, but it
- // causes a crash on Mac (http://crbug.com/78167).
- ScheduleCloseCrashBalloon(copied_extension_id);
+ // Closing the crash notification balloon for the app/extension here should
+ // be OK, but it causes a crash on Mac, see: http://crbug.com/78167
+ ScheduleCloseBalloon(copied_extension_id);
}
virtual bool HasClickedListener() OVERRIDE { return true; }
virtual std::string id() const OVERRIDE {
- return kCrashNotificationPrefix + extension_id_;
+ return kNotificationPrefix + extension_id_;
}
virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
@@ -155,48 +140,12 @@
DISALLOW_COPY_AND_ASSIGN(CrashNotificationDelegate);
};
-// Empty delegate for the 'app/extension is misbehaving' popup balloon, which is
-// triggered if a force-installed app/extension gets stuck in a crash/reload
-// cycle. Doesn't do anything on click because force-installed apps/extensions
-// get restarted automatically.
-class MisbehaveNotificationDelegate : public NotificationDelegate {
- public:
- explicit MisbehaveNotificationDelegate(const Extension* extension)
- : extension_id_(extension->id()) {
- }
-
- virtual void Display() OVERRIDE {}
-
- virtual void Error() OVERRIDE {}
-
- virtual void Close(bool by_user) OVERRIDE {}
-
- virtual void Click() OVERRIDE {}
-
- virtual bool HasClickedListener() OVERRIDE { return true; }
-
- virtual std::string id() const OVERRIDE {
- return kMisbehaveNotificationPrefix + extension_id_;
- }
-
- virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
- return NULL;
- }
-
- private:
- virtual ~MisbehaveNotificationDelegate() {}
-
- std::string extension_id_;
-
- DISALLOW_COPY_AND_ASSIGN(MisbehaveNotificationDelegate);
-};
-
#if defined(ENABLE_NOTIFICATIONS)
void NotificationImageReady(
const std::string extension_name,
const string16 message,
const GURL extension_url,
- scoped_refptr<NotificationDelegate> delegate,
+ scoped_refptr<CrashNotificationDelegate> delegate,
Profile* profile,
const gfx::Image& icon) {
gfx::Image notification_icon(icon);
@@ -216,27 +165,13 @@
#endif
// Show a popup notification balloon with a crash message for a given app/
-// extension. If |force_installed| is true we show an 'App/extension
-// is misbehaving' message instead of a crash message.
-void ShowBalloon(const Extension* extension, Profile* profile,
- bool force_installed) {
+// extension.
+void ShowBalloon(const Extension* extension, Profile* profile) {
#if defined(ENABLE_NOTIFICATIONS)
- string16 message;
- scoped_refptr<NotificationDelegate> delegate;
- if (force_installed) {
- message = l10n_util::GetStringFUTF16(
- extension->is_app() ?
- IDS_BACKGROUND_MISBEHAVING_APP_BALLOON_MESSAGE :
- IDS_BACKGROUND_MISBEHAVING_EXTENSION_BALLOON_MESSAGE,
- UTF8ToUTF16(extension->name()));
- delegate = new MisbehaveNotificationDelegate(extension);
- } else {
- message = l10n_util::GetStringFUTF16(
- extension->is_app() ? IDS_BACKGROUND_CRASHED_APP_BALLOON_MESSAGE :
- IDS_BACKGROUND_CRASHED_EXTENSION_BALLOON_MESSAGE,
- UTF8ToUTF16(extension->name()));
- delegate = new CrashNotificationDelegate(profile, extension);
- }
+ const string16 message = l10n_util::GetStringFUTF16(
+ extension->is_app() ? IDS_BACKGROUND_CRASHED_APP_BALLOON_MESSAGE :
+ IDS_BACKGROUND_CRASHED_EXTENSION_BALLOON_MESSAGE,
+ UTF8ToUTF16(extension->name()));
extension_misc::ExtensionIcons size(extension_misc::EXTENSION_ICON_MEDIUM);
extensions::ExtensionResource resource =
extensions::IconsInfo::GetIconResource(
@@ -254,13 +189,12 @@
extension->name(),
message,
extension->url(),
- delegate,
+ make_scoped_refptr(new CrashNotificationDelegate(profile, extension)),
profile));
#endif
}
-void ReloadExtension(
- const std::string& extension_id, Profile* profile) {
+void ReloadExtension(const std::string& extension_id, Profile* profile) {
if (g_browser_process->IsShuttingDown() ||
!g_browser_process->profile_manager()->IsValidProfile(profile)) {
return;
@@ -296,7 +230,6 @@
const char kFrameNameKey[] = "name";
int BackgroundContentsService::restart_delay_in_ms_ = 3000; // 3 seconds.
-int BackgroundContentsService::crash_window_in_ms_ = 1000; // 1 second.
BackgroundContentsService::BackgroundContentsService(
Profile* profile, const CommandLine* command_line)
@@ -320,10 +253,9 @@
// static
void BackgroundContentsService::
- SetCrashDelaysForForceInstalledAppsAndExtensionsForTesting(
- int restart_delay_in_ms, int crash_window_in_ms) {
+ SetRestartDelayForForceInstalledAppsAndExtensionsForTesting(
+ int restart_delay_in_ms) {
restart_delay_in_ms_ = restart_delay_in_ms;
- crash_window_in_ms_ = crash_window_in_ms;
}
std::vector<BackgroundContents*>
@@ -451,8 +383,8 @@
}
}
- // Remove any "app/extension has crashed" balloons.
- ScheduleCloseCrashBalloon(extension->id());
+ // Close the crash notification balloon for the app/extension, if any.
+ ScheduleCloseBalloon(extension->id());
SendChangeNotification(profile);
break;
}
@@ -487,9 +419,9 @@
// handling code as a task here so that it is not executed before this
// event.
base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&ShowBalloon, extension, profile, false));
+ FROM_HERE, base::Bind(&ShowBalloon, extension, profile));
} else {
- // Restart the extension; notify user if crash recurs frequently.
+ // Restart the extension.
RestartForceInstalledExtensionOnCrash(extension, profile);
}
break;
@@ -528,12 +460,9 @@
break;
case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: {
- const std::string& extension_id =
- content::Details<const Extension>(details).ptr()->id();
- // Remove any balloons shown for this app/extension.
- ScheduleCloseBalloons(extension_id);
- misbehaving_extensions_.erase(extension_id);
- extension_crashlog_map_.erase(extension_id);
+ // Close the crash notification balloon for the app/extension, if any.
+ ScheduleCloseBalloon(
+ content::Details<const Extension>(details).ptr()->id());
break;
}
@@ -544,38 +473,10 @@
}
void BackgroundContentsService::RestartForceInstalledExtensionOnCrash(
- const Extension* extension, Profile* profile) {
- const std::string& extension_id = extension->id();
- const bool already_notified = misbehaving_extensions_.find(extension_id) !=
- misbehaving_extensions_.end();
- std::queue<base::TimeTicks>& crashes = extension_crashlog_map_[extension_id];
- const base::TimeDelta recent_time_window =
- base::TimeDelta::FromMilliseconds(kMisbehaveCrashCountThreshold *
- (restart_delay_in_ms_ + crash_window_in_ms_));
- if (!already_notified) {
- // Show a notification if the threshold number of crashes has occurred
- // within a recent time period.
- const bool should_notify =
- crashes.size() == kMisbehaveCrashCountThreshold - 1 &&
- base::TimeTicks::Now() - crashes.front() < recent_time_window;
- if (should_notify) {
- base::MessageLoop::current()->PostTask(FROM_HERE,
- base::Bind(&ShowBalloon, extension, profile, true));
- misbehaving_extensions_.insert(extension_id);
- extension_crashlog_map_.erase(extension_id);
- } else {
- while (!crashes.empty() &&
- base::TimeTicks::Now() - crashes.front() > recent_time_window) {
- // Remove old timestamps.
- crashes.pop();
- }
- crashes.push(base::TimeTicks::Now());
- if (crashes.size() == kMisbehaveCrashCountThreshold)
- crashes.pop();
- }
- }
+ const Extension* extension,
+ Profile* profile) {
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&ReloadExtension, extension_id, profile),
+ base::Bind(&ReloadExtension, extension->id(), profile),
base::TimeDelta::FromMilliseconds(restart_delay_in_ms_));
}
@@ -801,7 +702,7 @@
contents_map_[details->application_id].contents = details->contents;
contents_map_[details->application_id].frame_name = details->frame_name;
- ScheduleCloseCrashBalloon(UTF16ToASCII(details->application_id));
+ ScheduleCloseBalloon(UTF16ToASCII(details->application_id));
}
// Used by test code and debug checks to verify whether a given
diff --git a/chrome/browser/background/background_contents_service.h b/chrome/browser/background/background_contents_service.h
index fe951a3..921aa91 100644
--- a/chrome/browser/background/background_contents_service.h
+++ b/chrome/browser/background/background_contents_service.h
@@ -6,16 +6,12 @@
#define CHROME_BROWSER_BACKGROUND_BACKGROUND_CONTENTS_SERVICE_H_
#include <map>
-#include <queue>
-#include <set>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
#include "chrome/browser/tab_contents/background_contents.h"
-#include "chrome/common/extensions/extension.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"
@@ -35,6 +31,10 @@
class SessionStorageNamespace;
}
+namespace extensions {
+class Extension;
+}
+
namespace gfx {
class Rect;
}
@@ -57,10 +57,9 @@
virtual ~BackgroundContentsService();
// Allows tests to reduce the time between a force-installed app/extension
- // crashing and when we reload it, and the amount of time we wait for further
- // crashes before showing a balloon saying the app/extension is misbehaving.
- static void SetCrashDelaysForForceInstalledAppsAndExtensionsForTesting(
- int restart_delay_in_ms, int crash_window_in_ms);
+ // crashing and when we reload it.
+ static void SetRestartDelayForForceInstalledAppsAndExtensionsForTesting(
+ int restart_delay_in_ms);
// Returns the BackgroundContents associated with the passed application id,
// or NULL if none.
@@ -131,10 +130,10 @@
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
- // Restarts a force-installed app/extension after a crash. Notifies user if
- // crash recurs frequently.
+ // Restarts a force-installed app/extension after a crash.
void RestartForceInstalledExtensionOnCrash(
- const extensions::Extension* extension, Profile* profile);
+ const extensions::Extension* extension,
+ Profile* profile);
// Loads all registered BackgroundContents at startup.
void LoadBackgroundContentsFromPrefs(Profile* profile);
@@ -188,12 +187,6 @@
// Delay (in ms) before restarting a force-installed extension that crashed.
static int restart_delay_in_ms_;
- // When a force-installed app/extension crashes, we check if it's in a crash/
- // reload loop by checking if the number of crashes exceeds a threshold in a
- // given time window. The duration of that window is given by:
- // kMisbehaveCrashCountThreshold * (restart_delay_in_ms + crash_window_in_ms)
- static int crash_window_in_ms_;
-
// PrefService used to store list of background pages (or NULL if this is
// running under an incognito profile).
PrefService* prefs_;
@@ -214,16 +207,6 @@
typedef std::map<string16, BackgroundContentsInfo> BackgroundContentsMap;
BackgroundContentsMap contents_map_;
- // Map associating IDs of force-installed extensions/apps with their most
- // recent crash timestamps.
- // Key: app/extension id.
- // Value: queue containing up to 5 most recent crash timestamps.
- std::map<std::string, std::queue<base::TimeTicks> > extension_crashlog_map_;
-
- // Map containing ids of force-installed apps/extensions for which we have
- // already shown an 'App/Extension is misbehaving' balloon.
- std::set<std::string> misbehaving_extensions_;
-
DISALLOW_COPY_AND_ASSIGN(BackgroundContentsService);
};
diff --git a/chrome/browser/bookmarks/OWNERS b/chrome/browser/bookmarks/OWNERS
index 1370a83..b221410 100644
--- a/chrome/browser/bookmarks/OWNERS
+++ b/chrome/browser/bookmarks/OWNERS
@@ -1,5 +1,2 @@
brettw@chromium.org
sky@chromium.org
-
-# Temporary owner, for refactoring changes only.
-kaiwang@chromium.org
diff --git a/chrome/browser/bookmarks/bookmark_node_data.cc b/chrome/browser/bookmarks/bookmark_node_data.cc
index 4ec9c74..b1d201f 100644
--- a/chrome/browser/bookmarks/bookmark_node_data.cc
+++ b/chrome/browser/bookmarks/bookmark_node_data.cc
@@ -13,7 +13,6 @@
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/profiles/profile.h"
-#include "net/base/escape.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
const char* BookmarkNodeData::kClipboardFormatString =
@@ -144,7 +143,7 @@
const std::string url = elements[0].url.spec();
scw.WriteBookmark(title, url);
- scw.WriteHyperlink(net::EscapeForHTML(title), url);
+ scw.WriteHyperlink(title, url);
// Also write the URL to the clipboard as text so that it can be pasted
// into text fields. We use WriteText instead of WriteURL because we don't
diff --git a/chrome/browser/bookmarks/bookmark_stats.cc b/chrome/browser/bookmarks/bookmark_stats.cc
new file mode 100644
index 0000000..5d4d3da
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_stats.cc
@@ -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.
+
+#include "chrome/browser/bookmarks/bookmark_stats.h"
+
+#include "base/metrics/histogram.h"
+#include "content/public/browser/user_metrics.h"
+
+void RecordBookmarkLaunch(BookmarkLaunchLocation location) {
+ if (location == BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR ||
+ location == BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR) {
+ content::RecordAction(
+ content::UserMetricsAction("ClickedBookmarkBarURLButton"));
+ }
+
+ UMA_HISTOGRAM_ENUMERATION(
+ "Bookmarks.LaunchLocation", location, BOOKMARK_LAUNCH_LOCATION_LIMIT);
+}
+
+void RecordBookmarkFolderOpen(BookmarkLaunchLocation location) {
+ if (location == BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR ||
+ location == BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR) {
+ content::RecordAction(
+ content::UserMetricsAction("ClickedBookmarkBarFolder"));
+ }
+}
+
+void RecordBookmarkAppsPageOpen(BookmarkLaunchLocation location) {
+ if (location == BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR ||
+ location == BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR) {
+ content::RecordAction(
+ content::UserMetricsAction("ClickedBookmarkBarAppsShortcutButton"));
+ }
+}
diff --git a/chrome/browser/bookmarks/bookmark_stats.h b/chrome/browser/bookmarks/bookmark_stats.h
new file mode 100644
index 0000000..f7f8a82
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_stats.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_BOOKMARKS_BOOKMARK_STATS_H_
+#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_STATS_H_
+
+// This enum is used for the Bookmarks.EntryPoint histogram.
+enum BookmarkEntryPoint {
+ BOOKMARK_ENTRY_POINT_ACCELERATOR,
+ BOOKMARK_ENTRY_POINT_STAR_GESTURE,
+ BOOKMARK_ENTRY_POINT_STAR_KEY,
+ BOOKMARK_ENTRY_POINT_STAR_MOUSE,
+
+ BOOKMARK_ENTRY_POINT_LIMIT // Keep this last.
+};
+
+// This enum is used for the Bookmarks.LaunchLocation histogram.
+enum BookmarkLaunchLocation {
+ BOOKMARK_LAUNCH_LOCATION_NONE,
+ BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR = 0,
+ BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR,
+ // These two are kind of sub-categories of the bookmark bar. Generally
+ // a launch from a context menu or subfolder could be classified in one of
+ // the other two bar buckets, but doing so is difficult because the menus
+ // don't know of their greater place in Chrome.
+ BOOKMARK_LAUNCH_LOCATION_BAR_SUBFOLDER,
+ BOOKMARK_LAUNCH_LOCATION_CONTEXT_MENU,
+
+ // Bookmarks menu within wrench menu.
+ BOOKMARK_LAUNCH_LOCATION_WRENCH_MENU,
+ // Bookmark manager.
+ BOOKMARK_LAUNCH_LOCATION_MANAGER,
+ // Autocomplete suggestion.
+ BOOKMARK_LAUNCH_LOCATION_OMNIBOX,
+
+ BOOKMARK_LAUNCH_LOCATION_LIMIT // Keep this last.
+};
+
+// Records the launch of a bookmark for UMA purposes.
+void RecordBookmarkLaunch(BookmarkLaunchLocation location);
+
+// Records the user opening a folder of bookmarks for UMA purposes.
+void RecordBookmarkFolderOpen(BookmarkLaunchLocation location);
+
+// Records the user opening the apps page for UMA purposes.
+void RecordBookmarkAppsPageOpen(BookmarkLaunchLocation location);
+
+#endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_STATS_H_
diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc
index f6ddf6c..065564a 100644
--- a/chrome/browser/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_utils.cc
@@ -10,23 +10,19 @@
#include "base/files/file_path.h"
#include "base/i18n/case_conversion.h"
#include "base/i18n/string_search.h"
-#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string16.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_node_data.h"
#include "chrome/browser/history/query_parser.h"
#include "chrome/common/pref_names.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/user_metrics.h"
#include "net/base/net_util.h"
#include "ui/base/models/tree_node_iterator.h"
-#include "ui/events/event.h"
using base::Time;
-using content::UserMetricsAction;
namespace {
@@ -322,23 +318,4 @@
}
}
-void RecordBookmarkFolderOpen(BookmarkLaunchLocation location) {
- if (location == LAUNCH_DETACHED_BAR || location == LAUNCH_ATTACHED_BAR)
- content::RecordAction(UserMetricsAction("ClickedBookmarkBarFolder"));
-}
-
-void RecordBookmarkLaunch(BookmarkLaunchLocation location) {
- if (location == LAUNCH_DETACHED_BAR || location == LAUNCH_ATTACHED_BAR)
- content::RecordAction(UserMetricsAction("ClickedBookmarkBarURLButton"));
-
- UMA_HISTOGRAM_ENUMERATION("Bookmarks.LaunchLocation", location, LAUNCH_LIMIT);
-}
-
-void RecordAppsPageOpen(BookmarkLaunchLocation location) {
- if (location == LAUNCH_DETACHED_BAR || location == LAUNCH_ATTACHED_BAR) {
- content::RecordAction(
- UserMetricsAction("ClickedBookmarkBarAppsShortcutButton"));
- }
-}
-
} // namespace bookmark_utils
diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h
index 7c60471..e813975 100644
--- a/chrome/browser/bookmarks/bookmark_utils.h
+++ b/chrome/browser/bookmarks/bookmark_utils.h
@@ -95,47 +95,6 @@
// Removes all bookmarks for the given |url|.
void RemoveAllBookmarks(BookmarkModel* model, const GURL& url);
-// This enum is used for the Bookmarks.EntryPoint histogram.
-enum BookmarkEntryPoint {
- ENTRY_POINT_ACCELERATOR,
- ENTRY_POINT_STAR_GESTURE,
- ENTRY_POINT_STAR_KEY,
- ENTRY_POINT_STAR_MOUSE,
-
- ENTRY_POINT_LIMIT // Keep this last.
-};
-
-// This enum is used for the Bookmarks.LaunchLocation histogram.
-enum BookmarkLaunchLocation {
- LAUNCH_NONE,
- LAUNCH_ATTACHED_BAR = 0,
- LAUNCH_DETACHED_BAR,
- // These two are kind of sub-categories of the bookmark bar. Generally
- // a launch from a context menu or subfolder could be classified in one of
- // the other two bar buckets, but doing so is difficult because the menus
- // don't know of their greater place in Chrome.
- LAUNCH_BAR_SUBFOLDER,
- LAUNCH_CONTEXT_MENU,
-
- // Bookmarks menu within wrench menu.
- LAUNCH_WRENCH_MENU,
- // Bookmark manager.
- LAUNCH_MANAGER,
- // Autocomplete suggestion.
- LAUNCH_OMNIBOX,
-
- LAUNCH_LIMIT // Keep this last.
-};
-
-// Records the launch of a bookmark for UMA purposes.
-void RecordBookmarkLaunch(BookmarkLaunchLocation location);
-
-// Records the user opening a folder of bookmarks for UMA purposes.
-void RecordBookmarkFolderOpen(BookmarkLaunchLocation location);
-
-// Records the user opening the apps page for UMA purposes.
-void RecordAppsPageOpen(BookmarkLaunchLocation location);
-
} // namespace bookmark_utils
#endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_UTILS_H_
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc
index 3ae6a81..df8d739 100644
--- a/chrome/browser/browser_about_handler.cc
+++ b/chrome/browser/browser_about_handler.cc
@@ -4,12 +4,9 @@
#include "chrome/browser/browser_about_handler.h"
-#include <algorithm>
#include <string>
-#include "base/command_line.h"
#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/ui/browser_dialogs.h"
diff --git a/chrome/browser/browser_about_handler.h b/chrome/browser/browser_about_handler.h
index 8519522..f0f7ad8 100644
--- a/chrome/browser/browser_about_handler.h
+++ b/chrome/browser/browser_about_handler.h
@@ -5,15 +5,6 @@
#ifndef CHROME_BROWSER_BROWSER_ABOUT_HANDLER_H_
#define CHROME_BROWSER_BROWSER_ABOUT_HANDLER_H_
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/process/process.h"
-#include "base/strings/stringprintf.h"
-#include "build/build_config.h" // USE_TCMALLOC
-
-template <typename T> struct DefaultSingletonTraits;
class GURL;
namespace content {
@@ -36,45 +27,4 @@
// case, normal tab navigation should be skipped.
bool HandleNonNavigationAboutURL(const GURL& url);
-#if defined(USE_TCMALLOC)
-// A map of header strings (e.g. "Browser", "Renderer PID 123")
-// to the tcmalloc output collected for each process.
-typedef std::map<std::string, std::string> AboutTcmallocOutputsType;
-
-class AboutTcmallocOutputs {
- public:
- // Returns the singleton instance.
- static AboutTcmallocOutputs* GetInstance();
-
- AboutTcmallocOutputsType* outputs() { return &outputs_; }
-
- // Records the output for a specified header string.
- void SetOutput(const std::string& header, const std::string& output) {
- outputs_[header] = output;
- }
-
- // Callback for output returned from renderer processes. Adds
- // the output for a canonical renderer header string that
- // incorporates the pid.
- void RendererCallback(base::ProcessId pid, const std::string& output) {
- SetOutput(
- base::StringPrintf("Renderer PID %d", static_cast<int>(pid)), output);
- }
-
- private:
- AboutTcmallocOutputs();
- ~AboutTcmallocOutputs();
-
- AboutTcmallocOutputsType outputs_;
-
- friend struct DefaultSingletonTraits<AboutTcmallocOutputs>;
-
- DISALLOW_COPY_AND_ASSIGN(AboutTcmallocOutputs);
-};
-
-// Glue between the callback task and the method in the singleton.
-void AboutTcmallocRendererCallback(base::ProcessId pid,
- const std::string& output);
-#endif // defined(USE_TCMALLOC)
-
#endif // CHROME_BROWSER_BROWSER_ABOUT_HANDLER_H_
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 82e17f8..8a6a8f2 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -314,7 +314,8 @@
<include name="IDR_NETWORK_MENU_JS" file="resources\chromeos\network_menu.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_NOTIFICATION_ICON_LINK_HTML" file="resources\chromeos\notification_icon_link.html" type="BINDATA" />
<include name="IDR_ECHO_MANIFEST" file="resources\chromeos\echo\manifest.json" type="BINDATA" />
- <include name="IDR_OFFLINE_LOAD_HTML" file="resources\chromeos\offline_load.html" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_OFFLINE_APP_LOAD_HTML" file="resources\chromeos\offline_app_load.html" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_OFFLINE_NET_LOAD_HTML" file="resources\chromeos\offline_net_load.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_MERGE_SESSION_LOAD_HTML" file="resources\chromeos\merge_session_load.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_OS_CREDITS_HTML" file="resources\chromeos\about_os_credits.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_PROXY_SETTINGS_HTML" file="resources\chromeos\proxy_settings.html" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index 23ede7b..b7af2e1 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -272,10 +272,12 @@
base::Unretained(this)),
&history_task_tracker_);
+#if defined(ENABLE_EXTENSIONS)
// The extension activity contains details of which websites extensions
// were active on. It therefore indirectly stores details of websites a
// user has visited so best clean from here as well.
extensions::ActivityLog::GetInstance(profile_)->RemoveURLs(restrict_urls);
+#endif
}
// Need to clear the host cache and accumulated speculative data, as it also
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
index 3de958d..559a199 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -84,7 +84,6 @@
const quota::StorageType kPersistent = quota::kStorageTypePersistent;
const quota::QuotaClient::ID kClientFile = quota::QuotaClient::kFileSystem;
-const quota::QuotaClient::ID kClientDB = quota::QuotaClient::kIndexedDatabase;
void PopulateTestQuotaManagedNonBrowsingData(quota::MockQuotaManager* manager) {
manager->AddOrigin(kOriginDevTools, kTemporary, kClientFile, base::Time());
diff --git a/chrome/browser/captive_portal/captive_portal_service_unittest.cc b/chrome/browser/captive_portal/captive_portal_service_unittest.cc
index 7357b22..f03e155 100644
--- a/chrome/browser/captive_portal/captive_portal_service_unittest.cc
+++ b/chrome/browser/captive_portal/captive_portal_service_unittest.cc
@@ -28,9 +28,6 @@
namespace {
-// A short amount of time that some tests wait for.
-const int kShortTimeMs = 10;
-
// An observer watches the CaptivePortalDetector. It tracks the last
// received result and the total number of received results.
class CaptivePortalObserver : public content::NotificationObserver {
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc
index 6f2b6fb..7219bee 100644
--- a/chrome/browser/chrome_browser_field_trials_desktop.cc
+++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -69,17 +69,10 @@
void DisableShowProfileSwitcherTrialIfNecessary() {
// This trial is created by the VariationsService, but it needs to be disabled
- // if multi-profiles isn't enabled or if browser frame avatar menu is
- // always hidden (Chrome OS).
- bool avatar_menu_always_hidden = false;
-#if defined(OS_CHROMEOS)
- avatar_menu_always_hidden = true;
-#endif
+ // if multi-profiles isn't enabled.
base::FieldTrial* trial = base::FieldTrialList::Find("ShowProfileSwitcher");
- if (trial && (!profiles::IsMultipleProfilesEnabled() ||
- avatar_menu_always_hidden)) {
+ if (trial && !profiles::IsMultipleProfilesEnabled())
trial->Disable();
- }
}
void SetupLowLatencyFlashAudioFieldTrial() {
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm
index 07f250c..83c1c06 100644
--- a/chrome/browser/chrome_browser_main_mac.mm
+++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -32,13 +32,6 @@
namespace {
-// This preference is used to track whether the KeychainReauthorize operation
-// has occurred at launch. This operation only makes sense while the
-// application continues to be signed by the old certificate.
-NSString* const kKeychainReauthorizeAtLaunchPref =
- @"KeychainReauthorizeInAppMay2012";
-const int kKeychainReauthorizeAtLaunchMaxTries = 2;
-
// Some users rarely restart Chrome, so they might never get a chance to run
// the at-launch KeychainReauthorize. To account for them, there's also an
// at-update KeychainReauthorize option, which runs from .keystone_install for
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index d30780f..96fc4df 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -41,7 +41,6 @@
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_web_ui.h"
#include "chrome/browser/extensions/extension_webkit_preferences.h"
-#include "chrome/browser/extensions/process_map.h"
#include "chrome/browser/extensions/suggest_permission_util.h"
#include "chrome/browser/geolocation/chrome_access_token_store.h"
#include "chrome/browser/google/google_util.h"
@@ -126,6 +125,7 @@
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_descriptors.h"
+#include "content/public/common/url_utils.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/constants.h"
#include "extensions/common/switches.h"
@@ -169,7 +169,7 @@
#include "chrome/browser/chrome_browser_main_posix.h"
#endif
-#if defined(OS_LINUX) || defined(OS_OPENBSD) || defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include "base/linux_util.h"
#include "chrome/browser/crash_handler_host_linux.h"
#endif
@@ -790,6 +790,7 @@
void ChromeContentBrowserClient::GuestWebContentsAttached(
WebContents* guest_web_contents,
WebContents* embedder_web_contents,
+ const GURL& embedder_frame_url,
const base::DictionaryValue& extra_params) {
Profile* profile = Profile::FromBrowserContext(
embedder_web_contents->GetBrowserContext());
@@ -799,9 +800,16 @@
NOTREACHED();
return;
}
- const GURL& url = embedder_web_contents->GetSiteInstance()->GetSiteURL();
- const Extension* extension =
- service->extensions()->GetExtensionOrAppByURL(url);
+
+ // We usually require BrowserPlugins to be hosted by a storage isolated
+ // extension. We treat WebUI pages as a special case if they host the
+ // BrowserPlugin in a component extension iframe. In that case, we use the
+ // iframe's URL to determine the extension.
+ const GURL& embedder_site_url =
+ embedder_web_contents->GetSiteInstance()->GetSiteURL();
+ const Extension* extension = service->extensions()->GetExtensionOrAppByURL(
+ content::HasWebUIScheme(embedder_site_url) ?
+ embedder_frame_url : embedder_site_url);
if (!extension) {
// It's ok to return here, since we could be running a browser plugin
// outside an extension, and don't need to attach a
@@ -1988,10 +1996,6 @@
if (is_guest)
return true;
- // Exempt extension processes from popup blocking.
- if (map->process_map().Contains(render_process_id))
- return true;
-
HostContentSettingsMap* content_settings =
ProfileIOData::FromResourceContext(context)->GetHostContentSettingsMap();
BlockedWindowParams blocked_params(target_url,
@@ -2332,6 +2336,9 @@
switches::kEnableBrowserPluginForAllViewTypes))
return true;
+ if (content::HasWebUIScheme(site_url))
+ return true;
+
Profile* profile = Profile::FromBrowserContext(browser_context);
ExtensionService* service =
extensions::ExtensionSystem::Get(profile)->extension_service();
@@ -2351,7 +2358,7 @@
content::BrowserContext* browser_context,
const GURL& url,
bool private_api,
- const content::SocketPermissionRequest& params) {
+ const content::SocketPermissionRequest* params) {
#if defined(ENABLE_PLUGINS)
Profile* profile = Profile::FromBrowserContext(browser_context);
const ExtensionSet* extension_set = NULL;
@@ -2372,11 +2379,19 @@
extension_set) {
const Extension* extension = extension_set->GetByID(url.host());
if (extension) {
- extensions::SocketPermission::CheckParam check_params(
- params.type, params.host, params.port);
- if (extensions::PermissionsData::CheckAPIPermissionWithParam(
- extension, extensions::APIPermission::kSocket, &check_params)) {
- return true;
+ if (params) {
+ extensions::SocketPermission::CheckParam check_params(
+ params->type, params->host, params->port);
+ if (extensions::PermissionsData::CheckAPIPermissionWithParam(
+ extension, extensions::APIPermission::kSocket,
+ &check_params)) {
+ return true;
+ }
+ } else {
+ if (extensions::PermissionsData::HasAPIPermission(
+ extension, extensions::APIPermission::kSocket)) {
+ return true;
+ }
}
}
}
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 41f7879..86ca435 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -67,6 +67,7 @@
virtual void GuestWebContentsAttached(
content::WebContents* guest_web_contents,
content::WebContents* embedder_web_contents,
+ const GURL& embedder_frame_url,
const base::DictionaryValue& extra_params) OVERRIDE;
virtual void RenderProcessHostCreated(
content::RenderProcessHost* host) OVERRIDE;
@@ -240,7 +241,7 @@
content::BrowserContext* browser_context,
const GURL& url,
bool private_api,
- const content::SocketPermissionRequest& params) OVERRIDE;
+ const content::SocketPermissionRequest* params) OVERRIDE;
virtual ui::SelectFilePolicy* CreateSelectFilePolicy(
content::WebContents* web_contents) OVERRIDE;
virtual void GetAdditionalAllowedSchemesForFileSystem(
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h
index 0e4c2b7..4f2c15e 100644
--- a/chrome/browser/chrome_notification_types.h
+++ b/chrome/browser/chrome_notification_types.h
@@ -47,13 +47,13 @@
// that was closed, no details are expected.
NOTIFICATION_WINDOW_CLOSED,
-#if defined(OS_LINUX)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
// On Linux maximize can be an asynchronous operation. This notification
// indicates that the window has been maximized. The source is
// a Source<BrowserWindow> containing the BrowserWindow that was maximized.
// No details are expected.
NOTIFICATION_BROWSER_WINDOW_MAXIMIZED,
-#endif // defined(OS_LINUX)
+#endif
// Sent when the language (English, French...) for a page has been detected.
// The details Details<std::string> contain the ISO 639-1 language code and
@@ -881,11 +881,6 @@
// unregistration is impossible due to unpredictable deletion order.
NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
- // This is sent to a ChromeOS settings observer when a system setting is
- // changed. The source is the CrosSettings and the details a std::string of
- // the changed setting.
- NOTIFICATION_SYSTEM_SETTING_CHANGED,
-
// Sent by SIM unlock dialog when it has finished with the process of
// updating RequirePin setting. RequirePin setting might have been changed
// to a new value or update might have been canceled.
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
index c9e4ef8..232b8b8 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
@@ -15,7 +15,6 @@
#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_data.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
#include "chrome/browser/chromeos/login/user_manager.h"
@@ -100,7 +99,7 @@
void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) {
SetAutoLoginState(AUTOLOGIN_REQUESTED);
- // Clean first, so the proper change notifications are triggered even
+ // Clean first, so the proper change callbacks are triggered even
// if we are only changing AutoLoginState here.
if (!auto_launch_app_id_.empty()) {
CrosSettings::Get()->SetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
@@ -314,19 +313,21 @@
KioskAppManager::KioskAppManager() : ownership_established_(false) {
UpdateAppData();
- CrosSettings::Get()->AddSettingsObserver(
- kAccountsPrefDeviceLocalAccounts, this);
- CrosSettings::Get()->AddSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginId, this);
+ local_accounts_subscription_ =
+ CrosSettings::Get()->AddSettingsObserver(
+ kAccountsPrefDeviceLocalAccounts,
+ base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
+ local_account_auto_login_id_subscription_ =
+ CrosSettings::Get()->AddSettingsObserver(
+ kAccountsPrefDeviceLocalAccountAutoLoginId,
+ base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
}
KioskAppManager::~KioskAppManager() {}
void KioskAppManager::CleanUp() {
- CrosSettings::Get()->RemoveSettingsObserver(
- kAccountsPrefDeviceLocalAccounts, this);
- CrosSettings::Get()->RemoveSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginId, this);
+ local_accounts_subscription_.reset();
+ local_account_auto_login_id_subscription_.reset();
apps_.clear();
}
@@ -394,13 +395,6 @@
OnKioskAppsSettingsChanged());
}
-void KioskAppManager::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK_EQ(chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED, type);
- UpdateAppData();
-}
-
void KioskAppManager::GetKioskAppIconCacheDir(base::FilePath* cache_dir) {
base::FilePath user_data_dir;
CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
index 332b9c1..4b826e8 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
@@ -11,11 +11,12 @@
#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/observer_list.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_data_delegate.h"
#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
-#include "content/public/browser/notification_observer.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "ui/gfx/image/image_skia.h"
class PrefRegistrySimple;
@@ -30,8 +31,7 @@
class KioskAppManagerObserver;
// KioskAppManager manages cached app data.
-class KioskAppManager : public content::NotificationObserver,
- public KioskAppDataDelegate {
+class KioskAppManager : public KioskAppDataDelegate {
public:
enum ConsumerKioskModeStatus {
// Consumer kiosk mode can be enabled on this machine.
@@ -152,11 +152,6 @@
// Update app data |apps_| based on CrosSettings.
void UpdateAppData();
- // content::NotificationObserver overrides:
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
-
// KioskAppDataDelegate overrides:
virtual void GetKioskAppIconCacheDir(base::FilePath* cache_dir) OVERRIDE;
virtual void OnKioskAppDataChanged(const std::string& app_id) OVERRIDE;
@@ -188,6 +183,11 @@
std::string auto_launch_app_id_;
ObserverList<KioskAppManagerObserver, true> observers_;
+ scoped_ptr<CrosSettings::ObserverSubscription>
+ local_accounts_subscription_;
+ scoped_ptr<CrosSettings::ObserverSubscription>
+ local_account_auto_login_id_subscription_;
+
DISALLOW_COPY_AND_ASSIGN(KioskAppManager);
};
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
index d738eca..1a6444c 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
@@ -26,7 +26,7 @@
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h"
+#include "chrome/common/extensions/manifest_handlers/kiosk_mode_info.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
@@ -153,7 +153,8 @@
ProfileOAuth2TokenService* profile_token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
- if (profile_token_service->RefreshTokenIsAvailable()) {
+ if (profile_token_service->RefreshTokenIsAvailable(
+ profile_token_service->GetPrimaryAccountId())) {
InitializeNetwork();
return;
}
@@ -221,7 +222,7 @@
extension_service()->GetInstalledExtension(app_id_);
CHECK(extension);
- if (!extensions::KioskEnabledInfo::IsKioskEnabled(extension)) {
+ if (!extensions::KioskModeInfo::IsKioskEnabled(extension)) {
OnLaunchFailure(KioskAppLaunchError::NOT_KIOSK_ENABLED);
return;
}
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
index d28dc3f..2734706 100644
--- a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
+++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
@@ -102,7 +102,10 @@
retry_delay_(kRetryDelay),
weak_factory_(this) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this);
+ attestation_subscription_ = cros_settings_->AddSettingsObserver(
+ kDeviceAttestationEnabled,
+ base::Bind(&AttestationPolicyObserver::AttestationSettingChanged,
+ base::Unretained(this)));
Start();
}
@@ -118,26 +121,19 @@
retry_delay_(kRetryDelay),
weak_factory_(this) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this);
+ attestation_subscription_ = cros_settings_->AddSettingsObserver(
+ kDeviceAttestationEnabled,
+ base::Bind(&AttestationPolicyObserver::AttestationSettingChanged,
+ base::Unretained(this)));
Start();
}
AttestationPolicyObserver::~AttestationPolicyObserver() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- cros_settings_->RemoveSettingsObserver(kDeviceAttestationEnabled, this);
}
-void AttestationPolicyObserver::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
+void AttestationPolicyObserver::AttestationSettingChanged() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- std::string* path = content::Details<std::string>(details).ptr();
- if (type != chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED ||
- *path != kDeviceAttestationEnabled) {
- LOG(WARNING) << "AttestationPolicyObserver: Unexpected event received.";
- return;
- }
num_retries_ = 0;
Start();
}
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.h b/chrome/browser/chromeos/attestation/attestation_policy_observer.h
index 1f78971..ec59537 100644
--- a/chrome/browser/chromeos/attestation/attestation_policy_observer.h
+++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.h
@@ -11,7 +11,7 @@
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "content/public/browser/notification_observer.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
namespace policy {
class CloudPolicyClient;
@@ -28,7 +28,7 @@
// A class which observes policy changes and triggers device attestation work if
// necessary.
-class AttestationPolicyObserver : public content::NotificationObserver {
+class AttestationPolicyObserver {
public:
// The observer immediately connects with CrosSettings to listen for policy
// changes. The CloudPolicyClient is used to upload the device certificate to
@@ -43,12 +43,7 @@
CryptohomeClient* cryptohome_client,
AttestationFlow* attestation_flow);
- virtual ~AttestationPolicyObserver();
-
- // content::NotificationObserver:
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
+ ~AttestationPolicyObserver();
// Sets the retry delay in seconds; useful in testing.
void set_retry_delay(int retry_delay) {
@@ -56,6 +51,9 @@
}
private:
+ // Called when the attestation setting changes.
+ void AttestationSettingChanged();
+
// Checks attestation policy and starts any necessary work.
void Start();
@@ -98,6 +96,8 @@
int num_retries_;
int retry_delay_;
+ scoped_ptr<CrosSettings::ObserverSubscription> attestation_subscription_;
+
// 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<AttestationPolicyObserver> weak_factory_;
diff --git a/chrome/browser/chromeos/contacts/google_contact_store.cc b/chrome/browser/chromeos/contacts/google_contact_store.cc
index 45f0301..73a6752 100644
--- a/chrome/browser/chromeos/contacts/google_contact_store.cc
+++ b/chrome/browser/chromeos/contacts/google_contact_store.cc
@@ -129,10 +129,13 @@
std::vector<std::string> scopes;
scopes.push_back(kContactsScope);
+ ProfileOAuth2TokenService* oauth2_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
gdata_service_.reset(new GDataContactsService(
url_request_context_getter_,
new google_apis::AuthService(
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile_),
+ oauth2_service,
+ oauth2_service->GetPrimaryAccountId(),
url_request_context_getter_, scopes)));
}
diff --git a/chrome/browser/chromeos/device_uma.cc b/chrome/browser/chromeos/device_uma.cc
index 3aee057..487c661 100644
--- a/chrome/browser/chromeos/device_uma.cc
+++ b/chrome/browser/chromeos/device_uma.cc
@@ -10,9 +10,9 @@
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
-#include "ui/base/x/device_data_manager.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_utils.h"
+#include "ui/events/x/device_data_manager.h"
// Enum type for CrOS gesture lib UMA
enum UMACrosGestureMetricsType{
diff --git a/chrome/browser/chromeos/drive/async_file_util.cc b/chrome/browser/chromeos/drive/async_file_util.cc
index ac20a5a..8745fb3 100644
--- a/chrome/browser/chromeos/drive/async_file_util.cc
+++ b/chrome/browser/chromeos/drive/async_file_util.cc
@@ -92,7 +92,6 @@
callback.Run(error, created);
}
-
// Runs |callback| with the arguments based on the given arguments.
void RunCreateSnapshotFileCallback(
const AsyncFileUtil::CreateSnapshotFileCallback& callback,
@@ -278,10 +277,13 @@
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // TODO(hidehiko): Support option.
+
base::FilePath src_path = util::ExtractDrivePathFromFileSystemUrl(src_url);
base::FilePath dest_path = util::ExtractDrivePathFromFileSystemUrl(dest_url);
if (src_path.empty() || dest_path.empty()) {
@@ -301,9 +303,12 @@
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // TODO(hidehiko): Support option.
+
base::FilePath src_path = util::ExtractDrivePathFromFileSystemUrl(src_url);
base::FilePath dest_path = util::ExtractDrivePathFromFileSystemUrl(dest_url);
if (src_path.empty() || dest_path.empty()) {
diff --git a/chrome/browser/chromeos/drive/async_file_util.h b/chrome/browser/chromeos/drive/async_file_util.h
index d816a41..1f585e3 100644
--- a/chrome/browser/chromeos/drive/async_file_util.h
+++ b/chrome/browser/chromeos/drive/async_file_util.h
@@ -66,12 +66,14 @@
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) OVERRIDE;
virtual void MoveFileLocal(
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) OVERRIDE;
virtual void CopyInForeignFile(
scoped_ptr<fileapi::FileSystemOperationContext> context,
diff --git a/chrome/browser/chromeos/drive/change_list_loader.cc b/chrome/browser/chromeos/drive/change_list_loader.cc
index f8a09e4..2f97279 100644
--- a/chrome/browser/chromeos/drive/change_list_loader.cc
+++ b/chrome/browser/chromeos/drive/change_list_loader.cc
@@ -940,7 +940,8 @@
util::Log(logging::LOG_INFO,
"Apply change lists (is delta: %d)",
is_delta_update);
- blocking_task_runner_->PostTaskAndReply(
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_,
FROM_HERE,
base::Bind(&ChangeListProcessor::Apply,
base::Unretained(change_list_processor),
@@ -959,7 +960,8 @@
ChangeListProcessor* change_list_processor,
bool should_notify_changed_directories,
base::Time start_time,
- const base::Closure& callback) {
+ const base::Closure& callback,
+ FileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(change_list_processor);
DCHECK(!callback.is_null());
diff --git a/chrome/browser/chromeos/drive/change_list_loader.h b/chrome/browser/chromeos/drive/change_list_loader.h
index 4286140..d4e2a60 100644
--- a/chrome/browser/chromeos/drive/change_list_loader.h
+++ b/chrome/browser/chromeos/drive/change_list_loader.h
@@ -262,7 +262,8 @@
ChangeListProcessor* change_list_processor,
bool should_notify,
base::Time start_time,
- const base::Closure& callback);
+ const base::Closure& callback,
+ FileError error);
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
ResourceMetadata* resource_metadata_; // Not owned.
diff --git a/chrome/browser/chromeos/drive/change_list_processor.cc b/chrome/browser/chromeos/drive/change_list_processor.cc
index ecdbb48..6718fec 100644
--- a/chrome/browser/chromeos/drive/change_list_processor.cc
+++ b/chrome/browser/chromeos/drive/change_list_processor.cc
@@ -84,7 +84,7 @@
ChangeListProcessor::~ChangeListProcessor() {
}
-void ChangeListProcessor::Apply(
+FileError ChangeListProcessor::Apply(
scoped_ptr<google_apis::AboutResource> about_resource,
ScopedVector<ChangeList> change_lists,
bool is_delta_update) {
@@ -120,38 +120,53 @@
}
}
- ApplyEntryMap(is_delta_update, about_resource.Pass());
+ FileError error = ApplyEntryMap(is_delta_update, about_resource.Pass());
+ if (error != FILE_ERROR_OK) {
+ DLOG(ERROR) << "ApplyEntryMap failed: " << FileErrorToString(error);
+ return error;
+ }
// Update the root entry and finish.
- UpdateRootEntry(largest_changestamp);
+ error = UpdateRootEntry(largest_changestamp);
+ if (error != FILE_ERROR_OK) {
+ DLOG(ERROR) << "UpdateRootEntry failed: " << FileErrorToString(error);
+ return error;
+ }
// Update changestamp.
- FileError error = resource_metadata_->SetLargestChangestamp(
- largest_changestamp);
- DLOG_IF(ERROR, error != FILE_ERROR_OK) << "SetLargestChangeStamp failed: "
- << FileErrorToString(error);
+ error = resource_metadata_->SetLargestChangestamp(largest_changestamp);
+ if (error != FILE_ERROR_OK) {
+ DLOG(ERROR) << "SetLargestChangeStamp failed: " << FileErrorToString(error);
+ return error;
+ }
// Shouldn't record histograms when processing delta update.
if (!is_delta_update)
uma_stats.UpdateFileCountUmaHistograms();
+
+ return FILE_ERROR_OK;
}
-void ChangeListProcessor::ApplyEntryMap(
+FileError ChangeListProcessor::ApplyEntryMap(
bool is_delta_update,
scoped_ptr<google_apis::AboutResource> about_resource) {
if (!is_delta_update) { // Full update.
DCHECK(about_resource);
FileError error = resource_metadata_->Reset();
-
- LOG_IF(ERROR, error != FILE_ERROR_OK) << "Failed to reset: "
- << FileErrorToString(error);
+ if (error != FILE_ERROR_OK) {
+ LOG(ERROR) << "Failed to reset: " << FileErrorToString(error);
+ return error;
+ }
changed_dirs_.insert(util::GetDriveGrandRootPath());
changed_dirs_.insert(util::GetDriveMyDriveRootPath());
// Create the MyDrive root directory.
- ApplyEntry(util::CreateMyDriveRootEntry(about_resource->root_folder_id()));
+ error = ApplyEntry(
+ util::CreateMyDriveRootEntry(about_resource->root_folder_id()));
+ if (error != FILE_ERROR_OK)
+ return error;
}
// Gather the set of changes in the old path.
@@ -215,18 +230,29 @@
// Apply the parent first.
std::reverse(entries.begin(), entries.end());
for (size_t i = 0; i < entries.size(); ++i) {
+ // TODO(hashimoto): Handle ApplyEntry errors correctly.
ResourceEntryMap::iterator it = entries[i];
- ApplyEntry(it->second);
+ FileError error = ApplyEntry(it->second);
+ DLOG_IF(WARNING, error != FILE_ERROR_OK)
+ << "ApplyEntry failed: " << FileErrorToString(error)
+ << ", title = " << it->second.title();
entry_map_.erase(it);
}
}
// Apply deleted entries.
- for (size_t i = 0; i < deleted_entries.size(); ++i)
- ApplyEntry(deleted_entries[i]);
+ for (size_t i = 0; i < deleted_entries.size(); ++i) {
+ // TODO(hashimoto): Handle ApplyEntry errors correctly.
+ FileError error = ApplyEntry(deleted_entries[i]);
+ DLOG_IF(WARNING, error != FILE_ERROR_OK)
+ << "ApplyEntry failed: " << FileErrorToString(error)
+ << ", title = " << deleted_entries[i].title();
+ }
+
+ return FILE_ERROR_OK;
}
-void ChangeListProcessor::ApplyEntry(const ResourceEntry& entry) {
+FileError ChangeListProcessor::ApplyEntry(const ResourceEntry& entry) {
// Lookup the entry.
ResourceEntry existing_entry;
FileError error = resource_metadata_->GetResourceEntryById(
@@ -235,35 +261,25 @@
if (error == FILE_ERROR_OK) {
if (entry.deleted()) {
// Deleted file/directory.
- RemoveEntry(entry);
+ error = resource_metadata_->RemoveEntry(entry.resource_id());
} else {
// Entry exists and needs to be refreshed.
- RefreshEntry(entry);
+ ResourceEntry new_entry(entry);
+ new_entry.set_local_id(existing_entry.local_id());
+ error = resource_metadata_->RefreshEntry(new_entry);
+ if (error == FILE_ERROR_OK)
+ UpdateChangedDirs(new_entry);
}
} else if (error == FILE_ERROR_NOT_FOUND && !entry.deleted()) {
// Adding a new entry.
- AddEntry(entry);
+ std::string local_id;
+ error = resource_metadata_->AddEntry(entry, &local_id);
+
+ if (error == FILE_ERROR_OK)
+ UpdateChangedDirs(entry);
}
-}
-void ChangeListProcessor::AddEntry(const ResourceEntry& entry) {
- std::string local_id;
- FileError error = resource_metadata_->AddEntry(entry, &local_id);
-
- if (error == FILE_ERROR_OK)
- UpdateChangedDirs(entry);
-}
-
-void ChangeListProcessor::RemoveEntry(const ResourceEntry& entry) {
- resource_metadata_->RemoveEntry(entry.resource_id());
-}
-
-void ChangeListProcessor::RefreshEntry(const ResourceEntry& entry) {
- FileError error =
- resource_metadata_->RefreshEntry(entry.resource_id(), entry);
-
- if (error == FILE_ERROR_OK)
- UpdateChangedDirs(entry);
+ return error;
}
// static
@@ -328,7 +344,14 @@
continue;
}
- error = resource_metadata->RefreshEntry(it->first, entry);
+ std::string local_id;
+ error = resource_metadata->GetIdByResourceId(it->first, &local_id);
+ if (error == FILE_ERROR_OK) {
+ ResourceEntry new_entry(entry);
+ new_entry.set_local_id(local_id);
+ error = resource_metadata->RefreshEntry(new_entry);
+ }
+
if (error == FILE_ERROR_NOT_FOUND) { // If refreshing fails, try adding.
std::string local_id;
error = resource_metadata->AddEntry(entry, &local_id);
@@ -340,8 +363,7 @@
directory.mutable_directory_specific_info()->set_changestamp(
directory_fetch_info.changestamp());
- error = resource_metadata->RefreshEntry(directory_fetch_info.resource_id(),
- directory);
+ error = resource_metadata->RefreshEntry(directory);
if (error != FILE_ERROR_OK)
return error;
@@ -349,7 +371,7 @@
return FILE_ERROR_OK;
}
-void ChangeListProcessor::UpdateRootEntry(int64 largest_changestamp) {
+FileError ChangeListProcessor::UpdateRootEntry(int64 largest_changestamp) {
std::string root_local_id;
FileError error = resource_metadata_->GetIdByPath(
util::GetDriveMyDriveRootPath(), &root_local_id);
@@ -361,15 +383,19 @@
if (error != FILE_ERROR_OK) {
// TODO(satorux): Need to trigger recovery if root is corrupt.
LOG(WARNING) << "Failed to get the entry for root directory";
- return;
+ return error;
}
// The changestamp should always be updated.
root.mutable_directory_specific_info()->set_changestamp(largest_changestamp);
- error = resource_metadata_->RefreshEntry(root_local_id, root);
+ error = resource_metadata_->RefreshEntry(root);
+ if (error != FILE_ERROR_OK) {
+ LOG(WARNING) << "Failed to refresh root directory";
+ return error;
+ }
- LOG_IF(WARNING, error != FILE_ERROR_OK) << "Failed to refresh root directory";
+ return FILE_ERROR_OK;
}
void ChangeListProcessor::UpdateChangedDirs(const ResourceEntry& entry) {
diff --git a/chrome/browser/chromeos/drive/change_list_processor.h b/chrome/browser/chromeos/drive/change_list_processor.h
index ed921ae..f0e0ba8 100644
--- a/chrome/browser/chromeos/drive/change_list_processor.h
+++ b/chrome/browser/chromeos/drive/change_list_processor.h
@@ -96,11 +96,9 @@
// it is full resource lists (false) or change lists (true).
//
// Must be run on the same task runner as |resource_metadata_| uses.
- //
- // TODO(hashimoto): Report error on failures.
- void Apply(scoped_ptr<google_apis::AboutResource> about_resource,
- ScopedVector<ChangeList> change_lists,
- bool is_delta_update);
+ FileError Apply(scoped_ptr<google_apis::AboutResource> about_resource,
+ ScopedVector<ChangeList> change_lists,
+ bool is_delta_update);
// Converts change lists into a ResourceEntryMap.
// |uma_stats| may be NULL.
@@ -123,30 +121,15 @@
// Applies the pre-processed metadata from entry_map_ onto the resource
// metadata. If this is not delta update (i.e. |is_delta_update| is false),
// |about_resource| must not be null.
- void ApplyEntryMap(bool is_delta_update,
- scoped_ptr<google_apis::AboutResource> about_resource);
-
- // Apply the next item from entry_map_ to the file system. The async
- // version posts to the message loop to avoid recursive stack-overflow.
- void ApplyNextEntry();
+ FileError ApplyEntryMap(
+ bool is_delta_update,
+ scoped_ptr<google_apis::AboutResource> about_resource);
// Apply |entry| to resource_metadata_.
- void ApplyEntry(const ResourceEntry& entry);
-
- // Helper function to add |entry| to its parent. Updates changed_dirs_
- // as a side effect.
- void AddEntry(const ResourceEntry& entry);
-
- // Removes entry pointed to by |resource_id| from its parent. Updates
- // changed_dirs_ as a side effect.
- void RemoveEntry(const ResourceEntry& entry);
-
- // Refreshes ResourceMetadata entry that has the same resource_id as
- // |entry| with |entry|. Updates changed_dirs_ as a side effect.
- void RefreshEntry(const ResourceEntry& entry);
+ FileError ApplyEntry(const ResourceEntry& entry);
// Updates the root directory entry. changestamp will be updated.
- void UpdateRootEntry(int64 largest_changestamp);
+ FileError UpdateRootEntry(int64 largest_changestamp);
// Adds the directories changed by the update on |entry| to |changed_dirs_|.
void UpdateChangedDirs(const ResourceEntry& entry);
diff --git a/chrome/browser/chromeos/drive/change_list_processor_unittest.cc b/chrome/browser/chromeos/drive/change_list_processor_unittest.cc
index 221ff98..5b0d6f9 100644
--- a/chrome/browser/chromeos/drive/change_list_processor_unittest.cc
+++ b/chrome/browser/chromeos/drive/change_list_processor_unittest.cc
@@ -65,26 +65,28 @@
// Applies the |changes| to |metadata_| as a full resource list of changestamp
// |kBaseResourceListChangestamp|.
- void ApplyFullResourceList(ScopedVector<ChangeList> changes) {
+ FileError ApplyFullResourceList(ScopedVector<ChangeList> changes) {
scoped_ptr<google_apis::AboutResource> about_resource(
new google_apis::AboutResource);
about_resource->set_largest_change_id(kBaseResourceListChangestamp);
about_resource->set_root_folder_id(kRootId);
ChangeListProcessor processor(metadata_.get());
- processor.Apply(about_resource.Pass(),
- changes.Pass(),
- false /* is_delta_update */);
+ return processor.Apply(about_resource.Pass(),
+ changes.Pass(),
+ false /* is_delta_update */);
}
// Applies the |changes| to |metadata_| as a delta update. Delta changelists
// should contain their changestamp in themselves.
- std::set<base::FilePath> ApplyChangeList(ScopedVector<ChangeList> changes) {
+ FileError ApplyChangeList(ScopedVector<ChangeList> changes,
+ std::set<base::FilePath>* changed_dirs) {
ChangeListProcessor processor(metadata_.get());
- processor.Apply(scoped_ptr<google_apis::AboutResource>(),
- changes.Pass(),
- true /* is_delta_update */);
- return processor.changed_dirs();
+ FileError error = processor.Apply(scoped_ptr<google_apis::AboutResource>(),
+ changes.Pass(),
+ true /* is_delta_update */);
+ *changed_dirs = processor.changed_dirs();
+ return error;
}
// Gets the resource entry for the path from |metadata_| synchronously.
@@ -108,7 +110,8 @@
} // namespace
TEST_F(ChangeListProcessorTest, ApplyFullResourceList) {
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
const EntryExpectation kExpected[] = {
// Root files
@@ -183,9 +186,11 @@
EXPECT_EQ("File in new dir", entry_map[kNewFileId].title());
// Apply the changelist and check the effect.
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
- std::set<base::FilePath> changed_dirs =
- ApplyChangeList(ParseChangeList(kTestJson));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
+ std::set<base::FilePath> changed_dirs;
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyChangeList(ParseChangeList(kTestJson), &changed_dirs));
// The value is written in kTestJson.
EXPECT_EQ(16730, metadata_->GetLargestChangestamp());
@@ -218,9 +223,11 @@
EXPECT_EQ(kDestId, entry_map[kMovedId].parent_local_id());
// Apply the changelist and check the effect.
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
- std::set<base::FilePath> changed_dirs =
- ApplyChangeList(ParseChangeList(kTestJson));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
+ std::set<base::FilePath> changed_dirs;
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyChangeList(ParseChangeList(kTestJson), &changed_dirs));
// The value is written in kTestJson.
EXPECT_EQ(16809, metadata_->GetLargestChangestamp());
@@ -259,9 +266,11 @@
EXPECT_EQ(kRootId, entry_map[kMovedId].parent_local_id());
// Apply the changelist and check the effect.
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
- std::set<base::FilePath> changed_dirs =
- ApplyChangeList(ParseChangeList(kTestJson));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
+ std::set<base::FilePath> changed_dirs;
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyChangeList(ParseChangeList(kTestJson), &changed_dirs));
// The value is written in kTestJson.
EXPECT_EQ(16815, metadata_->GetLargestChangestamp());
@@ -295,9 +304,11 @@
EXPECT_EQ("New SubDirectory File 1.txt", entry_map[kRenamedId].title());
// Apply the changelist and check the effect.
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
- std::set<base::FilePath> changed_dirs =
- ApplyChangeList(ParseChangeList(kTestJson));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
+ std::set<base::FilePath> changed_dirs;
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyChangeList(ParseChangeList(kTestJson), &changed_dirs));
// The value is written in kTestJson.
EXPECT_EQ(16767, metadata_->GetLargestChangestamp());
@@ -334,9 +345,11 @@
EXPECT_FALSE(entry_map[kFileId].deleted());
// Apply.
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
- std::set<base::FilePath> changed_dirs =
- ApplyChangeList(ParseChangeList(kTestJsonAdd));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
+ std::set<base::FilePath> changed_dirs;
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyChangeList(ParseChangeList(kTestJsonAdd), &changed_dirs));
EXPECT_EQ(16683, metadata_->GetLargestChangestamp());
EXPECT_TRUE(GetResourceEntry("drive/root/Added file.gdoc"));
EXPECT_EQ(1U, changed_dirs.size());
@@ -354,7 +367,8 @@
EXPECT_TRUE(entry_map[kFileId].deleted());
// Apply.
- changed_dirs = ApplyChangeList(ParseChangeList(kTestJsonDelete));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyChangeList(ParseChangeList(kTestJsonDelete), &changed_dirs));
EXPECT_EQ(16687, metadata_->GetLargestChangestamp());
EXPECT_FALSE(GetResourceEntry("drive/root/Added file.gdoc"));
EXPECT_EQ(1U, changed_dirs.size());
@@ -385,9 +399,11 @@
EXPECT_FALSE(entry_map[kFileId].deleted());
// Apply.
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
- std::set<base::FilePath> changed_dirs =
- ApplyChangeList(ParseChangeList(kTestJsonAdd));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
+ std::set<base::FilePath> changed_dirs;
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyChangeList(ParseChangeList(kTestJsonAdd), &changed_dirs));
EXPECT_EQ(16730, metadata_->GetLargestChangestamp());
EXPECT_TRUE(GetResourceEntry("drive/root/Directory 1/Added file.gdoc"));
@@ -408,7 +424,8 @@
EXPECT_TRUE(entry_map[kFileId].deleted());
// Apply.
- changed_dirs = ApplyChangeList(ParseChangeList(kTestJsonDelete));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyChangeList(ParseChangeList(kTestJsonDelete), &changed_dirs));
EXPECT_EQ(16770, metadata_->GetLargestChangestamp());
EXPECT_FALSE(GetResourceEntry("drive/root/Directory 1/Added file.gdoc"));
@@ -440,9 +457,11 @@
EXPECT_TRUE(entry_map[kDirId].deleted());
// Apply the changelist and check the effect.
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
- std::set<base::FilePath> changed_dirs =
- ApplyChangeList(ParseChangeList(kTestJson));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
+ std::set<base::FilePath> changed_dirs;
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyChangeList(ParseChangeList(kTestJson), &changed_dirs));
// The value is written in kTestJson.
EXPECT_EQ(16730, metadata_->GetLargestChangestamp());
@@ -453,7 +472,8 @@
TEST_F(ChangeListProcessorTest, RefreshDirectory) {
// Prepare metadata.
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
// Create a map.
ChangeListProcessor::ResourceEntryMap entry_map;
@@ -499,7 +519,8 @@
TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) {
// Prepare metadata.
- ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
+ EXPECT_EQ(FILE_ERROR_OK,
+ ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
// Create a map and add a new file to it.
ChangeListProcessor::ResourceEntryMap entry_map;
diff --git a/chrome/browser/chromeos/drive/debug_info_collector.cc b/chrome/browser/chromeos/drive/debug_info_collector.cc
index f13263b..f75b6ea 100644
--- a/chrome/browser/chromeos/drive/debug_info_collector.cc
+++ b/chrome/browser/chromeos/drive/debug_info_collector.cc
@@ -6,16 +6,33 @@
#include "base/callback.h"
#include "base/logging.h"
+#include "chrome/browser/google_apis/task_util.h"
#include "content/public/browser/browser_thread.h"
using content::BrowserThread;
namespace drive {
-DebugInfoCollector::DebugInfoCollector(FileSystemInterface* file_system,
- internal::FileCache* file_cache)
+namespace {
+
+void IterateFileCacheInternal(
+ internal::FileCache* file_cache,
+ const DebugInfoCollector::IterateFileCacheCallback& iteration_callback) {
+ scoped_ptr<internal::FileCache::Iterator> it = file_cache->GetIterator();
+ for (; !it->IsAtEnd(); it->Advance())
+ iteration_callback.Run(it->GetID(), it->GetValue());
+ DCHECK(!it->HasError());
+}
+
+} // namespace
+
+DebugInfoCollector::DebugInfoCollector(
+ FileSystemInterface* file_system,
+ internal::FileCache* file_cache,
+ base::SequencedTaskRunner* blocking_task_runner)
: file_system_(file_system),
- file_cache_(file_cache) {
+ file_cache_(file_cache),
+ blocking_task_runner_(blocking_task_runner) {
DCHECK(file_system_);
DCHECK(file_cache_);
}
@@ -24,13 +41,18 @@
}
void DebugInfoCollector::IterateFileCache(
- const CacheIterateCallback& iteration_callback,
+ const IterateFileCacheCallback& iteration_callback,
const base::Closure& completion_callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!iteration_callback.is_null());
DCHECK(!completion_callback.is_null());
- file_cache_->IterateOnUIThread(iteration_callback, completion_callback);
+ blocking_task_runner_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&IterateFileCacheInternal,
+ file_cache_,
+ google_apis::CreateRelayCallback(iteration_callback)),
+ completion_callback);
}
void DebugInfoCollector::GetMetadata(
diff --git a/chrome/browser/chromeos/drive/debug_info_collector.h b/chrome/browser/chromeos/drive/debug_info_collector.h
index 1151b09..9b9fcdb 100644
--- a/chrome/browser/chromeos/drive/debug_info_collector.h
+++ b/chrome/browser/chromeos/drive/debug_info_collector.h
@@ -17,14 +17,20 @@
// All the method should be called on UI thread.
class DebugInfoCollector {
public:
+ // Callback for IterateFileCache().
+ typedef base::Callback<void(const std::string& id,
+ const FileCacheEntry& cache_entry)>
+ IterateFileCacheCallback;
+
DebugInfoCollector(FileSystemInterface* file_system,
- internal::FileCache* file_cache);
+ internal::FileCache* file_cache,
+ base::SequencedTaskRunner* blocking_task_runner);
~DebugInfoCollector();
// Iterates all files in the file cache and calls |iteration_callback| for
// each file. |completion_callback| is run upon completion.
// |iteration_callback| and |completion_callback| must not be null.
- void IterateFileCache(const CacheIterateCallback& iteration_callback,
+ void IterateFileCache(const IterateFileCacheCallback& iteration_callback,
const base::Closure& completion_callback);
// Returns miscellaneous metadata of the file system like the largest
@@ -34,6 +40,7 @@
private:
FileSystemInterface* file_system_; // Not owned.
internal::FileCache* file_cache_; // Not owned.
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
DISALLOW_COPY_AND_ASSIGN(DebugInfoCollector);
};
diff --git a/chrome/browser/chromeos/drive/drive.proto b/chrome/browser/chromeos/drive/drive.proto
index 9d51409..bab4224 100644
--- a/chrome/browser/chromeos/drive/drive.proto
+++ b/chrome/browser/chromeos/drive/drive.proto
@@ -75,6 +75,9 @@
// Resource ID of the entry. Guaranteed to be unique.
optional string resource_id = 4;
+ // Local ID of the entry.
+ optional string local_id = 15;
+
// Local ID of the parent entry.
optional string parent_local_id = 7;
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 5479adb..28d2ab0 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -188,7 +188,7 @@
blocking_task_runner_ = blocking_pool->GetSequencedTaskRunner(
blocking_pool->GetSequenceToken());
- OAuth2TokenService* oauth_service =
+ ProfileOAuth2TokenService* oauth_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
if (test_drive_service) {
@@ -239,7 +239,8 @@
cache_root_directory_.Append(kTemporaryFileDirectory)));
download_handler_.reset(new DownloadHandler(file_system()));
debug_info_collector_.reset(
- new DebugInfoCollector(file_system(), cache_.get()));
+ new DebugInfoCollector(file_system(), cache_.get(),
+ blocking_task_runner_.get()));
if (preference_watcher) {
preference_watcher_.reset(preference_watcher);
@@ -421,7 +422,6 @@
DCHECK(enabled_);
state_ = INITIALIZING;
- drive_service_->Initialize();
base::PostTaskAndReplyWithResult(
blocking_task_runner_.get(),
@@ -441,6 +441,10 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK_EQ(INITIALIZING, state_);
+ drive_service_->Initialize(
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->
+ GetPrimaryAccountId());
+
if (error != FILE_ERROR_OK) {
LOG(WARNING) << "Failed to initialize: " << FileErrorToString(error);
diff --git a/chrome/browser/chromeos/drive/dummy_file_system.h b/chrome/browser/chromeos/drive/dummy_file_system.h
index 266c355..5d7962a 100644
--- a/chrome/browser/chromeos/drive/dummy_file_system.h
+++ b/chrome/browser/chromeos/drive/dummy_file_system.h
@@ -26,9 +26,11 @@
const OpenFileCallback& callback) OVERRIDE {}
virtual void Copy(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) OVERRIDE {}
virtual void Move(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) OVERRIDE {}
virtual void Remove(const base::FilePath& file_path,
bool is_recursive,
diff --git a/chrome/browser/chromeos/drive/fake_file_system.cc b/chrome/browser/chromeos/drive/fake_file_system.cc
index 427c669..44cae0e 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.cc
+++ b/chrome/browser/chromeos/drive/fake_file_system.cc
@@ -62,12 +62,14 @@
void FakeFileSystem::Copy(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
void FakeFileSystem::Move(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
diff --git a/chrome/browser/chromeos/drive/fake_file_system.h b/chrome/browser/chromeos/drive/fake_file_system.h
index bda1673..bb81c47 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.h
+++ b/chrome/browser/chromeos/drive/fake_file_system.h
@@ -56,9 +56,11 @@
const OpenFileCallback& callback) OVERRIDE;
virtual void Copy(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) OVERRIDE;
virtual void Move(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) OVERRIDE;
virtual void Remove(const base::FilePath& file_path,
bool is_recursive,
diff --git a/chrome/browser/chromeos/drive/file_cache.cc b/chrome/browser/chromeos/drive/file_cache.cc
index 98e8807..148d716 100644
--- a/chrome/browser/chromeos/drive/file_cache.cc
+++ b/chrome/browser/chromeos/drive/file_cache.cc
@@ -16,7 +16,6 @@
#include "chrome/browser/chromeos/drive/drive.pb.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,15 +79,6 @@
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(ResourceMetadataStorage* storage,
@@ -147,21 +137,6 @@
return storage_->GetCacheEntry(id, entry);
}
-void FileCache::IterateOnUIThread(
- const CacheIterateCallback& iteration_callback,
- const base::Closure& completion_callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!iteration_callback.is_null());
- DCHECK(!completion_callback.is_null());
-
- blocking_task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&IterateCache,
- base::Unretained(this),
- google_apis::CreateRelayCallback(iteration_callback)),
- completion_callback);
-}
-
scoped_ptr<FileCache::Iterator> FileCache::GetIterator() {
AssertOnSequencedWorkerPool();
return storage_->GetCacheEntryIterator();
@@ -205,23 +180,6 @@
return HasEnoughSpaceFor(num_bytes, cache_file_directory_);
}
-void FileCache::GetFileOnUIThread(const std::string& id,
- const GetFileFromCacheCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!callback.is_null());
-
- base::FilePath* cache_file_path = new base::FilePath;
- base::PostTaskAndReplyWithResult(blocking_task_runner_.get(),
- FROM_HERE,
- base::Bind(&FileCache::GetFile,
- base::Unretained(this),
- id,
- cache_file_path),
- base::Bind(&RunGetFileFromCacheCallback,
- callback,
- base::Owned(cache_file_path)));
-}
-
FileError FileCache::GetFile(const std::string& id,
base::FilePath* cache_file_path) {
AssertOnSequencedWorkerPool();
diff --git a/chrome/browser/chromeos/drive/file_cache.h b/chrome/browser/chromeos/drive/file_cache.h
index e0822ac..2084ee3 100644
--- a/chrome/browser/chromeos/drive/file_cache.h
+++ b/chrome/browser/chromeos/drive/file_cache.h
@@ -32,11 +32,6 @@
typedef base::Callback<void(bool success, const FileCacheEntry& cache_entry)>
GetCacheEntryCallback;
-// Callback for Iterate().
-typedef base::Callback<void(const std::string& id,
- const FileCacheEntry& cache_entry)>
- CacheIterateCallback;
-
namespace internal {
// Callback for GetFileFromCache.
@@ -98,12 +93,6 @@
// See also GetCacheEntryOnUIThread().
bool GetCacheEntry(const std::string& id, FileCacheEntry* entry);
- // Runs Iterate() with |iteration_callback| on |blocking_task_runner_| and
- // runs |completion_callback| upon completion.
- // Must be called on UI thread.
- void IterateOnUIThread(const CacheIterateCallback& iteration_callback,
- const base::Closure& completion_callback);
-
// Returns an object to iterate over entries.
scoped_ptr<Iterator> GetIterator();
@@ -113,13 +102,6 @@
// false.
bool FreeDiskSpaceIfNeededFor(int64 num_bytes);
- // Runs GetFile() on |blocking_task_runner_|, and calls |callback| with
- // the result asynchronously.
- // |callback| must not be null.
- // Must be called on the UI thread.
- void GetFileOnUIThread(const std::string& id,
- const GetFileFromCacheCallback& callback);
-
// Checks if file corresponding to |id| exists in cache, and returns
// FILE_ERROR_OK with |cache_file_path| storing the path to the file.
// |cache_file_path| must not be null.
diff --git a/chrome/browser/chromeos/drive/file_cache_unittest.cc b/chrome/browser/chromeos/drive/file_cache_unittest.cc
index 3b82ce1..d0f7d17 100644
--- a/chrome/browser/chromeos/drive/file_cache_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_cache_unittest.cc
@@ -38,20 +38,6 @@
TEST_CACHE_STATE_DIRTY = 1 << 2,
};
-// Copies results from Iterate().
-void OnIterate(std::vector<std::string>* out_ids,
- std::vector<FileCacheEntry>* out_cache_entries,
- const std::string& id,
- const FileCacheEntry& cache_entry) {
- out_ids->push_back(id);
- out_cache_entries->push_back(cache_entry);
-}
-
-// Called upon completion of Iterate().
-void OnIterateCompleted(bool* out_is_called) {
- *out_is_called = true;
-}
-
} // namespace
// Tests FileCache methods from UI thread. It internally uses a real blocking
@@ -111,24 +97,6 @@
ASSERT_TRUE(success);
}
- void TestGetFile(const std::string& id, FileError expected_error) {
- FileError error = FILE_ERROR_OK;
- base::FilePath cache_file_path;
- cache_->GetFileOnUIThread(id,
- google_apis::test_util::CreateCopyResultCallback(
- &error, &cache_file_path));
- test_util::RunBlockingPoolTask();
-
- EXPECT_EQ(expected_error, error);
- if (error == FILE_ERROR_OK) {
- // Verify filename of |cache_file_path|.
- EXPECT_EQ(util::EscapeCacheFileName(id),
- cache_file_path.BaseName().AsUTF8Unsafe());
- } else {
- EXPECT_TRUE(cache_file_path.empty());
- }
- }
-
void TestStoreToCache(const std::string& id,
const std::string& md5,
const base::FilePath& source_path,
@@ -221,10 +189,13 @@
// Verify filename.
if (error == FILE_ERROR_OK) {
base::FilePath cache_file_path;
- cache_->GetFileOnUIThread(
- id,
- google_apis::test_util::CreateCopyResultCallback(
- &error, &cache_file_path));
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_,
+ FROM_HERE,
+ base::Bind(&FileCache::GetFile,
+ base::Unretained(cache_.get()),
+ id, &cache_file_path),
+ google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -295,10 +266,13 @@
test_util::RunBlockingPoolTask();
base::FilePath cache_file_path;
- cache_->GetFileOnUIThread(
- id,
- google_apis::test_util::CreateCopyResultCallback(
- &error, &cache_file_path));
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_,
+ FROM_HERE,
+ base::Bind(&FileCache::GetFile,
+ base::Unretained(cache_.get()),
+ id, &cache_file_path),
+ google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -407,22 +381,6 @@
EXPECT_EQ(1U, CountCacheFiles(id, md5));
}
-
-TEST_F(FileCacheTestOnUIThread, GetFromCacheSimple) {
- std::string id("pdf:1a2b");
- std::string md5("abcdef0123456789");
- // First store a file to cache.
- TestStoreToCache(id, md5, dummy_file_path_,
- FILE_ERROR_OK, TEST_CACHE_STATE_PRESENT);
-
- // Then try to get the existing file from cache.
- TestGetFile(id, FILE_ERROR_OK);
-
- // Get file from cache with different ID.
- id = "document:1a2b";
- TestGetFile(id, FILE_ERROR_NOT_FOUND);
-}
-
TEST_F(FileCacheTestOnUIThread, RemoveFromCacheSimple) {
std::string id("pdf:1a2b");
std::string md5("abcdef0123456789");
@@ -494,24 +452,6 @@
TEST_CACHE_STATE_PRESENT | TEST_CACHE_STATE_PINNED);
}
-TEST_F(FileCacheTestOnUIThread, GetFromCachePinned) {
- std::string id("pdf:1a2b");
- std::string md5("abcdef0123456789");
-
- // Pin a non-existent file.
- TestPin(id, FILE_ERROR_OK, TEST_CACHE_STATE_PINNED);
-
- // Get the non-existent pinned file from cache.
- TestGetFile(id, FILE_ERROR_NOT_FOUND);
-
- // Store an existing file to the previously pinned non-existent file.
- TestStoreToCache(id, md5, dummy_file_path_, FILE_ERROR_OK,
- TEST_CACHE_STATE_PRESENT | TEST_CACHE_STATE_PINNED);
-
- // Get the previously pinned and stored file from cache.
- TestGetFile(id, FILE_ERROR_OK);
-}
-
TEST_F(FileCacheTestOnUIThread, RemoveFromCachePinned) {
std::string id("pdf:1a2b");
std::string md5("abcdef0123456789");
@@ -587,9 +527,13 @@
// Verifies dirty file exists.
base::FilePath dirty_path;
FileError error = FILE_ERROR_FAILED;
- cache_->GetFileOnUIThread(
- id,
- google_apis::test_util::CreateCopyResultCallback(&error, &dirty_path));
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_,
+ FROM_HERE,
+ base::Bind(&FileCache::GetFile,
+ base::Unretained(cache_.get()),
+ id, &dirty_path),
+ google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
EXPECT_TRUE(base::PathExists(dirty_path));
@@ -701,9 +645,13 @@
// Clear mounted state of the file.
base::FilePath file_path;
FileError error = FILE_ERROR_FAILED;
- cache_->GetFileOnUIThread(
- id,
- google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_,
+ FROM_HERE,
+ base::Bind(&FileCache::GetFile,
+ base::Unretained(cache_.get()),
+ id, &file_path),
+ google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -714,34 +662,6 @@
TestRemoveFromCache(id, FILE_ERROR_OK);
}
-TEST_F(FileCacheTestOnUIThread, Iterate) {
- const std::vector<test_util::TestCacheResource> cache_resources(
- test_util::GetDefaultTestCacheResources());
- ASSERT_TRUE(test_util::PrepareTestCacheResources(cache_.get(),
- cache_resources));
-
- std::vector<std::string> ids;
- std::vector<FileCacheEntry> cache_entries;
- bool completed = false;
- cache_->IterateOnUIThread(
- base::Bind(&OnIterate, &ids, &cache_entries),
- base::Bind(&OnIterateCompleted, &completed));
- test_util::RunBlockingPoolTask();
-
- ASSERT_TRUE(completed);
-
- sort(ids.begin(), ids.end());
- ASSERT_EQ(6U, ids.size());
- EXPECT_EQ("dirty:existing", ids[0]);
- EXPECT_EQ("dirty_and_pinned:existing", ids[1]);
- EXPECT_EQ("pinned:existing", ids[2]);
- EXPECT_EQ("pinned:non-existent", ids[3]);
- EXPECT_EQ("tmp:`~!@#$%^&*()-_=+[{|]}\\;',<.>/?", ids[4]);
- EXPECT_EQ("tmp:resource_id", ids[5]);
-
- ASSERT_EQ(6U, cache_entries.size());
-}
-
TEST_F(FileCacheTestOnUIThread, StoreToCacheNoSpace) {
fake_free_disk_space_getter_->set_default_value(0);
@@ -845,6 +765,31 @@
EXPECT_EQ(base::MD5String("foo"), cache_entry.md5());
}
+TEST_F(FileCacheTest, Iterator) {
+ base::FilePath src_file;
+ ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &src_file));
+
+ // Prepare entries.
+ std::map<std::string, std::string> md5s;
+ md5s["id1"] = "md5-1";
+ md5s["id2"] = "md5-2";
+ md5s["id3"] = "md5-3";
+ md5s["id4"] = "md5-4";
+ for (std::map<std::string, std::string>::iterator it = md5s.begin();
+ it != md5s.end(); ++it) {
+ EXPECT_EQ(FILE_ERROR_OK, cache_->Store(
+ it->first, it->second, src_file, FileCache::FILE_OPERATION_COPY));
+ }
+
+ // Iterate.
+ std::map<std::string, std::string> result;
+ scoped_ptr<FileCache::Iterator> it = cache_->GetIterator();
+ for (; !it->IsAtEnd(); it->Advance())
+ result[it->GetID()] = it->GetValue().md5();
+ EXPECT_EQ(md5s, result);
+ EXPECT_FALSE(it->HasError());
+}
+
TEST_F(FileCacheTest, FreeDiskSpaceIfNeededFor) {
base::FilePath src_file;
ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &src_file));
@@ -885,6 +830,54 @@
EXPECT_FALSE(cache_->FreeDiskSpaceIfNeededFor(kNeededBytes));
}
+TEST_F(FileCacheTest, GetFile) {
+ const base::FilePath src_file_path = temp_dir_.path().Append("test.dat");
+ const std::string src_contents = "test";
+ EXPECT_TRUE(google_apis::test_util::WriteStringToFile(src_file_path,
+ src_contents));
+ std::string id("id1");
+ std::string md5(base::MD5String(src_contents));
+
+ const base::FilePath cache_file_directory =
+ temp_dir_.path().AppendASCII(kCacheFileDirectory);
+
+ // Try to get an existing file from cache.
+ EXPECT_EQ(FILE_ERROR_OK, cache_->Store(id, md5, src_file_path,
+ FileCache::FILE_OPERATION_COPY));
+ base::FilePath cache_file_path;
+ EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(id, &cache_file_path));
+ EXPECT_EQ(
+ cache_file_directory.AppendASCII(util::EscapeCacheFileName(id)).value(),
+ cache_file_path.value());
+
+ std::string contents;
+ EXPECT_TRUE(base::ReadFileToString(cache_file_path, &contents));
+ EXPECT_EQ(src_contents, contents);
+
+ // Get file from cache with different id.
+ id = "id2";
+ EXPECT_EQ(FILE_ERROR_NOT_FOUND, cache_->GetFile(id, &cache_file_path));
+
+ // Pin a non-existent file.
+ EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(id));
+
+ // Get the non-existent pinned file from cache.
+ EXPECT_EQ(FILE_ERROR_NOT_FOUND, cache_->GetFile(id, &cache_file_path));
+
+ // Get a previously pinned and stored file from cache.
+ EXPECT_EQ(FILE_ERROR_OK, cache_->Store(id, md5, src_file_path,
+ FileCache::FILE_OPERATION_COPY));
+
+ EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(id, &cache_file_path));
+ EXPECT_EQ(
+ cache_file_directory.AppendASCII(util::EscapeCacheFileName(id)).value(),
+ cache_file_path.value());
+
+ contents.clear();
+ EXPECT_TRUE(base::ReadFileToString(cache_file_path, &contents));
+ EXPECT_EQ(src_contents, contents);
+}
+
TEST_F(FileCacheTest, CanonicalizeIDs) {
ResourceIdCanonicalizer id_canonicalizer = base::Bind(
(ResourceIdCanonicalizer::RunType*)(&StringToUpperASCII));
diff --git a/chrome/browser/chromeos/drive/file_system.cc b/chrome/browser/chromeos/drive/file_system.cc
index 6635f7a..0162221 100644
--- a/chrome/browser/chromeos/drive/file_system.cc
+++ b/chrome/browser/chromeos/drive/file_system.cc
@@ -426,18 +426,22 @@
void FileSystem::Copy(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
- copy_operation_->Copy(src_file_path, dest_file_path, callback);
+ copy_operation_->Copy(
+ src_file_path, dest_file_path, preserve_last_modified, callback);
}
void FileSystem::Move(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
- move_operation_->Move(src_file_path, dest_file_path, callback);
+ move_operation_->Move(
+ src_file_path, dest_file_path, preserve_last_modified, callback);
}
void FileSystem::Remove(const base::FilePath& file_path,
diff --git a/chrome/browser/chromeos/drive/file_system.h b/chrome/browser/chromeos/drive/file_system.h
index 4a4e631..07e4479 100644
--- a/chrome/browser/chromeos/drive/file_system.h
+++ b/chrome/browser/chromeos/drive/file_system.h
@@ -91,9 +91,11 @@
const OpenFileCallback& callback) OVERRIDE;
virtual void Copy(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) OVERRIDE;
virtual void Move(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) OVERRIDE;
virtual void Remove(const base::FilePath& file_path,
bool is_recursive,
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation.cc b/chrome/browser/chromeos/drive/file_system/copy_operation.cc
index da50aba..0f0899a 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation.cc
@@ -151,6 +151,13 @@
} // namespace
+struct CopyOperation::CopyParams {
+ base::FilePath src_file_path;
+ base::FilePath dest_file_path;
+ bool preserve_last_modified;
+ FileOperationCallback callback;
+};
+
CopyOperation::CopyOperation(base::SequencedTaskRunner* blocking_task_runner,
OperationObserver* observer,
JobScheduler* scheduler,
@@ -189,10 +196,17 @@
void CopyOperation::Copy(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
+ CopyParams params;
+ params.src_file_path = src_file_path;
+ params.dest_file_path = dest_file_path;
+ params.preserve_last_modified = preserve_last_modified;
+ params.callback = callback;
+
ResourceEntry* src_entry = new ResourceEntry;
std::string* parent_resource_id = new std::string;
base::PostTaskAndReplyWithResult(
@@ -202,38 +216,40 @@
metadata_, src_file_path, dest_file_path,
src_entry, parent_resource_id),
base::Bind(&CopyOperation::CopyAfterPrepare,
- weak_ptr_factory_.GetWeakPtr(),
- src_file_path, dest_file_path, callback,
+ weak_ptr_factory_.GetWeakPtr(), params,
base::Owned(src_entry), base::Owned(parent_resource_id)));
}
void CopyOperation::CopyAfterPrepare(
- const base::FilePath& src_file_path,
- const base::FilePath& dest_file_path,
- const FileOperationCallback& callback,
+ const CopyParams& params,
ResourceEntry* src_entry,
std::string* parent_resource_id,
FileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!callback.is_null());
+ DCHECK(!params.callback.is_null());
if (error != FILE_ERROR_OK) {
- callback.Run(error);
+ params.callback.Run(error);
return;
}
// If Drive API v2 is enabled, we can copy resources on server side.
if (util::IsDriveV2ApiEnabled()) {
- base::FilePath new_title = dest_file_path.BaseName();
+ base::FilePath new_title = params.dest_file_path.BaseName();
if (src_entry->file_specific_info().is_hosted_document()) {
// Drop the document extension, which should not be in the title.
// TODO(yoshiki): Remove this code with crbug.com/223304.
new_title = new_title.RemoveExtension();
}
+ base::Time last_modified =
+ params.preserve_last_modified ?
+ base::Time::FromInternalValue(src_entry->file_info().last_modified()) :
+ base::Time();
+
CopyResourceOnServer(
src_entry->resource_id(), *parent_resource_id,
- new_title.AsUTF8Unsafe(), callback);
+ new_title.AsUTF8Unsafe(), last_modified, params.callback);
return;
}
@@ -244,20 +260,21 @@
src_entry->resource_id(),
// Drop the document extension, which should not be in the title.
// TODO(yoshiki): Remove this code with crbug.com/223304.
- dest_file_path.RemoveExtension(),
- callback);
+ params.dest_file_path.RemoveExtension(),
+ params.callback);
return;
}
// For regular files, download the content, and then re-upload.
// Note that upload is done later by SyncClient.
download_operation_->EnsureFileDownloadedByPath(
- src_file_path,
+ params.src_file_path,
ClientContext(USER_INITIATED),
GetFileContentInitializedCallback(),
google_apis::GetContentCallback(),
base::Bind(&CopyOperation::CopyAfterDownload,
- weak_ptr_factory_.GetWeakPtr(), dest_file_path, callback));
+ weak_ptr_factory_.GetWeakPtr(),
+ params.dest_file_path, params.callback));
}
void CopyOperation::CopyAfterDownload(
@@ -337,6 +354,7 @@
// Drop the document extension, which should not be in the title.
// TODO(yoshiki): Remove this code with crbug.com/223304.
remote_dest_path.BaseName().RemoveExtension().AsUTF8Unsafe(),
+ base::Time(),
callback);
return;
}
@@ -354,12 +372,13 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
scheduler_->CopyResource(
- resource_id, parent_resource_id, new_title,
+ resource_id, parent_resource_id, new_title, last_modified,
base::Bind(&CopyOperation::CopyResourceOnServerAfterServerSideCopy,
weak_ptr_factory_.GetWeakPtr(),
callback));
@@ -572,7 +591,7 @@
DCHECK_EQ(util::GetDriveMyDriveRootPath().value(),
file_path->DirName().value()) << file_path->value();
- move_operation_->Move(*file_path, dest_path, callback);
+ move_operation_->Move(*file_path, dest_path, false, callback);
}
} // namespace file_system
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation.h b/chrome/browser/chromeos/drive/file_system/copy_operation.h
index 916940d..a55953c 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation.h
@@ -16,6 +16,7 @@
namespace base {
class FilePath;
class SequencedTaskRunner;
+class Time;
} // namespace base
namespace google_apis {
@@ -54,10 +55,14 @@
~CopyOperation();
// Performs the copy operation on the file at drive path |src_file_path|
- // with a target of |dest_file_path|. Invokes |callback| when finished with
- // the result of the operation. |callback| must not be null.
+ // with a target of |dest_file_path|.
+ // If |preserve_last_modified| is set to true, this tries to preserve
+ // last modified time stamp. This is supported only on Drive API v2.
+ // Invokes |callback| when finished with the result of the operation.
+ // |callback| must not be null.
void Copy(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback);
// Initiates transfer of |local_src_file_path| to |remote_dest_file_path|.
@@ -72,10 +77,11 @@
const FileOperationCallback& callback);
private:
+ // Params for Copy().
+ struct CopyParams;
+
// Part of Copy(). Called after prepartion is done.
- void CopyAfterPrepare(const base::FilePath& src_file_path,
- const base::FilePath& dest_file_path,
- const FileOperationCallback& callback,
+ void CopyAfterPrepare(const CopyParams& params,
ResourceEntry* src_entry,
std::string* parent_resource_id,
FileError error);
@@ -103,6 +109,7 @@
void CopyResourceOnServer(const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const FileOperationCallback& callback);
// Part of CopyResourceOnServer. Called after server side copy is done.
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
index 45e0dff..2afd3ed 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
@@ -162,6 +162,7 @@
FileError error = FILE_ERROR_OK;
operation_->Copy(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
@@ -183,6 +184,7 @@
FileError error = FILE_ERROR_OK;
operation_->Copy(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
@@ -208,6 +210,7 @@
FileError error = FILE_ERROR_OK;
operation_->Copy(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error);
@@ -230,10 +233,38 @@
FileError error = FILE_ERROR_OK;
operation_->Copy(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_NOT_A_FILE, error);
}
+TEST_F(CopyOperationTest, PreserveLastModified) {
+ // Preserve last modified feature is only available on Drive API v2.
+ if (util::IsDriveV2ApiEnabled()) {
+ base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
+ base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/File 2.txt"));
+
+ ResourceEntry entry;
+ ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
+ ASSERT_EQ(FILE_ERROR_OK,
+ GetLocalResourceEntry(dest_path.DirName(), &entry));
+
+ FileError error = FILE_ERROR_OK;
+ operation_->Copy(src_path,
+ dest_path,
+ true, // Preserve last modified.
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+
+ ResourceEntry entry2;
+ EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
+ EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &entry2));
+ EXPECT_EQ(entry.file_info().last_modified(),
+ entry2.file_info().last_modified());
+ }
+}
+
} // namespace file_system
} // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/move_operation.cc b/chrome/browser/chromeos/drive/file_system/move_operation.cc
index a74418e..6d73c6c 100644
--- a/chrome/browser/chromeos/drive/file_system/move_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/move_operation.cc
@@ -41,7 +41,7 @@
return error;
entry.set_title(new_title);
- return metadata->RefreshEntry(resource_id, entry);
+ return metadata->RefreshEntry(entry);
}
// Applies directory-moving to the local metadata.
@@ -55,11 +55,18 @@
// TODO(hidehiko,hashimoto): Set local id, instead of resource id.
entry.set_parent_local_id(parent_resource_id);
- return metadata->RefreshEntry(resource_id, entry);
+ return metadata->RefreshEntry(entry);
}
} // namespace
+struct MoveOperation::MoveParams {
+ base::FilePath src_file_path;
+ base::FilePath dest_file_path;
+ bool preserve_last_modified;
+ FileOperationCallback callback;
+};
+
MoveOperation::MoveOperation(base::SequencedTaskRunner* blocking_task_runner,
OperationObserver* observer,
JobScheduler* scheduler,
@@ -78,10 +85,17 @@
void MoveOperation::Move(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
+ MoveParams params;
+ params.src_file_path = src_file_path;
+ params.dest_file_path = dest_file_path;
+ params.preserve_last_modified = preserve_last_modified;
+ params.callback = callback;
+
scoped_ptr<ResourceEntry> src_entry(new ResourceEntry);
scoped_ptr<ResourceEntry> dest_parent_entry(new ResourceEntry);
ResourceEntry* src_entry_ptr = src_entry.get();
@@ -93,30 +107,27 @@
metadata_, src_file_path, dest_file_path.DirName(),
src_entry_ptr, dest_parent_entry_ptr),
base::Bind(&MoveOperation::MoveAfterPrepare,
- weak_ptr_factory_.GetWeakPtr(),
- src_file_path, dest_file_path, callback,
+ weak_ptr_factory_.GetWeakPtr(), params,
base::Passed(&src_entry),
base::Passed(&dest_parent_entry)));
}
void MoveOperation::MoveAfterPrepare(
- const base::FilePath& src_file_path,
- const base::FilePath& dest_file_path,
- const FileOperationCallback& callback,
+ const MoveParams& params,
scoped_ptr<ResourceEntry> src_entry,
scoped_ptr<ResourceEntry> dest_parent_entry,
FileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!callback.is_null());
+ DCHECK(!params.callback.is_null());
if (error != FILE_ERROR_OK) {
- callback.Run(error);
+ params.callback.Run(error);
return;
}
if (!dest_parent_entry->file_info().is_directory()) {
// The parent of the destination is not a directory.
- callback.Run(FILE_ERROR_NOT_A_DIRECTORY);
+ params.callback.Run(FILE_ERROR_NOT_A_DIRECTORY);
return;
}
@@ -124,21 +135,28 @@
const bool has_hosted_document_extension =
src_entry->has_file_specific_info() &&
src_entry->file_specific_info().is_hosted_document() &&
- dest_file_path.Extension() ==
+ params.dest_file_path.Extension() ==
src_entry->file_specific_info().document_extension();
const std::string new_title =
has_hosted_document_extension ?
- dest_file_path.BaseName().RemoveExtension().AsUTF8Unsafe() :
- dest_file_path.BaseName().AsUTF8Unsafe();
+ params.dest_file_path.BaseName().RemoveExtension().AsUTF8Unsafe() :
+ params.dest_file_path.BaseName().AsUTF8Unsafe();
// If Drive API v2 is enabled, we can move the file on server side by one
// request.
if (util::IsDriveV2ApiEnabled()) {
+ base::Time last_modified =
+ params.preserve_last_modified ?
+ base::Time::FromInternalValue(src_entry->file_info().last_modified()) :
+ base::Time();
+
scheduler_->MoveResource(
- src_entry->resource_id(), dest_parent_entry->resource_id(), new_title,
+ src_entry->resource_id(), dest_parent_entry->resource_id(),
+ new_title, last_modified,
base::Bind(&MoveOperation::MoveAfterMoveResource,
weak_ptr_factory_.GetWeakPtr(),
- src_file_path, dest_file_path, callback));
+ params.src_file_path, params.dest_file_path,
+ params.callback));
return;
}
@@ -146,7 +164,8 @@
Rename(*src_entry_ptr, new_title,
base::Bind(&MoveOperation::MoveAfterRename,
weak_ptr_factory_.GetWeakPtr(),
- src_file_path, dest_file_path, callback,
+ params.src_file_path, params.dest_file_path,
+ params.callback,
base::Passed(&src_entry),
base::Passed(&dest_parent_entry)));
}
@@ -173,13 +192,14 @@
}
// TODO(hashimoto): Resolve local ID before use. crbug.com/260514
+ entry.set_local_id(entry.resource_id());
entry.set_parent_local_id(parent_resource_id);
base::PostTaskAndReplyWithResult(
blocking_task_runner_.get(),
FROM_HERE,
base::Bind(&internal::ResourceMetadata::RefreshEntry,
- base::Unretained(metadata_), entry.resource_id(), entry),
+ base::Unretained(metadata_), entry),
base::Bind(&MoveOperation::MoveAfterRefreshEntry,
weak_ptr_factory_.GetWeakPtr(),
src_file_path, dest_file_path, callback));
diff --git a/chrome/browser/chromeos/drive/file_system/move_operation.h b/chrome/browser/chromeos/drive/file_system/move_operation.h
index 3c43372..cc88600 100644
--- a/chrome/browser/chromeos/drive/file_system/move_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/move_operation.h
@@ -42,17 +42,22 @@
~MoveOperation();
// Performs the move operation on the file at drive path |src_file_path|
- // with a target of |dest_file_path|. Invokes |callback| when finished with
- // the result of the operation. |callback| must not be null.
+ // with a target of |dest_file_path|.
+ // If |preserve_last_modified| is set to true, this tries to preserve
+ // last modified time stamp. This is supported only on Drive API v2.
+ // Invokes |callback| when finished with the result of the operation.
+ // |callback| must not be null.
void Move(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback);
private:
+ // Params of Move().
+ struct MoveParams;
+
// Part of Move(). Called after local metadata look up.
- void MoveAfterPrepare(const base::FilePath& src_file_path,
- const base::FilePath& dest_file_path,
- const FileOperationCallback& callback,
+ void MoveAfterPrepare(const MoveParams& params,
scoped_ptr<ResourceEntry> src_entry,
scoped_ptr<ResourceEntry> dest_parent_entry,
FileError error);
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 0cd4040..328fe14 100644
--- a/chrome/browser/chromeos/drive/file_system/move_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/move_operation_unittest.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/chromeos/drive/file_system/copy_operation.h"
#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
+#include "chrome/browser/drive/drive_api_util.h"
#include "chrome/browser/drive/fake_drive_service.h"
#include "chrome/browser/google_apis/test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -48,6 +49,7 @@
FileError error = FILE_ERROR_FAILED;
operation_->Move(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -73,6 +75,7 @@
FileError error = FILE_ERROR_FAILED;
operation_->Move(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -99,6 +102,7 @@
FileError error = FILE_ERROR_FAILED;
operation_->Move(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -126,6 +130,7 @@
FileError error = FILE_ERROR_FAILED;
operation_->Move(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -153,6 +158,7 @@
FileError error = FILE_ERROR_FAILED;
operation_->Move(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -184,6 +190,7 @@
copy_operation_->Copy(
src_path,
src_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -196,6 +203,7 @@
// Move the copied file.
operation_->Move(copied_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -218,6 +226,7 @@
FileError error = FILE_ERROR_OK;
operation_->Move(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
@@ -234,6 +243,7 @@
FileError error = FILE_ERROR_OK;
operation_->Move(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
@@ -253,6 +263,7 @@
FileError error = FILE_ERROR_OK;
operation_->Move(src_path,
dest_path,
+ false,
google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error);
@@ -262,5 +273,35 @@
EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(dest_path, &entry));
}
+TEST_F(MoveOperationTest, PreserveLastModified) {
+ // Preserve last modified feature is only available on Drive API v2.
+ if (util::IsDriveV2ApiEnabled()) {
+ const base::FilePath src_path(
+ FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
+ const base::FilePath dest_path(
+ FILE_PATH_LITERAL("drive/root/Directory 1/Test.log"));
+
+ ResourceEntry src_entry, dest_entry;
+ ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &src_entry));
+ ASSERT_EQ(FILE_ERROR_NOT_FOUND,
+ GetLocalResourceEntry(dest_path, &dest_entry));
+
+ FileError error = FILE_ERROR_FAILED;
+ operation_->Move(src_path,
+ dest_path,
+ true, // Preserve last modified.
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+
+ EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &dest_entry));
+ EXPECT_EQ(src_entry.resource_id(), dest_entry.resource_id());
+ EXPECT_EQ(src_entry.file_info().last_modified(),
+ dest_entry.file_info().last_modified());
+ EXPECT_EQ(FILE_ERROR_NOT_FOUND,
+ GetLocalResourceEntry(src_path, &src_entry));
+ }
+}
+
} // namespace file_system
} // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/open_file_operation.cc b/chrome/browser/chromeos/drive/file_system/open_file_operation.cc
index 95fedf3..9b54aa8 100644
--- a/chrome/browser/chromeos/drive/file_system/open_file_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/open_file_operation.cc
@@ -126,17 +126,17 @@
FROM_HERE,
base::Bind(&internal::FileCache::MarkDirty,
base::Unretained(cache_),
- entry->resource_id()),
+ entry->local_id()),
base::Bind(&OpenFileOperation::OpenFileAfterMarkDirty,
weak_ptr_factory_.GetWeakPtr(),
local_file_path,
- entry->resource_id(),
+ entry->local_id(),
callback));
}
void OpenFileOperation::OpenFileAfterMarkDirty(
const base::FilePath& local_file_path,
- const std::string& resource_id,
+ const std::string& local_id,
const OpenFileCallback& callback,
FileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -147,20 +147,20 @@
return;
}
- ++open_files_[resource_id];
+ ++open_files_[local_id];
callback.Run(error, local_file_path,
base::Bind(&OpenFileOperation::CloseFile,
- weak_ptr_factory_.GetWeakPtr(), resource_id));
+ weak_ptr_factory_.GetWeakPtr(), local_id));
}
-void OpenFileOperation::CloseFile(const std::string& resource_id) {
+void OpenFileOperation::CloseFile(const std::string& local_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_GT(open_files_[resource_id], 0);
+ DCHECK_GT(open_files_[local_id], 0);
- if (--open_files_[resource_id] == 0) {
+ if (--open_files_[local_id] == 0) {
// All clients closes this file, so notify to upload the file.
- open_files_.erase(resource_id);
- observer_->OnCacheFileUploadNeededByOperation(resource_id);
+ open_files_.erase(local_id);
+ observer_->OnCacheFileUploadNeededByOperation(local_id);
// Clients may have enlarged the file. By FreeDiskpSpaceIfNeededFor(0),
// we try to ensure (0 + the-minimum-safe-margin = 512MB as of now) space.
diff --git a/chrome/browser/chromeos/drive/file_system/open_file_operation.h b/chrome/browser/chromeos/drive/file_system/open_file_operation.h
index 771df3c..4c86e6d 100644
--- a/chrome/browser/chromeos/drive/file_system/open_file_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/open_file_operation.h
@@ -72,12 +72,12 @@
// Part of OpenFile(). Called after marking the cache file dirty.
void OpenFileAfterMarkDirty(const base::FilePath& local_file_path,
- const std::string& resource_id,
+ const std::string& local_id,
const OpenFileCallback& callback,
FileError error);
- // Closes the file with |resource_id|.
- void CloseFile(const std::string& resource_id);
+ // Closes the file with |local_id|.
+ void CloseFile(const std::string& local_id);
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
OperationObserver* observer_;
@@ -86,7 +86,7 @@
scoped_ptr<CreateFileOperation> create_file_operation_;
scoped_ptr<DownloadOperation> download_operation_;
- // The map from resource id for an opened file to the number how many times
+ // The map from local id for an opened file to the number how many times
// the file is opened.
std::map<std::string, int> open_files_;
diff --git a/chrome/browser/chromeos/drive/file_system/open_file_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/open_file_operation_unittest.cc
index 6770af5..3a7eba4 100644
--- a/chrome/browser/chromeos/drive/file_system/open_file_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/open_file_operation_unittest.cc
@@ -59,7 +59,7 @@
close_callback.Run();
EXPECT_EQ(
1U,
- observer()->upload_needed_local_ids().count(src_entry.resource_id()));
+ observer()->upload_needed_local_ids().count(src_entry.local_id()));
}
TEST_F(OpenFileOperationTest, OpenNonExistingFile) {
@@ -127,9 +127,9 @@
ASSERT_FALSE(close_callback.is_null());
close_callback.Run();
- // Here we don't know about the resource id, so just make sure
- // OnCacheFileUploadNeededByOperation is called actually.
- EXPECT_EQ(1U, observer()->upload_needed_local_ids().size());
+ EXPECT_EQ(
+ 1U,
+ observer()->upload_needed_local_ids().count(GetLocalId(file_in_root)));
}
TEST_F(OpenFileOperationTest, OpenOrCreateExistingFile) {
@@ -164,12 +164,12 @@
close_callback.Run();
EXPECT_EQ(
1U,
- observer()->upload_needed_local_ids().count(src_entry.resource_id()));
+ observer()->upload_needed_local_ids().count(src_entry.local_id()));
bool success = false;
FileCacheEntry cache_entry;
cache()->GetCacheEntryOnUIThread(
- src_entry.resource_id(),
+ src_entry.local_id(),
google_apis::test_util::CreateCopyResultCallback(&success, &cache_entry));
test_util::RunBlockingPoolTask();
EXPECT_TRUE(success);
@@ -200,9 +200,9 @@
ASSERT_FALSE(close_callback.is_null());
close_callback.Run();
- // Here we don't know about the resource id, so just make sure
- // OnCacheFileUploadNeededByOperation is called actually.
- EXPECT_EQ(1U, observer()->upload_needed_local_ids().size());
+ EXPECT_EQ(
+ 1U,
+ observer()->upload_needed_local_ids().count(GetLocalId(file_in_root)));
}
TEST_F(OpenFileOperationTest, OpenFileTwice) {
@@ -259,7 +259,7 @@
// Here, all the clients close the file, so it should be uploaded then.
EXPECT_EQ(
1U,
- observer()->upload_needed_local_ids().count(src_entry.resource_id()));
+ observer()->upload_needed_local_ids().count(src_entry.local_id()));
}
} // namespace file_system
diff --git a/chrome/browser/chromeos/drive/file_system/remove_operation.cc b/chrome/browser/chromeos/drive/file_system/remove_operation.cc
index c1a0c58..f8073f2 100644
--- a/chrome/browser/chromeos/drive/file_system/remove_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/remove_operation.cc
@@ -20,9 +20,14 @@
namespace {
// Checks local metadata state before requesting remote delete.
+// |parent_resource_id| is set to the resource ID of the parent directory of
+// |path|. If it is a special folder like drive/other, empty string is set.
+// |local_id| is set to the local ID of the entry located at |path|.
+// |entry| is the resource entry for the |path|.
FileError CheckLocalState(internal::ResourceMetadata* metadata,
const base::FilePath& path,
bool is_recursive,
+ std::string* parent_resource_id,
std::string* local_id,
ResourceEntry* entry) {
FileError error = metadata->GetIdByPath(path, local_id);
@@ -43,14 +48,27 @@
return FILE_ERROR_NOT_EMPTY;
}
+ // Get the resource_id of the parent folder. If it is a special folder that
+ // does not have the server side ID, returns an empty string (not an error).
+ if (util::IsSpecialResourceId(entry->parent_local_id())) {
+ *parent_resource_id = "";
+ } else {
+ ResourceEntry parent_entry;
+ error = metadata->GetResourceEntryById(entry->parent_local_id(),
+ &parent_entry);
+ if (error != FILE_ERROR_OK)
+ return error;
+ *parent_resource_id = parent_entry.resource_id();
+ }
+
return FILE_ERROR_OK;
}
// Updates local metadata and cache state after remote delete.
-FileError UpdateLocalState(internal::ResourceMetadata* metadata,
- internal::FileCache* cache,
- const std::string& local_id,
- base::FilePath* changed_directory_path) {
+FileError UpdateLocalStateAfterDelete(internal::ResourceMetadata* metadata,
+ internal::FileCache* cache,
+ const std::string& local_id,
+ base::FilePath* changed_directory_path) {
*changed_directory_path = metadata->GetFilePath(local_id).DirName();
FileError error = metadata->RemoveEntry(local_id);
if (error != FILE_ERROR_OK)
@@ -62,6 +80,21 @@
return FILE_ERROR_OK;
}
+// Updates local metadata and after remote unparenting.
+FileError UpdateLocalStateAfterUnparent(
+ internal::ResourceMetadata* metadata,
+ const std::string& local_id,
+ base::FilePath* changed_directory_path) {
+ *changed_directory_path = metadata->GetFilePath(local_id).DirName();
+
+ ResourceEntry entry;
+ FileError error = metadata->GetResourceEntryById(local_id, &entry);
+ if (error != FILE_ERROR_OK)
+ return error;
+ entry.set_parent_local_id(util::kDriveOtherDirSpecialResourceId);
+ return metadata->RefreshEntry(entry);
+}
+
} // namespace
RemoveOperation::RemoveOperation(
@@ -89,6 +122,7 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
+ std::string* parent_resource_id = new std::string;
std::string* local_id = new std::string;
ResourceEntry* entry = new ResourceEntry;
base::PostTaskAndReplyWithResult(
@@ -98,17 +132,20 @@
metadata_,
path,
is_recursive,
+ parent_resource_id,
local_id,
entry),
base::Bind(&RemoveOperation::RemoveAfterCheckLocalState,
weak_ptr_factory_.GetWeakPtr(),
callback,
+ base::Owned(parent_resource_id),
base::Owned(local_id),
base::Owned(entry)));
}
void RemoveOperation::RemoveAfterCheckLocalState(
const FileOperationCallback& callback,
+ const std::string* parent_resource_id,
const std::string* local_id,
const ResourceEntry* entry,
FileError error) {
@@ -120,17 +157,40 @@
return;
}
- scheduler_->DeleteResource(
- entry->resource_id(),
- base::Bind(&RemoveOperation::RemoveAfterDeleteResource,
- weak_ptr_factory_.GetWeakPtr(),
- callback,
- *local_id));
+ // To match with the behavior of drive.google.com:
+ // Removal of shared entries under MyDrive is just removing from the parent.
+ // The entry will stay in shared-with-me (in other words, in "drive/other".)
+ //
+ // TODO(kinaba): to be more precise, we might be better to branch by whether
+ // or not the current account is an owner of the file. The code below is
+ // written under the assumption that |shared_with_me| coincides with that.
+ if (entry->shared_with_me() && !parent_resource_id->empty()) {
+ scheduler_->RemoveResourceFromDirectory(
+ *parent_resource_id,
+ entry->resource_id(),
+ base::Bind(&RemoveOperation::RemoveAfterUpdateRemoteState,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ base::Bind(&UpdateLocalStateAfterUnparent,
+ metadata_,
+ *local_id)));
+ } else {
+ // Otherwise try sending the entry to trash.
+ scheduler_->DeleteResource(
+ entry->resource_id(),
+ base::Bind(&RemoveOperation::RemoveAfterUpdateRemoteState,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ base::Bind(&UpdateLocalStateAfterDelete,
+ metadata_,
+ cache_,
+ *local_id)));
+ }
}
-void RemoveOperation::RemoveAfterDeleteResource(
+void RemoveOperation::RemoveAfterUpdateRemoteState(
const FileOperationCallback& callback,
- const std::string& local_id,
+ const base::Callback<FileError(base::FilePath*)>& local_update_task,
google_apis::GDataErrorCode status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
@@ -145,11 +205,7 @@
base::PostTaskAndReplyWithResult(
blocking_task_runner_.get(),
FROM_HERE,
- base::Bind(&UpdateLocalState,
- metadata_,
- cache_,
- local_id,
- changed_directory_path),
+ base::Bind(local_update_task, changed_directory_path),
base::Bind(&RemoveOperation::RemoveAfterUpdateLocalState,
weak_ptr_factory_.GetWeakPtr(),
callback,
diff --git a/chrome/browser/chromeos/drive/file_system/remove_operation.h b/chrome/browser/chromeos/drive/file_system/remove_operation.h
index 5c606c2..e3468bb 100644
--- a/chrome/browser/chromeos/drive/file_system/remove_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/remove_operation.h
@@ -55,14 +55,16 @@
private:
// Part of Remove(). Called after CheckLocalState() completion.
void RemoveAfterCheckLocalState(const FileOperationCallback& callback,
+ const std::string* parent_resource_id,
const std::string* local_id,
const ResourceEntry* entry,
FileError error);
// Part of Remove(). Called after server-side removal is done.
- void RemoveAfterDeleteResource(const FileOperationCallback& callback,
- const std::string& local_id,
- google_apis::GDataErrorCode status);
+ void RemoveAfterUpdateRemoteState(
+ const FileOperationCallback& callback,
+ const base::Callback<FileError(base::FilePath*)>& local_update_task,
+ google_apis::GDataErrorCode status);
// Part of Remove(). Called after UpdateLocalState() completion.
void RemoveAfterUpdateLocalState(const FileOperationCallback& callback,
diff --git a/chrome/browser/chromeos/drive/file_system/remove_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/remove_operation_unittest.cc
index 84ab831..8916267 100644
--- a/chrome/browser/chromeos/drive/file_system/remove_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/remove_operation_unittest.cc
@@ -40,6 +40,8 @@
// Remove a file in subdirectory.
error = FILE_ERROR_FAILED;
ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_subdir, &entry));
+ const std::string resource_id = entry.resource_id();
+
operation.Remove(file_in_subdir,
false, // is_recursive
google_apis::test_util::CreateCopyResultCallback(&error));
@@ -48,6 +50,17 @@
EXPECT_EQ(FILE_ERROR_NOT_FOUND,
GetLocalResourceEntry(file_in_subdir, &entry));
+ // Verify the file is indeed removed in the server.
+ google_apis::GDataErrorCode gdata_error = google_apis::GDATA_OTHER_ERROR;
+ scoped_ptr<google_apis::ResourceEntry> gdata_entry;
+ fake_service()->GetResourceEntry(
+ resource_id,
+ google_apis::test_util::CreateCopyResultCallback(&gdata_error,
+ &gdata_entry));
+ test_util::RunBlockingPoolTask();
+ ASSERT_EQ(google_apis::HTTP_SUCCESS, gdata_error);
+ EXPECT_TRUE(gdata_entry->deleted());
+
// Try removing non-existing file.
error = FILE_ERROR_FAILED;
ASSERT_EQ(FILE_ERROR_NOT_FOUND,
@@ -113,5 +126,54 @@
GetLocalResourceEntry(file_in_non_empty_dir, &entry));
}
+TEST_F(RemoveOperationTest, RemoveShared) {
+ RemoveOperation operation(blocking_task_runner(), observer(), scheduler(),
+ metadata(), cache());
+
+ const base::FilePath kPathInMyDrive(FILE_PATH_LITERAL(
+ "drive/root/shared.txt"));
+ const base::FilePath kPathInOther(FILE_PATH_LITERAL(
+ "drive/other/shared.txt"));
+
+ // Prepare a shared file to the root folder.
+ google_apis::GDataErrorCode gdata_error = google_apis::GDATA_OTHER_ERROR;
+ scoped_ptr<google_apis::ResourceEntry> gdata_entry;
+ fake_service()->AddNewFile(
+ "text/plain",
+ "dummy content",
+ fake_service()->GetRootResourceId(),
+ kPathInMyDrive.BaseName().AsUTF8Unsafe(),
+ true, // shared_with_me,
+ google_apis::test_util::CreateCopyResultCallback(&gdata_error,
+ &gdata_entry));
+ test_util::RunBlockingPoolTask();
+ ASSERT_EQ(google_apis::HTTP_CREATED, gdata_error);
+ CheckForUpdates();
+
+ // Remove it. Locally, the file should be moved to drive/other.
+ FileError error = FILE_ERROR_FAILED;
+ ResourceEntry entry;
+ operation.Remove(kPathInMyDrive,
+ false, // is_recursive
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+ EXPECT_EQ(FILE_ERROR_NOT_FOUND,
+ GetLocalResourceEntry(kPathInMyDrive, &entry));
+ EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kPathInOther, &entry));
+
+ // Remotely, the entry should have lost its parent.
+ gdata_error = google_apis::GDATA_OTHER_ERROR;
+ const std::string resource_id = gdata_entry->resource_id();
+ fake_service()->GetResourceEntry(
+ resource_id,
+ google_apis::test_util::CreateCopyResultCallback(&gdata_error,
+ &gdata_entry));
+ test_util::RunBlockingPoolTask();
+ ASSERT_EQ(google_apis::HTTP_SUCCESS, gdata_error);
+ EXPECT_FALSE(gdata_entry->deleted()); // It's not deleted.
+ EXPECT_FALSE(gdata_entry->GetLinkByType(google_apis::Link::LINK_PARENT));
+}
+
} // namespace file_system
} // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/touch_operation.cc b/chrome/browser/chromeos/drive/file_system/touch_operation.cc
index 1ead717..feaa5c0 100644
--- a/chrome/browser/chromeos/drive/file_system/touch_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/touch_operation.cc
@@ -53,9 +53,10 @@
if (error != FILE_ERROR_OK)
return error;
+ entry.set_local_id(local_id);
entry.set_parent_local_id(parent_local_id);
- error = metadata->RefreshEntry(local_id, entry);
+ error = metadata->RefreshEntry(entry);
if (error != FILE_ERROR_OK)
return error;
diff --git a/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc
index 0109d94..af46e53 100644
--- a/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/truncate_operation_unittest.cc
@@ -6,6 +6,7 @@
#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/task_runner_util.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"
@@ -47,9 +48,13 @@
base::FilePath local_path;
error = FILE_ERROR_FAILED;
- cache()->GetFileOnUIThread(
- GetLocalId(file_in_root),
- google_apis::test_util::CreateCopyResultCallback(&error, &local_path));
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner(),
+ FROM_HERE,
+ base::Bind(&internal::FileCache::GetFile,
+ base::Unretained(cache()),
+ GetLocalId(file_in_root), &local_path),
+ google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
ASSERT_EQ(FILE_ERROR_OK, error);
@@ -106,9 +111,13 @@
base::FilePath local_path;
error = FILE_ERROR_FAILED;
- cache()->GetFileOnUIThread(
- GetLocalId(file_in_root),
- google_apis::test_util::CreateCopyResultCallback(&error, &local_path));
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner(),
+ FROM_HERE,
+ base::Bind(&internal::FileCache::GetFile,
+ base::Unretained(cache()),
+ GetLocalId(file_in_root), &local_path),
+ google_apis::test_util::CreateCopyResultCallback(&error));
test_util::RunBlockingPoolTask();
ASSERT_EQ(FILE_ERROR_OK, error);
diff --git a/chrome/browser/chromeos/drive/file_system/update_operation.cc b/chrome/browser/chromeos/drive/file_system/update_operation.cc
index 212ff97..b25ccb6 100644
--- a/chrome/browser/chromeos/drive/file_system/update_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/update_operation.cc
@@ -83,9 +83,10 @@
&parent_local_id);
if (error != FILE_ERROR_OK)
return error;
+ entry.set_local_id(local_id);
entry.set_parent_local_id(parent_local_id);
- error = metadata->RefreshEntry(local_id, entry);
+ error = metadata->RefreshEntry(entry);
if (error != FILE_ERROR_OK)
return error;
diff --git a/chrome/browser/chromeos/drive/file_system_backend_delegate.cc b/chrome/browser/chromeos/drive/file_system_backend_delegate.cc
index 4c4ed96..ee606b6 100644
--- a/chrome/browser/chromeos/drive/file_system_backend_delegate.cc
+++ b/chrome/browser/chromeos/drive/file_system_backend_delegate.cc
@@ -70,7 +70,8 @@
DCHECK_EQ(fileapi::kFileSystemTypeDrive, url.type());
base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
- if (file_path.empty())
+ // Hosted documents don't support stream writer.
+ if (file_path.empty() || util::HasGDocFileExtension(file_path))
return scoped_ptr<fileapi::FileStreamWriter>();
return scoped_ptr<fileapi::FileStreamWriter>(
diff --git a/chrome/browser/chromeos/drive/file_system_interface.h b/chrome/browser/chromeos/drive/file_system_interface.h
index 8bf50a0..59373ee 100644
--- a/chrome/browser/chromeos/drive/file_system_interface.h
+++ b/chrome/browser/chromeos/drive/file_system_interface.h
@@ -203,6 +203,9 @@
// |dest_file_path| is expected to be of the same type of |src_file_path|
// (i.e. if |src_file_path| is a file, |dest_file_path| will be created as
// a file).
+ // If |preserve_last_modified| is set to true, the last modified time will be
+ // preserved. This feature is only supported on Drive API v2 protocol because
+ // GData WAPI doesn't support updating modification time.
//
// This method also has the following assumptions/limitations that may be
// relaxed or addressed later:
@@ -218,6 +221,7 @@
// |callback| must not be null.
virtual void Copy(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) = 0;
// Moves |src_file_path| to |dest_file_path| on the file system.
@@ -225,6 +229,9 @@
// |dest_file_path| is expected to be of the same type of |src_file_path|
// (i.e. if |src_file_path| is a file, |dest_file_path| will be created as
// a file).
+ // If |preserve_last_modified| is set to true, the last modified time will be
+ // preserved. This feature is only supported on Drive API v2 protocol because
+ // GData WAPI doesn't support updating modification time.
//
// This method also has the following assumptions/limitations that may be
// relaxed or addressed later:
@@ -238,6 +245,7 @@
// |callback| must not be null.
virtual void Move(const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
+ bool preserve_last_modified,
const FileOperationCallback& callback) = 0;
// Removes |file_path| from the file system. If |is_recursive| is set and
diff --git a/chrome/browser/chromeos/drive/fileapi_worker.cc b/chrome/browser/chromeos/drive/fileapi_worker.cc
index 7cdab85..eaa5ba1 100644
--- a/chrome/browser/chromeos/drive/fileapi_worker.cc
+++ b/chrome/browser/chromeos/drive/fileapi_worker.cc
@@ -225,7 +225,7 @@
const StatusCallback& callback,
FileSystemInterface* file_system) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- file_system->Copy(src_file_path, dest_file_path,
+ file_system->Copy(src_file_path, dest_file_path, false,
base::Bind(&RunStatusCallbackByFileError, callback));
}
@@ -234,7 +234,7 @@
const StatusCallback& callback,
FileSystemInterface* file_system) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- file_system->Move(src_file_path, dest_file_path,
+ file_system->Move(src_file_path, dest_file_path, false,
base::Bind(&RunStatusCallbackByFileError, callback));
}
diff --git a/chrome/browser/chromeos/drive/job_list.cc b/chrome/browser/chromeos/drive/job_list.cc
index 36bd6b8..1be5965 100644
--- a/chrome/browser/chromeos/drive/job_list.cc
+++ b/chrome/browser/chromeos/drive/job_list.cc
@@ -28,8 +28,6 @@
return "TYPE_GET_REMAINING_CHANGE_LIST";
case TYPE_GET_REMAINING_FILE_LIST:
return "TYPE_GET_REMAINING_FILE_LIST";
- case TYPE_GET_RESOURCE_ENTRY:
- return "TYPE_GET_RESOURCE_ENTRY";
case TYPE_GET_SHARE_URL:
return "TYPE_GET_SHARE_URL";
case TYPE_DELETE_RESOURCE:
@@ -125,7 +123,6 @@
case TYPE_GET_CHANGE_LIST:
case TYPE_GET_REMAINING_CHANGE_LIST:
case TYPE_GET_REMAINING_FILE_LIST:
- case TYPE_GET_RESOURCE_ENTRY:
case TYPE_GET_SHARE_URL:
case TYPE_DELETE_RESOURCE:
case TYPE_COPY_RESOURCE:
diff --git a/chrome/browser/chromeos/drive/job_list.h b/chrome/browser/chromeos/drive/job_list.h
index 1473634..940d2d5 100644
--- a/chrome/browser/chromeos/drive/job_list.h
+++ b/chrome/browser/chromeos/drive/job_list.h
@@ -23,7 +23,6 @@
TYPE_GET_CHANGE_LIST,
TYPE_GET_REMAINING_CHANGE_LIST,
TYPE_GET_REMAINING_FILE_LIST,
- TYPE_GET_RESOURCE_ENTRY,
TYPE_GET_SHARE_URL,
TYPE_DELETE_RESOURCE,
TYPE_COPY_RESOURCE,
diff --git a/chrome/browser/chromeos/drive/job_scheduler.cc b/chrome/browser/chromeos/drive/job_scheduler.cc
index ca44eb9..1f0a599 100644
--- a/chrome/browser/chromeos/drive/job_scheduler.cc
+++ b/chrome/browser/chromeos/drive/job_scheduler.cc
@@ -337,27 +337,6 @@
StartJob(new_job);
}
-void JobScheduler::GetResourceEntry(
- const std::string& resource_id,
- const ClientContext& context,
- const google_apis::GetResourceEntryCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!callback.is_null());
-
- JobEntry* new_job = CreateNewJob(TYPE_GET_RESOURCE_ENTRY);
- new_job->context = context;
- new_job->task = base::Bind(
- &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 = google_apis::CreateErrorRunCallback(callback);
- StartJob(new_job);
-}
-
void JobScheduler::GetShareUrl(
const std::string& resource_id,
const GURL& embed_origin,
@@ -405,6 +384,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
@@ -416,6 +396,7 @@
resource_id,
parent_resource_id,
new_title,
+ last_modified,
base::Bind(&JobScheduler::OnGetResourceEntryJobDone,
weak_ptr_factory_.GetWeakPtr(),
new_job->job_info.job_id,
@@ -449,6 +430,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
@@ -460,6 +442,7 @@
resource_id,
parent_resource_id,
new_title,
+ last_modified,
base::Bind(&JobScheduler::OnGetResourceEntryJobDone,
weak_ptr_factory_.GetWeakPtr(),
new_job->job_info.job_id,
@@ -1111,7 +1094,6 @@
case TYPE_GET_CHANGE_LIST:
case TYPE_GET_REMAINING_CHANGE_LIST:
case TYPE_GET_REMAINING_FILE_LIST:
- case TYPE_GET_RESOURCE_ENTRY:
case TYPE_GET_SHARE_URL:
case TYPE_DELETE_RESOURCE:
case TYPE_COPY_RESOURCE:
diff --git a/chrome/browser/chromeos/drive/job_scheduler.h b/chrome/browser/chromeos/drive/job_scheduler.h
index eae8aed..a58ec15 100644
--- a/chrome/browser/chromeos/drive/job_scheduler.h
+++ b/chrome/browser/chromeos/drive/job_scheduler.h
@@ -103,11 +103,6 @@
const GURL& next_link,
const google_apis::GetResourceListCallback& callback);
- // Adds a GetResourceEntry operation to the queue.
- void GetResourceEntry(const std::string& resource_id,
- const ClientContext& context,
- const google_apis::GetResourceEntryCallback& callback);
-
// Adds a GetShareUrl operation to the queue.
void GetShareUrl(const std::string& resource_id,
const GURL& embed_origin,
@@ -123,6 +118,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback);
// Adds a CopyHostedDocument operation to the queue.
@@ -136,6 +132,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback);
// Adds a RenameResource operation to the queue.
diff --git a/chrome/browser/chromeos/drive/job_scheduler_unittest.cc b/chrome/browser/chromeos/drive/job_scheduler_unittest.cc
index 67586a1..d713d96 100644
--- a/chrome/browser/chromeos/drive/job_scheduler_unittest.cc
+++ b/chrome/browser/chromeos/drive/job_scheduler_unittest.cc
@@ -12,6 +12,7 @@
#include "base/prefs/testing_pref_service.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/strings/stringprintf.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"
@@ -28,12 +29,11 @@
// Dummy value passed for the |expected_file_size| parameter of DownloadFile().
const int64 kDummyDownloadFileSize = 0;
-void CopyResourceIdFromGetResourceEntryCallback(
- std::vector<std::string>* id_list_out,
- const std::string& requested_id,
+void CopyTitleFromGetResourceEntryCallback(
+ std::vector<std::string>* title_list_out,
google_apis::GDataErrorCode error_in,
scoped_ptr<google_apis::ResourceEntry> resource_entry_in) {
- id_list_out->push_back(requested_id);
+ title_list_out->push_back(resource_entry_in->title());
}
class JobListLogger : public JobListObserver {
@@ -326,22 +326,6 @@
ASSERT_TRUE(resource_list);
}
-TEST_F(JobSchedulerTest, GetResourceEntry) {
- ConnectToWifi();
-
- google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
- scoped_ptr<google_apis::ResourceEntry> entry;
-
- scheduler_->GetResourceEntry(
- "file:2_file_resource_id", // resource ID
- ClientContext(USER_INITIATED),
- google_apis::test_util::CreateCopyResultCallback(&error, &entry));
- base::RunLoop().RunUntilIdle();
-
- ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
- ASSERT_TRUE(entry);
-}
-
TEST_F(JobSchedulerTest, GetShareUrl) {
ConnectToWifi();
@@ -382,6 +366,7 @@
"file:2_file_resource_id", // resource ID
"folder:1_folder_resource_id", // parent resource ID
"New Document", // new title
+ base::Time(),
google_apis::test_util::CreateCopyResultCallback(&error, &entry));
base::RunLoop().RunUntilIdle();
@@ -415,6 +400,7 @@
"file:2_file_resource_id", // resource ID
"folder:1_folder_resource_id", // parent resource ID
"New Document", // new title
+ base::Time(),
google_apis::test_util::CreateCopyResultCallback(&error, &entry));
base::RunLoop().RunUntilIdle();
@@ -480,69 +466,79 @@
ASSERT_TRUE(entry);
}
-TEST_F(JobSchedulerTest, GetResourceEntryPriority) {
+TEST_F(JobSchedulerTest, PriorityHandling) {
+ const base::FilePath kDummyFilePath(FILE_PATH_LITERAL("dummy"));
+
// 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",
+ scheduler_->CreateFile(
+ fake_drive_service_->GetRootResourceId(),
+ kDummyFilePath,
+ base::StringPrintf("uninteresting file %d", i),
+ "text/plain",
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");
- std::string resource_4("file:4_file_resource_id");
- std::vector<std::string> resource_ids;
+ std::string title_1("new file 1");
+ std::string title_2("new file 2");
+ std::string title_3("new file 3");
+ std::string title_4("new file 4");
+ std::vector<std::string> titles;
- scheduler_->GetResourceEntry(
- resource_1, // resource ID
+ scheduler_->CreateFile(
+ fake_drive_service_->GetRootResourceId(),
+ kDummyFilePath,
+ title_1,
+ "text/plain",
ClientContext(USER_INITIATED),
- base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
- &resource_ids,
- resource_1));
- scheduler_->GetResourceEntry(
- resource_2, // resource ID
+ base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
+ scheduler_->CreateFile(
+ fake_drive_service_->GetRootResourceId(),
+ kDummyFilePath,
+ title_2,
+ "text/plain",
ClientContext(BACKGROUND),
- base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
- &resource_ids,
- resource_2));
- scheduler_->GetResourceEntry(
- resource_3, // resource ID
+ base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
+ scheduler_->CreateFile(
+ fake_drive_service_->GetRootResourceId(),
+ kDummyFilePath,
+ title_3,
+ "text/plain",
ClientContext(BACKGROUND),
- base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
- &resource_ids,
- resource_3));
- scheduler_->GetResourceEntry(
- resource_4, // resource ID
+ base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
+ scheduler_->CreateFile(
+ fake_drive_service_->GetRootResourceId(),
+ kDummyFilePath,
+ title_4,
+ "text/plain",
ClientContext(USER_INITIATED),
- base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
- &resource_ids,
- resource_4));
+ base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(resource_ids.size(), 4ul);
- 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);
+ ASSERT_EQ(4ul, titles.size());
+ EXPECT_EQ(title_1, titles[0]);
+ EXPECT_EQ(title_4, titles[1]);
+ EXPECT_EQ(title_2, titles[2]);
+ EXPECT_EQ(title_3, titles[3]);
}
-TEST_F(JobSchedulerTest, GetResourceEntryNoConnectionUserInitiated) {
+TEST_F(JobSchedulerTest, NoConnectionUserInitiated) {
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,
+ scheduler_->CreateFile(
+ fake_drive_service_->GetRootResourceId(),
+ base::FilePath(FILE_PATH_LITERAL("dummy")),
+ "title",
+ "text/plain",
ClientContext(USER_INITIATED),
google_apis::test_util::CreateCopyResultCallback(&error, &entry));
base::RunLoop().RunUntilIdle();
@@ -550,15 +546,18 @@
EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error);
}
-TEST_F(JobSchedulerTest, GetResourceEntryNoConnectionBackground) {
+TEST_F(JobSchedulerTest, NoConnectionBackground) {
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,
+ scheduler_->CreateFile(
+ fake_drive_service_->GetRootResourceId(),
+ base::FilePath(FILE_PATH_LITERAL("dummy")),
+ "title",
+ "text/plain",
ClientContext(BACKGROUND),
google_apis::test_util::CreateCopyResultCallback(&error, &entry));
base::RunLoop().RunUntilIdle();
@@ -572,7 +571,7 @@
EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
ASSERT_TRUE(entry);
- EXPECT_EQ(resource_id, entry->resource_id());
+ EXPECT_EQ("title", entry->title());
}
TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) {
diff --git a/chrome/browser/chromeos/drive/resource_metadata.cc b/chrome/browser/chromeos/drive/resource_metadata.cc
index 457eedd..de07b4d 100644
--- a/chrome/browser/chromeos/drive/resource_metadata.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata.cc
@@ -119,19 +119,20 @@
ResourceEntry root;
root.mutable_file_info()->set_is_directory(true);
root.set_resource_id(util::kDriveGrandRootSpecialResourceId);
+ root.set_local_id(util::kDriveGrandRootSpecialResourceId);
root.set_title(util::kDriveGrandRootDirName);
SetBaseNameFromTitle(&root);
- if (!storage_->PutEntry(util::kDriveGrandRootSpecialResourceId, root))
+ if (!storage_->PutEntry(root))
return false;
}
if (!storage_->GetEntry(util::kDriveOtherDirSpecialResourceId, &entry)) {
ResourceEntry other_dir;
other_dir.mutable_file_info()->set_is_directory(true);
other_dir.set_resource_id(util::kDriveOtherDirSpecialResourceId);
+ other_dir.set_local_id(util::kDriveOtherDirSpecialResourceId);
other_dir.set_parent_local_id(util::kDriveGrandRootSpecialResourceId);
other_dir.set_title(util::kDriveOtherDirName);
- if (!PutEntryUnderDirectory(util::kDriveOtherDirSpecialResourceId,
- other_dir))
+ if (!PutEntryUnderDirectory(other_dir))
return false;
}
return true;
@@ -178,8 +179,10 @@
// TODO(hashimoto): Generate local ID here. crbug.com/26051
const std::string local_id = entry.resource_id();
+ ResourceEntry new_entry(entry);
+ new_entry.set_local_id(local_id);
- if (!PutEntryUnderDirectory(local_id, entry))
+ if (!PutEntryUnderDirectory(new_entry))
return FILE_ERROR_FAILED;
*out_id = local_id;
@@ -313,8 +316,7 @@
return FILE_ERROR_OK;
}
-FileError ResourceMetadata::RefreshEntry(const std::string& id,
- const ResourceEntry& entry) {
+FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry) {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
// TODO(hashimoto): Return an error if the operation will result in having
// multiple entries with the same resource ID.
@@ -323,7 +325,7 @@
return FILE_ERROR_NO_LOCAL_SPACE;
ResourceEntry old_entry;
- if (!storage_->GetEntry(id, &old_entry))
+ if (!storage_->GetEntry(entry.local_id(), &old_entry))
return FILE_ERROR_NOT_FOUND;
if (old_entry.parent_local_id().empty() || // Reject root.
@@ -340,7 +342,7 @@
return FILE_ERROR_NOT_A_DIRECTORY;
// Remove from the old parent and add it to the new parent with the new data.
- if (!PutEntryUnderDirectory(id, entry))
+ if (!PutEntryUnderDirectory(entry))
return FILE_ERROR_FAILED;
return FILE_ERROR_OK;
}
@@ -422,9 +424,10 @@
return error;
}
-bool ResourceMetadata::PutEntryUnderDirectory(const std::string& id,
- const ResourceEntry& entry) {
+bool ResourceMetadata::PutEntryUnderDirectory(const ResourceEntry& entry) {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(!entry.local_id().empty());
+ DCHECK(!entry.parent_local_id().empty());
ResourceEntry updated_entry(entry);
@@ -440,7 +443,7 @@
while (true) {
const std::string existing_entry_id =
storage_->GetChild(entry.parent_local_id(), new_base_name);
- if (existing_entry_id.empty() || existing_entry_id == id)
+ if (existing_entry_id.empty() || existing_entry_id == entry.local_id())
break;
base::FilePath new_path =
@@ -454,7 +457,7 @@
updated_entry.set_base_name(new_base_name);
// Add the entry to resource map.
- return storage_->PutEntry(id, updated_entry);
+ return storage_->PutEntry(updated_entry);
}
bool ResourceMetadata::RemoveEntryRecursively(const std::string& id) {
diff --git a/chrome/browser/chromeos/drive/resource_metadata.h b/chrome/browser/chromeos/drive/resource_metadata.h
index c88680e..aa40bed 100644
--- a/chrome/browser/chromeos/drive/resource_metadata.h
+++ b/chrome/browser/chromeos/drive/resource_metadata.h
@@ -103,8 +103,8 @@
FileError ReadDirectoryByPath(const base::FilePath& file_path,
ResourceEntryVector* out_entries);
- // Replaces an existing entry whose ID is |id| with |entry|.
- FileError RefreshEntry(const std::string& id, const ResourceEntry& entry);
+ // Replaces an existing entry with the same local ID as |entry|.
+ FileError RefreshEntry(const ResourceEntry& entry);
// Recursively gets directories under the entry pointed to by |id|.
void GetSubDirectoriesRecursively(const std::string& id,
@@ -143,9 +143,7 @@
// parent if there is. This method will also do name de-duplication to ensure
// that the exposed presentation path does not have naming conflicts. Two
// files with the same name "Foo" will be renamed to "Foo (1)" and "Foo (2)".
- // |id| is used as the ID of the entry.
- bool PutEntryUnderDirectory(const std::string& id,
- const ResourceEntry& entry);
+ bool PutEntryUnderDirectory(const ResourceEntry& entry);
// Removes the entry and its descendants.
bool RemoveEntryRecursively(const std::string& id);
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage.cc b/chrome/browser/chromeos/drive/resource_metadata_storage.cc
index 5b2fa28..418f78c 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage.cc
@@ -405,9 +405,10 @@
return header.largest_changestamp();
}
-bool ResourceMetadataStorage::PutEntry(const std::string& id,
- const ResourceEntry& entry) {
+bool ResourceMetadataStorage::PutEntry(const ResourceEntry& entry) {
base::ThreadRestrictions::AssertIOAllowed();
+
+ const std::string& id = entry.local_id();
DCHECK(!id.empty());
std::string serialized_entry;
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage.h b/chrome/browser/chromeos/drive/resource_metadata_storage.h
index 167f15f..28d79c2 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage.h
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage.h
@@ -36,7 +36,7 @@
public:
// This should be incremented when incompatibility change is made to DB
// format.
- static const int kDBVersion = 8;
+ static const int kDBVersion = 9;
// Object to iterate over entries stored in this storage.
class Iterator {
@@ -126,7 +126,7 @@
int64 GetLargestChangestamp();
// Puts the entry to this storage.
- bool PutEntry(const std::string& id, const ResourceEntry& entry);
+ bool PutEntry(const ResourceEntry& entry);
// Gets an entry stored in this storage.
bool GetEntry(const std::string& id, ResourceEntry* out_entry);
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc b/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc
index 5a7a709..9dbd6dd 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage_unittest.cc
@@ -76,14 +76,14 @@
const std::string name2 = "ABCD";
const std::string name3 = "EFGH";
- ResourceEntry entry1;
-
// key1 not found.
ResourceEntry result;
EXPECT_FALSE(storage_->GetEntry(key1, &result));
// Put entry1.
- EXPECT_TRUE(storage_->PutEntry(key1, entry1));
+ ResourceEntry entry1;
+ entry1.set_local_id(key1);
+ EXPECT_TRUE(storage_->PutEntry(entry1));
// key1 found.
EXPECT_TRUE(storage_->GetEntry(key1, &result));
@@ -93,9 +93,10 @@
// Put entry2 as a child of entry1.
ResourceEntry entry2;
+ entry2.set_local_id(key2);
entry2.set_parent_local_id(key1);
entry2.set_base_name(name2);
- EXPECT_TRUE(storage_->PutEntry(key2, entry2));
+ EXPECT_TRUE(storage_->PutEntry(entry2));
// key2 found.
EXPECT_TRUE(storage_->GetEntry(key2, &result));
@@ -103,9 +104,10 @@
// Put entry3 as a child of entry2.
ResourceEntry entry3;
+ entry3.set_local_id(key3);
entry3.set_parent_local_id(key2);
entry3.set_base_name(name3);
- EXPECT_TRUE(storage_->PutEntry(key3, entry3));
+ EXPECT_TRUE(storage_->PutEntry(entry3));
// key3 found.
EXPECT_TRUE(storage_->GetEntry(key3, &result));
@@ -113,7 +115,7 @@
// Change entry3's parent to entry1.
entry3.set_parent_local_id(key1);
- EXPECT_TRUE(storage_->PutEntry(key3, entry3));
+ EXPECT_TRUE(storage_->PutEntry(entry3));
// entry3 is a child of entry1 now.
EXPECT_TRUE(storage_->GetChild(key2, name3).empty());
@@ -137,8 +139,11 @@
keys.push_back("entry3");
keys.push_back("entry4");
- for (size_t i = 0; i < keys.size(); ++i)
- EXPECT_TRUE(storage_->PutEntry(keys[i], ResourceEntry()));
+ for (size_t i = 0; i < keys.size(); ++i) {
+ ResourceEntry entry;
+ entry.set_local_id(keys[i]);
+ EXPECT_TRUE(storage_->PutEntry(entry));
+ }
// Insert some cache entries.
std::map<std::string, FileCacheEntry> cache_entries;
@@ -221,8 +226,11 @@
EXPECT_TRUE(storage_->PutCacheEntry(it->first, it->second));
// Insert some dummy entries.
- EXPECT_TRUE(storage_->PutEntry("entry1", ResourceEntry()));
- EXPECT_TRUE(storage_->PutEntry("entry2", ResourceEntry()));
+ ResourceEntry entry;
+ entry.set_local_id("entry1");
+ EXPECT_TRUE(storage_->PutEntry(entry));
+ entry.set_local_id("entry2");
+ EXPECT_TRUE(storage_->PutEntry(entry));
// Iterate and check the result.
scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
@@ -259,16 +267,20 @@
children_name_id[4].push_back(std::make_pair("iapetus", "saturn_vii"));
// Put parents.
- for (size_t i = 0; i < arraysize(parents_id); ++i)
- EXPECT_TRUE(storage_->PutEntry(parents_id[i], ResourceEntry()));
+ for (size_t i = 0; i < arraysize(parents_id); ++i) {
+ ResourceEntry entry;
+ entry.set_local_id(parents_id[i]);
+ EXPECT_TRUE(storage_->PutEntry(entry));
+ }
// 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;
+ entry.set_local_id(children_name_id[i][j].second);
entry.set_parent_local_id(parents_id[i]);
entry.set_base_name(children_name_id[i][j].first);
- EXPECT_TRUE(storage_->PutEntry(children_name_id[i][j].second, entry));
+ EXPECT_TRUE(storage_->PutEntry(entry));
}
}
@@ -297,13 +309,15 @@
const std::string child_id1 = "qwerty";
ResourceEntry entry1;
+ entry1.set_local_id(parent_id1);
ResourceEntry entry2;
+ entry2.set_local_id(child_id1);
entry2.set_parent_local_id(parent_id1);
entry2.set_base_name(child_name1);
// Put some data.
- EXPECT_TRUE(storage_->PutEntry(parent_id1, entry1));
- EXPECT_TRUE(storage_->PutEntry(child_id1, entry2));
+ EXPECT_TRUE(storage_->PutEntry(entry1));
+ EXPECT_TRUE(storage_->PutEntry(entry2));
// Close DB and reopen.
storage_.reset(new ResourceMetadataStorage(
@@ -328,7 +342,8 @@
// Put some data.
EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp));
ResourceEntry entry;
- EXPECT_TRUE(storage_->PutEntry(key1, ResourceEntry()));
+ entry.set_local_id(key1);
+ EXPECT_TRUE(storage_->PutEntry(entry));
EXPECT_TRUE(storage_->GetEntry(key1, &entry));
FileCacheEntry cache_entry;
EXPECT_TRUE(storage_->PutCacheEntry(key1, FileCacheEntry()));
@@ -353,7 +368,8 @@
// Put some data.
EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp));
ResourceEntry entry;
- EXPECT_TRUE(storage_->PutEntry(key1, ResourceEntry()));
+ entry.set_local_id(key1);
+ EXPECT_TRUE(storage_->PutEntry(entry));
EXPECT_TRUE(storage_->GetEntry(key1, &entry));
FileCacheEntry cache_entry;
EXPECT_TRUE(storage_->PutCacheEntry(key1, FileCacheEntry()));
@@ -395,14 +411,16 @@
// Put entry with key1.
ResourceEntry entry;
+ entry.set_local_id(key1);
entry.set_base_name(name1);
- EXPECT_TRUE(storage_->PutEntry(key1, entry));
+ EXPECT_TRUE(storage_->PutEntry(entry));
EXPECT_TRUE(CheckValidity());
// Put entry with key2 under key1.
+ entry.set_local_id(key2);
entry.set_parent_local_id(key1);
entry.set_base_name(name2);
- EXPECT_TRUE(storage_->PutEntry(key2, entry));
+ EXPECT_TRUE(storage_->PutEntry(entry));
EXPECT_TRUE(CheckValidity());
RemoveChild(key1, name2);
@@ -417,9 +435,10 @@
EXPECT_FALSE(CheckValidity()); // key3 is not stored in the storage.
// Put entry with key3 under key2.
+ entry.set_local_id(key3);
entry.set_parent_local_id(key2);
entry.set_base_name(name3);
- EXPECT_TRUE(storage_->PutEntry(key3, entry));
+ EXPECT_TRUE(storage_->PutEntry(entry));
EXPECT_TRUE(CheckValidity());
// Parent-child relationship with wrong name.
diff --git a/chrome/browser/chromeos/drive/resource_metadata_unittest.cc b/chrome/browser/chromeos/drive/resource_metadata_unittest.cc
index a33f9f3..93ab5c8 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_unittest.cc
+++ b/chrome/browser/chromeos/drive/resource_metadata_unittest.cc
@@ -394,7 +394,7 @@
ResourceEntry file_entry(entry);
file_entry.set_title("file100");
EXPECT_EQ(FILE_ERROR_OK,
- resource_metadata_->RefreshEntry(file_id, file_entry));
+ resource_metadata_->RefreshEntry(file_entry));
EXPECT_EQ("drive/root/dir1/dir3/file100",
resource_metadata_->GetFilePath(file_id).AsUTF8Unsafe());
@@ -410,7 +410,7 @@
file_entry = entry;
file_entry.mutable_file_specific_info()->set_md5(updated_md5);
EXPECT_EQ(FILE_ERROR_OK,
- resource_metadata_->RefreshEntry(file_id, file_entry));
+ resource_metadata_->RefreshEntry(file_entry));
EXPECT_EQ("drive/root/dir1/dir3/file100",
resource_metadata_->GetFilePath(file_id).AsUTF8Unsafe());
@@ -443,7 +443,7 @@
ResourceEntry dir_entry(entry);
dir_entry.set_title("dir100");
dir_entry.set_parent_local_id("id:dir3");
- EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(dir_id, dir_entry));
+ EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(dir_entry));
EXPECT_EQ("drive/root/dir1/dir3/dir100",
resource_metadata_->GetFilePath(dir_id).AsUTF8Unsafe());
@@ -468,15 +468,16 @@
// Make sure that directory cannot move under a file.
dir_entry.set_parent_local_id(file_id);
EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY,
- resource_metadata_->RefreshEntry(dir_id, dir_entry));
+ resource_metadata_->RefreshEntry(dir_entry));
// Cannot refresh root.
dir_entry.Clear();
dir_entry.set_resource_id(util::kDriveGrandRootSpecialResourceId);
+ dir_entry.set_local_id(util::kDriveGrandRootSpecialResourceId);
dir_entry.set_title("new-root-name");
dir_entry.set_parent_local_id("id:dir1");
- EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, resource_metadata_->RefreshEntry(
- util::kDriveGrandRootSpecialResourceId, dir_entry));
+ EXPECT_EQ(FILE_ERROR_INVALID_OPERATION,
+ resource_metadata_->RefreshEntry(dir_entry));
}
TEST_F(ResourceMetadataTest, GetSubDirectoriesRecursively) {
diff --git a/chrome/browser/chromeos/drive/sync_client.cc b/chrome/browser/chromeos/drive/sync_client.cc
index ce2419a..413bdce 100644
--- a/chrome/browser/chromeos/drive/sync_client.cc
+++ b/chrome/browser/chromeos/drive/sync_client.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/chromeos/drive/file_system/download_operation.h"
#include "chrome/browser/chromeos/drive/file_system/update_operation.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/google_apis/task_util.h"
#include "content/public/browser/browser_thread.h"
using content::BrowserThread;
@@ -41,21 +42,68 @@
// The delay constant is used to delay retrying a sync task on server errors.
const int kLongDelaySeconds = 600;
-// Appends |local_id| to |to_fetch| if the file is pinned but not fetched
-// (not present locally), or to |to_upload| if the file is dirty but not
-// uploaded.
-void CollectBacklog(std::vector<std::string>* to_fetch,
- std::vector<std::string>* to_upload,
- const std::string& local_id,
- const FileCacheEntry& cache_entry) {
+// Iterates cache entries and appends IDs to |to_fetch| if the file is pinned
+// but not fetched (not present locally), or to |to_upload| if the file is dirty
+// but not uploaded.
+void CollectBacklog(FileCache* cache,
+ std::vector<std::string>* to_fetch,
+ std::vector<std::string>* to_upload) {
DCHECK(to_fetch);
DCHECK(to_upload);
- if (cache_entry.is_pinned() && !cache_entry.is_present())
- to_fetch->push_back(local_id);
+ scoped_ptr<FileCache::Iterator> it = cache->GetIterator();
+ for (; !it->IsAtEnd(); it->Advance()) {
+ const FileCacheEntry& cache_entry = it->GetValue();
+ const std::string& local_id = it->GetID();
+ if (cache_entry.is_pinned() && !cache_entry.is_present())
+ to_fetch->push_back(local_id);
- if (cache_entry.is_dirty())
- to_upload->push_back(local_id);
+ if (cache_entry.is_dirty())
+ to_upload->push_back(local_id);
+ }
+ DCHECK(!it->HasError());
+}
+
+// Iterates cache entries and collects IDs of ones with obsolete cache files.
+void CheckExistingPinnedFiles(ResourceMetadata* metadata,
+ FileCache* cache,
+ std::vector<std::string>* local_ids) {
+ scoped_ptr<FileCache::Iterator> it = cache->GetIterator();
+ for (; !it->IsAtEnd(); it->Advance()) {
+ const FileCacheEntry& cache_entry = it->GetValue();
+ const std::string& local_id = it->GetID();
+ if (!cache_entry.is_pinned() || !cache_entry.is_present())
+ continue;
+
+ ResourceEntry entry;
+ FileError error = metadata->GetResourceEntryById(local_id, &entry);
+ if (error != FILE_ERROR_OK) {
+ LOG(WARNING) << "Entry not found: " << local_id;
+ continue;
+ }
+
+ // If MD5s don't match, it indicates the local cache file is stale, unless
+ // the file is dirty (the MD5 is "local"). We should never re-fetch the
+ // file when we have a locally modified version.
+ if (entry.file_specific_info().md5() == cache_entry.md5() ||
+ cache_entry.is_dirty())
+ continue;
+
+ error = cache->Remove(local_id);
+ if (error != FILE_ERROR_OK) {
+ LOG(WARNING) << "Failed to remove cache entry: " << local_id;
+ continue;
+ }
+
+ error = cache->Pin(local_id);
+ if (error != FILE_ERROR_OK) {
+ LOG(WARNING) << "Failed to pin cache entry: " << local_id;
+ continue;
+ }
+
+ local_ids->push_back(local_id);
+ }
+ DCHECK(!it->HasError());
}
} // namespace
@@ -66,7 +114,8 @@
ResourceMetadata* metadata,
FileCache* cache,
const base::FilePath& temporary_file_directory)
- : metadata_(metadata),
+ : blocking_task_runner_(blocking_task_runner),
+ metadata_(metadata),
cache_(cache),
download_operation_(new file_system::DownloadOperation(
blocking_task_runner,
@@ -95,20 +144,28 @@
std::vector<std::string>* to_fetch = new std::vector<std::string>;
std::vector<std::string>* to_upload = new std::vector<std::string>;
- cache_->IterateOnUIThread(base::Bind(&CollectBacklog, to_fetch, to_upload),
- base::Bind(&SyncClient::OnGetLocalIdsOfBacklog,
- weak_ptr_factory_.GetWeakPtr(),
- base::Owned(to_fetch),
- base::Owned(to_upload)));
+ blocking_task_runner_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&CollectBacklog, cache_, to_fetch, to_upload),
+ base::Bind(&SyncClient::OnGetLocalIdsOfBacklog,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(to_fetch),
+ base::Owned(to_upload)));
}
void SyncClient::StartCheckingExistingPinnedFiles() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- cache_->IterateOnUIThread(
- base::Bind(&SyncClient::OnGetLocalIdOfExistingPinnedFile,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&base::DoNothing));
+ std::vector<std::string>* local_ids = new std::vector<std::string>;
+ blocking_task_runner_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&CheckExistingPinnedFiles,
+ metadata_,
+ cache_,
+ local_ids),
+ base::Bind(&SyncClient::AddFetchTasks,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(local_ids)));
}
void SyncClient::AddFetchTask(const std::string& local_id) {
@@ -220,73 +277,11 @@
}
}
-void SyncClient::OnGetLocalIdOfExistingPinnedFile(
- const std::string& local_id,
- const FileCacheEntry& cache_entry) {
+void SyncClient::AddFetchTasks(const std::vector<std::string>* local_ids) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (cache_entry.is_pinned() && cache_entry.is_present()) {
- metadata_->GetResourceEntryByIdOnUIThread(
- local_id,
- base::Bind(&SyncClient::OnGetResourceEntryById,
- weak_ptr_factory_.GetWeakPtr(),
- local_id,
- cache_entry));
- }
-}
-
-void SyncClient::OnGetResourceEntryById(const std::string& local_id,
- const FileCacheEntry& cache_entry,
- FileError error,
- scoped_ptr<ResourceEntry> entry) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (entry.get() && !entry->has_file_specific_info())
- error = FILE_ERROR_NOT_FOUND;
-
- if (error != FILE_ERROR_OK) {
- LOG(WARNING) << "Entry not found: " << local_id;
- return;
- }
-
- // If MD5s don't match, it indicates the local cache file is stale, unless
- // the file is dirty (the MD5 is "local"). We should never re-fetch the
- // file when we have a locally modified version.
- if (entry->file_specific_info().md5() != cache_entry.md5() &&
- !cache_entry.is_dirty()) {
- cache_->RemoveOnUIThread(local_id,
- base::Bind(&SyncClient::OnRemove,
- weak_ptr_factory_.GetWeakPtr(),
- local_id));
- }
-}
-
-void SyncClient::OnRemove(const std::string& local_id, FileError error) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (error != FILE_ERROR_OK) {
- LOG(WARNING) << "Failed to remove cache entry: " << local_id;
- return;
- }
-
- // Before fetching, we should pin this file again, so that the fetched file
- // is downloaded properly to the persistent directory and marked pinned.
- cache_->PinOnUIThread(local_id,
- base::Bind(&SyncClient::OnPinned,
- weak_ptr_factory_.GetWeakPtr(),
- local_id));
-}
-
-void SyncClient::OnPinned(const std::string& local_id, FileError error) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (error != FILE_ERROR_OK) {
- LOG(WARNING) << "Failed to pin cache entry: " << local_id;
- return;
- }
-
- // Finally, adding to the queue.
- AddTaskToQueue(FETCH, local_id, delay_);
+ for (size_t i = 0; i < local_ids->size(); ++i)
+ AddFetchTask((*local_ids)[i]);
}
void SyncClient::OnFetchFileComplete(const std::string& local_id,
diff --git a/chrome/browser/chromeos/drive/sync_client.h b/chrome/browser/chromeos/drive/sync_client.h
index fd55fde..e6b2b53 100644
--- a/chrome/browser/chromeos/drive/sync_client.h
+++ b/chrome/browser/chromeos/drive/sync_client.h
@@ -100,29 +100,10 @@
// Called when the local IDs of files in the backlog are obtained.
void OnGetLocalIdsOfBacklog(const std::vector<std::string>* to_fetch,
- const std::vector<std::string>* to_upload);
+ const std::vector<std::string>* to_upload);
- // Called when the local ID of a pinned file is obtained.
- void OnGetLocalIdOfExistingPinnedFile(const std::string& local_id,
- const FileCacheEntry& cache_entry);
-
- // Called when a file entry is obtained.
- void OnGetResourceEntryById(const std::string& local_id,
- const FileCacheEntry& cache_entry,
- FileError error,
- scoped_ptr<ResourceEntry> entry);
-
- // Called when a cache entry is obtained.
- void OnGetCacheEntry(const std::string& local_id,
- const std::string& latest_md5,
- bool success,
- const FileCacheEntry& cache_entry);
-
- // Called when an existing cache entry and the local files are removed.
- void OnRemove(const std::string& local_id, FileError error);
-
- // Called when a file is pinned.
- void OnPinned(const std::string& local_id, FileError error);
+ // Adds fetch tasks.
+ void AddFetchTasks(const std::vector<std::string>* local_ids);
// Called when the file for |local_id| is fetched.
// Calls DoSyncLoop() to go back to the sync loop.
@@ -135,6 +116,7 @@
// Calls DoSyncLoop() to go back to the sync loop.
void OnUploadFileComplete(const std::string& local_id, FileError error);
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
ResourceMetadata* metadata_;
FileCache* cache_;
diff --git a/chrome/browser/chromeos/extensions/external_cache.cc b/chrome/browser/chromeos/extensions/external_cache.cc
index 8174772..eb47ec2 100644
--- a/chrome/browser/chromeos/extensions/external_cache.cc
+++ b/chrome/browser/chromeos/extensions/external_cache.cc
@@ -30,16 +30,24 @@
// File name extension for CRX files (not case sensitive).
const char kCRXFileExtension[] = ".crx";
+// Name of flag file that indicates that cache is ready (import finished).
+const char kCacheReadyFlagFileName[] = ".initialized";
+
+// Delay between checking cache ready flag file.
+const int64_t kCacheReadyDelayMs = 1000;
+
} // namespace
ExternalCache::ExternalCache(const std::string& cache_dir,
net::URLRequestContextGetter* request_context,
Delegate* delegate,
- bool always_check_updates)
+ bool always_check_updates,
+ bool wait_cache_initialization)
: cache_dir_(cache_dir),
request_context_(request_context),
delegate_(delegate),
always_check_updates_(always_check_updates),
+ wait_cache_initialization_(wait_cache_initialization),
cached_extensions_(new base::DictionaryValue()),
weak_ptr_factory_(this),
worker_pool_token_(
@@ -155,15 +163,6 @@
std::string(version)));
}
-void ExternalCache::OnBlacklistDownloadFinished(
- const std::string& data,
- const std::string& package_hash,
- const std::string& version,
- const extensions::ExtensionDownloaderDelegate::PingResult& ping_result,
- const std::set<int>& request_ids) {
- NOTREACHED();
-}
-
bool ExternalCache::IsExtensionPending(const std::string& id) {
// Pending means that there is no installed version yet.
return extensions_->HasKey(id) && !cached_extensions_->HasKey(id);
@@ -185,8 +184,10 @@
PostBlockingTask(FROM_HERE,
base::Bind(&ExternalCache::BlockingCheckCache,
weak_ptr_factory_.GetWeakPtr(),
+ worker_pool_token_,
std::string(cache_dir_),
- base::Passed(&prefs)));
+ base::Passed(&prefs),
+ wait_cache_initialization_));
}
void ExternalCache::UpdateExtensionLoader() {
@@ -198,8 +199,27 @@
// static
void ExternalCache::BlockingCheckCache(
base::WeakPtr<ExternalCache> external_cache,
+ base::SequencedWorkerPool::SequenceToken sequence_token,
const std::string& cache_dir,
- scoped_ptr<base::DictionaryValue> prefs) {
+ scoped_ptr<base::DictionaryValue> prefs,
+ bool wait_cache_initialization) {
+
+ base::FilePath dir(cache_dir);
+ if (wait_cache_initialization &&
+ !base::PathExists(dir.AppendASCII(kCacheReadyFlagFileName))) {
+ content::BrowserThread::GetBlockingPool()->PostDelayedSequencedWorkerTask(
+ sequence_token,
+ FROM_HERE,
+ base::Bind(&ExternalCache::BlockingCheckCache,
+ external_cache,
+ sequence_token,
+ std::string(cache_dir),
+ base::Passed(&prefs),
+ wait_cache_initialization),
+ base::TimeDelta::FromMilliseconds(kCacheReadyDelayMs));
+ return;
+ }
+
BlockingCheckCacheInternal(cache_dir, prefs.get());
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(&ExternalCache::OnCacheUpdated,
@@ -239,6 +259,10 @@
continue;
}
+ // Skip flag file that indicates that cache is ready.
+ if (basename == kCacheReadyFlagFileName)
+ continue;
+
// crx files in the cache are named <extension-id>-<version>.crx.
std::string id;
std::string version;
diff --git a/chrome/browser/chromeos/extensions/external_cache.h b/chrome/browser/chromeos/extensions/external_cache.h
index 07f2252..b69301c 100644
--- a/chrome/browser/chromeos/extensions/external_cache.h
+++ b/chrome/browser/chromeos/extensions/external_cache.h
@@ -49,10 +49,12 @@
// The |request_context| is used for the update checks.
// By default updates are checked for the extensions with external_update_url.
// If |always_check_webstore| set, updates will be check for external_crx too.
+ // If |wait_cache_initialization|, cache will wait for flag file in cache dir.
ExternalCache(const std::string& cache_dir,
net::URLRequestContextGetter* request_context,
Delegate* delegate,
- bool always_check_updates);
+ bool always_check_updates,
+ bool wait_cache_initialization);
virtual ~ExternalCache();
// Returns already cached extensions.
@@ -90,13 +92,6 @@
const PingResult& ping_result,
const std::set<int>& request_ids) OVERRIDE;
- virtual void OnBlacklistDownloadFinished(
- const std::string& data,
- const std::string& package_hash,
- const std::string& version,
- const PingResult& ping_result,
- const std::set<int>& request_ids) OVERRIDE;
-
virtual bool IsExtensionPending(const std::string& id) OVERRIDE;
virtual bool GetExtensionExistingVersion(const std::string& id,
@@ -115,8 +110,10 @@
// Ownership of |prefs| is transferred to this function.
static void BlockingCheckCache(
base::WeakPtr<ExternalCache> external_cache,
+ base::SequencedWorkerPool::SequenceToken token,
const std::string& app_cache_dir,
- scoped_ptr<base::DictionaryValue> prefs);
+ scoped_ptr<base::DictionaryValue> prefs,
+ bool wait_cache_initialization);
// Helper for BlockingCheckCache(), updates |prefs|.
static void BlockingCheckCacheInternal(
@@ -156,6 +153,9 @@
// Updates needs to be check for the extensions with external_crx too.
bool always_check_updates_;
+ // Set to true if cache should wait for initialization flag file.
+ bool wait_cache_initialization_;
+
// This is the list of extensions currently configured.
scoped_ptr<base::DictionaryValue> extensions_;
diff --git a/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc b/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
index 470b743..d05a269 100644
--- a/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
+++ b/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
@@ -7,8 +7,10 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/singleton.h"
+#include "base/observer_list.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/extensions/external_cache.h"
#include "content/public/browser/browser_thread.h"
namespace chromeos {
@@ -18,14 +20,81 @@
// Directory where the extensions are cached.
const char kPreinstalledAppsCacheDir[] = "/var/cache/external_cache";
+// Singleton class that holds ExternalCache and dispatches cache update events
+// to per-profile instances of ExternalPrefCacheLoader. This multiplexing
+// is required for multi-profile case.
+class ExternalCacheDispatcher : public ExternalCache::Delegate {
+ public:
+ static ExternalCacheDispatcher* GetInstance() {
+ return Singleton<ExternalCacheDispatcher>::get();
+ }
+
+ // Implementation of ExternalCache::Delegate:
+ virtual void OnExtensionListsUpdated(
+ const base::DictionaryValue* prefs) OVERRIDE {
+ is_extensions_list_ready_ = true;
+ FOR_EACH_OBSERVER(ExternalPrefCacheLoader, pref_loaders_,
+ OnExtensionListsUpdated(prefs));
+ }
+
+ void UpdateExtensionsList(scoped_ptr<base::DictionaryValue> prefs) {
+ DCHECK(!is_extensions_list_ready_);
+ external_cache_.UpdateExtensionsList(prefs.Pass());
+ }
+
+ // Return false if cache doesn't have list of extensions and it needs to
+ // be provided via UpdateExtensionsList.
+ bool RegisterExternalPrefCacheLoader(ExternalPrefCacheLoader* observer,
+ int base_path_id) {
+ pref_loaders_.AddObserver(observer);
+
+ if (base_path_id_ == 0) {
+ // First ExternalPrefCacheLoader is registered.
+ base_path_id_ = base_path_id;
+ return false;
+ } else {
+ CHECK_EQ(base_path_id_, base_path_id);
+ if (is_extensions_list_ready_) {
+ // If list of extensions is not ready, |observer| will be notified later
+ // in OnExtensionListsUpdated.
+ observer->OnExtensionListsUpdated(external_cache_.cached_extensions());
+ }
+ return true;
+ }
+ }
+
+ void UnregisterExternalPrefCacheLoader(ExternalPrefCacheLoader* observer) {
+ pref_loaders_.RemoveObserver(observer);
+ }
+
+ private:
+ friend struct DefaultSingletonTraits<ExternalCacheDispatcher>;
+
+ ExternalCacheDispatcher()
+ : external_cache_(kPreinstalledAppsCacheDir,
+ g_browser_process->system_request_context(),
+ this, true, true),
+ base_path_id_(0),
+ is_extensions_list_ready_(false) {
+ }
+
+ ExternalCache external_cache_;
+ ObserverList<ExternalPrefCacheLoader> pref_loaders_;
+ int base_path_id_;
+ bool is_extensions_list_ready_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalCacheDispatcher);
+};
+
} // namespace
-ExternalPrefCacheLoader::ExternalPrefCacheLoader(int base_path_id,
- Options options)
- : ExternalPrefLoader(base_path_id, options) {
+ExternalPrefCacheLoader::ExternalPrefCacheLoader(int base_path_id)
+ : ExternalPrefLoader(base_path_id, ExternalPrefLoader::NONE) {
}
ExternalPrefCacheLoader::~ExternalPrefCacheLoader() {
+ ExternalCacheDispatcher::GetInstance()->UnregisterExternalPrefCacheLoader(
+ this);
}
void ExternalPrefCacheLoader::OnExtensionListsUpdated(
@@ -34,14 +103,16 @@
ExternalPrefLoader::LoadFinished();
}
-void ExternalPrefCacheLoader::LoadFinished() {
- if (!external_cache_.get()) {
- external_cache_.reset(new ExternalCache(kPreinstalledAppsCacheDir,
- g_browser_process->system_request_context(),
- this, true));
+void ExternalPrefCacheLoader::StartLoading() {
+ if (!ExternalCacheDispatcher::GetInstance()->RegisterExternalPrefCacheLoader(
+ this, base_path_id_)) {
+ // ExternalCacheDispatcher doesn't know list of extensions load it.
+ ExternalPrefLoader::StartLoading();
}
+}
- external_cache_->UpdateExtensionsList(prefs_.Pass());
+void ExternalPrefCacheLoader::LoadFinished() {
+ ExternalCacheDispatcher::GetInstance()->UpdateExtensionsList(prefs_.Pass());
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/external_pref_cache_loader.h b/chrome/browser/chromeos/extensions/external_pref_cache_loader.h
index f886f85..16a08ff 100644
--- a/chrome/browser/chromeos/extensions/external_pref_cache_loader.h
+++ b/chrome/browser/chromeos/extensions/external_pref_cache_loader.h
@@ -5,7 +5,6 @@
#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_PREF_CACHE_LOADER_H_
#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_EXTERNAL_PREF_CACHE_LOADER_H_
-#include "chrome/browser/chromeos/extensions/external_cache.h"
#include "chrome/browser/extensions/external_pref_loader.h"
namespace chromeos {
@@ -13,24 +12,22 @@
// A specialization of the ExternalPrefCacheLoader that caches crx files for
// external extensions with update URL in common place for all users on the
// machine.
-class ExternalPrefCacheLoader : public extensions::ExternalPrefLoader,
- public ExternalCache::Delegate {
+class ExternalPrefCacheLoader : public extensions::ExternalPrefLoader {
public:
- ExternalPrefCacheLoader(int base_path_id, Options options);
+ // All instances of ExternalPrefCacheLoader use the same cache so
+ // |base_path_id| must be the same for all profile in session.
+ // It is checked in run-time with CHECK.
+ explicit ExternalPrefCacheLoader(int base_path_id);
- // Implementation of ExternalCache::Delegate:
- virtual void OnExtensionListsUpdated(
- const base::DictionaryValue* prefs) OVERRIDE;
-
- protected:
- virtual ~ExternalPrefCacheLoader();
-
- virtual void LoadFinished() OVERRIDE;
+ void OnExtensionListsUpdated(const base::DictionaryValue* prefs);
private:
friend class base::RefCountedThreadSafe<ExternalLoader>;
- scoped_ptr<ExternalCache> external_cache_;
+ virtual ~ExternalPrefCacheLoader();
+
+ virtual void StartLoading() OVERRIDE;
+ virtual void LoadFinished() OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(ExternalPrefCacheLoader);
};
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index 56e653d..0471ec2 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -297,9 +297,9 @@
switch (type) {
case fileapi::FileSystemOperation::BEGIN_COPY_ENTRY:
- return CopyProgressStatus::TYPE_BEGIN_ENTRY_COPY;
+ return CopyProgressStatus::TYPE_BEGIN_COPY_ENTRY;
case fileapi::FileSystemOperation::END_COPY_ENTRY:
- return CopyProgressStatus::TYPE_END_ENTRY_COPY;
+ return CopyProgressStatus::TYPE_END_COPY_ENTRY;
case fileapi::FileSystemOperation::PROGRESS:
return CopyProgressStatus::TYPE_PROGRESS;
}
@@ -470,15 +470,18 @@
}
}
-void EventRouter::OnCopyCompleted(
- int copy_id, const GURL& url, base::PlatformFileError error) {
+void EventRouter::OnCopyCompleted(int copy_id,
+ const GURL& source_url,
+ const GURL& destination_url,
+ base::PlatformFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
file_browser_private::CopyProgressStatus status;
if (error == base::PLATFORM_FILE_OK) {
// Send success event.
status.type = file_browser_private::CopyProgressStatus::TYPE_SUCCESS;
- status.url.reset(new std::string(url.spec()));
+ status.source_url.reset(new std::string(source_url.spec()));
+ status.destination_url.reset(new std::string(destination_url.spec()));
} else {
// Send error event.
status.type = file_browser_private::CopyProgressStatus::TYPE_ERROR;
@@ -495,13 +498,16 @@
void EventRouter::OnCopyProgress(
int copy_id,
fileapi::FileSystemOperation::CopyProgressType type,
- const GURL& url,
+ const GURL& source_url,
+ const GURL& destination_url,
int64 size) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
file_browser_private::CopyProgressStatus status;
status.type = CopyProgressTypeToCopyProgressStatusType(type);
- status.url.reset(new std::string(url.spec()));
+ status.source_url.reset(new std::string(source_url.spec()));
+ if (type == fileapi::FileSystemOperation::END_COPY_ENTRY)
+ status.destination_url.reset(new std::string(destination_url.spec()));
if (type == fileapi::FileSystemOperation::PROGRESS)
status.size.reset(new double(size));
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.h b/chrome/browser/chromeos/extensions/file_manager/event_router.h
index 1c75b30..2b96a77 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.h
@@ -72,12 +72,14 @@
// Called when a copy task is completed.
void OnCopyCompleted(
- int copy_id, const GURL& url, base::PlatformFileError error);
+ int copy_id, const GURL& source_url, const GURL& destination_url,
+ base::PlatformFileError error);
// Called when a copy task progress is updated.
void OnCopyProgress(int copy_id,
fileapi::FileSystemOperation::CopyProgressType type,
- const GURL& url,
+ const GURL& source_url,
+ const GURL& destination_url,
int64 size);
// chromeos::NetworkStateHandlerObserver overrides.
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
index dc52b7e..2726349 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/api/file_browser_private.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
@@ -43,11 +44,11 @@
void DoNothingWithBool(bool /* success */) {
}
-// Copies properties from |entry_proto| to |property_dict|.
+// Copies properties from |entry_proto| to |properties|.
void FillDriveEntryPropertiesValue(
const drive::ResourceEntry& entry_proto,
- DictionaryValue* property_dict) {
- property_dict->SetBoolean("sharedWithMe", entry_proto.shared_with_me());
+ api::file_browser_private::DriveEntryProperties* properties) {
+ properties->shared_with_me.reset(new bool(entry_proto.shared_with_me()));
if (!entry_proto.has_file_specific_info())
return;
@@ -55,11 +56,12 @@
const drive::FileSpecificInfo& file_specific_info =
entry_proto.file_specific_info();
- property_dict->SetString("thumbnailUrl", file_specific_info.thumbnail_url());
- property_dict->SetBoolean("isHosted",
- file_specific_info.is_hosted_document());
- property_dict->SetString("contentMimeType",
- file_specific_info.content_mime_type());
+ properties->thumbnail_url.reset(
+ new std::string(file_specific_info.thumbnail_url()));
+ properties->is_hosted.reset(
+ new bool(file_specific_info.is_hosted_document()));
+ properties->content_mime_type.reset(
+ new std::string(file_specific_info.content_mime_type()));
}
} // namespace
@@ -75,16 +77,17 @@
bool FileBrowserPrivateGetDriveEntryPropertiesFunction::RunImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- std::string file_url_str;
- if (args_->GetSize() != 1 || !args_->GetString(0, &file_url_str))
- return false;
+ using extensions::api::file_browser_private::GetDriveEntryProperties::Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
- GURL file_url = GURL(file_url_str);
+ const GURL file_url = GURL(params->file_url);
file_path_ = drive::util::ExtractDrivePath(
file_manager::util::GetLocalPathFromURL(
render_view_host(), profile(), file_url));
- properties_.reset(new base::DictionaryValue);
+ properties_.reset(new extensions::api::file_browser_private::
+ DriveEntryProperties);
// Start getting the file info.
drive::FileSystemInterface* file_system =
@@ -157,7 +160,7 @@
const GURL doc_icon =
drive::util::FindPreferredIcon(app_info->document_icons,
drive::util::kPreferredIconSize);
- properties_->SetString("customIconUrl", doc_icon.spec());
+ properties_->custom_icon_url.reset(new std::string(doc_icon.spec()));
}
}
}
@@ -173,44 +176,35 @@
const drive::FileCacheEntry& cache_entry) {
// In case of an error (i.e. success is false), cache_entry.is_*() all
// returns false.
- properties_->SetBoolean("isPinned", cache_entry.is_pinned());
- properties_->SetBoolean("isPresent", cache_entry.is_present());
+ properties_->is_pinned.reset(new bool(cache_entry.is_pinned()));
+ properties_->is_present.reset(new bool(cache_entry.is_present()));
CompleteGetFileProperties(drive::FILE_ERROR_OK);
}
void FileBrowserPrivateGetDriveEntryPropertiesFunction::
CompleteGetFileProperties(drive::FileError error) {
- SetResult(properties_.release());
+ results_ = extensions::api::file_browser_private::GetDriveEntryProperties::
+ Results::Create(*properties_);
SendResponse(true);
}
-FileBrowserPrivatePinDriveFileFunction::
- FileBrowserPrivatePinDriveFileFunction() {
-}
-
-FileBrowserPrivatePinDriveFileFunction::
- ~FileBrowserPrivatePinDriveFileFunction() {
-}
-
bool FileBrowserPrivatePinDriveFileFunction::RunImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- std::string url;
- bool set_pin = false;
- if (args_->GetSize() != 2 ||
- !args_->GetString(0, &url) ||
- !args_->GetBoolean(1, &set_pin))
- return false;
- drive::FileSystemInterface* file_system =
+ using extensions::api::file_browser_private::PinDriveFile::Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ drive::FileSystemInterface* const file_system =
drive::util::GetFileSystemByProfile(profile());
if (!file_system) // |file_system| is NULL if Drive is disabled.
return false;
- base::FilePath drive_path =
+ const base::FilePath drive_path =
drive::util::ExtractDrivePath(file_manager::util::GetLocalPathFromURL(
- render_view_host(), profile(), GURL(url)));
- if (set_pin) {
+ render_view_host(), profile(), GURL(params->file_url)));
+ if (params->pin) {
file_system->Pin(drive_path,
base::Bind(&FileBrowserPrivatePinDriveFileFunction::
OnPinStateSet, this));
@@ -235,7 +229,7 @@
}
FileBrowserPrivateGetDriveFilesFunction::
- FileBrowserPrivateGetDriveFilesFunction() : local_paths_(NULL) {
+ FileBrowserPrivateGetDriveFilesFunction() {
}
FileBrowserPrivateGetDriveFilesFunction::
@@ -243,23 +237,19 @@
}
bool FileBrowserPrivateGetDriveFilesFunction::RunImpl() {
- ListValue* file_urls_as_strings = NULL;
- if (!args_->GetList(0, &file_urls_as_strings))
- return false;
+ using extensions::api::file_browser_private::GetDriveFiles::Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
// Convert the list of strings to a list of GURLs.
- for (size_t i = 0; i < file_urls_as_strings->GetSize(); ++i) {
- std::string file_url_as_string;
- if (!file_urls_as_strings->GetString(i, &file_url_as_string))
- return false;
+ for (size_t i = 0; i < params->file_urls.size(); ++i) {
const base::FilePath path = file_manager::util::GetLocalPathFromURL(
- render_view_host(), profile(), GURL(file_url_as_string));
+ render_view_host(), profile(), GURL(params->file_urls[i]));
DCHECK(drive::util::IsUnderDriveMountPoint(path));
base::FilePath drive_path = drive::util::ExtractDrivePath(path);
remaining_drive_paths_.push(drive_path);
}
- local_paths_ = new ListValue;
GetFileOrSendResponse();
return true;
}
@@ -267,7 +257,8 @@
void FileBrowserPrivateGetDriveFilesFunction::GetFileOrSendResponse() {
// Send the response if all files are obtained.
if (remaining_drive_paths_.empty()) {
- SetResult(local_paths_);
+ results_ = extensions::api::file_browser_private::
+ GetDriveFiles::Results::Create(local_paths_);
SendResponse(true);
return;
}
@@ -297,7 +288,7 @@
base::FilePath drive_path = remaining_drive_paths_.front();
if (error == drive::FILE_ERROR_OK) {
- local_paths_->Append(new base::StringValue(local_path.value()));
+ local_paths_.push_back(local_path.AsUTF8Unsafe());
DVLOG(1) << "Got " << drive_path.value() << " as " << local_path.value();
// TODO(benchan): If the file is a hosted document, a temporary JSON file
@@ -306,7 +297,7 @@
// file_manager.js to manage the lifetime of the temporary file.
// See crosbug.com/28058.
} else {
- local_paths_->Append(new base::StringValue(""));
+ local_paths_.push_back("");
DVLOG(1) << "Failed to get " << drive_path.value()
<< " with error code: " << error;
}
@@ -317,18 +308,10 @@
GetFileOrSendResponse();
}
-FileBrowserPrivateCancelFileTransfersFunction::
- FileBrowserPrivateCancelFileTransfersFunction() {
-}
-
-FileBrowserPrivateCancelFileTransfersFunction::
- ~FileBrowserPrivateCancelFileTransfersFunction() {
-}
-
bool FileBrowserPrivateCancelFileTransfersFunction::RunImpl() {
- ListValue* url_list = NULL;
- if (!args_->GetList(0, &url_list))
- return false;
+ using extensions::api::file_browser_private::CancelFileTransfers::Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
drive::DriveIntegrationService* integration_service =
drive::DriveIntegrationServiceFactory::FindForProfile(profile_);
@@ -348,19 +331,16 @@
}
// Cancel by Job ID.
- scoped_ptr<ListValue> responses(new ListValue());
- for (size_t i = 0; i < url_list->GetSize(); ++i) {
- std::string url_as_string;
- url_list->GetString(i, &url_as_string);
-
+ std::vector<linked_ptr<api::file_browser_private::
+ FileTransferCancelStatus> > responses;
+ for (size_t i = 0; i < params->file_urls.size(); ++i) {
base::FilePath file_path = file_manager::util::GetLocalPathFromURL(
- render_view_host(), profile(), GURL(url_as_string));
+ render_view_host(), profile(), GURL(params->file_urls[i]));
if (file_path.empty())
continue;
DCHECK(drive::util::IsUnderDriveMountPoint(file_path));
file_path = drive::util::ExtractDrivePath(file_path);
- scoped_ptr<DictionaryValue> result(new DictionaryValue());
// Cancel all the jobs for the file.
PathToIdMap::iterator it = path_to_id_map.find(file_path);
@@ -368,39 +348,26 @@
for (size_t i = 0; i < it->second.size(); ++i)
job_list->CancelJob(it->second[i]);
}
- result->SetBoolean("canceled", it != path_to_id_map.end());
+ linked_ptr<api::file_browser_private::FileTransferCancelStatus> result(
+ new api::file_browser_private::FileTransferCancelStatus);
+ result->canceled = it != path_to_id_map.end();
// TODO(kinaba): simplify cancelFileTransfer() to take single URL each time,
// and eliminate this field; it is just returning a copy of the argument.
- result->SetString("fileUrl", url_as_string);
- responses->Append(result.release());
+ result->file_url = params->file_urls[i];
+ responses.push_back(result);
}
- SetResult(responses.release());
+ results_ = api::file_browser_private::CancelFileTransfers::Results::Create(
+ responses);
SendResponse(true);
return true;
}
-FileBrowserPrivateSearchDriveFunction::
- FileBrowserPrivateSearchDriveFunction() {
-}
-
-FileBrowserPrivateSearchDriveFunction::
- ~FileBrowserPrivateSearchDriveFunction() {
-}
-
bool FileBrowserPrivateSearchDriveFunction::RunImpl() {
- DictionaryValue* search_params;
- if (!args_->GetDictionary(0, &search_params))
- return false;
+ using extensions::api::file_browser_private::SearchDrive::Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
- std::string query;
- if (!search_params->GetString("query", &query))
- return false;
-
- std::string next_feed;
- if (!search_params->GetString("nextFeed", &next_feed))
- return false;
-
- drive::FileSystemInterface* file_system =
+ drive::FileSystemInterface* const file_system =
drive::util::GetFileSystemByProfile(profile());
if (!file_system) {
// |file_system| is NULL if Drive is disabled.
@@ -408,7 +375,7 @@
}
file_system->Search(
- query, GURL(next_feed),
+ params->search_params.query, GURL(params->search_params.next_feed),
base::Bind(&FileBrowserPrivateSearchDriveFunction::OnSearch, this));
return true;
}
@@ -450,61 +417,50 @@
SendResponse(true);
}
-FileBrowserPrivateSearchDriveMetadataFunction::
- FileBrowserPrivateSearchDriveMetadataFunction() {
-}
-
-FileBrowserPrivateSearchDriveMetadataFunction::
- ~FileBrowserPrivateSearchDriveMetadataFunction() {
-}
-
bool FileBrowserPrivateSearchDriveMetadataFunction::RunImpl() {
- DictionaryValue* search_params;
- if (!args_->GetDictionary(0, &search_params))
- return false;
-
- std::string query;
- if (!search_params->GetString("query", &query))
- return false;
-
- std::string types;
- if (!search_params->GetString("types", &types))
- return false;
-
- int max_results = 0;
- if (!search_params->GetInteger("maxResults", &max_results))
- return false;
+ using extensions::api::file_browser_private::SearchDriveMetadata::Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
drive::util::Log(logging::LOG_INFO,
"%s[%d] called. (types: '%s', maxResults: '%d')",
name().c_str(),
request_id(),
- types.c_str(),
- max_results);
+ Params::SearchParams::ToString(
+ params->search_params.types).c_str(),
+ params->search_params.max_results);
set_log_on_completion(true);
- drive::FileSystemInterface* file_system =
+ drive::FileSystemInterface* const file_system =
drive::util::GetFileSystemByProfile(profile());
if (!file_system) {
// |file_system| is NULL if Drive is disabled.
return false;
}
- int options = drive::SEARCH_METADATA_ALL;
- // TODO(hirono): Switch to the JSON scheme compiler. http://crbug.com/241693
- if (types == "EXCLUDE_DIRECTORIES")
- options = drive::SEARCH_METADATA_EXCLUDE_DIRECTORIES;
- else if (types == "SHARED_WITH_ME")
- options = drive::SEARCH_METADATA_SHARED_WITH_ME;
- else if (types == "OFFLINE")
- options = drive::SEARCH_METADATA_OFFLINE;
- else
- DCHECK_EQ("ALL", types);
+ int options = -1;
+ switch (params->search_params.types) {
+ case Params::SearchParams::TYPES_EXCLUDE_DIRECTORIES:
+ options = drive::SEARCH_METADATA_EXCLUDE_DIRECTORIES;
+ break;
+ case Params::SearchParams::TYPES_SHARED_WITH_ME:
+ options = drive::SEARCH_METADATA_SHARED_WITH_ME;
+ break;
+ case Params::SearchParams::TYPES_OFFLINE:
+ options = drive::SEARCH_METADATA_OFFLINE;
+ break;
+ case Params::SearchParams::TYPES_ALL:
+ options = drive::SEARCH_METADATA_ALL;
+ break;
+ case Params::SearchParams::TYPES_NONE:
+ break;
+ }
+ DCHECK_NE(options, -1);
file_system->SearchMetadata(
- query,
+ params->search_params.query,
options,
- max_results,
+ params->search_params.max_results,
base::Bind(&FileBrowserPrivateSearchDriveMetadataFunction::
OnSearchMetadata, this));
return true;
@@ -553,14 +509,6 @@
SendResponse(true);
}
-FileBrowserPrivateClearDriveCacheFunction::
- FileBrowserPrivateClearDriveCacheFunction() {
-}
-
-FileBrowserPrivateClearDriveCacheFunction::
- ~FileBrowserPrivateClearDriveCacheFunction() {
-}
-
bool FileBrowserPrivateClearDriveCacheFunction::RunImpl() {
drive::DriveIntegrationService* integration_service =
drive::DriveIntegrationServiceFactory::FindForProfile(profile_);
@@ -576,64 +524,46 @@
return true;
}
-FileBrowserPrivateGetDriveConnectionStateFunction::
- FileBrowserPrivateGetDriveConnectionStateFunction() {
-}
-
-FileBrowserPrivateGetDriveConnectionStateFunction::
- ~FileBrowserPrivateGetDriveConnectionStateFunction() {
-}
-
bool FileBrowserPrivateGetDriveConnectionStateFunction::RunImpl() {
- drive::DriveServiceInterface* drive_service =
+ drive::DriveServiceInterface* const drive_service =
drive::util::GetDriveServiceByProfile(profile());
- bool ready = drive_service && drive_service->CanSendRequest();
- bool is_connection_cellular =
+ api::file_browser_private::GetDriveConnectionState::Results::Result result;
+
+ const bool ready = drive_service && drive_service->CanSendRequest();
+ const bool is_connection_cellular =
net::NetworkChangeNotifier::IsConnectionCellular(
net::NetworkChangeNotifier::GetConnectionType());
- std::string type_string;
- scoped_ptr<ListValue> reasons(new ListValue());
if (net::NetworkChangeNotifier::IsOffline() || !ready) {
- type_string = kDriveConnectionTypeOffline;
+ result.type = kDriveConnectionTypeOffline;
if (net::NetworkChangeNotifier::IsOffline())
- reasons->AppendString(kDriveConnectionReasonNoNetwork);
+ result.reasons.push_back(kDriveConnectionReasonNoNetwork);
if (!ready)
- reasons->AppendString(kDriveConnectionReasonNotReady);
+ result.reasons.push_back(kDriveConnectionReasonNotReady);
if (!drive_service)
- reasons->AppendString(kDriveConnectionReasonNoService);
+ result.reasons.push_back(kDriveConnectionReasonNoService);
} else if (
is_connection_cellular &&
profile_->GetPrefs()->GetBoolean(prefs::kDisableDriveOverCellular)) {
- type_string = kDriveConnectionTypeMetered;
+ result.type = kDriveConnectionTypeMetered;
} else {
- type_string = kDriveConnectionTypeOnline;
+ result.type = kDriveConnectionTypeOnline;
}
- scoped_ptr<DictionaryValue> value(new DictionaryValue());
- value->SetString("type", type_string);
- value->Set("reasons", reasons.release());
- SetResult(value.release());
+ results_ = api::file_browser_private::GetDriveConnectionState::Results::
+ Create(result);
drive::util::Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
return true;
}
-FileBrowserPrivateRequestAccessTokenFunction::
- FileBrowserPrivateRequestAccessTokenFunction() {
-}
-
-FileBrowserPrivateRequestAccessTokenFunction::
- ~FileBrowserPrivateRequestAccessTokenFunction() {
-}
-
bool FileBrowserPrivateRequestAccessTokenFunction::RunImpl() {
- bool refresh;
- if (!args_->GetBoolean(0, &refresh))
- return false;
+ using extensions::api::file_browser_private::RequestAccessToken::Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
- drive::DriveServiceInterface* drive_service =
+ drive::DriveServiceInterface* const drive_service =
drive::util::GetDriveServiceByProfile(profile());
if (!drive_service) {
@@ -644,7 +574,7 @@
}
// If refreshing is requested, then clear the token to refetch it.
- if (refresh)
+ if (params->refresh)
drive_service->ClearAccessToken();
// Retrieve the cached auth token (if available), otherwise the AuthService
@@ -662,25 +592,18 @@
SendResponse(true);
}
-FileBrowserPrivateGetShareUrlFunction::FileBrowserPrivateGetShareUrlFunction() {
-}
-
-FileBrowserPrivateGetShareUrlFunction::
- ~FileBrowserPrivateGetShareUrlFunction() {
-}
-
bool FileBrowserPrivateGetShareUrlFunction::RunImpl() {
- std::string file_url;
- if (!args_->GetString(0, &file_url))
- return false;
+ using extensions::api::file_browser_private::GetShareUrl::Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
const base::FilePath path = file_manager::util::GetLocalPathFromURL(
- render_view_host(), profile(), GURL(file_url));
+ render_view_host(), profile(), GURL(params->url));
DCHECK(drive::util::IsUnderDriveMountPoint(path));
- base::FilePath drive_path = drive::util::ExtractDrivePath(path);
+ const base::FilePath drive_path = drive::util::ExtractDrivePath(path);
- drive::FileSystemInterface* file_system =
+ drive::FileSystemInterface* const file_system =
drive::util::GetFileSystemByProfile(profile());
if (!file_system) {
// |file_system| is NULL if Drive is disabled.
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
index 171e34f..2156e53 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
@@ -19,6 +19,11 @@
}
namespace extensions {
+namespace api {
+namespace file_browser_private{
+struct DriveEntryProperties;
+}
+}
// Retrieves property information for an entry and returns it as a dictionary.
// On error, returns a dictionary with the key "error" set to the error number
@@ -47,7 +52,8 @@
void CompleteGetFileProperties(drive::FileError error);
base::FilePath file_path_;
- scoped_ptr<base::DictionaryValue> properties_;
+ scoped_ptr<extensions::api::file_browser_private::
+ DriveEntryProperties> properties_;
};
// Implements the chrome.fileBrowserPrivate.pinDriveFile method.
@@ -57,10 +63,8 @@
DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.pinDriveFile",
FILEBROWSERPRIVATE_PINDRIVEFILE)
- FileBrowserPrivatePinDriveFileFunction();
-
protected:
- virtual ~FileBrowserPrivatePinDriveFileFunction();
+ virtual ~FileBrowserPrivatePinDriveFileFunction() {}
// AsyncExtensionFunction overrides.
virtual bool RunImpl() OVERRIDE;
@@ -104,7 +108,7 @@
scoped_ptr<drive::ResourceEntry> entry);
std::queue<base::FilePath> remaining_drive_paths_;
- ListValue* local_paths_;
+ std::vector<std::string> local_paths_;
};
// Implements the chrome.fileBrowserPrivate.cancelFileTransfers method.
@@ -114,10 +118,8 @@
DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.cancelFileTransfers",
FILEBROWSERPRIVATE_CANCELFILETRANSFERS)
- FileBrowserPrivateCancelFileTransfersFunction();
-
protected:
- virtual ~FileBrowserPrivateCancelFileTransfersFunction();
+ virtual ~FileBrowserPrivateCancelFileTransfersFunction() {}
// AsyncExtensionFunction overrides.
virtual bool RunImpl() OVERRIDE;
@@ -129,10 +131,8 @@
DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.searchDrive",
FILEBROWSERPRIVATE_SEARCHDRIVE)
- FileBrowserPrivateSearchDriveFunction();
-
protected:
- virtual ~FileBrowserPrivateSearchDriveFunction();
+ virtual ~FileBrowserPrivateSearchDriveFunction() {}
virtual bool RunImpl() OVERRIDE;
@@ -151,10 +151,8 @@
DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.searchDriveMetadata",
FILEBROWSERPRIVATE_SEARCHDRIVEMETADATA)
- FileBrowserPrivateSearchDriveMetadataFunction();
-
protected:
- virtual ~FileBrowserPrivateSearchDriveMetadataFunction();
+ virtual ~FileBrowserPrivateSearchDriveMetadataFunction() {}
virtual bool RunImpl() OVERRIDE;
@@ -170,10 +168,8 @@
DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.clearDriveCache",
FILEBROWSERPRIVATE_CLEARDRIVECACHE)
- FileBrowserPrivateClearDriveCacheFunction();
-
protected:
- virtual ~FileBrowserPrivateClearDriveCacheFunction();
+ virtual ~FileBrowserPrivateClearDriveCacheFunction() {}
virtual bool RunImpl() OVERRIDE;
};
@@ -186,10 +182,8 @@
"fileBrowserPrivate.getDriveConnectionState",
FILEBROWSERPRIVATE_GETDRIVECONNECTIONSTATE);
- FileBrowserPrivateGetDriveConnectionStateFunction();
-
protected:
- virtual ~FileBrowserPrivateGetDriveConnectionStateFunction();
+ virtual ~FileBrowserPrivateGetDriveConnectionStateFunction() {}
virtual bool RunImpl() OVERRIDE;
};
@@ -201,10 +195,8 @@
DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.requestAccessToken",
FILEBROWSERPRIVATE_REQUESTACCESSTOKEN)
- FileBrowserPrivateRequestAccessTokenFunction();
-
protected:
- virtual ~FileBrowserPrivateRequestAccessTokenFunction();
+ virtual ~FileBrowserPrivateRequestAccessTokenFunction() {}
// AsyncExtensionFunction overrides.
virtual bool RunImpl() OVERRIDE;
@@ -221,10 +213,8 @@
DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.getShareUrl",
FILEBROWSERPRIVATE_GETSHAREURL)
- FileBrowserPrivateGetShareUrlFunction();
-
protected:
- virtual ~FileBrowserPrivateGetShareUrlFunction();
+ virtual ~FileBrowserPrivateGetShareUrlFunction() {}
// AsyncExtensionFunction overrides.
virtual bool RunImpl() OVERRIDE;
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
index a3d8ea3..179e87d 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -198,7 +198,8 @@
void* profile_id,
fileapi::FileSystemOperationRunner::OperationID operation_id,
fileapi::FileSystemOperation::CopyProgressType type,
- const FileSystemURL& url,
+ const FileSystemURL& source_url,
+ const FileSystemURL& destination_url,
int64 size) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -206,7 +207,8 @@
GetEventRouterByProfileId(profile_id);
if (event_router) {
event_router->OnCopyProgress(
- operation_id, type, url.ToGURL(), size);
+ operation_id, type,
+ source_url.ToGURL(), destination_url.ToGURL(), size);
}
}
@@ -215,28 +217,33 @@
void* profile_id,
fileapi::FileSystemOperationRunner::OperationID* operation_id,
fileapi::FileSystemOperation::CopyProgressType type,
- const FileSystemURL& url,
+ const FileSystemURL& source_url,
+ const FileSystemURL& destination_url,
int64 size) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&NotifyCopyProgress,
- profile_id, *operation_id, type, url, size));
+ profile_id, *operation_id, type,
+ source_url, destination_url, size));
}
// Notifies the copy completion to extensions via event router.
void NotifyCopyCompletion(
void* profile_id,
fileapi::FileSystemOperationRunner::OperationID operation_id,
- const FileSystemURL& dest_url,
+ const FileSystemURL& source_url,
+ const FileSystemURL& destination_url,
base::PlatformFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
file_manager::EventRouter* event_router =
GetEventRouterByProfileId(profile_id);
if (event_router)
- event_router->OnCopyCompleted(operation_id, dest_url.ToGURL(), error);
+ event_router->OnCopyCompleted(
+ operation_id,
+ source_url.ToGURL(), destination_url.ToGURL(), error);
}
// Callback invoked upon completion of Copy() (regardless of succeeded or
@@ -244,14 +251,16 @@
void OnCopyCompleted(
void* profile_id,
fileapi::FileSystemOperationRunner::OperationID* operation_id,
- const FileSystemURL& dest_url,
+ const FileSystemURL& source_url,
+ const FileSystemURL& destination_url,
base::PlatformFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&NotifyCopyCompletion,
- profile_id, *operation_id, dest_url, error));
+ profile_id, *operation_id,
+ source_url, destination_url, error));
}
// Starts the copy operation via FileSystemOperationRunner.
@@ -259,7 +268,7 @@
void* profile_id,
scoped_refptr<fileapi::FileSystemContext> file_system_context,
const FileSystemURL& source_url,
- const FileSystemURL& dest_url) {
+ const FileSystemURL& destination_url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Note: |operation_id| is owned by the callback for
@@ -268,11 +277,13 @@
fileapi::FileSystemOperationRunner::OperationID* operation_id =
new fileapi::FileSystemOperationRunner::OperationID;
*operation_id = file_system_context->operation_runner()->Copy(
- source_url, dest_url,
+ source_url, destination_url,
+ fileapi::FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED,
base::Bind(&OnCopyProgress,
profile_id, base::Unretained(operation_id)),
base::Bind(&OnCopyCompleted,
- profile_id, base::Owned(operation_id), dest_url));
+ profile_id, base::Owned(operation_id),
+ source_url, destination_url));
return *operation_id;
}
@@ -670,10 +681,10 @@
fileapi::FileSystemURL source_url(
file_system_context->CrackURL(GURL(params->source_url)));
- fileapi::FileSystemURL dest_url(file_system_context->CrackURL(
+ fileapi::FileSystemURL destination_url(file_system_context->CrackURL(
GURL(params->parent + "/" + params->new_name)));
- if (!source_url.is_valid() || !dest_url.is_valid()) {
+ if (!source_url.is_valid() || !destination_url.is_valid()) {
error_ = base::IntToString(fileapi::PlatformFileErrorToWebFileError(
base::PLATFORM_FILE_ERROR_INVALID_URL));
return false;
@@ -683,7 +694,7 @@
BrowserThread::IO,
FROM_HERE,
base::Bind(&StartCopyOnIOThread,
- profile(), file_system_context, source_url, dest_url),
+ profile(), file_system_context, source_url, destination_url),
base::Bind(&FileBrowserPrivateStartCopyFunction::RunAfterStartCopy,
this));
}
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
index 5db622e..63ea1c5 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -229,7 +229,7 @@
std::vector<std::string> scopes;
scopes.push_back(kCWSScope);
- OAuth2TokenService* oauth_service =
+ ProfileOAuth2TokenService* oauth_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
net::URLRequestContextGetter* url_request_context_getter =
g_browser_process->system_request_context();
@@ -244,6 +244,7 @@
auth_service_.reset(new google_apis::AuthService(
oauth_service,
+ oauth_service->GetPrimaryAccountId(),
url_request_context_getter,
scopes));
auth_service_->StartAuthentication(base::Bind(
diff --git a/chrome/browser/chromeos/extensions/virtual_keyboard_browsertest.cc b/chrome/browser/chromeos/extensions/virtual_keyboard_browsertest.cc
new file mode 100644
index 0000000..3e0adbb
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/virtual_keyboard_browsertest.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 <vector>
+
+#include "base/command_line.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 "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "ui/keyboard/keyboard_switches.h"
+
+namespace {
+
+const base::FilePath kWebuiTestDir =
+ base::FilePath(FILE_PATH_LITERAL("webui"));
+
+const base::FilePath kVirtualKeyboardTestDir =
+ base::FilePath(FILE_PATH_LITERAL("chromeos/virtual_keyboard"));
+
+const base::FilePath kMockController =
+ base::FilePath(FILE_PATH_LITERAL("mock_controller.js"));
+
+const base::FilePath kBaseKeyboardTestFramework =
+ base::FilePath(FILE_PATH_LITERAL("virtual_keyboard_test_base.js"));
+
+} // namespace
+
+class VirtualKeyboardBrowserTest : public InProcessBrowserTest {
+ public:
+
+ /**
+ * Ensure that the virtual keyboard is enabled.
+ */
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ command_line->AppendSwitch(
+ keyboard::switches::kEnableVirtualKeyboard);
+ }
+
+ /**
+ * Injects javascript in |file| into the keyboard page and runs test methods.
+ */
+ void RunTest(const base::FilePath& file) {
+ ui_test_utils::NavigateToURL(browser(), GURL("chrome://keyboard"));
+
+ content::RenderViewHost* rvh = browser()->tab_strip_model()
+ ->GetActiveWebContents()->GetRenderViewHost();
+ ASSERT_TRUE(rvh);
+
+ // Inject testing scripts.
+ InjectJavascript(kWebuiTestDir, kMockController);
+ InjectJavascript(kVirtualKeyboardTestDir, kBaseKeyboardTestFramework);
+ InjectJavascript(kVirtualKeyboardTestDir, file);
+
+ ASSERT_TRUE(content::ExecuteScript(rvh, utf8_content_));
+
+ // Inject DOM-automation test harness and run tests.
+ std::vector<int> resource_ids;
+ EXPECT_TRUE(ExecuteWebUIResourceTest(rvh, resource_ids));
+ }
+
+ private:
+
+ /**
+ * Injects javascript into the keyboard page. The test |file| is in
+ * directory |dir| relative to the root testing directory.
+ */
+ void InjectJavascript(const base::FilePath& dir,
+ const base::FilePath& file) {
+ base::FilePath path = ui_test_utils::GetTestFilePath(dir, file);
+ std::string library_content;
+ ASSERT_TRUE(base::ReadFileToString(path, &library_content))
+ << path.value();
+ utf8_content_.append(library_content);
+ utf8_content_.append(";\n");
+ }
+
+ std::string utf8_content_;
+};
+
+IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, TypingTest) {
+ RunTest(base::FilePath(FILE_PATH_LITERAL("typing_test.js")));
+}
+
+// TODO(kevers|rsadam|bshe): Add UI tests for remaining virtual keyboard
+// functionality.
diff --git a/chrome/browser/chromeos/extensions/wallpaper_api.cc b/chrome/browser/chromeos/extensions/wallpaper_api.cc
index 7bf7679..1f0f785 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_api.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_api.cc
@@ -72,7 +72,7 @@
unsafe_wallpaper_decoder_ = NULL;
if (generate_thumbnail_) {
- wallpaper.EnsureRepsForSupportedScaleFactors();
+ wallpaper.EnsureRepsForSupportedScales();
scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper.DeepCopy());
// Generates thumbnail before call api function callback. We can then
// request thumbnail in the javascript callback.
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
index 2ad4362..9448649 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -8,6 +8,7 @@
#include "ash/shell.h"
#include "ash/wm/mru_window_tracker.h"
+#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
@@ -118,17 +119,16 @@
std::vector<aura::Window*>::iterator last =
std::remove(windows_.begin(), windows_.end(), active_window);
// Removes unfocusable windows.
- last =
- std::remove_if(
- windows_.begin(),
- last,
- std::ptr_fun(ash::wm::IsWindowMinimized));
+ last = std::remove_if(
+ windows_.begin(),
+ last,
+ std::ptr_fun(ash::wm::IsWindowMinimized));
windows_.erase(last, windows_.end());
for (std::vector<aura::Window*>::iterator iter = windows_.begin();
iter != windows_.end(); ++iter) {
(*iter)->AddObserver(this);
- ash::wm::MinimizeWindow(*iter);
+ ash::wm::GetWindowState(*iter)->Minimize();
}
}
@@ -370,7 +370,7 @@
sequence_token_));
std::string file_name = GURL(url_).ExtractFileName();
if (SaveData(chrome::DIR_CHROMEOS_WALLPAPERS, file_name, image_data_)) {
- wallpaper_.EnsureRepsForSupportedScaleFactors();
+ wallpaper_.EnsureRepsForSupportedScales();
scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper_.DeepCopy());
// ImageSkia is not RefCountedThreadSafe. Use a deep copied ImageSkia if
// post to another thread.
@@ -502,7 +502,7 @@
unsafe_wallpaper_decoder_ = NULL;
if (generate_thumbnail_) {
- wallpaper.EnsureRepsForSupportedScaleFactors();
+ wallpaper.EnsureRepsForSupportedScales();
scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper.DeepCopy());
// Generates thumbnail before call api function callback. We can then
// request thumbnail in the javascript callback.
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
index f72c165..e3e0487 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
@@ -5,7 +5,7 @@
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/test_shell_delegate.h"
-#include "ash/wm/window_util.h"
+#include "ash/wm/window_state.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/chromeos/extensions/wallpaper_private_api.h"
#include "ui/aura/root_window.h"
@@ -50,28 +50,33 @@
scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
scoped_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
- ash::wm::MinimizeWindow(window3.get());
- ash::wm::MaximizeWindow(window1.get());
+ ash::wm::WindowState* window0_state = ash::wm::GetWindowState(window0.get());
+ ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1.get());
+ ash::wm::WindowState* window2_state = ash::wm::GetWindowState(window2.get());
+ ash::wm::WindowState* window3_state = ash::wm::GetWindowState(window3.get());
+
+ window3_state->Minimize();
+ window1_state->Maximize();
// Window 3 starts minimized, window 1 starts maximized.
- EXPECT_FALSE(ash::wm::IsWindowMinimized(window0.get()));
- EXPECT_FALSE(ash::wm::IsWindowMinimized(window1.get()));
- EXPECT_FALSE(ash::wm::IsWindowMinimized(window2.get()));
- EXPECT_TRUE(ash::wm::IsWindowMinimized(window3.get()));
+ EXPECT_FALSE(window0_state->IsMinimized());
+ EXPECT_FALSE(window1_state->IsMinimized());
+ EXPECT_FALSE(window2_state->IsMinimized());
+ EXPECT_TRUE(window3_state->IsMinimized());
// We then activate window 0 (i.e. wallpaper picker) and call the minimize
// function.
- ash::wm::ActivateWindow(window0.get());
- EXPECT_TRUE(ash::wm::IsActiveWindow(window0.get()));
+ window0_state->Activate();
+ EXPECT_TRUE(window0_state->IsActive());
scoped_refptr<TestMinimizeFunction> minimize_function(
new TestMinimizeFunction());
EXPECT_TRUE(minimize_function->RunImpl());
// All windows except window 0 should be minimized.
- EXPECT_FALSE(ash::wm::IsWindowMinimized(window0.get()));
- EXPECT_TRUE(ash::wm::IsWindowMinimized(window1.get()));
- EXPECT_TRUE(ash::wm::IsWindowMinimized(window2.get()));
- EXPECT_TRUE(ash::wm::IsWindowMinimized(window3.get()));
+ EXPECT_FALSE(window0_state->IsMinimized());
+ EXPECT_TRUE(window1_state->IsMinimized());
+ EXPECT_TRUE(window2_state->IsMinimized());
+ EXPECT_TRUE(window3_state->IsMinimized());
// Then we destroy window 0 and call the restore function.
window0.reset();
@@ -81,8 +86,8 @@
// Windows 1 and 2 should no longer be minimized. Window 1 should again
// be maximized. Window 3 should still be minimized.
- EXPECT_FALSE(ash::wm::IsWindowMinimized(window1.get()));
- EXPECT_TRUE(ash::wm::IsWindowMaximized(window1.get()));
- EXPECT_FALSE(ash::wm::IsWindowMinimized(window2.get()));
- EXPECT_TRUE(ash::wm::IsWindowMinimized(window3.get()));
+ EXPECT_FALSE(window1_state->IsMinimized());
+ EXPECT_TRUE(window1_state->IsMaximized());
+ EXPECT_FALSE(window2_state->IsMinimized());
+ EXPECT_TRUE(window3_state->IsMinimized());
}
diff --git a/chrome/browser/chromeos/external_metrics.cc b/chrome/browser/chromeos/external_metrics.cc
index 98b62c4..b0ae298 100644
--- a/chrome/browser/chromeos/external_metrics.cc
+++ b/chrome/browser/chromeos/external_metrics.cc
@@ -61,7 +61,8 @@
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::FilePath group_file_path(
+ "/home/chronos/.progressive_scan_variation");
const base::FieldTrial::Probability kDivisor = 1000;
scoped_refptr<base::FieldTrial> trial =
base::FieldTrialList::FactoryGetFieldTrial(
@@ -85,15 +86,13 @@
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())) {
+ int size = static_cast<int>(group_char.length());
+ if (file_util::WriteFile(group_file_path, group_char.c_str(), size) == size) {
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;
+ LOG(ERROR) << "Couldn't write to " << group_file_path.value();
}
}
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index 2c74133..74fce8d 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -22,6 +22,7 @@
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/drive/file_system_interface.h"
+#include "chrome/browser/chromeos/drive/test_util.h"
#include "chrome/browser/chromeos/file_manager/drive_test_util.h"
#include "chrome/browser/drive/fake_drive_service.h"
#include "chrome/browser/extensions/api/test/test_api.h"
@@ -115,13 +116,13 @@
TestEntryInfo(EntryType type,
const std::string& source_file_name,
- const std::string& target_name,
+ const std::string& target_path,
const std::string& mime_type,
SharedOption shared_option,
const base::Time& last_modified_time) :
type(type),
source_file_name(source_file_name),
- target_name(target_name),
+ target_path(target_path),
mime_type(mime_type),
shared_option(shared_option),
last_modified_time(last_modified_time) {
@@ -129,7 +130,7 @@
EntryType type;
std::string source_file_name; // Source file name to be used as a prototype.
- std::string target_name; // Target file or directory name.
+ std::string target_path; // Target file or directory path.
std::string mime_type;
SharedOption shared_option;
base::Time last_modified_time;
@@ -147,7 +148,7 @@
&MapStringToEntryType);
converter->RegisterStringField("sourceFileName",
&TestEntryInfo::source_file_name);
- converter->RegisterStringField("targetName", &TestEntryInfo::target_name);
+ converter->RegisterStringField("targetPath", &TestEntryInfo::target_path);
converter->RegisterStringField("mimeType", &TestEntryInfo::mime_type);
converter->RegisterCustomField("sharedOption",
&TestEntryInfo::shared_option,
@@ -207,10 +208,13 @@
}
void CreateEntry(const TestEntryInfo& entry) {
- base::FilePath target_path = local_path_.AppendASCII(entry.target_name);
+ const base::FilePath target_path =
+ local_path_.AppendASCII(entry.target_path);
+
+ entries_.insert(std::make_pair(target_path, entry));
switch (entry.type) {
case FILE: {
- base::FilePath source_path =
+ const base::FilePath source_path =
google_apis::test_util::GetTestFilePath("chromeos/file_manager").
AppendASCII(entry.source_file_name);
ASSERT_TRUE(base::CopyFile(source_path, target_path))
@@ -223,13 +227,32 @@
"Failed to create a directory: " << target_path.value();
break;
}
- ASSERT_TRUE(
- file_util::SetLastModifiedTime(target_path, entry.last_modified_time));
+ ASSERT_TRUE(UpdateModifiedTime(entry));
}
private:
+ // Updates ModifiedTime of the entry and its parents by referring
+ // TestEntryInfo. Returns true on success.
+ bool UpdateModifiedTime(const TestEntryInfo& entry) {
+ const base::FilePath path = local_path_.AppendASCII(entry.target_path);
+ if (!file_util::SetLastModifiedTime(path, entry.last_modified_time))
+ return false;
+
+ // Update the modified time of parent directories because it may be also
+ // affected by the update of child items.
+ if (path.DirName() != local_path_) {
+ const std::map<base::FilePath, const TestEntryInfo>::iterator it =
+ entries_.find(path.DirName());
+ if (it == entries_.end())
+ return false;
+ return UpdateModifiedTime(it->second);
+ }
+ return true;
+ }
+
base::FilePath local_path_;
base::ScopedTempDir tmp_dir_;
+ std::map<base::FilePath, const TestEntryInfo> entries_;
};
// The drive volume class for test.
@@ -254,32 +277,51 @@
}
void CreateEntry(const TestEntryInfo& entry) {
+ const base::FilePath path =
+ base::FilePath::FromUTF8Unsafe(entry.target_path);
+ const std::string target_name = path.BaseName().AsUTF8Unsafe();
+
+ // Obtain the parent entry.
+ drive::FileError error = drive::FILE_ERROR_OK;
+ scoped_ptr<drive::ResourceEntry> parent_entry(new drive::ResourceEntry);
+ integration_service_->file_system()->GetResourceEntryByPath(
+ drive::util::GetDriveMyDriveRootPath().Append(path).DirName(),
+ google_apis::test_util::CreateCopyResultCallback(
+ &error, &parent_entry));
+ drive::test_util::RunBlockingPoolTask();
+ ASSERT_EQ(drive::FILE_ERROR_OK, error);
+ ASSERT_TRUE(parent_entry);
+
switch (entry.type) {
case FILE:
CreateFile(entry.source_file_name,
- entry.target_name,
+ parent_entry->resource_id(),
+ target_name,
entry.mime_type,
entry.shared_option == SHARED,
entry.last_modified_time);
break;
case DIRECTORY:
- CreateDirectory(entry.target_name, entry.last_modified_time);
+ CreateDirectory(parent_entry->resource_id(),
+ target_name,
+ entry.last_modified_time);
break;
}
}
// Creates an empty directory with the given |name| and |modification_time|.
- void CreateDirectory(const std::string& name,
+ void CreateDirectory(const std::string& parent_id,
+ const std::string& target_name,
const base::Time& modification_time) {
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::ResourceEntry> resource_entry;
fake_drive_service_->AddNewDirectory(
- fake_drive_service_->GetRootResourceId(),
- name,
+ parent_id,
+ target_name,
google_apis::test_util::CreateCopyResultCallback(&error,
&resource_entry));
base::MessageLoop::current()->RunUntilIdle();
- ASSERT_TRUE(error == google_apis::HTTP_CREATED);
+ ASSERT_EQ(google_apis::HTTP_CREATED, error);
ASSERT_TRUE(resource_entry);
fake_drive_service_->SetLastModifiedTime(
@@ -296,7 +338,8 @@
// Creates a test file with the given spec.
// Serves |test_file_name| file. Pass an empty string for an empty file.
void CreateFile(const std::string& source_file_name,
- const std::string& target_file_name,
+ const std::string& parent_id,
+ const std::string& target_name,
const std::string& mime_type,
bool shared_with_me,
const base::Time& modification_time) {
@@ -314,8 +357,8 @@
fake_drive_service_->AddNewFile(
mime_type,
content_data,
- fake_drive_service_->GetRootResourceId(),
- target_file_name,
+ parent_id,
+ target_name,
shared_with_me,
google_apis::test_util::CreateCopyResultCallback(&error,
&resource_entry));
@@ -638,5 +681,12 @@
::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "restoreGeometry"),
TestParameter(IN_GUEST_MODE, "restoreGeometry")));
+INSTANTIATE_TEST_CASE_P(
+ Traverse,
+ FileManagerBrowserTest,
+ ::testing::Values(TestParameter(IN_GUEST_MODE, "traverseDownloads"),
+ TestParameter(NOT_IN_GUEST_MODE, "traverseDownloads"),
+ TestParameter(NOT_IN_GUEST_MODE, "traverseDrive")));
+
} // namespace
} // namespace file_manager
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.cc b/chrome/browser/chromeos/fileapi/file_system_backend.cc
index 0da8d35..33c3f6c 100644
--- a/chrome/browser/chromeos/fileapi/file_system_backend.cc
+++ b/chrome/browser/chromeos/fileapi/file_system_backend.cc
@@ -109,10 +109,13 @@
fileapi::FileSystemType type,
fileapi::OpenFileSystemMode mode,
const OpenFileSystemCallback& callback) {
- DCHECK(fileapi::IsolatedContext::IsIsolatedType(type));
+ DCHECK(CanHandleType(type));
+ // TODO(nhiroki): Avoid this hard-coded mount type to support multiple
+ // filesystems (http://crbug.com/297412).
+ fileapi::FileSystemType mount_type = fileapi::kFileSystemTypeExternal;
// Nothing to validate for external filesystem.
- callback.Run(GetFileSystemRootURI(origin_url, type),
- GetFileSystemName(origin_url, type),
+ callback.Run(GetFileSystemRootURI(origin_url, mount_type),
+ GetFileSystemName(origin_url, mount_type),
base::PLATFORM_FILE_OK);
}
diff --git a/chrome/browser/chromeos/input_method/ibus_controller_impl.cc b/chrome/browser/chromeos/input_method/ibus_controller_impl.cc
index 256937b..ac2a8d0 100644
--- a/chrome/browser/chromeos/input_method/ibus_controller_impl.cc
+++ b/chrome/browser/chromeos/input_method/ibus_controller_impl.cc
@@ -33,154 +33,9 @@
#include "ui/aura/root_window.h"
#include "ui/base/ime/input_method_ibus.h"
-namespace {
-
-// Finds a property which has |new_prop.key| from |prop_list|, and replaces the
-// property with |new_prop|. Returns true if such a property is found.
-bool FindAndUpdateProperty(
- const chromeos::input_method::InputMethodProperty& new_prop,
- chromeos::input_method::InputMethodPropertyList* prop_list) {
- for (size_t i = 0; i < prop_list->size(); ++i) {
- chromeos::input_method::InputMethodProperty& prop = prop_list->at(i);
- if (prop.key == new_prop.key) {
- prop = new_prop;
- return true;
- }
- }
- return false;
-}
-
-} // namespace
-
namespace chromeos {
namespace input_method {
-namespace {
-
-// Returns true if |key| is blacklisted.
-bool PropertyKeyIsBlacklisted(const std::string& key) {
- // The list of input method property keys that we don't handle.
- static const char* kInputMethodPropertyKeysBlacklist[] = {
- "setup", // used in ibus-m17n.
- "status", // used in ibus-m17n.
- };
- for (size_t i = 0; i < arraysize(kInputMethodPropertyKeysBlacklist); ++i) {
- if (key == kInputMethodPropertyKeysBlacklist[i])
- return true;
- }
- return false;
-}
-
-// This function is called by and FlattenProperty() and converts IBus
-// representation of a property, |ibus_prop|, to our own and push_back the
-// result to |out_prop_list|. This function returns true on success, and
-// returns false if sanity checks for |ibus_prop| fail.
-bool ConvertProperty(const IBusProperty& ibus_prop,
- InputMethodPropertyList* out_prop_list) {
- DCHECK(out_prop_list);
- DCHECK(!ibus_prop.key().empty());
- IBusProperty::IBusPropertyType type = ibus_prop.type();
-
- // Sanity checks.
- const bool has_sub_props = !ibus_prop.sub_properties().empty();
- if (has_sub_props && (type != IBusProperty::IBUS_PROPERTY_TYPE_MENU)) {
- DVLOG(1) << "The property has sub properties, "
- << "but the type of the property is not PROP_TYPE_MENU";
- return false;
- }
- if ((!has_sub_props) &&
- (type == IBusProperty::IBUS_PROPERTY_TYPE_MENU)) {
- // This is usually not an error. ibus-daemon sometimes sends empty props.
- DVLOG(1) << "Property list is empty";
- return false;
- }
- if (type == IBusProperty::IBUS_PROPERTY_TYPE_SEPARATOR ||
- type == IBusProperty::IBUS_PROPERTY_TYPE_MENU) {
- // This is not an error, but we don't push an item for these types.
- return true;
- }
-
- // This label will be localized later.
- // See chrome/browser/chromeos/input_method/input_method_util.cc.
- std::string label_to_use;
- if (!ibus_prop.tooltip().empty())
- label_to_use = ibus_prop.tooltip();
- else if (!ibus_prop.label().empty())
- label_to_use = ibus_prop.label();
- else
- label_to_use = ibus_prop.key();
-
- out_prop_list->push_back(InputMethodProperty(
- ibus_prop.key(),
- label_to_use,
- (type == IBusProperty::IBUS_PROPERTY_TYPE_RADIO),
- ibus_prop.checked()));
- return true;
-}
-
-// Converts |ibus_prop| to |out_prop_list|. Please note that |ibus_prop|
-// may or may not have children. See the comment for FlattenPropertyList
-// for details. Returns true if no error is found.
-bool FlattenProperty(const IBusProperty& ibus_prop,
- InputMethodPropertyList* out_prop_list) {
- DCHECK(out_prop_list);
-
- // Filter out unnecessary properties.
- if (PropertyKeyIsBlacklisted(ibus_prop.key()))
- return true;
-
- // Convert |prop| to InputMethodProperty and push it to |out_prop_list|.
- if (!ConvertProperty(ibus_prop, out_prop_list))
- return false;
-
- // Process childrens iteratively (if any). Push all sub properties to the
- // stack.
- if (!ibus_prop.sub_properties().empty()) {
- const IBusPropertyList& sub_props = ibus_prop.sub_properties();
- for (size_t i = 0; i < sub_props.size(); ++i) {
- if (!FlattenProperty(*sub_props[i], out_prop_list))
- return false;
- }
- }
- return true;
-}
-
-// Converts IBus representation of a property list, |ibus_prop_list| to our
-// own. This function also flatten the original list (actually it's a tree).
-// Returns true if no error is found. The conversion to our own type is
-// necessary since our language switcher in Chrome tree don't (or can't) know
-// IBus types. Here is an example:
-//
-// ======================================================================
-// Input:
-//
-// --- Item-1
-// |- Item-2
-// |- SubMenuRoot --- Item-3-1
-// | |- Item-3-2
-// | |- Item-3-3
-// |- Item-4
-//
-// (Note: Item-3-X is a selection item since they're on a sub menu.)
-//
-// Output:
-//
-// Item-1, Item-2, Item-3-1, Item-3-2, Item-3-3, Item-4
-// (Note: SubMenuRoot does not appear in the output.)
-// ======================================================================
-bool FlattenPropertyList(const IBusPropertyList& ibus_prop_list,
- InputMethodPropertyList* out_prop_list) {
- DCHECK(out_prop_list);
-
- bool result = true;
- for (size_t i = 0; i < ibus_prop_list.size(); ++i) {
- result &= FlattenProperty(*ibus_prop_list[i], out_prop_list);
- }
- return result;
-}
-
-} // namespace
-
IBusControllerImpl::IBusControllerImpl() {
IBusBridge::Get()->SetPropertyHandler(this);
}
@@ -230,36 +85,10 @@
}
void IBusControllerImpl::RegisterProperties(
- const IBusPropertyList& ibus_prop_list) {
- current_property_list_.clear();
- if (!FlattenPropertyList(ibus_prop_list, ¤t_property_list_))
- current_property_list_.clear(); // Clear properties on errors.
+ const InputMethodPropertyList& ibus_prop_list) {
+ current_property_list_ = ibus_prop_list;
FOR_EACH_OBSERVER(IBusController::Observer, observers_, PropertyChanged());
}
-void IBusControllerImpl::UpdateProperty(const IBusProperty& ibus_prop) {
- InputMethodPropertyList prop_list; // our representation.
- if (!FlattenProperty(ibus_prop, &prop_list)) {
- // Don't update the UI on errors.
- DVLOG(1) << "Malformed properties are detected";
- return;
- }
-
- // Notify the change.
- if (!prop_list.empty()) {
- for (size_t i = 0; i < prop_list.size(); ++i) {
- FindAndUpdateProperty(prop_list[i], ¤t_property_list_);
- }
- FOR_EACH_OBSERVER(IBusController::Observer, observers_, PropertyChanged());
- }
-}
-
-// static
-bool IBusControllerImpl::FindAndUpdatePropertyForTesting(
- const chromeos::input_method::InputMethodProperty& new_prop,
- chromeos::input_method::InputMethodPropertyList* prop_list) {
- return FindAndUpdateProperty(new_prop, prop_list);
-}
-
} // namespace input_method
} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/ibus_controller_impl.h b/chrome/browser/chromeos/input_method/ibus_controller_impl.h
index 45de917..96f8b75 100644
--- a/chrome/browser/chromeos/input_method/ibus_controller_impl.h
+++ b/chrome/browser/chromeos/input_method/ibus_controller_impl.h
@@ -16,9 +16,6 @@
namespace chromeos {
namespace input_method {
-struct InputMethodProperty;
-typedef std::vector<InputMethodProperty> InputMethodPropertyList;
-
// The IBusController implementation.
class IBusControllerImpl : public IBusController,
public IBusPanelPropertyHandlerInterface {
@@ -36,12 +33,6 @@
virtual const InputMethodPropertyList& GetCurrentProperties() const OVERRIDE;
virtual void ClearProperties() OVERRIDE;
- // Calls <anonymous_namespace>::FindAndUpdateProperty. This method is just for
- // unit testing.
- static bool FindAndUpdatePropertyForTesting(
- const InputMethodProperty& new_prop,
- InputMethodPropertyList* prop_list);
-
protected:
ObserverList<Observer> observers_;
@@ -52,8 +43,7 @@
private:
// IBusPanelPropertyHandlerInterface overrides:
virtual void RegisterProperties(
- const IBusPropertyList& properties) OVERRIDE;
- virtual void UpdateProperty(const IBusProperty& property) OVERRIDE;
+ const InputMethodPropertyList& properties) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(IBusControllerImpl);
};
diff --git a/chrome/browser/chromeos/input_method/ibus_controller_impl_unittest.cc b/chrome/browser/chromeos/input_method/ibus_controller_impl_unittest.cc
index da9afcf..109a8c9 100644
--- a/chrome/browser/chromeos/input_method/ibus_controller_impl_unittest.cc
+++ b/chrome/browser/chromeos/input_method/ibus_controller_impl_unittest.cc
@@ -12,12 +12,6 @@
namespace {
-bool FindAndUpdateProperty(const InputMethodProperty& new_prop,
- InputMethodPropertyList* prop_list) {
- return IBusControllerImpl::FindAndUpdatePropertyForTesting(new_prop,
- prop_list);
-}
-
// A mock class for testing AddObserver() and RemoveObserver() methods
// in IBusControllerImpl.
class TestIBusController : public IBusControllerImpl {
@@ -43,35 +37,6 @@
};
} // namespace
-TEST(IBusControllerImplTest, TestFindAndUpdateProperty) {
- InputMethodPropertyList properties;
- EXPECT_FALSE(FindAndUpdateProperty(InputMethodProperty(), &properties));
-
- properties.push_back(
- InputMethodProperty("key1", "label1", false, false));
- EXPECT_FALSE(FindAndUpdateProperty(InputMethodProperty(), &properties));
- EXPECT_FALSE(FindAndUpdateProperty(
- InputMethodProperty("keyX", "labelX", false, false), &properties));
- EXPECT_EQ(InputMethodProperty("key1", "label1", false, false),
- properties[0]);
- EXPECT_TRUE(FindAndUpdateProperty(
- InputMethodProperty("key1", "labelY", false, false), &properties));
- EXPECT_EQ(InputMethodProperty("key1", "labelY", false, false),
- properties[0]);
-
- properties.push_back(
- InputMethodProperty("key2", "label2", false, false));
- EXPECT_FALSE(FindAndUpdateProperty(InputMethodProperty(), &properties));
- EXPECT_FALSE(FindAndUpdateProperty(
- InputMethodProperty("keyX", "labelX", false, false), &properties));
- EXPECT_EQ(InputMethodProperty("key2", "label2", false, false),
- properties[1]);
- EXPECT_TRUE(FindAndUpdateProperty(
- InputMethodProperty("key2", "labelZ", false, false), &properties));
- EXPECT_EQ(InputMethodProperty("key2", "labelZ", false, false),
- properties[1]);
-}
-
TEST(IBusControllerImplTest, TestAddRemoveObserver) {
IBusBridge::Initialize();
{
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 6320ff9..c7bd462 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_ibus.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_ibus.cc
@@ -103,7 +103,7 @@
component_->set_author(engine_name);
// TODO(nona): Remove IBusComponent once ibus is gone.
- chromeos::IBusComponent::EngineDescription engine_desc;
+ IBusComponent::EngineDescription engine_desc;
engine_desc.engine_id = ibus_id_;
engine_desc.display_name = description;
engine_desc.description = description;
@@ -179,7 +179,7 @@
*preedit_text_.get(),
preedit_cursor_,
true,
- chromeos::IBusEngineService::IBUS_ENGINE_PREEEDIT_FOCUS_OUT_MODE_COMMIT);
+ IBusEngineService::IBUS_ENGINE_PREEEDIT_FOCUS_OUT_MODE_COMMIT);
return true;
}
@@ -200,7 +200,7 @@
*preedit_text_.get(),
0,
false,
- chromeos::IBusEngineService::IBUS_ENGINE_PREEEDIT_FOCUS_OUT_MODE_COMMIT);
+ IBusEngineService::IBUS_ENGINE_PREEEDIT_FOCUS_OUT_MODE_COMMIT);
return true;
}
@@ -372,27 +372,7 @@
}
bool InputMethodEngineIBus::SetMenuItems(const std::vector<MenuItem>& items) {
- if (!active_)
- return false;
-
- IBusPropertyList properties;
- for (std::vector<MenuItem>::const_iterator item = items.begin();
- item != items.end(); ++item) {
- IBusProperty* property = new IBusProperty();
- if (!MenuItemToProperty(*item, property)) {
- delete property;
- DVLOG(1) << "Bad menu item";
- return false;
- }
- properties.push_back(property);
- }
-
- IBusPanelPropertyHandlerInterface* handler =
- IBusBridge::Get()->GetPropertyHandler();
- if (handler)
- handler->RegisterProperties(properties);
-
- return true;
+ return UpdateMenuItems(items);
}
bool InputMethodEngineIBus::UpdateMenuItems(
@@ -400,22 +380,18 @@
if (!active_)
return false;
- IBusPropertyList properties;
+ input_method::InputMethodPropertyList property_list;
for (std::vector<MenuItem>::const_iterator item = items.begin();
item != items.end(); ++item) {
- IBusProperty* property = new IBusProperty();
- if (!MenuItemToProperty(*item, property)) {
- delete property;
- DVLOG(1) << "Bad menu item";
- return false;
- }
- properties.push_back(property);
+ input_method::InputMethodProperty property;
+ MenuItemToProperty(*item, &property);
+ property_list.push_back(property);
}
IBusPanelPropertyHandlerInterface* handler =
IBusBridge::Get()->GetPropertyHandler();
if (handler)
- handler->RegisterProperties(properties);
+ handler->RegisterProperties(property_list);
return true;
}
@@ -578,59 +554,45 @@
return DBusThreadManager::Get()->GetIBusEngineService(object_path_);
}
-bool InputMethodEngineIBus::MenuItemToProperty(
+void InputMethodEngineIBus::MenuItemToProperty(
const MenuItem& item,
- IBusProperty* property) {
- property->set_key(item.id);
+ input_method::InputMethodProperty* property) {
+ property->key = item.id;
if (item.modified & MENU_ITEM_MODIFIED_LABEL) {
- property->set_label(item.label);
+ property->label = item.label;
}
if (item.modified & MENU_ITEM_MODIFIED_VISIBLE) {
- property->set_visible(item.visible);
+ // TODO(nona): Implement it.
}
if (item.modified & MENU_ITEM_MODIFIED_CHECKED) {
- property->set_checked(item.checked);
+ property->is_selection_item_checked = item.checked;
}
if (item.modified & MENU_ITEM_MODIFIED_ENABLED) {
// TODO(nona): implement sensitive entry(crbug.com/140192).
}
if (item.modified & MENU_ITEM_MODIFIED_STYLE) {
- IBusProperty::IBusPropertyType type =
- IBusProperty::IBUS_PROPERTY_TYPE_NORMAL;
if (!item.children.empty()) {
- type = IBusProperty::IBUS_PROPERTY_TYPE_MENU;
+ // TODO(nona): Implement it.
} else {
switch (item.style) {
case MENU_ITEM_STYLE_NONE:
- type = IBusProperty::IBUS_PROPERTY_TYPE_NORMAL;
+ NOTREACHED();
break;
case MENU_ITEM_STYLE_CHECK:
- type = IBusProperty::IBUS_PROPERTY_TYPE_TOGGLE;
+ // TODO(nona): Implement it.
break;
case MENU_ITEM_STYLE_RADIO:
- type = IBusProperty::IBUS_PROPERTY_TYPE_RADIO;
+ property->is_selection_item = true;
break;
case MENU_ITEM_STYLE_SEPARATOR:
- type = IBusProperty::IBUS_PROPERTY_TYPE_SEPARATOR;
+ // TODO(nona): Implement it.
break;
}
}
- property->set_type(type);
}
- for (std::vector<MenuItem>::const_iterator child = item.children.begin();
- child != item.children.end(); ++child) {
- IBusProperty* new_property = new IBusProperty();
- if (!MenuItemToProperty(*child, new_property)) {
- delete new_property;
- DVLOG(1) << "Bad menu item child";
- return false;
- }
- property->mutable_sub_properties()->push_back(new_property);
- }
-
- return true;
+ // TODO(nona): Support item.children.
}
void InputMethodEngineIBus::OnConnected() {
@@ -645,8 +607,7 @@
}
void InputMethodEngineIBus::RegisterComponent() {
- chromeos::IBusClient* client =
- chromeos::DBusThreadManager::Get()->GetIBusClient();
+ IBusClient* client = DBusThreadManager::Get()->GetIBusClient();
client->RegisterComponent(
*component_.get(),
base::Bind(&InputMethodEngineIBus::OnComponentRegistered,
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_ibus.h b/chrome/browser/chromeos/input_method/input_method_engine_ibus.h
index aeb8080..7de9e19 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_ibus.h
+++ b/chrome/browser/chromeos/input_method/input_method_engine_ibus.h
@@ -108,8 +108,9 @@
// Returns true if the connection to ibus-daemon is avaiable.
bool IsConnected();
- // Converts MenuItem to IBusProperty.
- bool MenuItemToProperty(const MenuItem& item, IBusProperty* property);
+ // Converts MenuItem to InputMethodProperty.
+ void MenuItemToProperty(const MenuItem& item,
+ input_method::InputMethodProperty* property);
// Registers the engine component.
void RegisterComponent();
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 026f263..90c4ffc 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
@@ -753,29 +753,26 @@
host->host_contents(), set_menu_item_test_script));
EXPECT_EQ(1, mock_property->register_properties_call_count());
- const IBusPropertyList& props =
+ const InputMethodPropertyList& props =
mock_property->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("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("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[2].is_selection_item);
+ // TODO(nona): Add tests for style: ["toggle" and "separator"]
+ // and visible:, when implement them.
- EXPECT_TRUE(props[3]->visible());
- EXPECT_TRUE(props[4]->visible());
-
- EXPECT_TRUE(props[4]->checked());
+ EXPECT_TRUE(props[4].is_selection_item_checked);
}
{
SCOPED_TRACE("deleteSurroundingText test");
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 d7f227a..fb01418 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -427,20 +427,10 @@
FOR_EACH_OBSERVER(InputMethodManager::Observer,
observers_,
InputMethodPropertyChanged(this));
- // Hack for fixing http://crosbug.com/p/12798
- // We should notify IME switching to ibus-daemon, otherwise
- // IBusPreeditFocusMode does not work. To achieve it, change engine to
- // itself if the next engine is XKB layout.
- if (current_input_method_id.empty() ||
- InputMethodUtil::IsKeyboardLayout(current_input_method_id)) {
- if (engine)
- engine->Reset();
- } else {
- if (client)
- client->SetGlobalEngine(current_input_method_id,
- base::Bind(&base::DoNothing));
+ if (engine) {
+ engine->Disable();
+ IBusBridge::Get()->SetEngineHandler(NULL);
}
- IBusBridge::Get()->SetEngineHandler(NULL);
} else {
DCHECK(client);
client->SetGlobalEngine(input_method_id_to_switch,
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 ea2276b..1557173 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
@@ -1111,15 +1111,15 @@
ids.push_back(nacl_mozc_us_id);
EXPECT_TRUE(manager_->EnableInputMethods(ids));
EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
- EXPECT_EQ(1, mock_engine_handler_->reset_call_count());
+ EXPECT_EQ(0, mock_engine_handler_->reset_call_count());
manager_->ChangeInputMethod(nacl_mozc_us_id);
EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
EXPECT_EQ(nacl_mozc_us_id, mock_ibus_client_->latest_global_engine_name());
- EXPECT_EQ(1, mock_engine_handler_->reset_call_count());
+ EXPECT_EQ(0, mock_engine_handler_->reset_call_count());
manager_->ChangeInputMethod("xkb:us::eng");
- EXPECT_EQ(2, mock_ibus_client_->set_global_engine_call_count());
+ EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
EXPECT_EQ(nacl_mozc_us_id, mock_ibus_client_->latest_global_engine_name());
- EXPECT_EQ(1, mock_engine_handler_->reset_call_count());
+ EXPECT_EQ(0, mock_engine_handler_->reset_call_count());
}
TEST_F(InputMethodManagerImplTest,
diff --git a/chrome/browser/chromeos/input_method/keyboard_browsertest.cc b/chrome/browser/chromeos/input_method/keyboard_browsertest.cc
deleted file mode 100644
index fb3579d..0000000
--- a/chrome/browser/chromeos/input_method/keyboard_browsertest.cc
+++ /dev/null
@@ -1,96 +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/chromeos/input_method/textinput_test_helper.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/test/base/interactive_test_utils.h"
-#include "content/public/test/browser_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chromeos {
-
-typedef TextInputTestBase KeyboardEventEndToEndTest;
-
-// Flaky test: 268049
-IN_PROC_BROWSER_TEST_F(KeyboardEventEndToEndTest,
- DISABLED_AltGrToCtrlAltKeyDown) {
- TextInputTestHelper helper;
-
- GURL url = ui_test_utils::GetTestUrl(
- base::FilePath(FILE_PATH_LITERAL("textinput")),
- base::FilePath(FILE_PATH_LITERAL("keyevent_logging.html")));
- ui_test_utils::NavigateToURL(browser(), url);
-
- content::WebContents* tab =
- browser()->tab_strip_model()->GetActiveWebContents();
-
- helper.ClickElement("text_id", tab);
- helper.WaitForTextInputStateChanged(ui::TEXT_INPUT_TYPE_TEXT);
-
- {
- ASSERT_TRUE(content::ExecuteScript(
- tab,
- "initKeyDownExpectations(["
- // Alt down has (only) altKey true in this case.
- "{ keyCode:18, shiftKey:false, ctrlKey:false, altKey:true }]);"));
- EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(),
- ui::VKEY_MENU,
- false,
- false,
- false,
- false));
- bool result = false;
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- tab,
- "didTestSucceed();",
- &result));
- EXPECT_TRUE(result);
- }
- {
- ASSERT_TRUE(content::ExecuteScript(
- tab,
- "initKeyDownExpectations(["
- // Ctrl down has (only) ctrlKey true in this case.
- "{ keyCode:17, shiftKey:false, ctrlKey:true, altKey:false }]);"));
- EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(),
- ui::VKEY_CONTROL,
- false,
- false,
- false,
- false));
- bool result = false;
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- tab,
- "didTestSucceed();",
- &result));
- EXPECT_TRUE(result);
- }
- {
- ASSERT_TRUE(content::ExecuteScript(
- tab,
- "initKeyDownExpectations(["
- // Ctrl down has ctrlKey false in this case.
- "{ keyCode:17, shiftKey:false , ctrlKey:false , altKey:false },"
- // Alt down has altKey false in this case.
- "{ keyCode:18, shiftKey:false , ctrlKey:false , altKey:false }]);"));
- EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(),
- ui::VKEY_ALTGR,
- false,
- false,
- false,
- false));
- bool result = false;
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- tab,
- "didTestSucceed();",
- &result));
- EXPECT_TRUE(result);
- }
-}
-
-// TODO(nona): Add AltGr modifier test. Need to add AltGr handling into
-// SendKeyPressSync(crbug.com/262928).
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc b/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc
index bad1aaa..8763eba 100644
--- a/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc
+++ b/chrome/browser/chromeos/keyboard_driven_event_rewriter_unittest.cc
@@ -7,8 +7,8 @@
#include "base/strings/stringprintf.h"
#include "chrome/browser/chromeos/keyboard_driven_event_rewriter.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/x/x11_util.h"
#include "ui/events/event.h"
+#include "ui/events/x/events_x_utils.h"
#include <X11/keysym.h>
#include <X11/XF86keysym.h>
@@ -35,7 +35,7 @@
class KeyboardDrivenEventRewriterTest : public testing::Test {
public:
KeyboardDrivenEventRewriterTest()
- : display_(ui::GetXDisplay()),
+ : display_(gfx::GetXDisplay()),
keycode_a_(XKeysymToKeycode(display_, XK_a)),
keycode_up_(XKeysymToKeycode(display_, XK_Up)),
keycode_down_(XKeysymToKeycode(display_, XK_Down)),
@@ -64,7 +64,7 @@
return base::StringPrintf("ui_flags=%d x_state=%u", ui_flags, x_state);
}
- Display* display_;
+ XDisplay* display_;
const KeyCode keycode_a_;
const KeyCode keycode_up_;
const KeyCode keycode_down_;
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 397eca1..dded032 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -36,6 +36,7 @@
#include "media/base/media_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/compositor_switches.h"
+#include "ui/events/event_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "ui/views/corewm/corewm_switches.h"
@@ -75,6 +76,7 @@
::switches::kDisableAcceleratedPlugins,
::switches::kDisableAcceleratedVideoDecode,
::switches::kDisableBrowserPluginCompositing,
+ ::switches::kDisableDeadlineScheduling,
::switches::kDisableDelegatedRenderer,
::switches::kDisableForceCompositingMode,
::switches::kDisableGpuShaderDiskCache,
@@ -92,8 +94,9 @@
::switches::kEnableAcceleratedFixedRootBackground,
::switches::kEnableAcceleratedOverflowScroll,
::switches::kEnableBeginFrameScheduling,
- ::switches::kEnableBrowserInputController,
+ ::switches::kEnableBufferedInputRouter,
::switches::kEnableCompositingForFixedPosition,
+ ::switches::kEnableDeadlineScheduling,
::switches::kEnableDelegatedRenderer,
::switches::kEnableEncryptedMedia,
::switches::kEnableGestureTapHighlight,
@@ -125,7 +128,9 @@
::switches::kTouchDevices,
::switches::kTouchEvents,
::switches::kTouchOptimizedUI,
+ ::switches::kUIDisableDeadlineScheduling,
::switches::kUIDisableThreadedCompositing,
+ ::switches::kUIEnableDeadlineScheduling,
::switches::kUIMaxFramesPending,
::switches::kUIPrioritizeInGpuProcess,
#if defined(USE_CRAS)
@@ -139,6 +144,7 @@
#if defined(ENABLE_WEBRTC)
::switches::kDisableWebRtcHWDecoding,
::switches::kDisableWebRtcHWEncoding,
+ ::switches::kEnableWebRtcHWVp8Encoding,
#endif
ash::switches::kAshDefaultGuestWallpaperLarge,
ash::switches::kAshDefaultGuestWallpaperSmall,
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
index ee3c249..8224331 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
@@ -19,6 +19,7 @@
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/policy/cloud/enterprise_metrics.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/session_manager_client.h"
#include "google_apis/gaia/gaia_auth_util.h"
@@ -34,9 +35,6 @@
policy::kMetricEnrollmentSize);
}
-// Does nothing. Used as a VoidDBusMethodCallback.
-void EmptyVoidDBusMethodCallback(DBusMethodCallStatus result) {}
-
} // namespace
EnrollmentScreen::EnrollmentScreen(
@@ -52,7 +50,7 @@
// Init the TPM if it has not been done until now (in debug build we might
// have not done that yet).
DBusThreadManager::Get()->GetCryptohomeClient()->TpmCanAttemptOwnership(
- base::Bind(&EmptyVoidDBusMethodCallback));
+ EmptyVoidDBusMethodCallback());
}
EnrollmentScreen::~EnrollmentScreen() {}
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 5530fb7..6488898 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -151,16 +151,32 @@
registrar_.Add(this,
chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources());
- cros_settings_->AddSettingsObserver(kAccountsPrefShowUserNamesOnSignIn, this);
- cros_settings_->AddSettingsObserver(kAccountsPrefAllowNewUser, this);
- cros_settings_->AddSettingsObserver(kAccountsPrefAllowGuest, this);
- cros_settings_->AddSettingsObserver(kAccountsPrefUsers, this);
- cros_settings_->AddSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginId,
- this);
- cros_settings_->AddSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginDelay,
- this);
+ show_user_names_subscription_ = cros_settings_->AddSettingsObserver(
+ kAccountsPrefShowUserNamesOnSignIn,
+ base::Bind(&ExistingUserController::DeviceSettingsChanged,
+ base::Unretained(this)));
+ allow_new_user_subscription_ = cros_settings_->AddSettingsObserver(
+ kAccountsPrefAllowNewUser,
+ base::Bind(&ExistingUserController::DeviceSettingsChanged,
+ base::Unretained(this)));
+ allow_guest_subscription_ = cros_settings_->AddSettingsObserver(
+ kAccountsPrefAllowGuest,
+ base::Bind(&ExistingUserController::DeviceSettingsChanged,
+ base::Unretained(this)));
+ users_subscription_ = cros_settings_->AddSettingsObserver(
+ kAccountsPrefUsers,
+ base::Bind(&ExistingUserController::DeviceSettingsChanged,
+ base::Unretained(this)));
+ local_account_auto_login_id_subscription_ =
+ cros_settings_->AddSettingsObserver(
+ kAccountsPrefDeviceLocalAccountAutoLoginId,
+ base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
+ base::Unretained(this)));
+ local_account_auto_login_delay_subscription_ =
+ cros_settings_->AddSettingsObserver(
+ kAccountsPrefDeviceLocalAccountAutoLoginDelay,
+ base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
+ base::Unretained(this)));
}
void ExistingUserController::Init(const UserList& users) {
@@ -232,22 +248,9 @@
registrar_.RemoveAll();
return;
}
- if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED) {
- const std::string setting = *content::Details<const std::string>(
- details).ptr();
- if (setting == kAccountsPrefDeviceLocalAccountAutoLoginId ||
- setting == kAccountsPrefDeviceLocalAccountAutoLoginDelay) {
- ConfigurePublicSessionAutoLogin();
- }
- }
- if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED ||
- type == chrome::NOTIFICATION_USER_LIST_CHANGED) {
- if (host_ != NULL) {
- // Signed settings or user list changed. Notify views and update them.
- UpdateLoginDisplay(chromeos::UserManager::Get()->GetUsers());
- ConfigurePublicSessionAutoLogin();
- return;
- }
+ if (type == chrome::NOTIFICATION_USER_LIST_CHANGED) {
+ DeviceSettingsChanged();
+ return;
}
if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
// Possibly the user has authenticated against a proxy server and we might
@@ -285,18 +288,6 @@
ExistingUserController::~ExistingUserController() {
LoginUtils::Get()->DelegateDeleted(this);
- cros_settings_->RemoveSettingsObserver(kAccountsPrefShowUserNamesOnSignIn,
- this);
- cros_settings_->RemoveSettingsObserver(kAccountsPrefAllowNewUser, this);
- cros_settings_->RemoveSettingsObserver(kAccountsPrefAllowGuest, this);
- cros_settings_->RemoveSettingsObserver(kAccountsPrefUsers, this);
- cros_settings_->RemoveSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginId,
- this);
- cros_settings_->RemoveSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginDelay,
- this);
-
if (current_controller_ == this) {
current_controller_ = NULL;
} else {
@@ -940,6 +931,15 @@
////////////////////////////////////////////////////////////////////////////////
// ExistingUserController, private:
+void ExistingUserController::DeviceSettingsChanged() {
+ if (host_ != NULL) {
+ // Signed settings or user list changed. Notify views and update them.
+ UpdateLoginDisplay(chromeos::UserManager::Get()->GetUsers());
+ ConfigurePublicSessionAutoLogin();
+ return;
+ }
+}
+
void ExistingUserController::ActivateWizard(const std::string& screen_name) {
scoped_ptr<DictionaryValue> params;
host_->StartWizard(screen_name, params.Pass());
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index dde8e6e..80fbcd5 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -21,6 +21,7 @@
#include "chrome/browser/chromeos/login/login_performer.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/user.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -147,6 +148,9 @@
// LoginUtils::Delegate implementation:
virtual void OnProfilePrepared(Profile* profile) OVERRIDE;
+ // Called when device settings change.
+ void DeviceSettingsChanged();
+
// Starts WizardController with the specified screen.
void ActivateWizard(const std::string& screen_name);
@@ -298,6 +302,15 @@
scoped_ptr<login::NetworkStateHelper> network_state_helper_;
+ scoped_ptr<CrosSettings::ObserverSubscription> show_user_names_subscription_;
+ scoped_ptr<CrosSettings::ObserverSubscription> allow_new_user_subscription_;
+ scoped_ptr<CrosSettings::ObserverSubscription> allow_guest_subscription_;
+ scoped_ptr<CrosSettings::ObserverSubscription> users_subscription_;
+ scoped_ptr<CrosSettings::ObserverSubscription>
+ local_account_auto_login_id_subscription_;
+ scoped_ptr<CrosSettings::ObserverSubscription>
+ local_account_auto_login_delay_subscription_;
+
FRIEND_TEST_ALL_PREFIXES(ExistingUserControllerTest, ExistingUserLogin);
DISALLOW_COPY_AND_ASSIGN(ExistingUserController);
diff --git a/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc b/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc
index 128f1b8..68e267c 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc
@@ -87,12 +87,10 @@
CrosSettings::Get()->Set(kAccountsPrefDeviceLocalAccounts, accounts);
// Prevent settings changes from auto-starting the timer.
- CrosSettings::Get()->RemoveSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginId,
- existing_user_controller());
- CrosSettings::Get()->RemoveSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginDelay,
- existing_user_controller());
+ existing_user_controller_->
+ local_account_auto_login_id_subscription_.reset();
+ existing_user_controller_->
+ local_account_auto_login_delay_subscription_.reset();
}
const ExistingUserController* existing_user_controller() const {
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
index e327615..33aae88 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/location.h"
+#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/authenticator.h"
@@ -452,40 +453,34 @@
.Times(0);
}
- scoped_ptr<base::RunLoop> CreateSettingsObserverRunLoop(
- content::MockNotificationObserver& observer, const char* setting) {
- base::RunLoop* loop = new base::RunLoop;
- EXPECT_CALL(observer, Observe(chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED,
- _, HasDetails(setting)))
- .Times(1)
- .WillOnce(InvokeWithoutArgs(loop, &base::RunLoop::Quit));
- CrosSettings::Get()->AddSettingsObserver(setting, &observer);
- return make_scoped_ptr(loop);
- }
-
void SetAutoLoginPolicy(const std::string& username, int delay) {
// Wait until ExistingUserController has finished auto-login
// configuration by observing the same settings that trigger
// ConfigurePublicSessionAutoLogin.
- content::MockNotificationObserver observer;
em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
// If both settings have changed we need to wait for both to
// propagate, so check the new values against the old ones.
- scoped_ptr<base::RunLoop> runner1;
+ scoped_refptr<content::MessageLoopRunner> runner1;
+ scoped_ptr<CrosSettings::ObserverSubscription> subscription1;
if (!proto.has_device_local_accounts() ||
!proto.device_local_accounts().has_auto_login_id() ||
proto.device_local_accounts().auto_login_id() != username) {
- runner1 = CreateSettingsObserverRunLoop(
- observer, kAccountsPrefDeviceLocalAccountAutoLoginId);
+ runner1 = new content::MessageLoopRunner;
+ subscription1 = chromeos::CrosSettings::Get()->AddSettingsObserver(
+ chromeos::kAccountsPrefDeviceLocalAccountAutoLoginId,
+ runner1->QuitClosure());
}
- scoped_ptr<base::RunLoop> runner2;
+ scoped_refptr<content::MessageLoopRunner> runner2;
+ scoped_ptr<CrosSettings::ObserverSubscription> subscription2;
if (!proto.has_device_local_accounts() ||
!proto.device_local_accounts().has_auto_login_delay() ||
proto.device_local_accounts().auto_login_delay() != delay) {
- runner2 = CreateSettingsObserverRunLoop(
- observer, kAccountsPrefDeviceLocalAccountAutoLoginDelay);
+ runner1 = new content::MessageLoopRunner;
+ subscription1 = chromeos::CrosSettings::Get()->AddSettingsObserver(
+ chromeos::kAccountsPrefDeviceLocalAccountAutoLoginDelay,
+ runner1->QuitClosure());
}
// Update the policy.
@@ -494,18 +489,10 @@
RefreshDevicePolicy();
// Wait for ExistingUserController to read the updated settings.
- if (runner1)
+ if (runner1.get())
runner1->Run();
- if (runner2)
+ if (runner2.get())
runner2->Run();
-
- // Clean up.
- CrosSettings::Get()->RemoveSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginId,
- &observer);
- CrosSettings::Get()->RemoveSettingsObserver(
- kAccountsPrefDeviceLocalAccountAutoLoginDelay,
- &observer);
}
void ConfigureAutoLogin() {
diff --git a/chrome/browser/chromeos/login/fake_login_utils.cc b/chrome/browser/chromeos/login/fake_login_utils.cc
index 91100d3..555b581 100644
--- a/chrome/browser/chromeos/login/fake_login_utils.cc
+++ b/chrome/browser/chromeos/login/fake_login_utils.cc
@@ -63,7 +63,10 @@
if (should_launch_browser_) {
profile = CreateProfile(user_context.username);
} else {
- profile = new TestingProfile();
+ TestingProfile* testing_profile = new TestingProfile();
+ testing_profile->set_profile_name(user_context.username);
+
+ profile = testing_profile;
g_browser_process->profile_manager()->
RegisterTestingProfile(profile, false, false);
}
diff --git a/chrome/browser/chromeos/login/fake_user_manager.cc b/chrome/browser/chromeos/login/fake_user_manager.cc
new file mode 100644
index 0000000..007ce1a
--- /dev/null
+++ b/chrome/browser/chromeos/login/fake_user_manager.cc
@@ -0,0 +1,284 @@
+// Copyright 2013 The Chromium 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/login/fake_user_manager.h"
+
+namespace {
+
+// As defined in /chromeos/dbus/cryptohome_client.cc.
+static const char kUserIdHashSuffix[] = "-hash";
+
+} // namespace
+
+namespace chromeos {
+
+FakeUserManager::FakeUserManager() : primary_user_(NULL) {}
+
+FakeUserManager::~FakeUserManager() {
+ // Can't use STLDeleteElements because of the private destructor of User.
+ for (UserList::iterator it = user_list_.begin(); it != user_list_.end();
+ it = user_list_.erase(it)) {
+ delete *it;
+ }
+}
+
+void FakeUserManager::AddUser(const std::string& email) {
+ User* user = User::CreateRegularUser(email);
+ user->set_username_hash(email + kUserIdHashSuffix);
+ user->SetStubImage(User::kProfileImageIndex, false);
+ user_list_.push_back(user);
+}
+
+void FakeUserManager::AddKioskAppUser(const std::string& kiosk_app_username) {
+ User* user = User::CreateKioskAppUser(kiosk_app_username);
+ user->set_username_hash(kiosk_app_username + kUserIdHashSuffix);
+ user_list_.push_back(user);
+}
+
+void FakeUserManager::LoginUser(const std::string& email) {
+ UserLoggedIn(email, email + kUserIdHashSuffix, false);
+}
+
+const UserList& FakeUserManager::GetUsers() const {
+ return user_list_;
+}
+
+UserList FakeUserManager::GetUsersAdmittedForMultiProfile() const {
+ UserList result;
+ for (UserList::const_iterator it = user_list_.begin();
+ it != user_list_.end();
+ ++it) {
+ if ((*it)->GetType() == User::USER_TYPE_REGULAR && !(*it)->is_logged_in())
+ result.push_back(*it);
+ }
+ return result;
+}
+
+const UserList& FakeUserManager::GetLoggedInUsers() const {
+ return logged_in_users_;
+}
+
+void FakeUserManager::UserLoggedIn(const std::string& email,
+ const std::string& username_hash,
+ bool browser_restart) {
+ for (UserList::const_iterator it = user_list_.begin();
+ it != user_list_.end();
+ ++it) {
+ if ((*it)->username_hash() == username_hash) {
+ (*it)->set_is_logged_in(true);
+ logged_in_users_.push_back(*it);
+
+ if (!primary_user_)
+ primary_user_ = *it;
+ break;
+ }
+ }
+}
+
+User* FakeUserManager::GetActiveUserInternal() const {
+ if (user_list_.size())
+ return user_list_[0];
+ return NULL;
+}
+
+const User* FakeUserManager::GetActiveUser() const {
+ return GetActiveUserInternal();
+}
+
+User* FakeUserManager::GetActiveUser() {
+ return GetActiveUserInternal();
+}
+
+void FakeUserManager::SaveUserDisplayName(
+ const std::string& username,
+ const string16& display_name) {
+ for (UserList::iterator it = user_list_.begin();
+ it != user_list_.end(); ++it) {
+ if ((*it)->email() == username) {
+ (*it)->set_display_name(display_name);
+ return;
+ }
+ }
+}
+
+void FakeUserManager::UpdateUserAccountData(const std::string&, const string16&,
+ const std::string&) {
+ // Not implemented
+}
+
+UserImageManager* FakeUserManager::GetUserImageManager() {
+ return NULL;
+}
+
+const UserList& FakeUserManager::GetLRULoggedInUsers() {
+ return user_list_;
+}
+
+UserList FakeUserManager::GetUnlockUsers() const {
+ return user_list_;
+}
+
+const std::string& FakeUserManager::GetOwnerEmail() {
+ return owner_email_;
+}
+
+const User* FakeUserManager::CreateLocallyManagedUserRecord(
+ const std::string& manager_id,
+ const std::string& local_user_id,
+ const std::string& sync_user_id,
+ const string16& display_name) {
+ return NULL;
+}
+
+std::string FakeUserManager::GenerateUniqueLocallyManagedUserId() {
+ return std::string();
+}
+
+bool FakeUserManager::IsKnownUser(const std::string& email) const {
+ return true;
+}
+
+const User* FakeUserManager::FindUser(const std::string& email) const {
+ return NULL;
+}
+
+const User* FakeUserManager::FindLocallyManagedUser(
+ const string16& display_name) const {
+ return NULL;
+}
+
+const User* FakeUserManager::GetLoggedInUser() const {
+ return NULL;
+}
+
+User* FakeUserManager::GetLoggedInUser() {
+ return NULL;
+}
+
+const User* FakeUserManager::GetPrimaryUser() const {
+ return primary_user_;
+}
+
+string16 FakeUserManager::GetUserDisplayName(
+ const std::string& username) const {
+ return string16();
+}
+
+std::string FakeUserManager::GetUserDisplayEmail(
+ const std::string& username) const {
+ return std::string();
+}
+
+std::string FakeUserManager::GetManagedUserSyncId(
+ const std::string& managed_user_id) const {
+ return std::string();
+}
+
+string16 FakeUserManager::GetManagerDisplayNameForManagedUser(
+ const std::string& managed_user_id) const {
+ return string16();
+}
+
+std::string FakeUserManager::GetManagerUserIdForManagedUser(
+ const std::string& managed_user_id) const {
+ return std::string();
+}
+
+std::string FakeUserManager::GetManagerDisplayEmailForManagedUser(
+ const std::string& managed_user_id) const {
+ return std::string();
+}
+
+bool FakeUserManager::IsCurrentUserOwner() const {
+ return false;
+}
+
+bool FakeUserManager::IsCurrentUserNew() const {
+ return false;
+}
+
+bool FakeUserManager::IsCurrentUserNonCryptohomeDataEphemeral() const {
+ return false;
+}
+
+bool FakeUserManager::CanCurrentUserLock() const {
+ return false;
+}
+
+bool FakeUserManager::IsUserLoggedIn() const {
+ return logged_in_users_.size() > 0;
+}
+
+bool FakeUserManager::IsLoggedInAsRegularUser() const {
+ return true;
+}
+
+bool FakeUserManager::IsLoggedInAsDemoUser() const {
+ return false;
+}
+
+bool FakeUserManager::IsLoggedInAsPublicAccount() const {
+ return false;
+}
+
+bool FakeUserManager::IsLoggedInAsGuest() const {
+ return false;
+}
+
+bool FakeUserManager::IsLoggedInAsLocallyManagedUser() const {
+ return false;
+}
+
+bool FakeUserManager::IsLoggedInAsKioskApp() const {
+ const User* active_user = GetActiveUser();
+ return active_user ?
+ active_user->GetType() == User::USER_TYPE_KIOSK_APP :
+ false;
+}
+
+bool FakeUserManager::IsLoggedInAsStub() const {
+ return false;
+}
+
+bool FakeUserManager::IsSessionStarted() const {
+ return false;
+}
+
+bool FakeUserManager::UserSessionsRestored() const {
+ return false;
+}
+
+bool FakeUserManager::HasBrowserRestarted() const {
+ return false;
+}
+
+bool FakeUserManager::IsUserNonCryptohomeDataEphemeral(
+ const std::string& email) const {
+ return false;
+}
+
+UserFlow* FakeUserManager::GetCurrentUserFlow() const {
+ return NULL;
+}
+
+UserFlow* FakeUserManager::GetUserFlow(const std::string& email) const {
+ return NULL;
+}
+
+bool FakeUserManager::GetAppModeChromeClientOAuthInfo(
+ std::string* chrome_client_id,
+ std::string* chrome_client_secret) {
+ return false;
+}
+
+bool FakeUserManager::AreLocallyManagedUsersAllowed() const {
+ return true;
+}
+
+base::FilePath FakeUserManager::GetUserProfileDir(
+ const std::string&email) const {
+ return base::FilePath();
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/fake_user_manager.h b/chrome/browser/chromeos/login/fake_user_manager.h
new file mode 100644
index 0000000..f8399a9
--- /dev/null
+++ b/chrome/browser/chromeos/login/fake_user_manager.h
@@ -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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_FAKE_USER_MANAGER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_FAKE_USER_MANAGER_H_
+
+#include <string>
+
+#include "chrome/browser/chromeos/login/user.h"
+#include "chrome/browser/chromeos/login/user_flow.h"
+#include "chrome/browser/chromeos/login/user_image.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+
+namespace chromeos {
+
+// Fake user manager with a barebones implementation. Users can be added
+// and set as logged in, and those users can be returned.
+class FakeUserManager : public UserManager {
+ public:
+ FakeUserManager();
+ virtual ~FakeUserManager();
+
+ // Create and add a new user.
+ void AddUser(const std::string& email);
+
+ // Create and add a kiosk app user.
+ void AddKioskAppUser(const std::string& kiosk_app_username);
+
+ // Calculates the user name hash and calls UserLoggedIn to login a user.
+ void LoginUser(const std::string& email);
+
+ // UserManager overrides.
+ virtual const UserList& GetUsers() const OVERRIDE;
+ virtual UserList GetUsersAdmittedForMultiProfile() const OVERRIDE;
+ virtual const UserList& GetLoggedInUsers() const OVERRIDE;
+
+ // Set the user as logged in.
+ virtual void UserLoggedIn(const std::string& email,
+ const std::string& username_hash,
+ bool browser_restart) OVERRIDE;
+
+ virtual const User* GetActiveUser() const OVERRIDE;
+ virtual User* GetActiveUser() OVERRIDE;
+ virtual void SaveUserDisplayName(const std::string& username,
+ const string16& display_name) OVERRIDE;
+ virtual void UpdateUserAccountData(const std::string&, const string16&,
+ const std::string&) OVERRIDE;
+
+ // Not implemented.
+ virtual void Shutdown() OVERRIDE {}
+ virtual UserImageManager* GetUserImageManager() OVERRIDE;
+ virtual const UserList& GetLRULoggedInUsers() OVERRIDE;
+ virtual UserList GetUnlockUsers() const OVERRIDE;
+ virtual const std::string& GetOwnerEmail() OVERRIDE;
+ virtual void SwitchActiveUser(const std::string& email) OVERRIDE {}
+ virtual void SessionStarted() OVERRIDE {}
+ virtual void RestoreActiveSessions() OVERRIDE {}
+ virtual const User* CreateLocallyManagedUserRecord(
+ const std::string& manager_id,
+ const std::string& local_user_id,
+ const std::string& sync_user_id,
+ const string16& display_name) OVERRIDE;
+ virtual std::string GenerateUniqueLocallyManagedUserId() OVERRIDE;
+ virtual void RemoveUser(const std::string& email,
+ RemoveUserDelegate* delegate) OVERRIDE {}
+ virtual void RemoveUserFromList(const std::string& email) OVERRIDE {}
+ virtual bool IsKnownUser(const std::string& email) const OVERRIDE;
+ virtual const User* FindUser(const std::string& email) const OVERRIDE;
+ virtual const User* FindLocallyManagedUser(
+ const string16& display_name) const OVERRIDE;
+ virtual const User* GetLoggedInUser() const OVERRIDE;
+ virtual User* GetLoggedInUser() OVERRIDE;
+ virtual const User* GetPrimaryUser() const OVERRIDE;
+ virtual void SaveUserOAuthStatus(
+ const std::string& username,
+ User::OAuthTokenStatus oauth_token_status) OVERRIDE {}
+ virtual string16 GetUserDisplayName(
+ const std::string& username) const OVERRIDE;
+ virtual void SaveUserDisplayEmail(const std::string& username,
+ const std::string& display_email) OVERRIDE {}
+ virtual std::string GetUserDisplayEmail(
+ const std::string& username) const OVERRIDE;
+ virtual std::string GetManagedUserSyncId(
+ const std::string& managed_user_id) const OVERRIDE;
+ virtual string16 GetManagerDisplayNameForManagedUser(
+ const std::string& managed_user_id) const OVERRIDE;
+ virtual std::string GetManagerUserIdForManagedUser(
+ const std::string& managed_user_id) const OVERRIDE;
+ virtual std::string GetManagerDisplayEmailForManagedUser(
+ const std::string& managed_user_id) const OVERRIDE;
+ virtual bool IsCurrentUserOwner() const OVERRIDE;
+ virtual bool IsCurrentUserNew() const OVERRIDE;
+ virtual bool IsCurrentUserNonCryptohomeDataEphemeral() const OVERRIDE;
+ virtual bool CanCurrentUserLock() const OVERRIDE;
+ virtual bool IsUserLoggedIn() const OVERRIDE;
+ virtual bool IsLoggedInAsRegularUser() const OVERRIDE;
+ virtual bool IsLoggedInAsDemoUser() const OVERRIDE;
+ virtual bool IsLoggedInAsPublicAccount() const OVERRIDE;
+ virtual bool IsLoggedInAsGuest() const OVERRIDE;
+ virtual bool IsLoggedInAsLocallyManagedUser() const OVERRIDE;
+ virtual bool IsLoggedInAsKioskApp() const OVERRIDE;
+ virtual bool IsLoggedInAsStub() const OVERRIDE;
+ virtual bool IsSessionStarted() const OVERRIDE;
+ virtual bool UserSessionsRestored() const OVERRIDE;
+ virtual bool HasBrowserRestarted() const OVERRIDE;
+ virtual bool IsUserNonCryptohomeDataEphemeral(
+ const std::string& email) const OVERRIDE;
+ virtual void StartLocallyManagedUserCreationTransaction(
+ const string16& display_name) OVERRIDE {}
+ virtual void SetLocallyManagedUserCreationTransactionUserId(
+ const std::string& email) OVERRIDE {}
+ virtual void CommitLocallyManagedUserCreationTransaction() OVERRIDE {}
+ virtual void SetUserFlow(const std::string& email, UserFlow* flow) OVERRIDE {}
+ virtual UserFlow* GetCurrentUserFlow() const OVERRIDE;
+ virtual UserFlow* GetUserFlow(const std::string& email) const OVERRIDE;
+ virtual void ResetUserFlow(const std::string& email) OVERRIDE {}
+ virtual bool GetAppModeChromeClientOAuthInfo(
+ std::string* chrome_client_id,
+ std::string* chrome_client_secret) OVERRIDE;
+ virtual void SetAppModeChromeClientOAuthInfo(
+ const std::string& chrome_client_id,
+ const std::string& chrome_client_secret) OVERRIDE {}
+ virtual void AddObserver(Observer* obs) OVERRIDE {}
+ virtual void RemoveObserver(Observer* obs) OVERRIDE {}
+ virtual void AddSessionStateObserver(
+ UserSessionStateObserver* obs) OVERRIDE {}
+ virtual void RemoveSessionStateObserver(
+ UserSessionStateObserver* obs) OVERRIDE {}
+ virtual void NotifyLocalStateChanged() OVERRIDE {}
+ virtual bool AreLocallyManagedUsersAllowed() const OVERRIDE;
+ virtual base::FilePath GetUserProfileDir(const std::string& email) const
+ OVERRIDE;
+
+ void set_owner_email(const std::string& owner_email) {
+ owner_email_ = owner_email;
+ }
+
+ private:
+ // We use this internal function for const-correctness.
+ User* GetActiveUserInternal() const;
+
+ UserList user_list_;
+ UserList logged_in_users_;
+ std::string owner_email_;
+ User* primary_user_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeUserManager);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_FAKE_USER_MANAGER_H_
diff --git a/chrome/browser/chromeos/login/helper.cc b/chrome/browser/chromeos/login/helper.cc
index 58e85a0..c75fb09 100644
--- a/chrome/browser/chromeos/login/helper.cc
+++ b/chrome/browser/chromeos/login/helper.cc
@@ -15,6 +15,7 @@
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/screen.h"
namespace chromeos {
@@ -36,8 +37,7 @@
float scale_factor = gfx::Display::GetForcedDeviceScaleFactor();
if (scale_factor > 1.0f)
return static_cast<int>(scale_factor * kBaseUserImageSize);
- return kBaseUserImageSize *
- ui::GetScaleFactorScale(ui::GetMaxScaleFactor());
+ return kBaseUserImageSize * gfx::ImageSkia::GetMaxSupportedScale();
}
namespace login {
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index 0039b82..c5530f1 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -2,7 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "apps/native_app_window.h"
+#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/command_line.h"
+#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
@@ -20,12 +26,17 @@
#include "chrome/browser/chromeos/login/mock_user_manager.h"
#include "chrome/browser/chromeos/login/webui_login_display.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/cros_settings_names.h"
+#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
+#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.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/lifetime/application_lifetime.h"
+#include "chrome/browser/policy/cloud/policy_builder.h"
+#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
@@ -40,6 +51,7 @@
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "google_apis/gaia/fake_gaia.h"
#include "google_apis/gaia/gaia_switches.h"
@@ -50,22 +62,36 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace em = enterprise_management;
namespace chromeos {
namespace {
-// Webstore data json is in
+// This is a simple test app that creates an app window and immediately closes
+// it again. Webstore data json is in
// chrome/test/data/chromeos/app_mode/webstore/inlineinstall/
// detail/ggbflgnkafappblpkiflbgpmkfdpnhhe
const char kTestKioskApp[] = "ggbflgnkafappblpkiflbgpmkfdpnhhe";
+// This app creates a window and declares usage of the identity API in its
+// manifest, so we can test device robot token minting via the identity API.
+// Webstore data json is in
+// chrome/test/data/chromeos/app_mode/webstore/inlineinstall/
+// detail/ibjkkfdnfcaoapcpheeijckmpcfkifob
+const char kTestEnterpriseKioskApp[] = "ibjkkfdnfcaoapcpheeijckmpcfkifob";
+
// Timeout while waiting for network connectivity during tests.
const int kTestNetworkTimeoutSeconds = 1;
// Email of owner account for test.
const char kTestOwnerEmail[] = "owner@example.com";
+const char kTestEnterpriseAccountId[] = "enterprise-kiosk-app@localhost";
+const char kTestEnterpriseServiceAccountId[] = "service_account@example.com";
+const char kTestRefreshToken[] = "fake-refresh-token";
+const char kTestAccessToken[] = "fake-access-token";
+
// Helper function for GetConsumerKioskModeStatusCallback.
void ConsumerKioskModeStatusCheck(
KioskAppManager::ConsumerKioskModeStatus* out_status,
@@ -412,8 +438,8 @@
// A network error screen should be shown after authenticating.
OobeScreenWaiter error_screen_waiter(OobeDisplay::SCREEN_ERROR_MESSAGE);
- static_cast<AppLaunchSigninScreen::Delegate*>(GetAppLaunchController())
- ->OnOwnerSigninSuccess();
+ static_cast<AppLaunchSigninScreen::Delegate*>(GetAppLaunchController())
+ ->OnOwnerSigninSuccess();
error_screen_waiter.Wait();
ASSERT_TRUE(GetAppLaunchController()->showing_network_dialog());
@@ -590,4 +616,154 @@
INSTANTIATE_TEST_CASE_P(KioskTestInstantiation, KioskTest, testing::Bool());
+// Helper class that monitors app windows to wait for a window to appear.
+class ShellWindowObserver : public apps::ShellWindowRegistry::Observer {
+ public:
+ ShellWindowObserver(apps::ShellWindowRegistry* registry,
+ const std::string& app_id)
+ : registry_(registry), app_id_(app_id), window_(NULL), running_(false) {
+ registry_->AddObserver(this);
+ }
+ virtual ~ShellWindowObserver() {
+ registry_->RemoveObserver(this);
+ }
+
+ apps::ShellWindow* Wait() {
+ running_ = true;
+ message_loop_runner_ = new content::MessageLoopRunner;
+ message_loop_runner_->Run();
+ EXPECT_TRUE(window_);
+ return window_;
+ }
+
+ // ShellWindowRegistry::Observer
+ virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE {
+ if (!running_)
+ return;
+
+ if (shell_window->extension_id() == app_id_) {
+ window_ = shell_window;
+ message_loop_runner_->Quit();
+ running_ = false;
+ }
+ }
+ virtual void OnShellWindowIconChanged(
+ apps::ShellWindow* shell_window) OVERRIDE {}
+ virtual void OnShellWindowRemoved(apps::ShellWindow* shell_window) OVERRIDE {}
+
+ private:
+ apps::ShellWindowRegistry* registry_;
+ std::string app_id_;
+ scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+ apps::ShellWindow* window_;
+ bool running_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellWindowObserver);
+};
+
+class KioskEnterpriseTest : public KioskTest {
+ protected:
+ KioskEnterpriseTest() {}
+
+ virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+ device_policy_test_helper_.MarkAsEnterpriseOwned();
+ device_policy_test_helper_.InstallOwnerKey();
+
+ KioskTest::SetUpInProcessBrowserTestFixture();
+ }
+
+ virtual void SetUpOnMainThread() OVERRIDE {
+ // Configure kTestEnterpriseKioskApp in device policy.
+ em::DeviceLocalAccountsProto* accounts =
+ device_policy_test_helper_.device_policy()->payload()
+ .mutable_device_local_accounts();
+ em::DeviceLocalAccountInfoProto* account = accounts->add_account();
+ account->set_account_id(kTestEnterpriseAccountId);
+ account->set_type(
+ em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_KIOSK_APP);
+ account->mutable_kiosk_app()->set_app_id(kTestEnterpriseKioskApp);
+ accounts->set_auto_login_id(kTestEnterpriseAccountId);
+ em::PolicyData& policy_data =
+ device_policy_test_helper_.device_policy()->policy_data();
+ policy_data.set_service_account_identity(kTestEnterpriseServiceAccountId);
+ device_policy_test_helper_.device_policy()->Build();
+ DBusThreadManager::Get()->GetSessionManagerClient()->StoreDevicePolicy(
+ device_policy_test_helper_.device_policy()->GetBlob(),
+ base::Bind(&KioskEnterpriseTest::StorePolicyCallback));
+
+ DeviceSettingsService::Get()->Load();
+
+ // Configure OAuth authentication.
+ FakeGaia::AccessTokenInfo token_info;
+ token_info.token = kTestAccessToken;
+ token_info.email = kTestEnterpriseServiceAccountId;
+ fake_gaia_.IssueOAuthToken(kTestRefreshToken, token_info);
+ DeviceOAuth2TokenServiceFactory::Get()
+ ->SetAndSaveRefreshToken(kTestRefreshToken);
+
+ KioskTest::SetUpOnMainThread();
+ }
+
+ static void StorePolicyCallback(bool result) {
+ ASSERT_TRUE(result);
+ }
+
+ policy::DevicePolicyCrosTestHelper device_policy_test_helper_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(KioskEnterpriseTest);
+};
+
+IN_PROC_BROWSER_TEST_P(KioskEnterpriseTest, EnterpriseKioskApp) {
+ chromeos::WizardController::SkipPostLoginScreensForTesting();
+ chromeos::WizardController* wizard_controller =
+ chromeos::WizardController::default_controller();
+ wizard_controller->SkipToLoginForTesting();
+
+ // Wait for the Kiosk App configuration to reload, then launch the app.
+ KioskAppManager::App app;
+ content::WindowedNotificationObserver(
+ chrome::NOTIFICATION_KIOSK_APPS_LOADED,
+ base::Bind(&KioskAppManager::GetApp,
+ base::Unretained(KioskAppManager::Get()),
+ kTestEnterpriseKioskApp, &app)).Wait();
+
+ GetLoginUI()->CallJavascriptFunction(
+ "login.AppsMenuButton.runAppForTesting",
+ base::StringValue(kTestEnterpriseKioskApp));
+
+ // Wait for the Kiosk App to launch.
+ content::WindowedNotificationObserver(
+ chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
+ content::NotificationService::AllSources()).Wait();
+
+ // Check installer status.
+ EXPECT_EQ(chromeos::KioskAppLaunchError::NONE,
+ chromeos::KioskAppLaunchError::Get());
+
+ // Wait for the window to appear.
+ apps::ShellWindow* window = ShellWindowObserver(
+ apps::ShellWindowRegistry::Get(ProfileManager::GetDefaultProfile()),
+ kTestEnterpriseKioskApp).Wait();
+ ASSERT_TRUE(window);
+
+ // Check whether the app can retrieve an OAuth2 access token.
+ std::string result;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ window->web_contents(),
+ "chrome.identity.getAuthToken({ 'interactive': false }, function(token) {"
+ " window.domAutomationController.send(token);"
+ "});",
+ &result));
+ EXPECT_EQ(kTestAccessToken, result);
+
+ // Terminate the app.
+ window->GetBaseWindow()->Close();
+ content::RunAllPendingInMessageLoop();
+}
+
+INSTANTIATE_TEST_CASE_P(KioskEnterpriseTestInstantiation,
+ KioskEnterpriseTest,
+ testing::Bool());
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_screen_policy_browsertest.cc b/chrome/browser/chromeos/login/login_screen_policy_browsertest.cc
index 8467736..2829d21 100644
--- a/chrome/browser/chromeos/login/login_screen_policy_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_screen_policy_browsertest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "chrome/browser/chrome_notification_types.h"
+#include "base/memory/ref_counted.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -11,8 +11,6 @@
#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
#include "chrome/common/chrome_switches.h"
#include "chromeos/chromeos_switches.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/test/mock_notification_observer.h"
#include "content/public/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -37,20 +35,20 @@
IN_PROC_BROWSER_TEST_F(LoginScreenPolicyTest, DisableSupervisedUsers) {
EXPECT_FALSE(chromeos::UserManager::Get()->AreLocallyManagedUsersAllowed());
- content::WindowedNotificationObserver windowed_observer(
- chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED,
- content::NotificationService::AllSources());
- chromeos::CrosSettings::Get()->AddSettingsObserver(
- chromeos::kAccountsPrefSupervisedUsersEnabled, &windowed_observer);
+ scoped_refptr<content::MessageLoopRunner> runner(
+ new content::MessageLoopRunner);
+ scoped_ptr<CrosSettings::ObserverSubscription> subscription(
+ chromeos::CrosSettings::Get()->AddSettingsObserver(
+ chromeos::kAccountsPrefSupervisedUsersEnabled,
+ runner->QuitClosure()));
+
em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
proto.mutable_supervised_users_settings()->set_supervised_users_enabled(true);
RefreshDevicePolicy();
- windowed_observer.Wait();
+
+ runner->Run();
EXPECT_TRUE(chromeos::UserManager::Get()->AreLocallyManagedUsersAllowed());
-
- chromeos::CrosSettings::Get()->RemoveSettingsObserver(
- chromeos::kAccountsPrefSupervisedUsersEnabled, &windowed_observer);
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index 36a3f74..144b614 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -35,7 +35,6 @@
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/login/chrome_restart_request.h"
-#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_display_host.h"
#include "chrome/browser/chromeos/login/oauth2_login_manager.h"
#include "chrome/browser/chromeos/login/oauth2_login_manager_factory.h"
@@ -106,6 +105,7 @@
has_web_auth_cookies_(false),
delegate_(NULL),
should_restore_auth_session_(false),
+ exit_after_session_restore_(false),
session_restore_strategy_(
OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN) {
net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
@@ -133,10 +133,11 @@
virtual void RestoreAuthenticationSession(Profile* profile) OVERRIDE;
virtual void InitRlzDelayed(Profile* user_profile) OVERRIDE;
- // OAuth2LoginManager::Delegate overrides.
+ // OAuth2LoginManager::Observer overrides.
virtual void OnSessionRestoreStateChanged(
Profile* user_profile,
OAuth2LoginManager::SessionRestoreState state) OVERRIDE;
+ virtual void OnNewRefreshTokenAvaiable(Profile* user_profile) OVERRIDE;
virtual void OnSessionAuthenticated(Profile* user_profile) OVERRIDE;
// net::NetworkChangeNotifier::ConnectionTypeObserver overrides.
@@ -147,9 +148,6 @@
// Restarts OAuth session authentication check.
void KickStartAuthentication(Profile* profile);
- // Check user's profile for kApplicationLocale setting.
- void RespectLocalePreference(Profile* pref);
-
// Callback for Profile::CREATE_STATUS_CREATED profile state.
// Initializes basic preferences for newly created profile. Any other
// early profile initialization that needs to happen before
@@ -187,6 +185,10 @@
// Starts signing related services. Initiates TokenService token retrieval.
void StartSignedInServices(Profile* profile);
+ // Attempts exiting browser process and esures this does not happen
+ // while we are still fetching new OAuth refresh tokens.
+ void AttemptExit(Profile* profile);
+
UserContext user_context_;
bool using_oauth_;
@@ -203,6 +205,9 @@
// online state change.
bool should_restore_auth_session_;
+ // True if we should restart chrome right after session restore.
+ bool exit_after_session_restore_;
+
// Sesion restore strategy.
OAuth2LoginManager::SessionRestoreStrategy session_restore_strategy_;
// OAuth2 refresh token for session restore.
@@ -265,7 +270,7 @@
VLOG(1) << "Restarting to apply per-session flags...";
DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser(
UserManager::Get()->GetActiveUser()->email(), flags);
- chrome::AttemptExit();
+ AttemptExit(profile);
return;
}
@@ -378,10 +383,6 @@
const User* user = UserManager::Get()->FindUser(email);
google_services_username.SetValue(user ? user->display_email() : email);
}
-
- // For multi-profile case don't apply profile local because it is not safe.
- if (UserManager::Get()->GetLoggedInUsers().size() == 1)
- RespectLocalePreference(user_profile);
}
void LoginUtilsImpl::InitSessionRestoreStrategy() {
@@ -431,12 +432,12 @@
CHECK(user_profile);
switch (status) {
- case Profile::CREATE_STATUS_INITIALIZED:
- UserProfileInitialized(user_profile);
- break;
case Profile::CREATE_STATUS_CREATED:
InitProfilePreferences(user_profile, email);
break;
+ case Profile::CREATE_STATUS_INITIALIZED:
+ UserProfileInitialized(user_profile);
+ break;
case Profile::CREATE_STATUS_LOCAL_FAIL:
case Profile::CREATE_STATUS_REMOTE_FAIL:
case Profile::CREATE_STATUS_CANCELED:
@@ -484,6 +485,7 @@
chromeos::switches::kOobeSkipPostLogin))
return;
+ exit_after_session_restore_ = false;
// Remove legacy OAuth1 token if we have one. If it's valid, we should already
// have OAuth2 refresh token in TokenService that could be used to retrieve
// all other tokens and user_context.
@@ -612,29 +614,6 @@
user_context_.auth_code.clear();
}
-void LoginUtilsImpl::RespectLocalePreference(Profile* profile) {
- DCHECK(profile != NULL);
- PrefService* prefs = profile->GetPrefs();
- DCHECK(prefs != NULL);
- if (g_browser_process == NULL)
- return;
-
- std::string pref_locale = prefs->GetString(prefs::kApplicationLocale);
- if (pref_locale.empty())
- pref_locale = prefs->GetString(prefs::kApplicationLocaleBackup);
- if (pref_locale.empty())
- pref_locale = g_browser_process->GetApplicationLocale();
- DCHECK(!pref_locale.empty());
- profile->ChangeAppLocale(pref_locale, Profile::APP_LOCALE_CHANGED_VIA_LOGIN);
- // Here we don't enable keyboard layouts. Input methods are set up when
- // the user first logs in. Then the user may customize the input methods.
- // Hence changing input methods here, just because the user's UI language
- // is different from the login screen UI language, is not desirable. Note
- // that input method preferences are synced, so users can use their
- // farovite input methods as soon as the preferences are synced.
- LanguageSwitchMenu::SwitchLanguage(pref_locale);
-}
-
void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) {
VLOG(1) << "Completing incognito login";
@@ -738,28 +717,49 @@
void LoginUtilsImpl::OnSessionRestoreStateChanged(
Profile* user_profile,
OAuth2LoginManager::SessionRestoreState state) {
+ User::OAuthTokenStatus user_status = User::OAUTH_TOKEN_STATUS_UNKNOWN;
OAuth2LoginManager* login_manager =
OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
switch (state) {
- case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
- break;
- case OAuth2LoginManager::SESSION_RESTORE_PREPARING:
- break;
- case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS:
- break;
case OAuth2LoginManager::SESSION_RESTORE_DONE:
- UserManager::Get()->SaveUserOAuthStatus(
- UserManager::Get()->GetLoggedInUser()->email(),
- User::OAUTH2_TOKEN_STATUS_VALID);
- login_manager->RemoveObserver(this);
+ user_status = User::OAUTH2_TOKEN_STATUS_VALID;
break;
case OAuth2LoginManager::SESSION_RESTORE_FAILED:
- UserManager::Get()->SaveUserOAuthStatus(
- UserManager::Get()->GetLoggedInUser()->email(),
- User::OAUTH2_TOKEN_STATUS_INVALID);
- login_manager->RemoveObserver(this);
+ user_status = User::OAUTH2_TOKEN_STATUS_INVALID;
break;
+ case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
+ return;
+ case OAuth2LoginManager::SESSION_RESTORE_PREPARING:
+ return;
+ case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS:
+ return;
}
+
+ // We are in one of "done" states here.
+ UserManager::Get()->SaveUserOAuthStatus(
+ UserManager::Get()->GetLoggedInUser()->email(),
+ user_status);
+ login_manager->RemoveObserver(this);
+}
+
+void LoginUtilsImpl::OnNewRefreshTokenAvaiable(Profile* user_profile) {
+ // Check if we were waiting to restart chrome.
+ if (!exit_after_session_restore_)
+ return;
+
+ OAuth2LoginManager* login_manager =
+ OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
+ login_manager->RemoveObserver(this);
+
+ // Mark user auth token status as valid.
+ UserManager::Get()->SaveUserOAuthStatus(
+ UserManager::Get()->GetLoggedInUser()->email(),
+ User::OAUTH2_TOKEN_STATUS_VALID);
+
+ LOG(WARNING) << "Exiting after new refresh token fetched";
+ // We need to exit cleanly in this case to make sure OAuth2 RT is actually
+ // saved.
+ chrome::ExitCleanly();
}
void LoginUtilsImpl::OnSessionAuthenticated(Profile* user_profile) {
@@ -786,6 +786,29 @@
}
}
+void LoginUtilsImpl::AttemptExit(Profile* profile) {
+ if (session_restore_strategy_ !=
+ OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR) {
+ chrome::AttemptExit();
+ return;
+ }
+
+ // We can't really quit if the session restore process that mints new
+ // refresh token is still in progress.
+ OAuth2LoginManager* login_manager =
+ OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile);
+ if (login_manager->state() !=
+ OAuth2LoginManager::SESSION_RESTORE_PREPARING &&
+ login_manager->state() !=
+ OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS) {
+ chrome::AttemptExit();
+ return;
+ }
+
+ LOG(WARNING) << "Attempting browser restart during session restore.";
+ exit_after_session_restore_ = true;
+}
+
// static
void LoginUtils::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc
index 6c2e111..843be727 100644
--- a/chrome/browser/chromeos/login/login_utils_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -59,6 +59,7 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_status.h"
+#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -279,6 +280,9 @@
browser_process_->SetProfileManager(
new ProfileManagerWithoutInit(scoped_temp_dir_.path()));
+ browser_process_->SetSystemRequestContext(
+ new net::TestURLRequestContextGetter(
+ base::MessageLoopProxy::current()));
connector_ = browser_process_->browser_policy_connector();
connector_->Init(local_state_.Get(),
browser_process_->system_request_context());
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 3b82a39..240b523 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
@@ -198,8 +198,6 @@
}
}
-void LocallyManagedUserCreationScreen::OnExit() {}
-
void LocallyManagedUserCreationScreen::OnActorDestroyed(
LocallyManagedUserCreationScreenHandler* actor) {
if (actor_ == actor)
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 addee85..e1761fb 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
@@ -65,7 +65,6 @@
virtual std::string GetName() const OVERRIDE;
// LocallyManagedUserCreationScreenHandler::Delegate implementation:
- virtual void OnExit() OVERRIDE;
virtual void OnActorDestroyed(LocallyManagedUserCreationScreenHandler* actor)
OVERRIDE;
virtual void CreateManagedUser(
diff --git a/chrome/browser/chromeos/login/managed/managed_user_authenticator.cc b/chrome/browser/chromeos/login/managed/managed_user_authenticator.cc
index 4984cf0..29e3948 100644
--- a/chrome/browser/chromeos/login/managed/managed_user_authenticator.cc
+++ b/chrome/browser/chromeos/login/managed/managed_user_authenticator.cc
@@ -103,6 +103,8 @@
// Get salt, ascii encode, update sha with that, then update with ascii
// of password, then end.
std::string ascii_salt = CryptohomeLibrary::Get()->GetSystemSalt();
+ // TODO(stevenjb/nkostylev): Handle empty system salt gracefully.
+ CHECK(!ascii_salt.empty());
char passhash_buf[kPasswordHashLength];
// Hash salt and password
diff --git a/chrome/browser/chromeos/login/mock_user_manager.h b/chrome/browser/chromeos/login/mock_user_manager.h
index e64364e..d13aedc 100644
--- a/chrome/browser/chromeos/login/mock_user_manager.h
+++ b/chrome/browser/chromeos/login/mock_user_manager.h
@@ -41,6 +41,8 @@
User::OAuthTokenStatus));
MOCK_METHOD2(SaveUserDisplayName, void(const std::string&,
const string16&));
+ MOCK_METHOD3(UpdateUserAccountData,
+ void(const std::string&, const string16&, const std::string&));
MOCK_CONST_METHOD1(GetUserDisplayName, string16(const std::string&));
MOCK_METHOD2(SaveUserDisplayEmail, void(const std::string&,
const std::string&));
diff --git a/chrome/browser/chromeos/login/multi_profile_first_run_notification.cc b/chrome/browser/chromeos/login/multi_profile_first_run_notification.cc
new file mode 100644
index 0000000..0b23ee3
--- /dev/null
+++ b/chrome/browser/chromeos/login/multi_profile_first_run_notification.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/browser/chromeos/login/multi_profile_first_run_notification.h"
+
+#include "base/prefs/pref_service.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.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/message_center/message_center.h"
+#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_delegate.h"
+
+using message_center::Notification;
+
+namespace chromeos {
+
+namespace {
+
+const char kNotificationId[] = "chrome:://login/multiprofile";
+
+} // namespace
+
+MultiProfileFirstRunNotification::MultiProfileFirstRunNotification()
+ : weak_ptr_factory_(this) {}
+
+MultiProfileFirstRunNotification::~MultiProfileFirstRunNotification() {}
+
+// static
+void MultiProfileFirstRunNotification::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterBooleanPref(
+ prefs::kMultiProfileNotificationDismissed,
+ false,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
+void MultiProfileFirstRunNotification::UserProfilePrepared(
+ Profile* user_profile) {
+ if (!UserManager::IsMultipleProfilesAllowed() ||
+ UserManager::Get()->GetLoggedInUsers().size() > 1 ||
+ user_profile->GetPrefs()->GetBoolean(
+ prefs::kMultiProfileNotificationDismissed)) {
+ return;
+ }
+
+ const base::string16 title;
+ const base::string16 display_source;
+ scoped_ptr<Notification> notification(new Notification(
+ message_center::NOTIFICATION_TYPE_SIMPLE,
+ kNotificationId,
+ title,
+ l10n_util::GetStringUTF16(IDS_MULTI_PROFILES_WARNING),
+ ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+ IDR_NOTIFICATION_ALERT),
+ display_source,
+ message_center::NotifierId(),
+ message_center::RichNotificationData(),
+ new message_center::HandleNotificationClickedDelegate(
+ base::Bind(&MultiProfileFirstRunNotification::OnDismissed,
+ weak_ptr_factory_.GetWeakPtr(),
+ user_profile))));
+ notification->SetSystemPriority();
+ message_center::MessageCenter::Get()->AddNotification(notification.Pass());
+}
+
+void MultiProfileFirstRunNotification::OnDismissed(Profile* user_profile) {
+ user_profile->GetPrefs()->SetBoolean(
+ prefs::kMultiProfileNotificationDismissed, true);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/multi_profile_first_run_notification.h b/chrome/browser/chromeos/login/multi_profile_first_run_notification.h
new file mode 100644
index 0000000..0a0d98c
--- /dev/null
+++ b/chrome/browser/chromeos/login/multi_profile_first_run_notification.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_LOGIN_MULTI_PROFILE_FIRST_RUN_NOTIFICATION_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_MULTI_PROFILE_FIRST_RUN_NOTIFICATION_H_
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+class Profile;
+
+namespace chromeos {
+
+class MultiProfileFirstRunNotification {
+ public:
+ MultiProfileFirstRunNotification();
+ ~MultiProfileFirstRunNotification();
+
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ // Invoked when the user profile is prepared. Show the notification for
+ // the primary user when multiprofile is enabled and user has not dismissed
+ // it yet.
+ void UserProfilePrepared(Profile* user_profile);
+
+ private:
+ // Invoked when user dismisses the notification.
+ void OnDismissed(Profile* user_profile);
+
+ base::WeakPtrFactory<MultiProfileFirstRunNotification> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MultiProfileFirstRunNotification);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_MULTI_PROFILE_FIRST_RUN_NOTIFICATION_H_
diff --git a/chrome/browser/chromeos/login/multi_profile_user_controller.cc b/chrome/browser/chromeos/login/multi_profile_user_controller.cc
new file mode 100644
index 0000000..8ba170d
--- /dev/null
+++ b/chrome/browser/chromeos/login/multi_profile_user_controller.cc
@@ -0,0 +1,161 @@
+// Copyright 2013 The Chromium 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/login/multi_profile_user_controller.h"
+
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_change_registrar.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/chromeos/login/multi_profile_user_controller_delegate.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "google_apis/gaia/gaia_auth_util.h"
+
+namespace chromeos {
+
+namespace {
+
+std::string SanitizeBehaviorValue(const std::string& value) {
+ if (value == MultiProfileUserController::kBehaviorUnrestricted ||
+ value == MultiProfileUserController::kBehaviorPrimaryOnly ||
+ value == MultiProfileUserController::kBehaviorNotAllowed) {
+ return value;
+ }
+
+ return std::string(MultiProfileUserController::kBehaviorUnrestricted);
+}
+
+} // namespace
+
+// static
+const char MultiProfileUserController::kBehaviorUnrestricted[] = "unrestricted";
+const char MultiProfileUserController::kBehaviorPrimaryOnly[] = "primary-only";
+const char MultiProfileUserController::kBehaviorNotAllowed[] = "not-allowed";
+
+MultiProfileUserController::MultiProfileUserController(
+ MultiProfileUserControllerDelegate* delegate,
+ PrefService* local_state)
+ : delegate_(delegate),
+ local_state_(local_state) {
+}
+
+MultiProfileUserController::~MultiProfileUserController() {}
+
+// static
+void MultiProfileUserController::RegisterPrefs(
+ PrefRegistrySimple* registry) {
+ registry->RegisterDictionaryPref(prefs::kCachedMultiProfileUserBehavior);
+}
+
+// static
+void MultiProfileUserController::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterStringPref(
+ prefs::kMultiProfileUserBehavior,
+ kBehaviorUnrestricted,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
+bool MultiProfileUserController::IsUserAllowedInSession(
+ const std::string& user_email) const {
+ UserManager* user_manager = UserManager::Get();
+ CHECK(user_manager);
+
+ std::string primary_user_email;
+ if (user_manager->GetPrimaryUser())
+ primary_user_email = user_manager->GetPrimaryUser()->email();
+
+ // Always allow if there is no primary user or user being checked is the
+ // primary user.
+ if (primary_user_email.empty() || primary_user_email == user_email)
+ return true;
+
+ // Owner is not allowed to be secondary user.
+ if (user_manager->GetOwnerEmail() == user_email)
+ return false;
+
+ // No user is allowed if the primary user policy forbids it.
+ const std::string primary_user_behavior = GetCachedValue(primary_user_email);
+ if (primary_user_behavior == kBehaviorNotAllowed)
+ return false;
+
+ // The user must have 'unrestricted' policy to be a secondary user.
+ const std::string behavior = GetCachedValue(user_email);
+ return behavior == kBehaviorUnrestricted;
+}
+
+void MultiProfileUserController::StartObserving(Profile* user_profile) {
+ // Profile name could be empty during tests.
+ if (user_profile->GetProfileName().empty())
+ return;
+
+ scoped_ptr<PrefChangeRegistrar> registrar(new PrefChangeRegistrar);
+ registrar->Init(user_profile->GetPrefs());
+ registrar->Add(
+ prefs::kMultiProfileUserBehavior,
+ base::Bind(&MultiProfileUserController::OnUserPrefChanged,
+ base::Unretained(this),
+ user_profile));
+ pref_watchers_.push_back(registrar.release());
+
+ OnUserPrefChanged(user_profile);
+}
+
+void MultiProfileUserController::RemoveCachedValue(
+ const std::string& user_email) {
+ DictionaryPrefUpdate update(local_state_,
+ prefs::kCachedMultiProfileUserBehavior);
+ update->RemoveWithoutPathExpansion(user_email, NULL);
+}
+
+std::string MultiProfileUserController::GetCachedValue(
+ const std::string& user_email) const {
+ const DictionaryValue* dict =
+ local_state_->GetDictionary(prefs::kCachedMultiProfileUserBehavior);
+ std::string value;
+ if (dict && dict->GetStringWithoutPathExpansion(user_email, &value))
+ return SanitizeBehaviorValue(value);
+
+ return std::string(kBehaviorUnrestricted);
+}
+
+void MultiProfileUserController::SetCachedValue(
+ const std::string& user_email,
+ const std::string& behavior) {
+ DictionaryPrefUpdate update(local_state_,
+ prefs::kCachedMultiProfileUserBehavior);
+ update->SetStringWithoutPathExpansion(user_email,
+ SanitizeBehaviorValue(behavior));
+}
+
+void MultiProfileUserController::CheckSessionUsers() {
+ const UserList& users = UserManager::Get()->GetLoggedInUsers();
+ for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
+ if (!IsUserAllowedInSession((*it)->email())) {
+ delegate_->OnUserNotAllowed();
+ return;
+ }
+ }
+}
+
+void MultiProfileUserController::OnUserPrefChanged(
+ Profile* user_profile) {
+ std::string user_email = user_profile->GetProfileName();
+ CHECK(!user_email.empty());
+ user_email = gaia::CanonicalizeEmail(user_email);
+
+ PrefService* prefs = user_profile->GetPrefs();
+ const std::string behavior =
+ prefs->GetString(prefs::kMultiProfileUserBehavior);
+ SetCachedValue(user_email, behavior);
+
+ CheckSessionUsers();
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/multi_profile_user_controller.h b/chrome/browser/chromeos/login/multi_profile_user_controller.h
new file mode 100644
index 0000000..0e86e7e
--- /dev/null
+++ b/chrome/browser/chromeos/login/multi_profile_user_controller.h
@@ -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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MULTI_PROFILE_USER_CONTROLLER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_MULTI_PROFILE_USER_CONTROLLER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_vector.h"
+
+class PrefChangeRegistrar;
+class PrefRegistrySimple;
+class PrefService;
+class Profile;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+namespace chromeos {
+
+class MultiProfileUserControllerDelegate;
+class UserManager;
+
+// MultiProfileUserController decides whether a user is allowed to be in a
+// multi-profiles session. It caches the multiprofile user behavior pref backed
+// by user policy into local state so that the value is available before the
+// user login and checks if the meaning of the value is respected.
+class MultiProfileUserController {
+ public:
+ MultiProfileUserController(MultiProfileUserControllerDelegate* delegate,
+ PrefService* local_state);
+ ~MultiProfileUserController();
+
+ static void RegisterPrefs(PrefRegistrySimple* registry);
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ // Returns true if the user is allowed to be in the current session.
+ bool IsUserAllowedInSession(const std::string& user_email) const;
+
+ // Starts to observe the multiprofile user behavior pref of the given profile.
+ void StartObserving(Profile* user_profile);
+
+ // Removes the cached value for the given user.
+ void RemoveCachedValue(const std::string& user_email);
+
+ // Possible behavior values.
+ static const char kBehaviorUnrestricted[];
+ static const char kBehaviorPrimaryOnly[];
+ static const char kBehaviorNotAllowed[];
+
+ private:
+ friend class MultiProfileUserControllerTest;
+
+ // Gets/sets the cached policy value.
+ std::string GetCachedValue(const std::string& user_email) const;
+ void SetCachedValue(const std::string& user_email,
+ const std::string& behavior);
+
+ // Checks if all users are allowed in the current session.
+ void CheckSessionUsers();
+
+ // Invoked when user behavior pref value changes.
+ void OnUserPrefChanged(Profile* profile);
+
+ MultiProfileUserControllerDelegate* delegate_; // Not owned.
+ PrefService* local_state_; // Not owned.
+ ScopedVector<PrefChangeRegistrar> pref_watchers_;
+
+ DISALLOW_COPY_AND_ASSIGN(MultiProfileUserController);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_MULTI_PROFILE_USER_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/login/multi_profile_user_controller_delegate.h b/chrome/browser/chromeos/login/multi_profile_user_controller_delegate.h
new file mode 100644
index 0000000..4707716
--- /dev/null
+++ b/chrome/browser/chromeos/login/multi_profile_user_controller_delegate.h
@@ -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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MULTI_PROFILE_USER_CONTROLLER_DELEGATE_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_MULTI_PROFILE_USER_CONTROLLER_DELEGATE_H_
+
+namespace chromeos {
+
+class MultiProfileUserControllerDelegate {
+ public:
+ // Invoked when the first user that is not allowed in the session is detected.
+ virtual void OnUserNotAllowed() = 0;
+
+ protected:
+ virtual ~MultiProfileUserControllerDelegate() {}
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_MULTI_PROFILE_USER_CONTROLLER_DELEGATE_H_
diff --git a/chrome/browser/chromeos/login/multi_profile_user_controller_unittest.cc b/chrome/browser/chromeos/login/multi_profile_user_controller_unittest.cc
new file mode 100644
index 0000000..a5e1a2a
--- /dev/null
+++ b/chrome/browser/chromeos/login/multi_profile_user_controller_unittest.cc
@@ -0,0 +1,266 @@
+// Copyright 2013 The Chromium 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/login/multi_profile_user_controller.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chromeos/login/fake_user_manager.h"
+#include "chrome/browser/chromeos/login/multi_profile_user_controller_delegate.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/prefs/browser_prefs.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_pref_service_syncable.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace {
+
+const char* kUsers[] = {"a@gmail.com", "b@gmail.com" };
+
+struct BehaviorTestCase {
+ const char* primary;
+ const char* secondary;
+ bool expected_allowed;
+};
+
+const BehaviorTestCase kBehaviorTestCases[] = {
+ {
+ MultiProfileUserController::kBehaviorUnrestricted,
+ MultiProfileUserController::kBehaviorUnrestricted,
+ true,
+ },
+ {
+ MultiProfileUserController::kBehaviorUnrestricted,
+ MultiProfileUserController::kBehaviorPrimaryOnly,
+ false,
+ },
+ {
+ MultiProfileUserController::kBehaviorUnrestricted,
+ MultiProfileUserController::kBehaviorNotAllowed,
+ false,
+ },
+ {
+ MultiProfileUserController::kBehaviorPrimaryOnly,
+ MultiProfileUserController::kBehaviorUnrestricted,
+ true,
+ },
+ {
+ MultiProfileUserController::kBehaviorPrimaryOnly,
+ MultiProfileUserController::kBehaviorPrimaryOnly,
+ false,
+ },
+ {
+ MultiProfileUserController::kBehaviorPrimaryOnly,
+ MultiProfileUserController::kBehaviorNotAllowed,
+ false,
+ },
+ {
+ MultiProfileUserController::kBehaviorNotAllowed,
+ MultiProfileUserController::kBehaviorUnrestricted,
+ false,
+ },
+ {
+ MultiProfileUserController::kBehaviorNotAllowed,
+ MultiProfileUserController::kBehaviorPrimaryOnly,
+ false,
+ },
+ {
+ MultiProfileUserController::kBehaviorNotAllowed,
+ MultiProfileUserController::kBehaviorNotAllowed,
+ false,
+ },
+};
+
+} // namespace
+
+class MultiProfileUserControllerTest
+ : public testing::Test,
+ public MultiProfileUserControllerDelegate {
+ public:
+ MultiProfileUserControllerTest()
+ : profile_manager_(TestingBrowserProcess::GetGlobal()),
+ fake_user_manager_(new FakeUserManager),
+ user_manager_enabler_(fake_user_manager_),
+ user_not_allowed_count_(0) {}
+ virtual ~MultiProfileUserControllerTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(profile_manager_.SetUp());
+ controller_.reset(new MultiProfileUserController(
+ this, TestingBrowserProcess::GetGlobal()->local_state()));
+
+ for (size_t i = 0; i < arraysize(kUsers); ++i) {
+ const std::string user_email(kUsers[i]);
+ fake_user_manager_->AddUser(user_email);
+
+ // Note that user profiles are created after user login in reality.
+ TestingProfile* user_profile =
+ profile_manager_.CreateTestingProfile(user_email);
+ user_profile->set_profile_name(user_email);
+ user_profiles_.push_back(user_profile);
+ }
+ }
+
+ void LoginUser(size_t user_index) {
+ ASSERT_LT(user_index, arraysize(kUsers));
+ fake_user_manager_->LoginUser(kUsers[user_index]);
+ controller_->StartObserving(user_profiles_[user_index]);
+ }
+
+ void SetOwner(size_t user_index) {
+ fake_user_manager_->set_owner_email(kUsers[user_index]);
+ }
+
+ PrefService* GetUserPrefs(size_t user_index) {
+ return user_profiles_[user_index]->GetPrefs();
+ }
+
+ void SetPrefBehavior(size_t user_index, const std::string& behavior) {
+ GetUserPrefs(user_index)->SetString(prefs::kMultiProfileUserBehavior,
+ behavior);
+ }
+
+ std::string GetCachedBehavior(size_t user_index) {
+ return controller_->GetCachedValue(kUsers[user_index]);
+ }
+
+ void SetCachedBehavior(size_t user_index,
+ const std::string& behavior) {
+ controller_->SetCachedValue(kUsers[user_index], behavior);
+ }
+
+ void ResetCounts() {
+ user_not_allowed_count_ = 0;
+ }
+
+ // MultiProfileUserControllerDeleagte overrides:
+ virtual void OnUserNotAllowed() OVERRIDE {
+ ++user_not_allowed_count_;
+ }
+
+ MultiProfileUserController* controller() { return controller_.get(); }
+ int user_not_allowed_count() const { return user_not_allowed_count_; }
+
+ private:
+ TestingProfileManager profile_manager_;
+ FakeUserManager* fake_user_manager_; // Not owned
+ ScopedUserManagerEnabler user_manager_enabler_;
+
+ scoped_ptr<MultiProfileUserController> controller_;
+
+ std::vector<TestingProfile*> user_profiles_;
+
+ int user_not_allowed_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MultiProfileUserControllerTest);
+};
+
+// Tests that everyone is allowed before a session starts.
+TEST_F(MultiProfileUserControllerTest, AllAllowedBeforeLogin) {
+ const char* kTestCases[] = {
+ MultiProfileUserController::kBehaviorUnrestricted,
+ MultiProfileUserController::kBehaviorPrimaryOnly,
+ MultiProfileUserController::kBehaviorNotAllowed,
+ };
+ for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+ SetCachedBehavior(0, kTestCases[i]);
+ EXPECT_TRUE(controller()->IsUserAllowedInSession(kUsers[0]))
+ << "Case " << i;
+ }
+}
+
+// Tests that invalid cache value would become the default "unrestricted".
+TEST_F(MultiProfileUserControllerTest, InvalidCacheBecomesDefault) {
+ const char kBad[] = "some invalid value";
+ SetCachedBehavior(0, kBad);
+ EXPECT_EQ(MultiProfileUserController::kBehaviorUnrestricted,
+ GetCachedBehavior(0));
+}
+
+// Tests that cached behavior value changes with user pref after login.
+TEST_F(MultiProfileUserControllerTest, CachedBehaviorUpdate) {
+ LoginUser(0);
+
+ const char* kTestCases[] = {
+ MultiProfileUserController::kBehaviorUnrestricted,
+ MultiProfileUserController::kBehaviorPrimaryOnly,
+ MultiProfileUserController::kBehaviorNotAllowed,
+ MultiProfileUserController::kBehaviorUnrestricted,
+ };
+ for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+ SetPrefBehavior(0, kTestCases[i]);
+ EXPECT_EQ(kTestCases[i], GetCachedBehavior(0));
+ }
+}
+
+// Tests that compromised cache value would be fixed and pref value is checked
+// upon login.
+TEST_F(MultiProfileUserControllerTest, CompromisedCacheFixedOnLogin) {
+ SetPrefBehavior(0, MultiProfileUserController::kBehaviorPrimaryOnly);
+ SetCachedBehavior(0, MultiProfileUserController::kBehaviorUnrestricted);
+ EXPECT_EQ(MultiProfileUserController::kBehaviorUnrestricted,
+ GetCachedBehavior(0));
+ LoginUser(0);
+ EXPECT_EQ(MultiProfileUserController::kBehaviorPrimaryOnly,
+ GetCachedBehavior(0));
+
+ EXPECT_EQ(0, user_not_allowed_count());
+ SetPrefBehavior(1, MultiProfileUserController::kBehaviorPrimaryOnly);
+ SetCachedBehavior(1, MultiProfileUserController::kBehaviorUnrestricted);
+ EXPECT_EQ(MultiProfileUserController::kBehaviorUnrestricted,
+ GetCachedBehavior(1));
+ LoginUser(1);
+ EXPECT_EQ(MultiProfileUserController::kBehaviorPrimaryOnly,
+ GetCachedBehavior(1));
+ EXPECT_EQ(1, user_not_allowed_count());
+}
+
+// Tests cases before the second user login.
+TEST_F(MultiProfileUserControllerTest, IsSecondaryAllowed) {
+ LoginUser(0);
+
+ for (size_t i = 0; i < arraysize(kBehaviorTestCases); ++i) {
+ SetPrefBehavior(0, kBehaviorTestCases[i].primary);
+ SetCachedBehavior(1, kBehaviorTestCases[i].secondary);
+ EXPECT_EQ(kBehaviorTestCases[i].expected_allowed,
+ controller()->IsUserAllowedInSession(kUsers[1])) << "Case " << i;
+ }
+}
+
+// Tests user behavior changes within a two-user session.
+TEST_F(MultiProfileUserControllerTest, PrimaryBehaviorChange) {
+ LoginUser(0);
+ LoginUser(1);
+
+ for (size_t i = 0; i < arraysize(kBehaviorTestCases); ++i) {
+ SetPrefBehavior(0, MultiProfileUserController::kBehaviorUnrestricted);
+ SetPrefBehavior(1, MultiProfileUserController::kBehaviorUnrestricted);
+ ResetCounts();
+
+ SetPrefBehavior(0, kBehaviorTestCases[i].primary);
+ SetPrefBehavior(1, kBehaviorTestCases[i].secondary);
+ EXPECT_EQ(kBehaviorTestCases[i].expected_allowed,
+ user_not_allowed_count() == 0) << "Case " << i;
+ }
+}
+
+// Tests that owner could not be a secondary user.
+TEST_F(MultiProfileUserControllerTest, NoSecondaryOwner) {
+ LoginUser(0);
+ SetOwner(1);
+
+ EXPECT_FALSE(controller()->IsUserAllowedInSession(kUsers[1]));
+
+ EXPECT_EQ(0, user_not_allowed_count());
+ LoginUser(1);
+ EXPECT_EQ(1, user_not_allowed_count());
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/oauth2_login_manager.cc b/chrome/browser/chromeos/login/oauth2_login_manager.cc
index 4491b24..6d5b8bf 100644
--- a/chrome/browser/chromeos/login/oauth2_login_manager.cc
+++ b/chrome/browser/chromeos/login/oauth2_login_manager.cc
@@ -108,6 +108,9 @@
const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) {
TokenService* token_service = SetupTokenService();
token_service->UpdateCredentialsWithOAuth2(oauth2_tokens);
+
+ FOR_EACH_OBSERVER(Observer, observer_list_,
+ OnNewRefreshTokenAvaiable(user_profile_));
}
void OAuth2LoginManager::LoadAndVerifyOAuth2Tokens() {
diff --git a/chrome/browser/chromeos/login/oauth2_login_manager.h b/chrome/browser/chromeos/login/oauth2_login_manager.h
index d0a4ae3..532f76e 100644
--- a/chrome/browser/chromeos/login/oauth2_login_manager.h
+++ b/chrome/browser/chromeos/login/oauth2_login_manager.h
@@ -64,6 +64,10 @@
// Raised when merge session state changes.
virtual void OnSessionRestoreStateChanged(Profile* user_profile,
SessionRestoreState state) {}
+
+ // Raised when a new OAuth2 refresh token is avaialble.
+ virtual void OnNewRefreshTokenAvaiable(Profile* user_profile) {}
+
// Raised when session's GAIA credentials (SID+LSID) are available to
// other signed in services.
virtual void OnSessionAuthenticated(Profile* user_profile) {}
diff --git a/chrome/browser/chromeos/login/oauth2_login_verifier.cc b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
index 8ade58b..748b2af 100644
--- a/chrome/browser/chromeos/login/oauth2_login_verifier.cc
+++ b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
@@ -56,7 +56,7 @@
const NetworkState* default_network =
NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
if (!default_network ||
- default_network->connection_state() == flimflam::kStatePortal) {
+ default_network->connection_state() == shill::kStatePortal) {
// If network is offline, defer the token fetching until online.
VLOG(1) << "Network is offline. Deferring OAuth2 access token fetch.";
BrowserThread::PostDelayedTask(
@@ -76,9 +76,13 @@
void OAuth2LoginVerifier::StartFetchingOAuthLoginAccessToken(Profile* profile) {
OAuth2TokenService::ScopeSet scopes;
scopes.insert(GaiaUrls::GetInstance()->oauth1_login_scope());
- login_token_request_ = ProfileOAuth2TokenServiceFactory::
- GetForProfile(profile)->StartRequestWithContext(
- system_request_context_.get(), scopes, this);
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+ login_token_request_ = token_service->StartRequestWithContext(
+ token_service->GetPrimaryAccountId(),
+ system_request_context_.get(),
+ scopes,
+ this);
}
void OAuth2LoginVerifier::StartOAuthLoginForUberToken() {
diff --git a/chrome/browser/chromeos/login/oauth2_token_fetcher.cc b/chrome/browser/chromeos/login/oauth2_token_fetcher.cc
index 31d3fd4..293b081 100644
--- a/chrome/browser/chromeos/login/oauth2_token_fetcher.cc
+++ b/chrome/browser/chromeos/login/oauth2_token_fetcher.cc
@@ -47,7 +47,7 @@
const NetworkState* default_network =
NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
if (!default_network ||
- default_network->connection_state() == flimflam::kStatePortal) {
+ default_network->connection_state() == shill::kStatePortal) {
// If network is offline, defer the token fetching until online.
VLOG(1) << "Network is offline. Deferring OAuth2 token fetch.";
BrowserThread::PostDelayedTask(
@@ -69,7 +69,7 @@
const NetworkState* default_network =
NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
if (!default_network ||
- default_network->connection_state() == flimflam::kStatePortal) {
+ default_network->connection_state() == shill::kStatePortal) {
// If network is offline, defer the token fetching until online.
VLOG(1) << "Network is offline. Deferring OAuth2 token fetch.";
BrowserThread::PostDelayedTask(
diff --git a/chrome/browser/chromeos/login/parallel_authenticator.cc b/chrome/browser/chromeos/login/parallel_authenticator.cc
index 54b5aaf..85f724d 100644
--- a/chrome/browser/chromeos/login/parallel_authenticator.cc
+++ b/chrome/browser/chromeos/login/parallel_authenticator.cc
@@ -187,6 +187,8 @@
// Get salt, ascii encode, update sha with that, then update with ascii
// of password, then end.
std::string ascii_salt = CryptohomeLibrary::Get()->GetSystemSalt();
+ // TODO(stevenjb/nkostylev): Handle empty system salt gracefully.
+ CHECK(!ascii_salt.empty());
char passhash_buf[kPasswordHashLength];
// Hash salt and password
diff --git a/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc b/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc
index e1896f2..5f56e83 100644
--- a/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc
@@ -517,7 +517,7 @@
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_cryptohome_library_, GetSystemSalt())
- .WillOnce(Return(std::string()))
+ .WillOnce(Return(std::string("mock_system_salt")))
.RetiresOnSaturation();
state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone());
@@ -538,7 +538,7 @@
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_cryptohome_library_, GetSystemSalt())
- .WillOnce(Return(std::string()))
+ .WillOnce(Return(std::string("mock_system_salt")))
.RetiresOnSaturation();
SetAttemptState(auth_.get(), state_.release());
@@ -649,7 +649,7 @@
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_cryptohome_library_, GetSystemSalt())
- .WillOnce(Return(std::string()))
+ .WillOnce(Return(std::string("mock_system_salt")))
.RetiresOnSaturation();
auth_->AuthenticateToUnlock(UserContext(username_,
diff --git a/chrome/browser/chromeos/login/user.cc b/chrome/browser/chromeos/login/user.cc
index ffe6c47..10e31ad 100644
--- a/chrome/browser/chromeos/login/user.cc
+++ b/chrome/browser/chromeos/login/user.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/chromeos/login/default_user_images.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
namespace chromeos {
@@ -207,11 +208,18 @@
image_is_stub_(false),
image_is_loading_(false),
is_logged_in_(false),
- is_active_(false) {
+ is_active_(false),
+ profile_is_created_(false) {
}
User::~User() {}
+void User::SetAccountLocale(const std::string& raw_account_locale) {
+ account_locale_.reset(new std::string);
+ // Ignore result
+ l10n_util::CheckAndResolveLocale(raw_account_locale, account_locale_.get());
+}
+
void User::SetImage(const UserImage& user_image, int image_index) {
user_image_ = user_image;
image_index_ = image_index;
@@ -309,4 +317,21 @@
return USER_TYPE_PUBLIC_ACCOUNT;
}
+bool User::has_gaia_account() const {
+ COMPILE_ASSERT(NUM_USER_TYPES == 6, num_user_types_unexpected);
+ switch (GetType()) {
+ case USER_TYPE_REGULAR:
+ return true;
+ case USER_TYPE_GUEST:
+ case USER_TYPE_RETAIL_MODE:
+ case USER_TYPE_PUBLIC_ACCOUNT:
+ case USER_TYPE_LOCALLY_MANAGED:
+ case USER_TYPE_KIOSK_APP:
+ return false;
+ default:
+ NOTREACHED();
+ }
+ return false;
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user.h b/chrome/browser/chromeos/login/user.h
index 4465aab..22166f4 100644
--- a/chrome/browser/chromeos/login/user.h
+++ b/chrome/browser/chromeos/login/user.h
@@ -167,6 +167,7 @@
friend class UserImageManagerImpl;
// For testing:
friend class MockUserManager;
+ friend class FakeUserManager;
// Do not allow anyone else to create new User instances.
static User* CreateRegularUser(const std::string& email);
@@ -179,7 +180,17 @@
explicit User(const std::string& email);
virtual ~User();
+ bool is_profile_created() const {
+ return profile_is_created_;
+ }
+
+ const std::string* GetAccountLocale() const {
+ return account_locale_.get();
+ }
+
// Setters are private so only UserManager can call them.
+ void SetAccountLocale(const std::string& raw_account_locale);
+
void SetImage(const UserImage& user_image, int image_index);
void SetImageURL(const GURL& image_url);
@@ -215,6 +226,13 @@
is_active_ = is_active;
}
+ void set_profile_is_created() {
+ profile_is_created_ = true;
+ }
+
+ // True if user has google account (not a guest or managed user).
+ bool has_gaia_account() const;
+
private:
std::string email_;
string16 display_name_;
@@ -223,6 +241,12 @@
UserImage user_image_;
OAuthTokenStatus oauth_token_status_;
+ // This is set to chromeos locale if account data has been downloaded.
+ // (Or failed to download, but at least one download attempt finished).
+ // An empty string indicates error in data load, or in
+ // translation of Account locale to chromeos locale.
+ scoped_ptr<std::string> account_locale_;
+
// Used to identify homedir mount point.
std::string username_hash_;
@@ -242,6 +266,9 @@
// True if user is currently logged in and active in current session.
bool is_active_;
+ // True if user Profile is created
+ bool profile_is_created_;
+
DISALLOW_COPY_AND_ASSIGN(User);
};
diff --git a/chrome/browser/chromeos/login/user_image_manager_impl.cc b/chrome/browser/chromeos/login/user_image_manager_impl.cc
index 005c75f..93ddf9d 100644
--- a/chrome/browser/chromeos/login/user_image_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_image_manager_impl.cc
@@ -659,10 +659,9 @@
UserManager* user_manager = UserManager::Get();
const User* user = user_manager->GetLoggedInUser();
- if (!downloader->GetProfileFullName().empty()) {
- user_manager->SaveUserDisplayName(
- user->email(), downloader->GetProfileFullName());
- }
+ user_manager->UpdateUserAccountData(user->email(),
+ downloader->GetProfileFullName(),
+ downloader->GetProfileLocale());
bool requested_image = downloading_profile_image_;
downloading_profile_image_ = false;
@@ -743,6 +742,12 @@
AddProfileImageTimeHistogram(kDownloadFailure, profile_image_download_reason_,
delta);
+ UserManager* user_manager = UserManager::Get();
+ const User* user = user_manager->GetLoggedInUser();
+
+ // Need note that at least one attempt finished.
+ user_manager->UpdateUserAccountData(user->email(), string16(), "");
+
// Retry download after some time if a network error has occured.
if (reason == ProfileDownloaderDelegate::NETWORK_ERROR) {
BrowserThread::PostDelayedTask(
diff --git a/chrome/browser/chromeos/login/user_manager.cc b/chrome/browser/chromeos/login/user_manager.cc
index 161a38f..09dd987 100644
--- a/chrome/browser/chromeos/login/user_manager.cc
+++ b/chrome/browser/chromeos/login/user_manager.cc
@@ -4,8 +4,10 @@
#include "chrome/browser/chromeos/login/user_manager.h"
-#include "base/logging.h"
+#include "base/command_line.h"
+#include "base/metrics/field_trial.h"
#include "chrome/browser/chromeos/login/user_manager_impl.h"
+#include "chrome/common/chrome_switches.h"
namespace chromeos {
@@ -69,6 +71,17 @@
return g_user_manager;
}
+// static
+bool UserManager::IsMultipleProfilesAllowed() {
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(::switches::kMultiProfiles))
+ return false;
+
+ // TODO(xiyuan): Get rid of this when the underlying support is ready.
+ const char kFieldTrialName[] = "ChromeOSUseMultiProfiles";
+ const char kEnable[] = "Enable";
+ return base::FieldTrialList::FindFullName(kFieldTrialName) == kEnable;
+}
+
UserManager::~UserManager() {
}
diff --git a/chrome/browser/chromeos/login/user_manager.h b/chrome/browser/chromeos/login/user_manager.h
index 1654bbe..ebef986 100644
--- a/chrome/browser/chromeos/login/user_manager.h
+++ b/chrome/browser/chromeos/login/user_manager.h
@@ -93,6 +93,9 @@
// Registers user manager preferences.
static void RegisterPrefs(PrefRegistrySimple* registry);
+ // Returns true if multiple profiles support is allowed.
+ static bool IsMultipleProfilesAllowed();
+
virtual ~UserManager();
virtual UserImageManager* GetUserImageManager() = 0;
@@ -211,6 +214,11 @@
virtual void SaveUserDisplayName(const std::string& username,
const string16& display_name) = 0;
+ // Updates data upon User Account download.
+ virtual void UpdateUserAccountData(const std::string& username,
+ const string16& display_name,
+ const std::string& locale) = 0;
+
// Returns the display name for user |username| if it is known (was
// previously set by a |SaveUserDisplayName| call).
// Otherwise, returns an empty string.
diff --git a/chrome/browser/chromeos/login/user_manager_impl.cc b/chrome/browser/chromeos/login/user_manager_impl.cc
index 05c3563..9e20d44 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_manager_impl.cc
@@ -28,17 +28,23 @@
#include "chrome/browser/chromeos/login/auth_sync_observer.h"
#include "chrome/browser/chromeos/login/auth_sync_observer_factory.h"
#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
+#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_display.h"
#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/chromeos/login/multi_profile_first_run_notification.h"
+#include "chrome/browser/chromeos/login/multi_profile_user_controller.h"
#include "chrome/browser/chromeos/login/remove_user_delegate.h"
#include "chrome/browser/chromeos/login/user_image_manager_impl.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/session_length_limiter.h"
#include "chrome/browser/chromeos/settings/cros_settings_names.h"
+#include "chrome/browser/lifetime/application_lifetime.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.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -228,18 +234,29 @@
is_current_user_ephemeral_regular_user_(false),
ephemeral_users_enabled_(false),
user_image_manager_(new UserImageManagerImpl),
- manager_creation_time_(base::TimeTicks::Now()) {
+ manager_creation_time_(base::TimeTicks::Now()),
+ multi_profile_first_run_notification_(
+ new MultiProfileFirstRunNotification) {
// UserManager instance should be used only on UI thread.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
content::NotificationService::AllSources());
registrar_.Add(this, chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
content::NotificationService::AllSources());
+ registrar_.Add(this,
+ chrome::NOTIFICATION_PROFILE_CREATED,
+ content::NotificationService::AllSources());
RetrieveTrustedDevicePolicies();
- cros_settings_->AddSettingsObserver(kAccountsPrefDeviceLocalAccounts,
- this);
- cros_settings_->AddSettingsObserver(kAccountsPrefSupervisedUsersEnabled,
- this);
+ local_accounts_subscription_ = cros_settings_->AddSettingsObserver(
+ kAccountsPrefDeviceLocalAccounts,
+ base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies,
+ base::Unretained(this)));
+ supervised_users_subscription_ = cros_settings_->AddSettingsObserver(
+ kAccountsPrefSupervisedUsersEnabled,
+ base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies,
+ base::Unretained(this)));
+ multi_profile_user_controller_.reset(new MultiProfileUserController(
+ this, g_browser_process->local_state()));
UpdateLoginState();
}
@@ -260,11 +277,8 @@
void UserManagerImpl::Shutdown() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- cros_settings_->RemoveSettingsObserver(kAccountsPrefDeviceLocalAccounts,
- this);
- cros_settings_->RemoveSettingsObserver(
- kAccountsPrefSupervisedUsersEnabled,
- this);
+ local_accounts_subscription_.reset();
+ supervised_users_subscription_.reset();
// Stop the session length limiter.
session_length_limiter_.reset();
@@ -272,6 +286,7 @@
device_local_account_policy_service_->RemoveObserver(this);
user_image_manager_->Shutdown();
+ multi_profile_user_controller_.reset();
}
UserImageManager* UserManagerImpl::GetUserImageManager() {
@@ -284,11 +299,18 @@
}
UserList UserManagerImpl::GetUsersAdmittedForMultiProfile() const {
+ if (!UserManager::IsMultipleProfilesAllowed())
+ return UserList();
+
UserList result;
const UserList& users = GetUsers();
for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
- if ((*it)->GetType() == User::USER_TYPE_REGULAR && !(*it)->is_logged_in())
+ if ((*it)->GetType() == User::USER_TYPE_REGULAR &&
+ !(*it)->is_logged_in() &&
+ multi_profile_user_controller_->IsUserAllowedInSession(
+ (*it)->email())) {
result.push_back(*it);
+ }
}
return result;
}
@@ -333,6 +355,8 @@
user->set_username_hash(username_hash);
logged_in_users_.push_back(user);
lru_logged_in_users_.push_back(user);
+ // Reset the new user flag if the user already exists.
+ is_current_user_new_ = false;
// Set active user wallpaper back.
WallpaperManager::Get()->SetUserWallpaper(active_user_->email());
return;
@@ -691,12 +715,34 @@
void UserManagerImpl::SaveUserDisplayName(const std::string& username,
const string16& display_name) {
+ UpdateUserAccountDataImpl(username, display_name, NULL);
+}
+
+void UserManagerImpl::UpdateUserAccountData(const std::string& username,
+ const string16& display_name,
+ const std::string& locale) {
+ UpdateUserAccountDataImpl(username, display_name, &locale);
+}
+
+void UserManagerImpl::UpdateUserAccountDataImpl(const std::string& username,
+ const string16& display_name,
+ const std::string* locale) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
User* user = FindUserAndModify(username);
if (!user)
return; // Ignore if there is no such user.
+ // locale is not NULL if User Account has been downloaded
+ // (i.e. it is UpdateUserAccountData(), not SaveUserDisplayName() )
+ if (locale != NULL) {
+ user->SetAccountLocale(*locale);
+ RespectLocalePreference(GetProfileByUser(user), user);
+ }
+
+ if (display_name.empty())
+ return;
+
user->set_display_name(display_name);
// Do not update local store if data stored or cached outside the user's
@@ -765,6 +811,97 @@
return user ? user->display_email() : username;
}
+// TODO(alemate): http://crbug.com/288941 : Respect preferred language list in
+// the Google user profile.
+void UserManagerImpl::RespectLocalePreference(Profile* profile,
+ const User* user) const {
+ if (g_browser_process == NULL)
+ return;
+ if ((user == NULL) || (user != GetPrimaryUser()) ||
+ (!user->is_profile_created()))
+ return;
+
+ // In case of Multi Profile mode we don't apply profile locale because it is
+ // unsafe.
+ if (GetLoggedInUsers().size() != 1)
+ return;
+ const PrefService* prefs = profile->GetPrefs();
+ if (prefs == NULL)
+ return;
+
+ std::string pref_locale;
+ const std::string pref_app_locale =
+ prefs->GetString(prefs::kApplicationLocale);
+ const std::string pref_bkup_locale =
+ prefs->GetString(prefs::kApplicationLocaleBackup);
+
+ pref_locale = pref_app_locale;
+ if (pref_locale.empty())
+ pref_locale = pref_bkup_locale;
+
+ const std::string* account_locale = NULL;
+ if (pref_locale.empty() && user->has_gaia_account()) {
+ if (user->GetAccountLocale() == NULL)
+ return; // wait until Account profile is loaded.
+ account_locale = user->GetAccountLocale();
+ pref_locale = *account_locale;
+ }
+ const std::string global_app_locale =
+ g_browser_process->GetApplicationLocale();
+ if (pref_locale.empty())
+ pref_locale = global_app_locale;
+ DCHECK(!pref_locale.empty());
+ LOG(WARNING) << "RespectLocalePreference: "
+ << "app_locale='" << pref_app_locale << "', "
+ << "bkup_locale='" << pref_bkup_locale << "', "
+ << (account_locale != NULL
+ ? (std::string("account_locale='") + (*account_locale) +
+ "'. ")
+ : (std::string("account_locale - unused. ")))
+ << " Selected '" << pref_locale << "'";
+ profile->ChangeAppLocale(pref_locale, Profile::APP_LOCALE_CHANGED_VIA_LOGIN);
+ // Here we don't enable keyboard layouts. Input methods are set up when
+ // the user first logs in. Then the user may customize the input methods.
+ // Hence changing input methods here, just because the user's UI language
+ // is different from the login screen UI language, is not desirable. Note
+ // that input method preferences are synced, so users can use their
+ // farovite input methods as soon as the preferences are synced.
+ chromeos::LanguageSwitchMenu::SwitchLanguage(pref_locale);
+}
+
+class UserHashMatcher {
+ public:
+ explicit UserHashMatcher(const std::string& h) : username_hash(h) {}
+ bool operator()(const User* user) const {
+ return user->username_hash() == username_hash;
+ }
+
+ private:
+ const std::string& username_hash;
+};
+
+// Returns NULL if user is not created
+User* UserManagerImpl::GetUserByProfile(Profile* profile) const {
+ if (ProfileHelper::IsSigninProfile(profile))
+ return NULL;
+
+ if (IsMultipleProfilesAllowed()) {
+ const std::string username_hash =
+ ProfileHelper::GetUserIdHashFromProfile(profile);
+ const UserList& users = GetUsers();
+ const UserList::const_iterator pos = std::find_if(
+ users.begin(), users.end(), UserHashMatcher(username_hash));
+ return (pos != users.end()) ? *pos : NULL;
+ }
+ return active_user_;
+}
+
+Profile* UserManagerImpl::GetProfileByUser(const User* user) const {
+ if (IsMultipleProfilesAllowed())
+ return ProfileHelper::GetProfileByUserIdHash(user->username_hash());
+ return g_browser_process->profile_manager()->GetDefaultProfile();
+}
+
void UserManagerImpl::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
@@ -789,15 +926,19 @@
AuthSyncObserver* sync_observer =
AuthSyncObserverFactory::GetInstance()->GetForProfile(profile);
sync_observer->StartObserving();
+ multi_profile_user_controller_->StartObserving(profile);
+ multi_profile_first_run_notification_->UserProfilePrepared(profile);
}
}
break;
- 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();
+ case chrome::NOTIFICATION_PROFILE_CREATED: {
+ Profile* profile = content::Source<Profile>(source).ptr();
+ User* user = GetUserByProfile(profile);
+ if (user != NULL) {
+ user->set_profile_is_created();
+ if (user == active_user_)
+ RespectLocalePreference(profile, user);
+ }
break;
}
default:
@@ -1349,6 +1490,8 @@
DictionaryPrefUpdate manager_emails_update(prefs,
kManagedUserManagerDisplayEmails);
manager_emails_update->RemoveWithoutPathExpansion(email, NULL);
+
+ multi_profile_user_controller_->RemoveCachedValue(email);
}
User* UserManagerImpl::RemoveRegularOrLocallyManagedUserFromList(
@@ -1832,4 +1975,10 @@
}
}
+void UserManagerImpl::OnUserNotAllowed() {
+ LOG(ERROR) << "Shutdown session because a user is not allowed to be in the "
+ "current session";
+ chrome::AttemptUserExit();
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_manager_impl.h b/chrome/browser/chromeos/login/user_manager_impl.h
index a2debdf..ae65f06 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.h
+++ b/chrome/browser/chromeos/login/user_manager_impl.h
@@ -15,6 +15,7 @@
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/chromeos/login/multi_profile_user_controller_delegate.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_image_manager_impl.h"
#include "chrome/browser/chromeos/login/user_manager.h"
@@ -35,6 +36,8 @@
namespace chromeos {
+class MultiProfileFirstRunNotification;
+class MultiProfileUserController;
class RemoveUserDelegate;
class SessionLengthLimiter;
@@ -43,7 +46,8 @@
: public UserManager,
public LoginUtils::Delegate,
public content::NotificationObserver,
- public policy::DeviceLocalAccountPolicyService::Observer {
+ public policy::DeviceLocalAccountPolicyService::Observer,
+ public MultiProfileUserControllerDelegate {
public:
virtual ~UserManagerImpl();
@@ -79,6 +83,9 @@
User::OAuthTokenStatus oauth_token_status) OVERRIDE;
virtual void SaveUserDisplayName(const std::string& username,
const string16& display_name) OVERRIDE;
+ virtual void UpdateUserAccountData(const std::string& username,
+ const string16& display_name,
+ const std::string& locale) OVERRIDE;
virtual string16 GetUserDisplayName(
const std::string& username) const OVERRIDE;
virtual void SaveUserDisplayEmail(const std::string& username,
@@ -152,6 +159,9 @@
virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE;
virtual void OnDeviceLocalAccountsChanged() OVERRIDE;
+ // Wait untill we have sufficient information on user locale and apply it.
+ void RespectLocalePreference(Profile* profile, const User* user) const;
+
private:
friend class UserManager;
friend class WallpaperManager;
@@ -302,6 +312,19 @@
// Sends metrics in response to a regular user logging in.
void SendRegularUserLoginMetrics(const std::string& email);
+ // UpdateUserAccountData() + SaveUserDisplayName() .
+ void UpdateUserAccountDataImpl(const std::string& username,
+ const string16& display_name,
+ const std::string* locale);
+
+ // Returns NULL if User is not created.
+ User* GetUserByProfile(Profile* profile) const;
+
+ Profile* GetProfileByUser(const User* user) const;
+
+ // MultiProfileUserControllerDelegate implementation:
+ virtual void OnUserNotAllowed() OVERRIDE;
+
// Interface to the signed settings store.
CrosSettings* cros_settings_;
@@ -404,6 +427,15 @@
// Time at which this object was created.
base::TimeTicks manager_creation_time_;
+ scoped_ptr<CrosSettings::ObserverSubscription>
+ local_accounts_subscription_;
+ scoped_ptr<CrosSettings::ObserverSubscription>
+ supervised_users_subscription_;
+
+ scoped_ptr<MultiProfileUserController> multi_profile_user_controller_;
+ scoped_ptr<MultiProfileFirstRunNotification>
+ multi_profile_first_run_notification_;
+
DISALLOW_COPY_AND_ASSIGN(UserManagerImpl);
};
diff --git a/chrome/browser/chromeos/login/user_manager_unittest.cc b/chrome/browser/chromeos/login/user_manager_unittest.cc
index 19a17e7..7c909ad 100644
--- a/chrome/browser/chromeos/login/user_manager_unittest.cc
+++ b/chrome/browser/chromeos/login/user_manager_unittest.cc
@@ -7,7 +7,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_service.h"
-#include "base/prefs/testing_pref_service.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
@@ -19,6 +18,7 @@
#include "chrome/browser/chromeos/settings/cros_settings_provider.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -42,20 +42,15 @@
SetDeviceSettings(false, "", false);
// Register an in-memory local settings instance.
- local_state_.reset(new TestingPrefServiceSimple);
- 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.
- UserImageManager::RegisterPrefs(local_state_->registry());
- WallpaperManager::RegisterPrefs(local_state_->registry());
+ local_state_.reset(
+ new ScopedTestingLocalState(TestingBrowserProcess::GetGlobal()));
ResetUserManager();
}
virtual void TearDown() OVERRIDE {
// Unregister the in-memory local settings instance.
- TestingBrowserProcess::GetGlobal()->SetLocalState(0);
+ local_state_.reset();
// Restore the real DeviceSettingsProvider.
EXPECT_TRUE(
@@ -119,7 +114,7 @@
CrosSettings* cros_settings_;
CrosSettingsProvider* device_settings_provider_;
StubCrosSettingsProvider stub_settings_provider_;
- scoped_ptr<TestingPrefServiceSimple> local_state_;
+ scoped_ptr<ScopedTestingLocalState> local_state_;
ScopedTestDeviceSettingsService test_device_settings_service_;
ScopedTestCrosSettings test_cros_settings_;
diff --git a/chrome/browser/chromeos/login/version_info_updater.cc b/chrome/browser/chromeos/login/version_info_updater.cc
index 84ff2ce..6b51e5f 100644
--- a/chrome/browser/chromeos/login/version_info_updater.cc
+++ b/chrome/browser/chromeos/login/version_info_updater.cc
@@ -13,7 +13,6 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
#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"
@@ -53,9 +52,6 @@
GetDeviceCloudPolicyManager();
if (policy_manager)
policy_manager->core()->store()->RemoveObserver(this);
-
- for (unsigned int i = 0; i < arraysize(kReportingFlags); ++i)
- cros_settings_->RemoveSettingsObserver(kReportingFlags[i], this);
}
void VersionInfoUpdater::StartUpdate(bool is_official_build) {
@@ -82,8 +78,14 @@
}
// Watch for changes to the reporting flags.
- for (unsigned int i = 0; i < arraysize(kReportingFlags); ++i)
- cros_settings_->AddSettingsObserver(kReportingFlags[i], this);
+ base::Closure callback =
+ base::Bind(&VersionInfoUpdater::UpdateEnterpriseInfo,
+ base::Unretained(this));
+ for (unsigned int i = 0; i < arraysize(kReportingFlags); ++i) {
+ subscriptions_.push_back(
+ cros_settings_->AddSettingsObserver(kReportingFlags[i],
+ callback).release());
+ }
}
void VersionInfoUpdater::UpdateVersionLabel() {
@@ -134,14 +136,4 @@
UpdateEnterpriseInfo();
}
-void VersionInfoUpdater::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED)
- UpdateEnterpriseInfo();
- else
- NOTREACHED();
-}
-
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/version_info_updater.h b/chrome/browser/chromeos/login/version_info_updater.h
index 376e85a..becce6b 100644
--- a/chrome/browser/chromeos/login/version_info_updater.h
+++ b/chrome/browser/chromeos/login/version_info_updater.h
@@ -7,11 +7,12 @@
#include <string>
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/version_loader.h"
#include "chrome/browser/policy/cloud/cloud_policy_store.h"
-#include "content/public/browser/notification_observer.h"
namespace chromeos {
@@ -19,8 +20,7 @@
// Fetches all info we want to show on OOBE/Login screens about system
// version, boot times and cloud policy.
-class VersionInfoUpdater : public policy::CloudPolicyStore::Observer,
- public content::NotificationObserver {
+class VersionInfoUpdater : public policy::CloudPolicyStore::Observer {
public:
class Delegate {
public:
@@ -50,12 +50,6 @@
virtual void OnStoreLoaded(policy::CloudPolicyStore* store) OVERRIDE;
virtual void OnStoreError(policy::CloudPolicyStore* store) OVERRIDE;
- // content::NotificationObserver interface.
- virtual void Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
-
// Update the version label.
void UpdateVersionLabel();
@@ -81,6 +75,8 @@
// Full text for the OS version label.
std::string os_version_label_text_;
+ ScopedVector<CrosSettings::ObserverSubscription> subscriptions_;
+
chromeos::CrosSettings* cros_settings_;
Delegate* delegate_;
diff --git a/chrome/browser/chromeos/login/wallpaper_manager.cc b/chrome/browser/chromeos/login/wallpaper_manager.cc
index 6da9819..3920d71 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager.cc
+++ b/chrome/browser/chromeos/login/wallpaper_manager.cc
@@ -130,8 +130,7 @@
}
WallpaperManager::WallpaperManager()
- : no_observers_(true),
- loaded_wallpapers_(0),
+ : loaded_wallpapers_(0),
wallpaper_loader_(new UserImageLoader(ImageDecoder::ROBUST_JPEG_CODEC)),
command_line_for_testing_(NULL),
should_cache_wallpaper_(false),
@@ -156,15 +155,13 @@
WallpaperManager::~WallpaperManager() {
// TODO(bshe): Lifetime of WallpaperManager needs more consideration.
// http://crbug.com/171694
- DCHECK(no_observers_);
+ DCHECK(!show_user_name_on_signin_subscription_);
ClearObsoleteWallpaperPrefs();
weak_factory_.InvalidateWeakPtrs();
}
void WallpaperManager::Shutdown() {
- CrosSettings::Get()->RemoveSettingsObserver(
- kAccountsPrefShowUserNamesOnSignIn, this);
- no_observers_ = true;
+ show_user_name_on_signin_subscription_.reset();
}
// static
@@ -175,9 +172,11 @@
}
void WallpaperManager::AddObservers() {
- CrosSettings::Get()->AddSettingsObserver(kAccountsPrefShowUserNamesOnSignIn,
- this);
- no_observers_ = false;
+ show_user_name_on_signin_subscription_ =
+ CrosSettings::Get()->AddSettingsObserver(
+ kAccountsPrefShowUserNamesOnSignIn,
+ base::Bind(&WallpaperManager::InitializeRegisteredDeviceWallpaper,
+ base::Unretained(this)));
}
void WallpaperManager::EnsureLoggedInUserWallpaperLoaded() {
@@ -310,13 +309,6 @@
}
break;
}
- case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED: {
- if (*content::Details<const std::string>(details).ptr() ==
- kAccountsPrefShowUserNamesOnSignIn) {
- InitializeRegisteredDeviceWallpaper();
- }
- break;
- }
default:
NOTREACHED() << "Unexpected notification " << type;
}
@@ -428,7 +420,7 @@
bool is_persistent =
!UserManager::Get()->IsUserNonCryptohomeDataEphemeral(username);
- wallpaper.image().EnsureRepsForSupportedScaleFactors();
+ wallpaper.image().EnsureRepsForSupportedScales();
scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper.image().DeepCopy());
WallpaperInfo wallpaper_info = {
diff --git a/chrome/browser/chromeos/login/wallpaper_manager.h b/chrome/browser/chromeos/login/wallpaper_manager.h
index 9c7ee4c..cbf7af5 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager.h
+++ b/chrome/browser/chromeos/login/wallpaper_manager.h
@@ -10,12 +10,14 @@
#include "ash/desktop_background/desktop_background_controller.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.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"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
@@ -285,9 +287,6 @@
bool update_wallpaper,
const base::FilePath& wallpaper_path);
- // True if wallpaper manager is not observering other objects.
- bool no_observers_;
-
// The number of loaded wallpapers.
int loaded_wallpapers_;
@@ -317,6 +316,9 @@
bool should_cache_wallpaper_;
+ scoped_ptr<CrosSettings::ObserverSubscription>
+ show_user_name_on_signin_subscription_;
+
base::WeakPtrFactory<WallpaperManager> weak_factory_;
content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/chromeos/mobile/mobile_activator.cc b/chrome/browser/chromeos/mobile/mobile_activator.cc
index e934931..655ff1a 100644
--- a/chrome/browser/chromeos/mobile/mobile_activator.cc
+++ b/chrome/browser/chromeos/mobile/mobile_activator.cc
@@ -206,7 +206,7 @@
if (state_ == PLAN_ACTIVATION_PAGE_LOADING)
return;
- if (!network || network->type() != flimflam::kTypeCellular)
+ if (!network || network->type() != shill::kTypeCellular)
return;
const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
@@ -289,11 +289,11 @@
const DictionaryValue* payment_dict;
std::string usage_url, payment_url;
if (!properties.GetStringWithoutPathExpansion(
- flimflam::kUsageURLProperty, &usage_url) ||
+ shill::kUsageURLProperty, &usage_url) ||
!properties.GetDictionaryWithoutPathExpansion(
- flimflam::kPaymentPortalProperty, &payment_dict) ||
+ shill::kPaymentPortalProperty, &payment_dict) ||
!payment_dict->GetStringWithoutPathExpansion(
- flimflam::kPaymentPortalURL, &payment_url)) {
+ shill::kPaymentPortalURL, &payment_url)) {
NET_LOG_ERROR("MobileActivator missing properties", service_path_);
return;
}
@@ -305,7 +305,7 @@
// We want shill to connect us after activations, so enable autoconnect.
DictionaryValue auto_connect_property;
- auto_connect_property.SetBoolean(flimflam::kAutoConnectProperty, true);
+ auto_connect_property.SetBoolean(shill::kAutoConnectProperty, true);
NetworkHandler::Get()->network_configuration_handler()->SetProperties(
service_path_,
auto_connect_property,
@@ -425,7 +425,7 @@
// over a non-cellular network.
ChangeState(
network,
- (network->activation_state() == flimflam::kActivationStateActivated) ?
+ (network->activation_state() == shill::kActivationStateActivated) ?
PLAN_ACTIVATION_DONE :
PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
"");
@@ -437,7 +437,7 @@
if (HasRecentCellularPlanPayment() &&
(network->activation_state() ==
- flimflam::kActivationStatePartiallyActivated)) {
+ shill::kActivationStatePartiallyActivated)) {
// Try to start with OTASP immediately if we have received payment recently.
state_ = PLAN_ACTIVATION_START_OTASP;
} else {
@@ -537,8 +537,8 @@
void MobileActivator::ContinueConnecting() {
const NetworkState* network = GetNetworkState(service_path_);
if (network && network->IsConnectedState()) {
- if (network->connection_state() == flimflam::kStatePortal &&
- network->error() == flimflam::kErrorDNSLookupFailed) {
+ if (network->connection_state() == shill::kStatePortal &&
+ network->error() == shill::kErrorDNSLookupFailed) {
// It isn't an error to be in a restricted pool, but if DNS doesn't work,
// then we're not getting traffic through at all. Just disconnect and
// try again.
@@ -573,7 +573,7 @@
if (network && network->activate_over_non_cellular_networks()) {
bool waiting = (state_ == PLAN_ACTIVATION_WAITING_FOR_CONNECTION);
bool is_online = nsh->DefaultNetwork() &&
- nsh->DefaultNetwork()->connection_state() == flimflam::kStateOnline;
+ nsh->DefaultNetwork()->connection_state() == shill::kStateOnline;
if (waiting && is_online) {
ChangeState(network, post_reconnect_state_, "");
} else if (!waiting && !is_online) {
@@ -633,11 +633,11 @@
// activated device. If that attempt failed, try to disconnect to clear the
// state and reconnect again.
const std::string& activation = network->activation_state();
- if ((activation == flimflam::kActivationStatePartiallyActivated ||
- activation == flimflam::kActivationStateActivating) &&
+ if ((activation == shill::kActivationStatePartiallyActivated ||
+ activation == shill::kActivationStateActivating) &&
(network->error().empty() ||
- network->error() == flimflam::kErrorOtaspFailed) &&
- network->connection_state() == flimflam::kStateActivationFailure) {
+ network->error() == shill::kErrorOtaspFailed) &&
+ network->connection_state() == shill::kStateActivationFailure) {
NET_LOG_EVENT("Activation failure detected ", network->path());
switch (state_) {
case PLAN_ACTIVATION_OTASP:
@@ -681,12 +681,12 @@
new_state = PLAN_ACTIVATION_RECONNECTING;
break;
case PLAN_ACTIVATION_START:
- if (activation == flimflam::kActivationStateActivated) {
- if (network->connection_state() == flimflam::kStatePortal)
+ if (activation == shill::kActivationStateActivated) {
+ if (network->connection_state() == shill::kStatePortal)
new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
else
new_state = PLAN_ACTIVATION_DONE;
- } else if (activation == flimflam::kActivationStatePartiallyActivated) {
+ } else if (activation == shill::kActivationStatePartiallyActivated) {
new_state = PLAN_ACTIVATION_TRYING_OTASP;
} else {
new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION;
@@ -705,21 +705,21 @@
const std::string& activation = network->activation_state();
switch (state_) {
case PLAN_ACTIVATION_START:
- if (activation == flimflam::kActivationStateActivated) {
- if (network->connection_state() == flimflam::kStatePortal)
+ if (activation == shill::kActivationStateActivated) {
+ if (network->connection_state() == shill::kStatePortal)
new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
else
new_state = PLAN_ACTIVATION_DONE;
- } else if (activation == flimflam::kActivationStatePartiallyActivated) {
+ } else if (activation == shill::kActivationStatePartiallyActivated) {
new_state = PLAN_ACTIVATION_TRYING_OTASP;
} else {
new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION;
}
break;
case PLAN_ACTIVATION_START_OTASP: {
- if (activation == flimflam::kActivationStatePartiallyActivated) {
+ if (activation == shill::kActivationStatePartiallyActivated) {
new_state = PLAN_ACTIVATION_OTASP;
- } else if (activation == flimflam::kActivationStateActivated) {
+ } else if (activation == shill::kActivationStateActivated) {
new_state = PLAN_ACTIVATION_RECONNECTING;
} else {
LOG(WARNING) << "Unexpected activation state for device "
@@ -733,11 +733,11 @@
case PLAN_ACTIVATION_INITIATING_ACTIVATION: {
if (pending_activation_request_) {
LOG(INFO) << "Waiting for pending activation attempt to finish";
- } else if (activation == flimflam::kActivationStateActivated ||
- activation == flimflam::kActivationStatePartiallyActivated) {
+ } else if (activation == shill::kActivationStateActivated ||
+ activation == shill::kActivationStatePartiallyActivated) {
new_state = PLAN_ACTIVATION_START;
- } else if (activation == flimflam::kActivationStateNotActivated ||
- activation == flimflam::kActivationStateActivating) {
+ } else if (activation == shill::kActivationStateNotActivated ||
+ activation == shill::kActivationStateActivating) {
// Wait in this state until activation state changes.
} else {
LOG(WARNING) << "Unknown transition";
@@ -748,19 +748,19 @@
case PLAN_ACTIVATION_TRYING_OTASP:
if (pending_activation_request_) {
LOG(INFO) << "Waiting for pending activation attempt to finish";
- } else if (activation == flimflam::kActivationStateNotActivated ||
- activation == flimflam::kActivationStateActivating) {
+ } else if (activation == shill::kActivationStateNotActivated ||
+ activation == shill::kActivationStateActivating) {
LOG(INFO) << "Waiting for the OTASP to finish and the service to "
<< "come back online";
- } else if (activation == flimflam::kActivationStateActivated) {
+ } else if (activation == shill::kActivationStateActivated) {
new_state = PLAN_ACTIVATION_DONE;
} else {
new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
}
break;
case PLAN_ACTIVATION_RECONNECTING_PAYMENT:
- if (network->connection_state() != flimflam::kStatePortal &&
- activation == flimflam::kActivationStateActivated)
+ if (network->connection_state() != shill::kStatePortal &&
+ activation == shill::kActivationStateActivated)
// We're not portalled, and we're already activated, so we're online!
new_state = PLAN_ACTIVATION_DONE;
else
@@ -985,7 +985,14 @@
}
void MobileActivator::ReEnableCertRevocationChecking() {
+ // Check that both the browser process and prefs exist before trying to
+ // use them, since this method can be called by the destructor while Chrome
+ // is shutting down, during which either could be NULL.
+ if (!g_browser_process)
+ return;
PrefService* prefs = g_browser_process->local_state();
+ if (!prefs)
+ return;
if (reenable_cert_check_) {
prefs->SetBoolean(prefs::kCertRevocationCheckingEnabled,
true);
@@ -1014,25 +1021,25 @@
const std::string& activation = network->activation_state();
// This is the magic for detection of errors in during activation process.
- if (network->connection_state() == flimflam::kStateFailure &&
- network->error() == flimflam::kErrorAaaFailed) {
- if (activation == flimflam::kActivationStatePartiallyActivated) {
+ if (network->connection_state() == shill::kStateFailure &&
+ network->error() == shill::kErrorAaaFailed) {
+ if (activation == shill::kActivationStatePartiallyActivated) {
error_code = kErrorBadConnectionPartial;
- } else if (activation == flimflam::kActivationStateActivated) {
- if (network->roaming() == flimflam::kRoamingStateHome)
+ } else if (activation == shill::kActivationStateActivated) {
+ if (network->roaming() == shill::kRoamingStateHome)
error_code = kErrorBadConnectionActivated;
- else if (network->roaming() == flimflam::kRoamingStateRoaming)
+ else if (network->roaming() == shill::kRoamingStateRoaming)
error_code = kErrorRoamingOnConnection;
}
got_error = true;
- } else if (network->connection_state() == flimflam::kStateActivationFailure) {
- if (network->error() == flimflam::kErrorNeedEvdo) {
- if (activation == flimflam::kActivationStatePartiallyActivated)
+ } else if (network->connection_state() == shill::kStateActivationFailure) {
+ if (network->error() == shill::kErrorNeedEvdo) {
+ if (activation == shill::kActivationStatePartiallyActivated)
error_code = kErrorNoEVDO;
- } else if (network->error() == flimflam::kErrorNeedHomeNetwork) {
- if (activation == flimflam::kActivationStateNotActivated) {
+ } else if (network->error() == shill::kErrorNeedHomeNetwork) {
+ if (activation == shill::kActivationStateNotActivated) {
error_code = kErrorRoamingActivation;
- } else if (activation == flimflam::kActivationStatePartiallyActivated) {
+ } else if (activation == shill::kActivationStatePartiallyActivated) {
error_code = kErrorRoamingPartiallyActivated;
}
}
diff --git a/chrome/browser/chromeos/mobile/mobile_activator_unittest.cc b/chrome/browser/chromeos/mobile/mobile_activator_unittest.cc
index 764dfd6..450a30e 100644
--- a/chrome/browser/chromeos/mobile/mobile_activator_unittest.cc
+++ b/chrome/browser/chromeos/mobile/mobile_activator_unittest.cc
@@ -116,24 +116,24 @@
// activated.
std::string error_description;
set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
- set_connection_state(flimflam::kStateIdle);
- set_network_activation_state(flimflam::kActivationStateNotActivated);
+ set_connection_state(shill::kStateIdle);
+ set_network_activation_state(shill::kActivationStateNotActivated);
EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
mobile_activator_.PickNextState(&cellular_network_,
&error_description));
// Now behave as if ChangeState() has initiated an activation.
set_activator_state(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION);
- set_network_activation_state(flimflam::kActivationStateActivating);
+ set_network_activation_state(shill::kActivationStateActivating);
// We'll sit in this state while we wait for the OTASP to finish.
EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
mobile_activator_.PickNextState(&cellular_network_,
&error_description));
- set_network_activation_state(flimflam::kActivationStatePartiallyActivated);
+ set_network_activation_state(shill::kActivationStatePartiallyActivated);
// We'll sit in this state until we go online as well.
EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
mobile_activator_.PickNextState(&cellular_network_,
&error_description));
- set_connection_state(flimflam::kStatePortal);
+ set_connection_state(shill::kStatePortal);
// After we go online, we go back to START, which acts as a jumping off
// point for the two types of initial OTASP.
EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_START,
@@ -145,12 +145,12 @@
&error_description));
// Very similar things happen while we're trying OTASP.
set_activator_state(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP);
- set_network_activation_state(flimflam::kActivationStateActivating);
+ set_network_activation_state(shill::kActivationStateActivating);
EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
mobile_activator_.PickNextState(&cellular_network_,
&error_description));
- set_network_activation_state(flimflam::kActivationStatePartiallyActivated);
- set_connection_state(flimflam::kStatePortal);
+ set_network_activation_state(shill::kActivationStatePartiallyActivated);
+ set_connection_state(shill::kStatePortal);
// And when we come back online again and aren't activating, load the portal.
EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
mobile_activator_.PickNextState(&cellular_network_,
@@ -176,11 +176,11 @@
&error_description));
// Similarly to TRYING_OTASP and INITIATING_OTASP above...
set_activator_state(MobileActivator::PLAN_ACTIVATION_OTASP);
- set_network_activation_state(flimflam::kActivationStateActivating);
+ set_network_activation_state(shill::kActivationStateActivating);
EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP,
mobile_activator_.PickNextState(&cellular_network_,
&error_description));
- set_network_activation_state(flimflam::kActivationStateActivated);
+ set_network_activation_state(shill::kActivationStateActivated);
EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_DONE,
mobile_activator_.PickNextState(&cellular_network_,
&error_description));
@@ -249,8 +249,8 @@
// like when we're displaying the portal care quite a bit about going
// offline. Lets test for those cases.
std::string error_description;
- set_connection_state(flimflam::kStateFailure);
- set_network_activation_state(flimflam::kActivationStatePartiallyActivated);
+ set_connection_state(shill::kStateFailure);
+ set_network_activation_state(shill::kActivationStatePartiallyActivated);
set_activator_state(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING);
EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING,
mobile_activator_.PickNextState(&cellular_network_,
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
index 40ae6e1..c8c454f 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
@@ -10,7 +10,7 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chromeos/dbus/shill_service_client_stub.h"
+#include "chromeos/dbus/shill_stub_helper.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/notification_service.h"
@@ -349,8 +349,7 @@
captive_portal::Result result = results.result;
int response_code = results.response_code;
- if (ShillServiceClientStub::IsStubPortalledWifiEnabled(
- default_service_path_)) {
+ if (shill_stub_helper::IsStubPortalledWifiEnabled(default_service_path_)) {
result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL;
response_code = 200;
}
@@ -378,7 +377,7 @@
if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED;
} else if (default_network && (default_network->connection_state() ==
- flimflam::kStatePortal)) {
+ shill::kStatePortal)) {
// Take into account shill's detection results.
state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
LOG(WARNING) << "Network " << default_network->guid() << " "
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 488aa42..8f3c18a 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
@@ -167,7 +167,7 @@
void SetBehindPortal(const std::string& service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
dbus::ObjectPath(service_path),
- flimflam::kStateProperty, base::StringValue(flimflam::kStatePortal),
+ shill::kStateProperty, base::StringValue(shill::kStatePortal),
base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
base::RunLoop().RunUntilIdle();
}
@@ -197,19 +197,19 @@
const bool add_to_watchlist = true;
service_test->AddService(kStubEthernet,
kStubEthernet,
- flimflam::kTypeEthernet, flimflam::kStateIdle,
+ shill::kTypeEthernet, shill::kStateIdle,
add_to_visible, add_to_watchlist);
service_test->AddService(kStubWireless1,
kStubWireless1,
- flimflam::kTypeWifi, flimflam::kStateIdle,
+ shill::kTypeWifi, shill::kStateIdle,
add_to_visible, add_to_watchlist);
service_test->AddService(kStubWireless2,
kStubWireless2,
- flimflam::kTypeWifi, flimflam::kStateIdle,
+ shill::kTypeWifi, shill::kStateIdle,
add_to_visible, add_to_watchlist);
service_test->AddService(kStubCellular,
kStubCellular,
- flimflam::kTypeCellular, flimflam::kStateIdle,
+ shill::kTypeCellular, shill::kStateIdle,
add_to_visible, add_to_watchlist);
}
@@ -707,7 +707,7 @@
set_min_time_between_attempts(base::TimeDelta());
set_lazy_check_interval(base::TimeDelta());
- SetNetworkDeviceEnabled(flimflam::kTypeWifi, false);
+ SetNetworkDeviceEnabled(shill::kTypeWifi, false);
SetConnected(kStubCellular);
// First portal detection attempt for cellular1 uses 5sec timeout.
@@ -737,7 +737,7 @@
net::URLFetcher::RESPONSE_CODE_INVALID);
ASSERT_TRUE(is_state_idle());
- SetNetworkDeviceEnabled(flimflam::kTypeWifi, true);
+ SetNetworkDeviceEnabled(shill::kTypeWifi, true);
SetConnected(kStubWireless1);
// First portal detection attempt for wifi1 uses 5sec timeout.
diff --git a/chrome/browser/chromeos/net/onc_utils.cc b/chrome/browser/chromeos/net/onc_utils.cc
index 853d52b..dbe4306 100644
--- a/chrome/browser/chromeos/net/onc_utils.cc
+++ b/chrome/browser/chromeos/net/onc_utils.cc
@@ -218,10 +218,10 @@
ui_data->FillDictionary(&ui_data_dict);
std::string ui_data_json;
base::JSONWriter::Write(&ui_data_dict, &ui_data_json);
- shill_dict->SetStringWithoutPathExpansion(flimflam::kUIDataProperty,
+ shill_dict->SetStringWithoutPathExpansion(shill::kUIDataProperty,
ui_data_json);
- shill_dict->SetStringWithoutPathExpansion(flimflam::kProfileProperty,
+ shill_dict->SetStringWithoutPathExpansion(shill::kProfileProperty,
profile->path);
NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration(
diff --git a/chrome/browser/chromeos/net/proxy_config_handler.cc b/chrome/browser/chromeos/net/proxy_config_handler.cc
index d82e894..a5c71bb 100644
--- a/chrome/browser/chromeos/net/proxy_config_handler.cc
+++ b/chrome/browser/chromeos/net/proxy_config_handler.cc
@@ -186,7 +186,7 @@
// TODO(pneubeck): Consider removing this legacy code.
shill_service_client->ClearProperty(
dbus::ObjectPath(network.path()),
- flimflam::kProxyConfigProperty,
+ shill::kProxyConfigProperty,
base::Bind(&NotifyNetworkStateHandler, network.path()),
base::Bind(&network_handler::ShillErrorCallbackFunction,
"SetProxyConfig.ClearProperty Failed",
@@ -197,7 +197,7 @@
base::JSONWriter::Write(&proxy_config.GetDictionary(), &proxy_config_str);
shill_service_client->SetProperty(
dbus::ObjectPath(network.path()),
- flimflam::kProxyConfigProperty,
+ shill::kProxyConfigProperty,
base::StringValue(proxy_config_str),
base::Bind(&NotifyNetworkStateHandler, network.path()),
base::Bind(&network_handler::ShillErrorCallbackFunction,
diff --git a/chrome/browser/chromeos/offline/offline_load_page.cc b/chrome/browser/chromeos/offline/offline_load_page.cc
index cc7f5f7..603f610 100644
--- a/chrome/browser/chromeos/offline/offline_load_page.cc
+++ b/chrome/browser/chromeos/offline/offline_load_page.cc
@@ -13,6 +13,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
@@ -23,6 +24,7 @@
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_icon_set.h"
#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
+#include "chrome/common/localized_error.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/interstitial_page.h"
@@ -34,6 +36,7 @@
#include "grit/google_chrome_strings.h"
#include "grit/theme_resources.h"
#include "net/base/escape.h"
+#include "net/base/net_errors.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/webui/jstemplate_builder.h"
@@ -78,27 +81,9 @@
}
std::string OfflineLoadPage::GetHTMLContents() {
- DictionaryValue strings;
- int64 time_to_wait = kMaxBlankPeriod;
- // Set the timeout to show the page.
- strings.SetInteger("time_to_wait", static_cast<int>(time_to_wait));
-
- // Button labels
- SetString(&strings, "msg", IDS_OFFLINE_LOAD_DESCRIPTION);
- SetString(&strings, "network_settings", IDS_OFFLINE_NETWORK_SETTINGS);
- SetString(&strings, "product_name", IDS_SHORT_PRODUCT_NAME_LOWER);
-
- // Get the Chromium/Chrome icon, we can't access the icon via chrome://theme
- // on the webpage since the interstitial page isn't a webui and doesn't have
- // access to chrome:// URL's.
- strings.SetString("icon",
- webui::GetBitmapDataUrlFromResource(IDR_PRODUCT_LOGO_32));
-
- webui::SetFontAndTextDirection(&strings);
- string16 failed_url(ASCIIToUTF16(url_.spec()));
- if (base::i18n::IsRTL())
- base::i18n::WrapStringWithLTRFormatting(&failed_url);
- strings.SetString("url", failed_url);
+ // Use a local error page.
+ int resource_id;
+ base::DictionaryValue error_strings;
// The offline page for app has icons and slightly different message.
Profile* profile = Profile::FromBrowserContext(
@@ -107,19 +92,27 @@
const extensions::Extension* extension = NULL;
ExtensionService* extensions_service =
extensions::ExtensionSystem::Get(profile)->extension_service();
+
// Extension service does not exist in test.
if (extensions_service)
extension = extensions_service->extensions()->GetHostedAppByURL(url_);
- if (extension)
- GetAppOfflineStrings(extension, &strings);
- else
- GetNormalOfflineStrings(&strings);
+ if (extension && !extension->from_bookmark()) {
+ LocalizedError::GetAppErrorStrings(url_, extension, &error_strings);
+ resource_id = IDR_OFFLINE_APP_LOAD_HTML;
+ } else {
+ const std::string locale = g_browser_process->GetApplicationLocale();
+ LocalizedError::GetStrings(net::ERR_INTERNET_DISCONNECTED,
+ net::kErrorDomain, url_, false, locale,
+ &error_strings);
+ resource_id = IDR_OFFLINE_NET_LOAD_HTML;
+ }
- base::StringPiece html(
+ const base::StringPiece template_html(
ResourceBundle::GetSharedInstance().GetRawDataResource(
- IDR_OFFLINE_LOAD_HTML));
- return webui::GetI18nTemplateHtml(html, &strings);
+ resource_id));
+ // "t" is the id of the templates root node.
+ return webui::GetTemplatesHtml(template_html, &error_strings, "t");
}
void OfflineLoadPage::OverrideRendererPrefs(
@@ -143,20 +136,6 @@
NotifyBlockingPageComplete(false);
}
-void OfflineLoadPage::GetAppOfflineStrings(
- const extensions::Extension* app,
- DictionaryValue* strings) const {
- strings->SetString("title", app->name());
- strings->SetString(
- "heading", l10n_util::GetStringUTF16(IDS_APP_OFFLINE_LOAD_HEADLINE));
-}
-
-void OfflineLoadPage::GetNormalOfflineStrings(DictionaryValue* strings) const {
- strings->SetString("title", web_contents_->GetTitle());
- strings->SetString(
- "heading", l10n_util::GetStringUTF16(IDS_SITE_OFFLINE_LOAD_HEADLINE));
-}
-
void OfflineLoadPage::CommandReceived(const std::string& cmd) {
std::string command(cmd);
// The Jasonified response has quotes, remove them.
diff --git a/chrome/browser/chromeos/offline/offline_load_page.h b/chrome/browser/chromeos/offline/offline_load_page.h
index 8fdab58..2ff53bb 100644
--- a/chrome/browser/chromeos/offline/offline_load_page.h
+++ b/chrome/browser/chromeos/offline/offline_load_page.h
@@ -68,12 +68,6 @@
virtual void OnConnectionTypeChanged(
net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
- // Retrieves template strings of the offline page for app and
- // normal site.
- void GetAppOfflineStrings(const extensions::Extension* app,
- base::DictionaryValue* strings) const;
- void GetNormalOfflineStrings(base::DictionaryValue* strings) const;
-
CompletionCallback callback_;
// True if the proceed is chosen.
diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc
index 5d07db7..4fa35c3 100644
--- a/chrome/browser/chromeos/options/network_config_view.cc
+++ b/chrome/browser/chromeos/options/network_config_view.cc
@@ -87,25 +87,25 @@
void NetworkConfigView::InitWithNetworkState(const NetworkState* network) {
DCHECK(network);
std::string service_path = network->path();
- if (network->type() == flimflam::kTypeWifi)
+ if (network->type() == shill::kTypeWifi)
child_config_view_ = new WifiConfigView(this, service_path, false);
- else if (network->type() == flimflam::kTypeWimax)
+ else if (network->type() == shill::kTypeWimax)
child_config_view_ = new WimaxConfigView(this, service_path);
- else if (network->type() == flimflam::kTypeVPN)
+ else if (network->type() == shill::kTypeVPN)
child_config_view_ = new VPNConfigView(this, service_path);
else
NOTREACHED();
}
void NetworkConfigView::InitWithType(const std::string& type) {
- if (type == flimflam::kTypeWifi) {
+ if (type == shill::kTypeWifi) {
child_config_view_ = new WifiConfigView(this,
"" /* service_path */,
false /* show_8021x */);
advanced_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADVANCED_BUTTON));
advanced_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
- } else if (type == flimflam::kTypeVPN) {
+ } else if (type == shill::kTypeVPN) {
child_config_view_ = new VPNConfigView(this,
"" /* service_path */);
} else {
diff --git a/chrome/browser/chromeos/options/vpn_config_view.cc b/chrome/browser/chromeos/options/vpn_config_view.cc
index cfbd30f..36ad62d 100644
--- a/chrome/browser/chromeos/options/vpn_config_view.cc
+++ b/chrome/browser/chromeos/options/vpn_config_view.cc
@@ -66,13 +66,13 @@
int ProviderTypeToIndex(const std::string& provider_type,
const std::string& client_cert_id) {
- if (provider_type == flimflam::kProviderL2tpIpsec) {
+ if (provider_type == shill::kProviderL2tpIpsec) {
if (!client_cert_id.empty())
return PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
else
return PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK;
} else {
- DCHECK(provider_type == flimflam::kProviderOpenVpn);
+ DCHECK(provider_type == shill::kProviderOpenVpn);
return PROVIDER_TYPE_INDEX_OPEN_VPN;
}
}
@@ -364,13 +364,13 @@
base::DictionaryValue properties;
// Identifying properties
properties.SetStringWithoutPathExpansion(
- flimflam::kTypeProperty, flimflam::kTypeVPN);
+ shill::kTypeProperty, shill::kTypeVPN);
properties.SetStringWithoutPathExpansion(
- flimflam::kNameProperty, GetService());
+ shill::kNameProperty, GetService());
properties.SetStringWithoutPathExpansion(
- flimflam::kProviderHostProperty, GetServer());
+ shill::kProviderHostProperty, GetServer());
properties.SetStringWithoutPathExpansion(
- flimflam::kProviderTypeProperty, GetProviderTypeString());
+ shill::kProviderTypeProperty, GetProviderTypeString());
SetConfigProperties(&properties);
ash::network_connect::CreateConfigurationAndConnect(
@@ -476,9 +476,9 @@
switch (index) {
case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
- return flimflam::kProviderL2tpIpsec;
+ return shill::kProviderL2tpIpsec;
case PROVIDER_TYPE_INDEX_OPEN_VPN:
- return flimflam::kProviderOpenVpn;
+ return shill::kProviderOpenVpn;
}
NOTREACHED();
return std::string();
@@ -489,7 +489,7 @@
if (!service_path_.empty()) {
vpn = NetworkHandler::Get()->network_state_handler()->
GetNetworkState(service_path_);
- DCHECK(vpn && vpn->type() == flimflam::kTypeVPN);
+ DCHECK(vpn && vpn->type() == shill::kTypeVPN);
}
layout_ = views::GridLayout::CreatePanel(this);
SetLayoutManager(layout_);
@@ -709,34 +709,34 @@
bool psk_passphrase_required = false;
const base::DictionaryValue* provider_properties;
if (service_properties.GetDictionaryWithoutPathExpansion(
- flimflam::kProviderProperty, &provider_properties)) {
+ shill::kProviderProperty, &provider_properties)) {
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kTypeProperty, &provider_type);
+ shill::kTypeProperty, &provider_type);
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kHostProperty, &server_hostname);
+ shill::kHostProperty, &server_hostname);
}
- if (provider_type == flimflam::kProviderL2tpIpsec) {
+ if (provider_type == shill::kProviderL2tpIpsec) {
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecClientCertIdProperty, &client_cert_id_);
+ shill::kL2tpIpsecClientCertIdProperty, &client_cert_id_);
ca_cert_pem_ = GetPemFromDictionary(
provider_properties, shill::kL2tpIpsecCaCertPemProperty);
provider_properties->GetBooleanWithoutPathExpansion(
- flimflam::kL2tpIpsecPskRequiredProperty, &psk_passphrase_required);
+ shill::kL2tpIpsecPskRequiredProperty, &psk_passphrase_required);
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecUserProperty, &username);
+ shill::kL2tpIpsecUserProperty, &username);
provider_properties->GetStringWithoutPathExpansion(
shill::kL2tpIpsecTunnelGroupProperty, &group_name);
- } else if (provider_type == flimflam::kProviderOpenVpn) {
+ } else if (provider_type == shill::kProviderOpenVpn) {
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kOpenVPNClientCertIdProperty, &client_cert_id_);
+ shill::kOpenVPNClientCertIdProperty, &client_cert_id_);
ca_cert_pem_ = GetPemFromDictionary(
provider_properties, shill::kOpenVPNCaCertPemProperty);
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kOpenVPNUserProperty, &username);
+ shill::kOpenVPNUserProperty, &username);
}
bool save_credentials = false;
service_properties.GetBooleanWithoutPathExpansion(
- flimflam::kSaveCredentialsProperty, &save_credentials);
+ shill::kSaveCredentialsProperty, &save_credentials);
provider_type_index_ = ProviderTypeToIndex(provider_type, client_cert_id_);
@@ -805,7 +805,7 @@
std::string psk_passphrase = GetPSKPassphrase();
if (!psk_passphrase.empty()) {
properties->SetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecPskProperty, GetPSKPassphrase());
+ shill::kL2tpIpsecPskProperty, GetPSKPassphrase());
}
if (!group_name.empty()) {
properties->SetStringWithoutPathExpansion(
@@ -813,11 +813,11 @@
}
if (!user_name.empty()) {
properties->SetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecUserProperty, user_name);
+ shill::kL2tpIpsecUserProperty, user_name);
}
if (!user_passphrase.empty()) {
properties->SetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecPasswordProperty, user_passphrase);
+ shill::kL2tpIpsecPasswordProperty, user_passphrase);
}
break;
}
@@ -830,18 +830,18 @@
shill::kL2tpIpsecCaCertPemProperty, pem_list);
}
properties->SetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecClientCertIdProperty, GetUserCertID());
+ shill::kL2tpIpsecClientCertIdProperty, GetUserCertID());
if (!group_name.empty()) {
properties->SetStringWithoutPathExpansion(
shill::kL2tpIpsecTunnelGroupProperty, GetGroupName());
}
if (!user_name.empty()) {
properties->SetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecUserProperty, user_name);
+ shill::kL2tpIpsecUserProperty, user_name);
}
if (!user_passphrase.empty()) {
properties->SetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecPasswordProperty, user_passphrase);
+ shill::kL2tpIpsecPasswordProperty, user_passphrase);
}
break;
}
@@ -854,17 +854,17 @@
shill::kOpenVPNCaCertPemProperty, pem_list);
}
properties->SetStringWithoutPathExpansion(
- flimflam::kOpenVPNClientCertIdProperty, GetUserCertID());
+ shill::kOpenVPNClientCertIdProperty, GetUserCertID());
properties->SetStringWithoutPathExpansion(
- flimflam::kOpenVPNUserProperty, GetUsername());
+ shill::kOpenVPNUserProperty, GetUsername());
if (!user_passphrase.empty()) {
properties->SetStringWithoutPathExpansion(
- flimflam::kOpenVPNPasswordProperty, user_passphrase);
+ shill::kOpenVPNPasswordProperty, user_passphrase);
}
std::string otp = GetOTP();
if (!otp.empty()) {
properties->SetStringWithoutPathExpansion(
- flimflam::kOpenVPNOTPProperty, otp);
+ shill::kOpenVPNOTPProperty, otp);
}
break;
}
@@ -873,7 +873,7 @@
break;
}
properties->SetBooleanWithoutPathExpansion(
- flimflam::kSaveCredentialsProperty, GetSaveCredentials());
+ shill::kSaveCredentialsProperty, GetSaveCredentials());
}
void VPNConfigView::Refresh() {
@@ -986,7 +986,7 @@
// TODO(kuan): differentiate between bad psk and user passphrases.
const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
GetNetworkState(service_path_);
- if (vpn && vpn->connection_state() == flimflam::kStateFailure)
+ if (vpn && vpn->connection_state() == shill::kStateFailure)
error_msg = ash::network_connect::ErrorString(vpn->error());
}
if (!error_msg.empty()) {
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc
index 869ea65..5402cb8 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -581,7 +581,7 @@
if (error_msg.empty() && !service_path_.empty()) {
const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
GetNetworkState(service_path_);
- if (wifi && wifi->connection_state() == flimflam::kStateFailure)
+ if (wifi && wifi->connection_state() == shill::kStateFailure)
error_msg = ash::network_connect::ErrorString(wifi->error());
}
if (!error_msg.empty()) {
@@ -649,39 +649,39 @@
// Set configuration properties.
base::DictionaryValue properties;
properties.SetStringWithoutPathExpansion(
- flimflam::kTypeProperty, flimflam::kTypeWifi);
+ shill::kTypeProperty, shill::kTypeWifi);
properties.SetStringWithoutPathExpansion(
- flimflam::kSSIDProperty, GetSsid());
+ shill::kSSIDProperty, GetSsid());
properties.SetStringWithoutPathExpansion(
- flimflam::kModeProperty, flimflam::kModeManaged);
+ shill::kModeProperty, shill::kModeManaged);
properties.SetBooleanWithoutPathExpansion(
- flimflam::kSaveCredentialsProperty, GetSaveCredentials());
- std::string security = flimflam::kSecurityNone;
+ shill::kSaveCredentialsProperty, GetSaveCredentials());
+ std::string security = shill::kSecurityNone;
if (!eap_method_combobox_) {
// Hidden ordinary Wi-Fi connection.
switch (security_combobox_->selected_index()) {
case SECURITY_INDEX_NONE:
- security = flimflam::kSecurityNone;
+ security = shill::kSecurityNone;
break;
case SECURITY_INDEX_WEP:
- security = flimflam::kSecurityWep;
+ security = shill::kSecurityWep;
break;
case SECURITY_INDEX_PSK:
- security = flimflam::kSecurityPsk;
+ security = shill::kSecurityPsk;
break;
}
std::string passphrase = GetPassphrase();
if (!passphrase.empty()) {
properties.SetStringWithoutPathExpansion(
- flimflam::kPassphraseProperty, GetPassphrase());
+ shill::kPassphraseProperty, GetPassphrase());
}
} else {
// Hidden 802.1X EAP Wi-Fi connection.
- security = flimflam::kSecurity8021x;
+ security = shill::kSecurity8021x;
SetEapProperties(&properties);
}
properties.SetStringWithoutPathExpansion(
- flimflam::kSecurityProperty, security);
+ shill::kSecurityProperty, security);
// Configure and connect to network.
bool shared = GetShareNetwork(share_default);
@@ -700,13 +700,13 @@
// Visible 802.1X EAP Wi-Fi connection.
SetEapProperties(&properties);
properties.SetBooleanWithoutPathExpansion(
- flimflam::kSaveCredentialsProperty, GetSaveCredentials());
+ shill::kSaveCredentialsProperty, GetSaveCredentials());
} else {
// Visible ordinary Wi-Fi connection.
const std::string passphrase = GetPassphrase();
if (!passphrase.empty()) {
properties.SetStringWithoutPathExpansion(
- flimflam::kPassphraseProperty, passphrase);
+ shill::kPassphraseProperty, passphrase);
}
}
bool share_network = GetShareNetwork(share_default);
@@ -748,13 +748,13 @@
DCHECK(eap_method_combobox_);
switch (eap_method_combobox_->selected_index()) {
case EAP_METHOD_INDEX_PEAP:
- return flimflam::kEapMethodPEAP;
+ return shill::kEapMethodPEAP;
case EAP_METHOD_INDEX_TLS:
- return flimflam::kEapMethodTLS;
+ return shill::kEapMethodTLS;
case EAP_METHOD_INDEX_TTLS:
- return flimflam::kEapMethodTTLS;
+ return shill::kEapMethodTTLS;
case EAP_METHOD_INDEX_LEAP:
- return flimflam::kEapMethodLEAP;
+ return shill::kEapMethodLEAP;
case EAP_METHOD_INDEX_NONE:
default:
return "";
@@ -763,20 +763,20 @@
std::string WifiConfigView::GetEapPhase2Auth() const {
DCHECK(phase_2_auth_combobox_);
- bool is_peap = (GetEapMethod() == flimflam::kEapMethodPEAP);
+ bool is_peap = (GetEapMethod() == shill::kEapMethodPEAP);
switch (phase_2_auth_combobox_->selected_index()) {
case PHASE_2_AUTH_INDEX_MD5:
- return is_peap ? flimflam::kEapPhase2AuthPEAPMD5
- : flimflam::kEapPhase2AuthTTLSMD5;
+ return is_peap ? shill::kEapPhase2AuthPEAPMD5
+ : shill::kEapPhase2AuthTTLSMD5;
case PHASE_2_AUTH_INDEX_MSCHAPV2:
- return is_peap ? flimflam::kEapPhase2AuthPEAPMSCHAPV2
- : flimflam::kEapPhase2AuthTTLSMSCHAPV2;
+ return is_peap ? shill::kEapPhase2AuthPEAPMSCHAPV2
+ : shill::kEapPhase2AuthTTLSMSCHAPV2;
case PHASE_2_AUTH_INDEX_MSCHAP:
- return flimflam::kEapPhase2AuthTTLSMSCHAP;
+ return shill::kEapPhase2AuthTTLSMSCHAP;
case PHASE_2_AUTH_INDEX_PAP:
- return flimflam::kEapPhase2AuthTTLSPAP;
+ return shill::kEapPhase2AuthTTLSPAP;
case PHASE_2_AUTH_INDEX_CHAP:
- return flimflam::kEapPhase2AuthTTLSCHAP;
+ return shill::kEapPhase2AuthTTLSCHAP;
case PHASE_2_AUTH_INDEX_AUTO:
default:
return "";
@@ -834,27 +834,27 @@
void WifiConfigView::SetEapProperties(base::DictionaryValue* properties) {
properties->SetStringWithoutPathExpansion(
- flimflam::kEapIdentityProperty, GetEapIdentity());
+ shill::kEapIdentityProperty, GetEapIdentity());
properties->SetStringWithoutPathExpansion(
- flimflam::kEapMethodProperty, GetEapMethod());
+ shill::kEapMethodProperty, GetEapMethod());
properties->SetStringWithoutPathExpansion(
- flimflam::kEapPhase2AuthProperty, GetEapPhase2Auth());
+ shill::kEapPhase2AuthProperty, GetEapPhase2Auth());
properties->SetStringWithoutPathExpansion(
- flimflam::kEapAnonymousIdentityProperty, GetEapAnonymousIdentity());
+ shill::kEapAnonymousIdentityProperty, GetEapAnonymousIdentity());
properties->SetStringWithoutPathExpansion(
shill::kEapSubjectMatchProperty, GetEapSubjectMatch());
// shill requires both CertID and KeyID for TLS connections, despite
// the fact that by convention they are the same ID.
properties->SetStringWithoutPathExpansion(
- flimflam::kEapCertIdProperty, GetEapClientCertPkcs11Id());
+ shill::kEapCertIdProperty, GetEapClientCertPkcs11Id());
properties->SetStringWithoutPathExpansion(
- flimflam::kEapKeyIdProperty, GetEapClientCertPkcs11Id());
+ shill::kEapKeyIdProperty, GetEapClientCertPkcs11Id());
properties->SetBooleanWithoutPathExpansion(
- flimflam::kEapUseSystemCasProperty, GetEapUseSystemCas());
+ shill::kEapUseSystemCasProperty, GetEapUseSystemCas());
properties->SetStringWithoutPathExpansion(
- flimflam::kEapPasswordProperty, GetPassphrase());
+ shill::kEapPasswordProperty, GetPassphrase());
base::ListValue* pem_list = new base::ListValue;
pem_list->AppendString(GetEapServerCaCertPEM());
@@ -875,8 +875,8 @@
const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
GetNetworkState(service_path_);
if (wifi) {
- DCHECK(wifi->type() == flimflam::kTypeWifi);
- if (wifi->security() == flimflam::kSecurity8021x)
+ DCHECK(wifi->type() == shill::kTypeWifi);
+ if (wifi->security() == shill::kSecurity8021x)
show_8021x = true;
ParseWiFiEAPUIProperty(&eap_method_ui_data_, wifi, onc::eap::kOuter);
ParseWiFiEAPUIProperty(&phase_2_auth_ui_data_, wifi, onc::eap::kInner);
@@ -1176,7 +1176,7 @@
if (!show_8021x) {
std::string passphrase;
properties.GetStringWithoutPathExpansion(
- flimflam::kPassphraseProperty, &passphrase);
+ shill::kPassphraseProperty, &passphrase);
passphrase_textfield_->SetText(UTF8ToUTF16(passphrase));
return;
}
@@ -1184,14 +1184,14 @@
// EAP Method
std::string eap_method;
properties.GetStringWithoutPathExpansion(
- flimflam::kEapMethodProperty, &eap_method);
- if (eap_method == flimflam::kEapMethodPEAP)
+ shill::kEapMethodProperty, &eap_method);
+ if (eap_method == shill::kEapMethodPEAP)
eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_PEAP);
- else if (eap_method == flimflam::kEapMethodTTLS)
+ else if (eap_method == shill::kEapMethodTTLS)
eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TTLS);
- else if (eap_method == flimflam::kEapMethodTLS)
+ else if (eap_method == shill::kEapMethodTLS)
eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TLS);
- else if (eap_method == flimflam::kEapMethodLEAP)
+ else if (eap_method == shill::kEapMethodLEAP)
eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_LEAP);
RefreshEapFields();
@@ -1199,21 +1199,21 @@
if (Phase2AuthActive()) {
std::string eap_phase_2_auth;
properties.GetStringWithoutPathExpansion(
- flimflam::kEapPhase2AuthProperty, &eap_phase_2_auth);
- if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMD5)
+ shill::kEapPhase2AuthProperty, &eap_phase_2_auth);
+ if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSMD5)
phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MD5);
- else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMSCHAPV2)
+ else if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSMSCHAPV2)
phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAPV2);
- else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMSCHAP)
+ else if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSMSCHAP)
phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAP);
- else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSPAP)
+ else if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSPAP)
phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_PAP);
- else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSCHAP)
+ else if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSCHAP)
phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_CHAP);
std::string eap_anonymous_identity;
properties.GetStringWithoutPathExpansion(
- flimflam::kEapAnonymousIdentityProperty, &eap_anonymous_identity);
+ shill::kEapAnonymousIdentityProperty, &eap_anonymous_identity);
identity_anonymous_textfield_->SetText(UTF8ToUTF16(eap_anonymous_identity));
}
@@ -1233,7 +1233,7 @@
if (eap_ca_cert_pem.empty()) {
bool eap_use_system_cas = false;
properties.GetBooleanWithoutPathExpansion(
- flimflam::kEapUseSystemCasProperty, &eap_use_system_cas);
+ shill::kEapUseSystemCasProperty, &eap_use_system_cas);
if (eap_use_system_cas) {
// "Default"
server_ca_cert_combobox_->SetSelectedIndex(0);
@@ -1260,7 +1260,7 @@
if (UserCertActive()) {
std::string eap_cert_id;
properties.GetStringWithoutPathExpansion(
- flimflam::kEapCertIdProperty, &eap_cert_id);
+ shill::kEapCertIdProperty, &eap_cert_id);
if (!eap_cert_id.empty()) {
int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id(
CertLibrary::CERT_TYPE_USER, eap_cert_id);
@@ -1272,27 +1272,27 @@
// Identity is always active.
std::string eap_identity;
properties.GetStringWithoutPathExpansion(
- flimflam::kEapIdentityProperty, &eap_identity);
+ shill::kEapIdentityProperty, &eap_identity);
identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
// Passphrase
if (PassphraseActive()) {
std::string eap_password;
properties.GetStringWithoutPathExpansion(
- flimflam::kEapPasswordProperty, &eap_password);
+ shill::kEapPasswordProperty, &eap_password);
passphrase_textfield_->SetText(UTF8ToUTF16(eap_password));
// If 'Connectable' is True, show a fake passphrase to indicate that it
// has already been set.
bool connectable = false;
properties.GetBooleanWithoutPathExpansion(
- flimflam::kConnectableProperty, &connectable);
+ shill::kConnectableProperty, &connectable);
passphrase_textfield_->SetShowFake(connectable);
}
// Save credentials
bool save_credentials = false;
properties.GetBooleanWithoutPathExpansion(
- flimflam::kSaveCredentialsProperty, &save_credentials);
+ shill::kSaveCredentialsProperty, &save_credentials);
save_credentials_checkbox_->SetChecked(save_credentials);
UpdateDialogButtons();
diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc
index 288ae22..4e86f8e 100644
--- a/chrome/browser/chromeos/options/wimax_config_view.cc
+++ b/chrome/browser/chromeos/options/wimax_config_view.cc
@@ -99,7 +99,7 @@
if (!service_path_.empty()) {
const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
GetNetworkState(service_path_);
- if (wimax && wimax->connection_state() == flimflam::kStateFailure)
+ if (wimax && wimax->connection_state() == shill::kStateFailure)
error_msg = ash::network_connect::ErrorString(wimax->error());
}
if (!error_msg.empty()) {
@@ -148,11 +148,11 @@
}
base::DictionaryValue properties;
properties.SetStringWithoutPathExpansion(
- flimflam::kEapIdentityProperty, GetEapIdentity());
+ shill::kEapIdentityProperty, GetEapIdentity());
properties.SetStringWithoutPathExpansion(
- flimflam::kEapPasswordProperty, GetEapPassphrase());
+ shill::kEapPasswordProperty, GetEapPassphrase());
properties.SetBooleanWithoutPathExpansion(
- flimflam::kSaveCredentialsProperty, GetSaveCredentials());
+ shill::kSaveCredentialsProperty, GetSaveCredentials());
const bool share_default = true;
bool share_network = GetShareNetwork(share_default);
@@ -187,7 +187,7 @@
void WimaxConfigView::Init() {
const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
GetNetworkState(service_path_);
- DCHECK(wimax && wimax->type() == flimflam::kTypeWimax);
+ DCHECK(wimax && wimax->type() == shill::kTypeWimax);
WifiConfigView::ParseWiFiEAPUIProperty(
&save_credentials_ui_data_, wimax, onc::eap::kSaveCredentials);
@@ -348,14 +348,14 @@
// EapIdentity
std::string eap_identity;
properties.GetStringWithoutPathExpansion(
- flimflam::kEapIdentityProperty, &eap_identity);
+ shill::kEapIdentityProperty, &eap_identity);
identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
// Save credentials
if (save_credentials_checkbox_) {
bool save_credentials = false;
properties.GetBooleanWithoutPathExpansion(
- flimflam::kSaveCredentialsProperty, &save_credentials);
+ shill::kSaveCredentialsProperty, &save_credentials);
save_credentials_checkbox_->SetChecked(save_credentials);
}
}
diff --git a/chrome/browser/chromeos/policy/app_pack_updater.cc b/chrome/browser/chromeos/policy/app_pack_updater.cc
index 9230628..59a6baa 100644
--- a/chrome/browser/chromeos/policy/app_pack_updater.cc
+++ b/chrome/browser/chromeos/policy/app_pack_updater.cc
@@ -6,16 +6,12 @@
#include "base/bind.h"
#include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/cros_settings_names.h"
#include "chrome/browser/extensions/external_loader.h"
#include "chrome/browser/extensions/external_provider_impl.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"
using content::BrowserThread;
@@ -66,8 +62,10 @@
: weak_ptr_factory_(this),
created_extension_loader_(false),
install_attributes_(install_attributes),
- external_cache_(kAppPackCacheDir, request_context, this, false) {
- chromeos::CrosSettings::Get()->AddSettingsObserver(chromeos::kAppPack, this);
+ external_cache_(kAppPackCacheDir, request_context, this, false, false) {
+ app_pack_subscription_ = chromeos::CrosSettings::Get()->AddSettingsObserver(
+ chromeos::kAppPack,
+ base::Bind(&AppPackUpdater::AppPackChanged, base::Unretained(this)));
if (install_attributes_->GetMode() == DEVICE_MODE_RETAIL_KIOSK) {
// Already in Kiosk mode, start loading.
@@ -81,8 +79,6 @@
}
AppPackUpdater::~AppPackUpdater() {
- chromeos::CrosSettings::Get()->RemoveSettingsObserver(
- chromeos::kAppPack, this);
}
extensions::ExternalLoader* AppPackUpdater::CreateExternalLoader() {
@@ -111,20 +107,9 @@
}
}
-void AppPackUpdater::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED:
- DCHECK_EQ(chromeos::kAppPack,
- *content::Details<const std::string>(details).ptr());
- if (install_attributes_->GetMode() == DEVICE_MODE_RETAIL_KIOSK)
- LoadPolicy();
- break;
-
- default:
- NOTREACHED();
- }
+void AppPackUpdater::AppPackChanged() {
+ if (install_attributes_->GetMode() == DEVICE_MODE_RETAIL_KIOSK)
+ LoadPolicy();
}
void AppPackUpdater::LoadPolicy() {
diff --git a/chrome/browser/chromeos/policy/app_pack_updater.h b/chrome/browser/chromeos/policy/app_pack_updater.h
index cd22b9c..54b4374 100644
--- a/chrome/browser/chromeos/policy/app_pack_updater.h
+++ b/chrome/browser/chromeos/policy/app_pack_updater.h
@@ -11,9 +11,10 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/extensions/external_cache.h"
-#include "content/public/browser/notification_observer.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
namespace extensions {
class ExternalLoader;
@@ -31,8 +32,7 @@
// The AppPackUpdater manages a set of extensions that are configured via a
// device policy to be locally cached and installed into the Demo user account
// at login time.
-class AppPackUpdater : public content::NotificationObserver,
- public chromeos::ExternalCache::Delegate {
+class AppPackUpdater : public chromeos::ExternalCache::Delegate {
public:
// Callback to listen for updates to the screensaver extension's path.
typedef base::Callback<void(const base::FilePath&)> ScreenSaverUpdateCallback;
@@ -63,15 +63,13 @@
void OnDamagedFileDetected(const base::FilePath& path);
private:
- // content::NotificationObserver:
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
-
// Implementation of ExternalCache::Delegate:
virtual void OnExtensionListsUpdated(
const base::DictionaryValue* prefs) OVERRIDE;
+ // Called when the app pack device setting changes.
+ void AppPackChanged();
+
// Loads the current policy and schedules a cache update.
void LoadPolicy();
@@ -105,6 +103,9 @@
// Extension cache.
chromeos::ExternalCache external_cache_;
+ scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
+ app_pack_subscription_;
+
DISALLOW_COPY_AND_ASSIGN(AppPackUpdater);
};
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client.cc b/chrome/browser/chromeos/policy/auto_enrollment_client.cc
index 197417d..8f05b19 100644
--- a/chrome/browser/chromeos/policy/auto_enrollment_client.cc
+++ b/chrome/browser/chromeos/policy/auto_enrollment_client.cc
@@ -21,7 +21,11 @@
#include "chrome/browser/policy/cloud/device_management_service.h"
#include "chrome/common/pref_names.h"
#include "chromeos/chromeos_switches.h"
+#include "content/public/browser/browser_thread.h"
#include "crypto/sha2.h"
+#include "net/url_request/url_request_context_getter.h"
+
+using content::BrowserThread;
namespace em = enterprise_management;
@@ -129,7 +133,9 @@
} else {
std::string url = BrowserPolicyConnector::GetDeviceManagementUrl();
if (!url.empty()) {
- service = new DeviceManagementService(url);
+ service = new DeviceManagementService(
+ g_browser_process->system_request_context(),
+ url);
service->ScheduleInitialization(0);
}
}
diff --git a/chrome/browser/chromeos/policy/cros_enterprise_test_utils.cc b/chrome/browser/chromeos/policy/cros_enterprise_test_utils.cc
deleted file mode 100644
index 7c7acaa..0000000
--- a/chrome/browser/chromeos/policy/cros_enterprise_test_utils.cc
+++ /dev/null
@@ -1,45 +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/chromeos/policy/cros_enterprise_test_utils.h"
-
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/path_service.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 "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-namespace test_utils {
-
-void MarkAsEnterpriseOwned(const std::string& username,
- const base::FilePath& temp_dir) {
- 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(username);
-
- const base::FilePath install_attrs_file =
- temp_dir.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));
-}
-
-} // namespace test_utils
-
-} // namespace policy
diff --git a/chrome/browser/chromeos/policy/cros_enterprise_test_utils.h b/chrome/browser/chromeos/policy/cros_enterprise_test_utils.h
deleted file mode 100644
index f3544c2..0000000
--- a/chrome/browser/chromeos/policy/cros_enterprise_test_utils.h
+++ /dev/null
@@ -1,26 +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_CHROMEOS_POLICY_CROS_ENTERPRISE_TEST_UTILS_H_
-#define CHROME_BROWSER_CHROMEOS_POLICY_CROS_ENTERPRISE_TEST_UTILS_H_
-
-#include <string>
-
-namespace base {
-class FilePath;
-}
-
-namespace policy {
-
-namespace test_utils {
-
-// Marks the device as enterprise-owned.
-void MarkAsEnterpriseOwned(const std::string& username,
- const base::FilePath& temp_dir);
-
-} // namespace test_utils
-
-} // namespace policy
-
-#endif // CHROME_BROWSER_CHROMEOS_POLICY_CROS_ENTERPRISE_TEST_UTILS_H_
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 b27dc19..49d993f 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
@@ -26,7 +26,6 @@
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chromeos/cryptohome/cryptohome_library.h"
-#include "chromeos/cryptohome/mock_cryptohome_library.h"
#include "chromeos/dbus/cryptohome_client_stub.h"
#include "chromeos/dbus/dbus_client_implementation_type.h"
#include "google_apis/gaia/gaia_oauth_client.h"
@@ -364,10 +363,12 @@
if (done_)
return;
+ chromeos::DeviceOAuth2TokenService* token_service =
+ chromeos::DeviceOAuth2TokenServiceFactory::Get();
// Process robot refresh token store.
EXPECT_EQ(
"refreshToken4Test",
- chromeos::DeviceOAuth2TokenServiceFactory::Get()->GetRefreshToken());
+ token_service->GetRefreshToken(token_service->GetRobotAccountId()));
}
bool is_auto_enrollment_;
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
index ba4e322..1aa2523 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/policy/device_local_account_policy_store.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -23,7 +22,6 @@
#include "chrome/browser/policy/cloud/device_management_service.h"
#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
#include "chromeos/dbus/session_manager_client.h"
-#include "content/public/browser/notification_details.h"
#include "policy/policy_constants.h"
namespace em = enterprise_management;
@@ -32,26 +30,6 @@
namespace {
-// Creates a broker for the device-local account with the given |user_id| and
-// |account_id|.
-scoped_ptr<DeviceLocalAccountPolicyBroker> CreateBroker(
- const std::string& user_id,
- const std::string& account_id,
- chromeos::SessionManagerClient* session_manager_client,
- chromeos::DeviceSettingsService* device_settings_service,
- DeviceLocalAccountPolicyService* device_local_account_policy_service) {
- scoped_ptr<DeviceLocalAccountPolicyStore> store(
- new DeviceLocalAccountPolicyStore(account_id, session_manager_client,
- device_settings_service));
- scoped_ptr<DeviceLocalAccountPolicyBroker> broker(
- new DeviceLocalAccountPolicyBroker(user_id,
- store.Pass(),
- base::MessageLoopProxy::current()));
- broker->core()->store()->AddObserver(device_local_account_policy_service);
- broker->core()->store()->Load();
- return broker.Pass();
-}
-
// Creates and initializes a cloud policy client. Returns NULL if the device
// doesn't have credentials in device settings (i.e. is not
// enterprise-enrolled).
@@ -126,10 +104,14 @@
DeviceLocalAccountPolicyBroker*
DeviceLocalAccountPolicyService::PolicyBrokerWrapper::GetBroker() {
if (!broker) {
- broker = CreateBroker(user_id, account_id,
- parent->session_manager_client_,
- parent->device_settings_service_,
- parent).release();
+ scoped_ptr<DeviceLocalAccountPolicyStore> store(
+ new DeviceLocalAccountPolicyStore(account_id,
+ parent->session_manager_client_,
+ parent->device_settings_service_));
+ broker = new DeviceLocalAccountPolicyBroker(
+ user_id, store.Pass(), base::MessageLoopProxy::current());
+ broker->core()->store()->AddObserver(parent);
+ broker->core()->store()->Load();
}
return broker;
}
@@ -166,14 +148,15 @@
cros_settings_(cros_settings),
device_management_service_(NULL),
cros_settings_callback_factory_(this) {
- cros_settings_->AddSettingsObserver(
- chromeos::kAccountsPrefDeviceLocalAccounts, this);
+ local_accounts_subscription_ = cros_settings_->AddSettingsObserver(
+ chromeos::kAccountsPrefDeviceLocalAccounts,
+ base::Bind(&DeviceLocalAccountPolicyService::
+ UpdateAccountListIfNonePending,
+ base::Unretained(this)));
UpdateAccountList();
}
DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
- cros_settings_->RemoveSettingsObserver(
- chromeos::kAccountsPrefDeviceLocalAccounts, this);
DeleteBrokers(&policy_brokers_);
}
@@ -224,24 +207,6 @@
observers_.RemoveObserver(observer);
}
-void DeviceLocalAccountPolicyService::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- if (type != chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED ||
- *content::Details<const std::string>(details).ptr() !=
- chromeos::kAccountsPrefDeviceLocalAccounts) {
- NOTREACHED();
- return;
- }
-
- // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still
- // pending (because the |cros_settings_| are not trusted yet), the updated
- // account list will be processed by that call when it eventually runs.
- if (!cros_settings_callback_factory_.HasWeakPtrs())
- UpdateAccountList();
-}
-
void DeviceLocalAccountPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
DCHECK(broker);
@@ -259,6 +224,14 @@
FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id()));
}
+void DeviceLocalAccountPolicyService::UpdateAccountListIfNonePending() {
+ // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still
+ // pending (because the |cros_settings_| are not trusted yet), the updated
+ // account list will be processed by that call when it eventually runs.
+ if (!cros_settings_callback_factory_.HasWeakPtrs())
+ UpdateAccountList();
+}
+
void DeviceLocalAccountPolicyService::UpdateAccountList() {
if (chromeos::CrosSettingsProvider::TRUSTED !=
cros_settings_->PrepareTrustedValues(
@@ -268,19 +241,20 @@
}
// Update |policy_brokers_|, keeping existing entries.
- PolicyBrokerMap new_policy_brokers;
+ PolicyBrokerMap old_policy_brokers;
+ policy_brokers_.swap(old_policy_brokers);
const std::vector<DeviceLocalAccount> device_local_accounts =
GetDeviceLocalAccounts(cros_settings_);
for (std::vector<DeviceLocalAccount>::const_iterator it =
device_local_accounts.begin();
it != device_local_accounts.end(); ++it) {
- PolicyBrokerWrapper& wrapper = new_policy_brokers[it->user_id];
+ PolicyBrokerWrapper& wrapper = policy_brokers_[it->user_id];
wrapper.user_id = it->user_id;
wrapper.account_id = it->account_id;
wrapper.parent = this;
// Reuse the existing broker if present.
- PolicyBrokerWrapper& existing_wrapper = policy_brokers_[it->user_id];
+ PolicyBrokerWrapper& existing_wrapper = old_policy_brokers[it->user_id];
wrapper.broker = existing_wrapper.broker;
existing_wrapper.broker = NULL;
@@ -288,8 +262,7 @@
// the cloud if this is an enterprise-managed device.
wrapper.ConnectIfPossible();
}
- policy_brokers_.swap(new_policy_brokers);
- DeleteBrokers(&new_policy_brokers);
+ DeleteBrokers(&old_policy_brokers);
FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged());
}
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service.h b/chrome/browser/chromeos/policy/device_local_account_policy_service.h
index ad25465..02b82f4 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_service.h
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_service.h
@@ -14,9 +14,9 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/policy/cloud/cloud_policy_core.h"
#include "chrome/browser/policy/cloud/cloud_policy_store.h"
-#include "content/public/browser/notification_observer.h"
namespace base {
class SequencedTaskRunner;
@@ -75,8 +75,7 @@
// The actual policy blobs are brokered by session_manager (to prevent file
// manipulation), and we're making signature checks on the policy blobs to
// ensure they're issued by the device owner.
-class DeviceLocalAccountPolicyService : public content::NotificationObserver,
- public CloudPolicyStore::Observer {
+class DeviceLocalAccountPolicyService : public CloudPolicyStore::Observer {
public:
// Interface for interested parties to observe policy changes.
class Observer {
@@ -113,11 +112,6 @@
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
- // NotificationObserver:
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
-
// CloudPolicyStore::Observer:
virtual void OnStoreLoaded(CloudPolicyStore* store) OVERRIDE;
virtual void OnStoreError(CloudPolicyStore* store) OVERRIDE;
@@ -151,6 +145,9 @@
// and updates |policy_brokers_| to match that list.
void UpdateAccountList();
+ // Calls |UpdateAccountList| if there are no previous calls pending.
+ void UpdateAccountListIfNonePending();
+
// Deletes brokers in |map| and clears it.
void DeleteBrokers(PolicyBrokerMap* map);
@@ -168,6 +165,9 @@
ObserverList<Observer, true> observers_;
+ scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
+ local_accounts_subscription_;
+
// Weak pointer factory for cros_settings_->PrepareTrustedValues() callbacks.
base::WeakPtrFactory<DeviceLocalAccountPolicyService>
cros_settings_callback_factory_;
diff --git a/chrome/browser/chromeos/policy/device_policy_builder.h b/chrome/browser/chromeos/policy/device_policy_builder.h
index 94fb311..c4bf0d2 100644
--- a/chrome/browser/chromeos/policy/device_policy_builder.h
+++ b/chrome/browser/chromeos/policy/device_policy_builder.h
@@ -6,10 +6,7 @@
#define CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_POLICY_BUILDER_H_
#include "chrome/browser/policy/cloud/policy_builder.h"
-
-namespace enterprise_management {
-class ChromeDeviceSettingsProto;
-} // namespace enterprise_management
+#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
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 d368d53..9305837 100644
--- a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
+++ b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
@@ -4,15 +4,16 @@
#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
+#include <string>
#include <vector>
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/stl_util.h"
-#include "chrome/browser/chromeos/policy/cros_enterprise_test_utils.h"
#include "chrome/browser/chromeos/policy/device_policy_builder.h"
-#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.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/fake_session_manager_client.h"
#include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
@@ -26,10 +27,48 @@
namespace policy {
-void DevicePolicyCrosBrowserTest::MarkAsEnterpriseOwned() {
- ASSERT_TRUE(temp_dir_.IsValid());
- test_utils::MarkAsEnterpriseOwned(DevicePolicyBuilder::kFakeUsername,
- temp_dir_.path());
+DevicePolicyCrosTestHelper::DevicePolicyCrosTestHelper() {
+ CHECK(temp_dir_.CreateUniqueTempDir());
+}
+
+DevicePolicyCrosTestHelper::~DevicePolicyCrosTestHelper() {}
+
+void DevicePolicyCrosTestHelper::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(device_policy_.policy_data().username());
+
+ 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 DevicePolicyCrosTestHelper::InstallOwnerKey() {
+ base::FilePath owner_key_file = temp_dir_.path().AppendASCII("owner.key");
+ std::vector<uint8> owner_key_bits;
+ ASSERT_TRUE(
+ device_policy()->GetSigningKey()->ExportPublicKey(&owner_key_bits));
+ ASSERT_EQ(
+ file_util::WriteFile(
+ owner_key_file,
+ reinterpret_cast<const char*>(vector_as_array(&owner_key_bits)),
+ owner_key_bits.size()),
+ static_cast<int>(owner_key_bits.size()));
+ ASSERT_TRUE(PathService::Override(chromeos::FILE_OWNER_KEY, owner_key_file));
}
DevicePolicyCrosBrowserTest::DevicePolicyCrosBrowserTest()
@@ -45,32 +84,25 @@
InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
}
+void DevicePolicyCrosBrowserTest::TearDownInProcessBrowserTestFixture() {
+ InProcessBrowserTest::TearDownInProcessBrowserTestFixture();
+ chromeos::DBusThreadManager::Shutdown();
+}
+
+void DevicePolicyCrosBrowserTest::MarkAsEnterpriseOwned() {
+ test_helper_.MarkAsEnterpriseOwned();
+}
+
void DevicePolicyCrosBrowserTest::InstallOwnerKey() {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- base::FilePath owner_key_file = temp_dir_.path().AppendASCII("owner.key");
- std::vector<uint8> owner_key_bits;
- ASSERT_TRUE(
- device_policy()->GetSigningKey()->ExportPublicKey(&owner_key_bits));
- ASSERT_EQ(
- file_util::WriteFile(
- owner_key_file,
- reinterpret_cast<const char*>(vector_as_array(&owner_key_bits)),
- owner_key_bits.size()),
- static_cast<int>(owner_key_bits.size()));
- ASSERT_TRUE(PathService::Override(chromeos::FILE_OWNER_KEY, owner_key_file));
+ test_helper_.InstallOwnerKey();
}
void DevicePolicyCrosBrowserTest::RefreshDevicePolicy() {
// Reset the key to its original state.
- device_policy_.SetDefaultSigningKey();
- device_policy_.Build();
- session_manager_client()->set_device_policy(device_policy_.GetBlob());
+ device_policy()->SetDefaultSigningKey();
+ device_policy()->Build();
+ session_manager_client()->set_device_policy(device_policy()->GetBlob());
session_manager_client()->OnPropertyChangeComplete(true);
}
-void DevicePolicyCrosBrowserTest::TearDownInProcessBrowserTestFixture() {
- InProcessBrowserTest::TearDownInProcessBrowserTestFixture();
- chromeos::DBusThreadManager::Shutdown();
-}
-
} // namespace policy
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 d00becc..1a0dafc 100644
--- a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.h
+++ b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.h
@@ -11,7 +11,6 @@
#include "chrome/browser/chromeos/policy/device_policy_builder.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
class FakeSessionManagerClient;
@@ -19,19 +18,44 @@
namespace policy {
-// Used to test Device policy changes in Chrome OS.
-class DevicePolicyCrosBrowserTest : public InProcessBrowserTest {
+class DevicePolicyCrosTestHelper {
public:
+ DevicePolicyCrosTestHelper();
+ ~DevicePolicyCrosTestHelper();
+
// 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();
+ // Writes the owner key to disk. To be called before installing a policy.
+ void InstallOwnerKey();
+
+ DevicePolicyBuilder* device_policy() { return &device_policy_; }
+
+ private:
+ // Stores the device owner key and the install attributes.
+ base::ScopedTempDir temp_dir_;
+
+ // Carries Chrome OS device policies for tests.
+ DevicePolicyBuilder device_policy_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevicePolicyCrosTestHelper);
+};
+
+// Used to test Device policy changes in Chrome OS.
+class DevicePolicyCrosBrowserTest : public InProcessBrowserTest {
protected:
DevicePolicyCrosBrowserTest();
virtual ~DevicePolicyCrosBrowserTest();
virtual void SetUpInProcessBrowserTestFixture() OVERRIDE;
+ virtual void TearDownInProcessBrowserTestFixture() OVERRIDE;
+
+ // 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();
// Writes the owner key to disk. To be called before installing a policy.
void InstallOwnerKey();
@@ -40,8 +64,6 @@
// recently changed).
void RefreshDevicePolicy();
- virtual void TearDownInProcessBrowserTestFixture() OVERRIDE;
-
chromeos::MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager() {
return mock_dbus_thread_manager_;
}
@@ -50,18 +72,14 @@
return mock_dbus_thread_manager_->fake_session_manager_client();
}
- DevicePolicyBuilder* device_policy() { return &device_policy_; }
+ DevicePolicyBuilder* device_policy() { return test_helper_.device_policy(); }
private:
- // Stores the device owner key and the install attributes.
- base::ScopedTempDir temp_dir_;
+ DevicePolicyCrosTestHelper test_helper_;
// MockDBusThreadManagerWithoutGMock uses FakeSessionManagerClient.
chromeos::MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager_;
- // Carries Chrome OS device policies for tests.
- DevicePolicyBuilder device_policy_;
-
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 8821050..f7d3fa9 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -44,11 +44,11 @@
Value* DecodeConnectionType(int value) {
static const char* const kConnectionTypes[] = {
- flimflam::kTypeEthernet,
- flimflam::kTypeWifi,
- flimflam::kTypeWimax,
- flimflam::kTypeBluetooth,
- flimflam::kTypeCellular,
+ shill::kTypeEthernet,
+ shill::kTypeWifi,
+ shill::kTypeWimax,
+ shill::kTypeBluetooth,
+ shill::kTypeCellular,
};
if (value < 0 || value >= static_cast<int>(arraysize(kConnectionTypes)))
diff --git a/chrome/browser/chromeos/policy/device_status_collector.cc b/chrome/browser/chromeos/policy/device_status_collector.cc
index 4df62a7..515ba1b 100644
--- a/chrome/browser/chromeos/policy/device_status_collector.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector.cc
@@ -15,7 +15,6 @@
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
-#include "chrome/browser/chrome_notification_types.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"
@@ -27,8 +26,6 @@
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
using base::Time;
@@ -148,13 +145,19 @@
// Watch for changes to the individual policies that control what the status
// reports contain.
- cros_settings_->AddSettingsObserver(chromeos::kReportDeviceVersionInfo, this);
- cros_settings_->AddSettingsObserver(chromeos::kReportDeviceActivityTimes,
- this);
- cros_settings_->AddSettingsObserver(chromeos::kReportDeviceBootMode, this);
- cros_settings_->AddSettingsObserver(chromeos::kReportDeviceLocation, this);
- cros_settings_->AddSettingsObserver(chromeos::kReportDeviceNetworkInterfaces,
- this);
+ base::Closure callback =
+ base::Bind(&DeviceStatusCollector::UpdateReportingSettings,
+ base::Unretained(this));
+ version_info_subscription_ = cros_settings_->AddSettingsObserver(
+ chromeos::kReportDeviceVersionInfo, callback);
+ activity_times_subscription_ = cros_settings_->AddSettingsObserver(
+ chromeos::kReportDeviceActivityTimes, callback);
+ boot_mode_subscription_ = cros_settings_->AddSettingsObserver(
+ chromeos::kReportDeviceBootMode, callback);
+ location_subscription_ = cros_settings_->AddSettingsObserver(
+ chromeos::kReportDeviceLocation, callback);
+ network_interfaces_subscription_ = cros_settings_->AddSettingsObserver(
+ chromeos::kReportDeviceNetworkInterfaces, callback);
// The last known location is persisted in local state. This makes location
// information available immediately upon startup and avoids the need to
@@ -191,14 +194,6 @@
}
DeviceStatusCollector::~DeviceStatusCollector() {
- cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceVersionInfo,
- this);
- cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceActivityTimes,
- this);
- cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceBootMode, this);
- cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceLocation, this);
- cros_settings_->RemoveSettingsObserver(
- chromeos::kReportDeviceNetworkInterfaces, this);
}
// static
@@ -417,11 +412,11 @@
const char* type_string;
em::NetworkInterface::NetworkDeviceType type_constant;
} kDeviceTypeMap[] = {
- { flimflam::kTypeEthernet, em::NetworkInterface::TYPE_ETHERNET, },
- { flimflam::kTypeWifi, em::NetworkInterface::TYPE_WIFI, },
- { flimflam::kTypeWimax, em::NetworkInterface::TYPE_WIMAX, },
- { flimflam::kTypeBluetooth, em::NetworkInterface::TYPE_BLUETOOTH, },
- { flimflam::kTypeCellular, em::NetworkInterface::TYPE_CELLULAR, },
+ { shill::kTypeEthernet, em::NetworkInterface::TYPE_ETHERNET, },
+ { shill::kTypeWifi, em::NetworkInterface::TYPE_WIFI, },
+ { shill::kTypeWimax, em::NetworkInterface::TYPE_WIMAX, },
+ { shill::kTypeBluetooth, em::NetworkInterface::TYPE_BLUETOOTH, },
+ { shill::kTypeCellular, em::NetworkInterface::TYPE_CELLULAR, },
};
chromeos::NetworkStateHandler::DeviceStateList device_list;
@@ -499,16 +494,6 @@
firmware_version_ = version;
}
-void DeviceStatusCollector::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED)
- UpdateReportingSettings();
- else
- NOTREACHED();
-}
-
void DeviceStatusCollector::ScheduleGeolocationUpdateRequest() {
if (geolocation_update_timer_.IsRunning() || geolocation_update_in_progress_)
return;
diff --git a/chrome/browser/chromeos/policy/device_status_collector.h b/chrome/browser/chromeos/policy/device_status_collector.h
index b19ed94..95c24b0 100644
--- a/chrome/browser/chromeos/policy/device_status_collector.h
+++ b/chrome/browser/chromeos/policy/device_status_collector.h
@@ -11,15 +11,16 @@
#include "base/callback_forward.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/time/time.h"
#include "base/timer/timer.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/version_loader.h"
#include "chrome/browser/idle.h"
#include "chrome/browser/policy/cloud/cloud_policy_client.h"
#include "chrome/common/cancelable_task_tracker.h"
#include "content/public/browser/geolocation_provider.h"
-#include "content/public/browser/notification_observer.h"
#include "content/public/common/geoposition.h"
namespace chromeos {
@@ -44,8 +45,7 @@
namespace policy {
// Collects and summarizes the status of an enterprised-managed ChromeOS device.
-class DeviceStatusCollector : public CloudPolicyClient::StatusProvider,
- public content::NotificationObserver {
+class DeviceStatusCollector : public CloudPolicyClient::StatusProvider {
public:
// TODO(bartfab): Remove this once crbug.com/125931 is addressed and a proper
// way to mock geolocation exists.
@@ -93,7 +93,7 @@
unsigned int max_stored_future_activity_days_;
private:
- // A helper class to manage receiving geolocation notifications on the IO
+ // A helper class to manage receiving geolocation callbacks on the IO
// thread.
class Context : public base::RefCountedThreadSafe<Context> {
public:
@@ -151,12 +151,6 @@
// Update the cached values of the reporting settings.
void UpdateReportingSettings();
- // content::NotificationObserver interface.
- virtual void Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
-
void ScheduleGeolocationUpdateRequest();
// content::GeolocationUpdateCallback implementation.
@@ -210,6 +204,17 @@
scoped_refptr<Context> context_;
+ scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
+ version_info_subscription_;
+ scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
+ activity_times_subscription_;
+ scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
+ boot_mode_subscription_;
+ scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
+ location_subscription_;
+ scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
+ network_interfaces_subscription_;
+
DISALLOW_COPY_AND_ASSIGN(DeviceStatusCollector);
};
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
index 9a6d3d1..73371e4 100644
--- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -599,22 +599,22 @@
};
static const FakeDeviceData kFakeDevices[] = {
- { "/device/ethernet", flimflam::kTypeEthernet, "ethernet",
+ { "/device/ethernet", shill::kTypeEthernet, "ethernet",
"112233445566", "", "",
em::NetworkInterface::TYPE_ETHERNET },
- { "/device/cellular1", flimflam::kTypeCellular, "cellular1",
+ { "/device/cellular1", shill::kTypeCellular, "cellular1",
"abcdefabcdef", "A10000009296F2", "",
em::NetworkInterface::TYPE_CELLULAR },
- { "/device/cellular2", flimflam::kTypeCellular, "cellular2",
+ { "/device/cellular2", shill::kTypeCellular, "cellular2",
"abcdefabcdef", "", "352099001761481",
em::NetworkInterface::TYPE_CELLULAR },
- { "/device/wifi", flimflam::kTypeWifi, "wifi",
+ { "/device/wifi", shill::kTypeWifi, "wifi",
"aabbccddeeff", "", "",
em::NetworkInterface::TYPE_WIFI },
- { "/device/bluetooth", flimflam::kTypeBluetooth, "bluetooth",
+ { "/device/bluetooth", shill::kTypeBluetooth, "bluetooth",
"", "", "",
em::NetworkInterface::TYPE_BLUETOOTH },
- { "/device/vpn", flimflam::kTypeVPN, "vpn",
+ { "/device/vpn", shill::kTypeVPN, "vpn",
"", "", "",
-1 },
};
@@ -635,17 +635,17 @@
dev.object_path);
if (*dev.mac_address) {
test_device_client->SetDeviceProperty(
- dev.device_path, flimflam::kAddressProperty,
+ dev.device_path, shill::kAddressProperty,
base::StringValue(dev.mac_address));
}
if (*dev.meid) {
test_device_client->SetDeviceProperty(
- dev.device_path, flimflam::kMeidProperty,
+ dev.device_path, shill::kMeidProperty,
base::StringValue(dev.meid));
}
if (*dev.imei) {
test_device_client->SetDeviceProperty(
- dev.device_path, flimflam::kImeiProperty,
+ dev.device_path, shill::kImeiProperty,
base::StringValue(dev.imei));
}
}
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc
index ba98790..bc6372c 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc
@@ -79,7 +79,8 @@
return;
}
- if (token_service_->RefreshTokenIsAvailable())
+ if (token_service_->RefreshTokenIsAvailable(
+ token_service_->GetPrimaryAccountId()))
RequestAccessToken();
else
token_service_->AddObserver(this);
@@ -88,7 +89,8 @@
void UserCloudPolicyTokenForwarder::RequestAccessToken() {
OAuth2TokenService::ScopeSet scopes;
scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth);
- request_ = token_service_->StartRequest(scopes, this);
+ request_ = token_service_->StartRequest(
+ token_service_->GetPrimaryAccountId(), scopes, this);
}
} // namespace policy
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index df79eca..ce8daf8 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -133,7 +133,7 @@
registry->RegisterBooleanPref(
prefs::kStickyKeysEnabled,
false,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
registry->RegisterBooleanPref(
prefs::kLargeCursorEnabled,
false,
@@ -145,15 +145,15 @@
registry->RegisterBooleanPref(
prefs::kHighContrastEnabled,
false,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
registry->RegisterBooleanPref(
prefs::kScreenMagnifierEnabled,
false,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
registry->RegisterIntegerPref(
prefs::kScreenMagnifierType,
ash::kDefaultMagnifierType,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
registry->RegisterDoublePref(
prefs::kScreenMagnifierScale,
std::numeric_limits<double>::min(),
@@ -161,7 +161,7 @@
registry->RegisterBooleanPref(
prefs::kShouldAlwaysShowAccessibilityMenu,
false,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
registry->RegisterIntegerPref(
prefs::kMouseSensitivity,
3,
diff --git a/chrome/browser/chromeos/profiles/avatar_menu_actions_chromeos.cc b/chrome/browser/chromeos/profiles/avatar_menu_actions_chromeos.cc
new file mode 100644
index 0000000..fd27cd4
--- /dev/null
+++ b/chrome/browser/chromeos/profiles/avatar_menu_actions_chromeos.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/profiles/avatar_menu_actions_chromeos.h"
+
+#include "ash/shell.h"
+#include "ash/system/tray/system_tray_delegate.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/profiles/profile_info_util.h"
+#include "chrome/browser/ui/browser.h"
+
+// static
+AvatarMenuActions* AvatarMenuActions::Create() {
+ return new chromeos::AvatarMenuActionsChromeOS();
+}
+
+namespace chromeos {
+
+AvatarMenuActionsChromeOS::AvatarMenuActionsChromeOS() {
+}
+
+AvatarMenuActionsChromeOS::~AvatarMenuActionsChromeOS() {
+}
+
+void AvatarMenuActionsChromeOS::AddNewProfile(ProfileMetrics::ProfileAdd type) {
+ // Let the user add another account to the session.
+ ash::Shell::GetInstance()->system_tray_delegate()->ShowUserLogin();
+}
+
+void AvatarMenuActionsChromeOS::EditProfile(Profile* profile, size_t index) {
+ NOTIMPLEMENTED();
+}
+
+bool AvatarMenuActionsChromeOS::ShouldShowAddNewProfileLink() const {
+ // |browser_| can be NULL in unit_tests.
+ return (!browser_ || !browser_->profile()->IsManaged()) &&
+ UserManager::Get()->GetUsersAdmittedForMultiProfile().size();
+}
+
+bool AvatarMenuActionsChromeOS::ShouldShowEditProfileLink() const {
+ return false;
+}
+
+content::WebContents* AvatarMenuActionsChromeOS::BeginSignOut() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void AvatarMenuActionsChromeOS::SetLogoutURL(const std::string& logout_url) {
+ NOTIMPLEMENTED();
+}
+
+void AvatarMenuActionsChromeOS::ActiveBrowserChanged(Browser* browser) {
+ browser_ = browser;
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/profiles/avatar_menu_actions_chromeos.h b/chrome/browser/chromeos/profiles/avatar_menu_actions_chromeos.h
new file mode 100644
index 0000000..c05c21a
--- /dev/null
+++ b/chrome/browser/chromeos/profiles/avatar_menu_actions_chromeos.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_PROFILES_AVATAR_MENU_ACTIONS_CHROMEOS_H_
+#define CHROME_BROWSER_CHROMEOS_PROFILES_AVATAR_MENU_ACTIONS_CHROMEOS_H_
+
+#include "chrome/browser/profiles/avatar_menu_actions.h"
+
+#include <string>
+
+class Browser;
+
+namespace chromeos {
+
+// This interface controls the behavior of avatar menu actions on ChromeOS.
+class AvatarMenuActionsChromeOS : public AvatarMenuActions {
+ public:
+ AvatarMenuActionsChromeOS();
+ virtual ~AvatarMenuActionsChromeOS();
+
+ // AvatarMenuActions overrides:
+ virtual void AddNewProfile(ProfileMetrics::ProfileAdd type) OVERRIDE;
+ virtual void EditProfile(Profile* profile, size_t index) OVERRIDE;
+ virtual bool ShouldShowAddNewProfileLink() const OVERRIDE;
+ virtual bool ShouldShowEditProfileLink() const OVERRIDE;
+ virtual content::WebContents* BeginSignOut() OVERRIDE;
+ virtual void SetLogoutURL(const std::string& logout_url) OVERRIDE;
+ virtual void ActiveBrowserChanged(Browser* browser) OVERRIDE;
+
+ private:
+ // Browser in which this avatar menu resides. Weak.
+ Browser* browser_;
+
+ DISALLOW_COPY_AND_ASSIGN(AvatarMenuActionsChromeOS);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_PROFILES_AVATAR_MENU_ACTIONS_CHROMEOS_H_
diff --git a/chrome/browser/chromeos/profiles/avatar_menu_chromeos.cc b/chrome/browser/chromeos/profiles/avatar_menu_chromeos.cc
new file mode 100644
index 0000000..23dacb7
--- /dev/null
+++ b/chrome/browser/chromeos/profiles/avatar_menu_chromeos.cc
@@ -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.
+
+#include "chrome/browser/profiles/avatar_menu.h"
+
+#include <string>
+
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile_manager.h"
+
+// static
+void AvatarMenu::GetImageForMenuButton(Profile* profile,
+ gfx::Image* image,
+ bool* is_rectangle) {
+ // Find the user for this profile.
+ std::string user_id_hash =
+ chromeos::ProfileHelper::GetUserIdHashFromProfile(profile);
+ chromeos::UserList users = chromeos::UserManager::Get()->GetLoggedInUsers();
+
+ for (chromeos::UserList::const_iterator it = users.begin();
+ it != users.end(); ++it) {
+ if ((*it)->username_hash() == user_id_hash) {
+ *image = gfx::Image((*it)->image());
+ break;
+ }
+ }
+
+ // ChromeOS user images are rectangular, unlike Chrome profile avatars.
+ *is_rectangle = true;
+}
diff --git a/chrome/browser/chromeos/profiles/profile_list_chromeos.cc b/chrome/browser/chromeos/profiles/profile_list_chromeos.cc
new file mode 100644
index 0000000..b27e01c
--- /dev/null
+++ b/chrome/browser/chromeos/profiles/profile_list_chromeos.cc
@@ -0,0 +1,106 @@
+// Copyright 2013 The Chromium 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/profiles/profile_list_chromeos.h"
+
+#include <algorithm>
+
+#include "ash/shell.h"
+#include "base/command_line.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile_info_util.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/chrome_switches.h"
+
+// static
+ProfileList* ProfileList::Create(ProfileInfoInterface* profile_cache) {
+ return new chromeos::ProfileListChromeOS(profile_cache);
+}
+
+namespace chromeos {
+
+ProfileListChromeOS::ProfileListChromeOS(ProfileInfoInterface* profile_cache)
+ : profile_info_(profile_cache) {
+}
+
+ProfileListChromeOS::~ProfileListChromeOS() {
+ ClearMenu();
+}
+
+size_t ProfileListChromeOS::GetNumberOfItems() const {
+ return items_.size();
+}
+
+const AvatarMenu::Item& ProfileListChromeOS::GetItemAt(size_t index) const {
+ DCHECK_LT(index, items_.size());
+ return *items_[index];
+}
+
+void ProfileListChromeOS::RebuildMenu() {
+ ClearMenu();
+
+ // Filter for profiles associated with logged-in users.
+ UserList users = UserManager::Get()->GetLoggedInUsers();
+
+ // Add corresponding profiles.
+ for (UserList::const_iterator it = users.begin();
+ it != users.end(); ++it) {
+ size_t i = profile_info_->GetIndexOfProfileWithPath(
+ ProfileHelper::GetProfilePathByUserIdHash((*it)->username_hash()));
+
+ gfx::Image icon = gfx::Image((*it)->image());
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kNewProfileManagement)) {
+ // old avatar menu uses resized-small images
+ icon = profiles::GetAvatarIconForMenu(icon, true);
+ }
+
+ AvatarMenu::Item* item = new AvatarMenu::Item(i, i, icon);
+ item->name = (*it)->GetDisplayName();
+ item->sync_state = profile_info_->GetUserNameOfProfileAtIndex(i);
+ item->managed = false;
+ item->signed_in = true;
+ item->active = profile_info_->GetPathOfProfileAtIndex(i) ==
+ active_profile_path_;
+ item->signin_required = profile_info_->ProfileIsSigninRequiredAtIndex(i);
+ items_.push_back(item);
+ }
+
+ SortMenu();
+
+ // After sorting, assign items their actual indices.
+ for (size_t i = 0; i < items_.size(); ++i)
+ items_[i]->menu_index = i;
+}
+
+size_t ProfileListChromeOS::MenuIndexFromProfileIndex(size_t index) {
+ // On ChromeOS, the active profile might be Default, which does not show
+ // up in the model as a logged-in user. In that case, we return 0.
+ size_t menu_index = 0;
+
+ for (size_t i = 0; i < GetNumberOfItems(); ++i) {
+ if (items_[i]->profile_index == index) {
+ menu_index = i;
+ break;
+ }
+ }
+
+ return menu_index;
+}
+
+void ProfileListChromeOS::ActiveProfilePathChanged(base::FilePath& path) {
+ active_profile_path_ = path;
+}
+
+void ProfileListChromeOS::ClearMenu() {
+ STLDeleteElements(&items_);
+}
+
+void ProfileListChromeOS::SortMenu() {
+ // Sort list of items by name.
+ std::sort(items_.begin(), items_.end(), &AvatarMenu::CompareItems);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/profiles/profile_list_chromeos.h b/chrome/browser/chromeos/profiles/profile_list_chromeos.h
new file mode 100644
index 0000000..31f8f40
--- /dev/null
+++ b/chrome/browser/chromeos/profiles/profile_list_chromeos.h
@@ -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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_PROFILES_PROFILE_LIST_CHROMEOS_H_
+#define CHROME_BROWSER_CHROMEOS_PROFILES_PROFILE_LIST_CHROMEOS_H_
+
+#include "chrome/browser/profiles/profile_list.h"
+
+#include <vector>
+
+class ProfileInfoInterface;
+
+namespace chromeos {
+
+// This model represents profiles corresponding to logged-in ChromeOS users.
+class ProfileListChromeOS : public ProfileList {
+ public:
+ explicit ProfileListChromeOS(ProfileInfoInterface* profile_cache);
+ virtual ~ProfileListChromeOS();
+
+ // ProfileList overrides:
+ virtual size_t GetNumberOfItems() const OVERRIDE;
+ virtual const AvatarMenu::Item& GetItemAt(size_t index) const OVERRIDE;
+ virtual void RebuildMenu() OVERRIDE;
+ virtual size_t MenuIndexFromProfileIndex(size_t index) OVERRIDE;
+ virtual void ActiveProfilePathChanged(base::FilePath& path) OVERRIDE;
+
+ private:
+ void ClearMenu();
+ void SortMenu();
+
+ // The cache that provides the profile information. Weak.
+ ProfileInfoInterface* profile_info_;
+
+ // The path of the currently active profile.
+ base::FilePath active_profile_path_;
+
+ // List of built "menu items."
+ std::vector<AvatarMenu::Item*> items_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileListChromeOS);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_PROFILES_PROFILE_LIST_CHROMEOS_H_
diff --git a/chrome/browser/chromeos/profiles/profile_list_chromeos_unittest.cc b/chrome/browser/chromeos/profiles/profile_list_chromeos_unittest.cc
new file mode 100644
index 0000000..bd311d9
--- /dev/null
+++ b/chrome/browser/chromeos/profiles/profile_list_chromeos_unittest.cc
@@ -0,0 +1,317 @@
+// Copyright 2013 The Chromium 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/command_line.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/chromeos/login/fake_user_manager.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
+#include "chrome/browser/profiles/avatar_menu.h"
+#include "chrome/browser/profiles/avatar_menu_observer.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
+#include "chrome/browser/ui/ash/chrome_shell_delegate.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "components/variations/entropy_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// As defined in /chromeos/dbus/cryptohome_client.cc.
+static const char kUserIdHashSuffix[] = "-hash";
+
+class MockObserver : public AvatarMenuObserver {
+ public:
+ MockObserver() : count_(0) {}
+ virtual ~MockObserver() {}
+
+ virtual void OnAvatarMenuChanged(
+ AvatarMenu* avatar_menu) OVERRIDE {
+ ++count_;
+ }
+
+ int change_count() const { return count_; }
+
+ private:
+ int count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockObserver);
+};
+
+} // namespace
+
+namespace chromeos {
+
+class ProfileListChromeOSTest : public testing::Test {
+ public:
+ ProfileListChromeOSTest()
+ : manager_(TestingBrowserProcess::GetGlobal()) {
+ }
+
+ virtual void SetUp() {
+ ASSERT_TRUE(manager_.SetUp());
+
+ // AvatarMenu and multiple profiles works after user logged in.
+ manager_.SetLoggedIn(true);
+
+ // We only instantiate UserMenuModel if multi-profile mode is enabled.
+ CommandLine* cl = CommandLine::ForCurrentProcess();
+ cl->AppendSwitch(switches::kMultiProfiles);
+
+ field_trial_list_.reset(new base::FieldTrialList(
+ new metrics::SHA1EntropyProvider("42")));
+ base::FieldTrialList::CreateTrialsFromString(
+ "ChromeOSUseMultiProfiles/Enable/",
+ base::FieldTrialList::ACTIVATE_TRIALS);
+
+ // Initialize the UserManager singleton to a fresh FakeUserManager instance.
+ user_manager_enabler_.reset(
+ new ScopedUserManagerEnabler(new FakeUserManager));
+ }
+
+ FakeUserManager* GetFakeUserManager() {
+ return static_cast<FakeUserManager*>(UserManager::Get());
+ }
+
+ void AddProfile(string16 name, bool log_in) {
+ std::string email_string = UTF16ToASCII(name) + "@example.com";
+
+ // Add a user to the fake user manager.
+ GetFakeUserManager()->AddUser(email_string);
+ if (log_in) {
+ GetFakeUserManager()->UserLoggedIn(
+ email_string,
+ email_string + kUserIdHashSuffix,
+ false);
+ }
+
+ // Create a profile for the user.
+ manager()->CreateTestingProfile(
+ chrome::kProfileDirPrefix + email_string + kUserIdHashSuffix,
+ scoped_ptr<PrefServiceSyncable>(),
+ ASCIIToUTF16(email_string), 0, std::string());
+ }
+
+ AvatarMenu* GetAvatarMenu() {
+ // Reset the MockObserver.
+ mock_observer_.reset(new MockObserver());
+ EXPECT_EQ(0, change_count());
+
+ // Reset the menu.
+ avatar_menu_.reset(new AvatarMenu(
+ manager()->profile_info_cache(),
+ mock_observer_.get(),
+ NULL));
+ avatar_menu_->RebuildMenu();
+ EXPECT_EQ(0, change_count());
+ return avatar_menu_.get();
+ }
+
+ TestingProfileManager* manager() { return &manager_; }
+
+ int change_count() const { return mock_observer_->change_count(); }
+
+ private:
+ TestingProfileManager manager_;
+ scoped_ptr<MockObserver> mock_observer_;
+ scoped_ptr<ScopedUserManagerEnabler> user_manager_enabler_;
+ scoped_ptr<AvatarMenu> avatar_menu_;
+ ChromeShellDelegate chrome_shell_delegate_;
+ scoped_ptr<base::FieldTrialList> field_trial_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileListChromeOSTest);
+};
+
+TEST_F(ProfileListChromeOSTest, InitialCreation) {
+ string16 name1(ASCIIToUTF16("p1"));
+
+ AddProfile(name1, true);
+
+ AvatarMenu* menu = GetAvatarMenu();
+
+ ASSERT_EQ(1U, menu->GetNumberOfItems());
+
+ const AvatarMenu::Item& item1 = menu->GetItemAt(0);
+ EXPECT_EQ(0U, item1.menu_index);
+ EXPECT_EQ(name1, item1.name);
+}
+
+TEST_F(ProfileListChromeOSTest, ShowLoggedInUsers) {
+ string16 name1(ASCIIToUTF16("p1"));
+ string16 name2(ASCIIToUTF16("p2"));
+ string16 name3(ASCIIToUTF16("p3"));
+ string16 name4(ASCIIToUTF16("p4"));
+
+ AddProfile(name1, true);
+ AddProfile(name2, false);
+ AddProfile(name3, true);
+ AddProfile(name4, false);
+
+ AvatarMenu* menu = GetAvatarMenu();
+
+ ASSERT_EQ(2U, menu->GetNumberOfItems());
+
+ const AvatarMenu::Item& item1 = menu->GetItemAt(0);
+ EXPECT_EQ(0U, item1.menu_index);
+ EXPECT_EQ(name1, item1.name);
+
+ const AvatarMenu::Item& item3 = menu->GetItemAt(1);
+ EXPECT_EQ(1U, item3.menu_index);
+ EXPECT_EQ(name3, item3.name);
+}
+
+TEST_F(ProfileListChromeOSTest, DontShowManagedUsers) {
+ string16 name1(ASCIIToUTF16("p1"));
+ string16 managed_name(ASCIIToUTF16("p2@example.com"));
+
+ AddProfile(name1, true);
+
+ // Add a managed user profile.
+ ProfileInfoCache* cache = manager()->profile_info_cache();
+ manager()->profile_info_cache()->AddProfileToCache(
+ cache->GetUserDataDir().AppendASCII("p2"), managed_name,
+ string16(), 0, "TEST_ID");
+
+ GetFakeUserManager()->AddUser(UTF16ToASCII(managed_name));
+
+ AvatarMenu* menu = GetAvatarMenu();
+ ASSERT_EQ(1U, menu->GetNumberOfItems());
+
+ const AvatarMenu::Item& item1 = menu->GetItemAt(0);
+ EXPECT_EQ(0U, item1.menu_index);
+ EXPECT_EQ(name1, item1.name);
+}
+
+TEST_F(ProfileListChromeOSTest, ShowAddProfileLink) {
+ string16 name1(ASCIIToUTF16("p1.com"));
+ string16 name2(ASCIIToUTF16("p2.com"));
+
+ AddProfile(name1, true);
+ AddProfile(name2, false);
+
+ AvatarMenu* menu = GetAvatarMenu();
+
+ ASSERT_EQ(1U, menu->GetNumberOfItems());
+ EXPECT_TRUE(menu->ShouldShowAddNewProfileLink());
+}
+
+TEST_F(ProfileListChromeOSTest, DontShowAddProfileLink) {
+ string16 name1(ASCIIToUTF16("p1.com"));
+ string16 name2(ASCIIToUTF16("p2.com"));
+
+ AddProfile(name1, true);
+ AddProfile(name2, true);
+
+ AvatarMenu* menu = GetAvatarMenu();
+
+ ASSERT_EQ(2U, menu->GetNumberOfItems());
+ EXPECT_FALSE(menu->ShouldShowAddNewProfileLink());
+}
+
+TEST_F(ProfileListChromeOSTest, ActiveItem) {
+ string16 name1(ASCIIToUTF16("p1.com"));
+ string16 name2(ASCIIToUTF16("p2.com"));
+
+ AddProfile(name1, true);
+ AddProfile(name2, true);
+
+ AvatarMenu* menu = GetAvatarMenu();
+
+ ASSERT_EQ(2U, menu->GetNumberOfItems());
+ // TODO(jeremy): Expand test to verify active profile index other than 0
+ // crbug.com/100871
+ ASSERT_EQ(0U, menu->GetActiveProfileIndex());
+}
+
+TEST_F(ProfileListChromeOSTest, ModifyingNameResortsCorrectly) {
+ string16 name1(ASCIIToUTF16("Alpha"));
+ string16 name2(ASCIIToUTF16("Beta"));
+ string16 newname1(ASCIIToUTF16("Gamma"));
+
+ AddProfile(name1, true);
+ AddProfile(name2, true);
+
+ AvatarMenu* menu = GetAvatarMenu();
+
+ ASSERT_EQ(2U, menu->GetNumberOfItems());
+
+ const AvatarMenu::Item& item1 = menu->GetItemAt(0);
+ EXPECT_EQ(0U, item1.menu_index);
+ EXPECT_EQ(name1, item1.name);
+
+ const AvatarMenu::Item& item2 = menu->GetItemAt(1);
+ EXPECT_EQ(1U, item2.menu_index);
+ EXPECT_EQ(name2, item2.name);
+
+ // Change name of the first profile, to trigger resorting of the profiles:
+ // now the first menu item should be named "beta", and the second be "gamma".
+ GetFakeUserManager()->SaveUserDisplayName(
+ UTF16ToASCII(name1) + "@example.com", newname1);
+ manager()->profile_info_cache()->SetNameOfProfileAtIndex(0, newname1);
+
+ const AvatarMenu::Item& item1next = menu->GetItemAt(0);
+ EXPECT_GT(change_count(), 1);
+ EXPECT_EQ(0U, item1next.menu_index);
+ EXPECT_EQ(name2, item1next.name);
+
+ const AvatarMenu::Item& item2next = menu->GetItemAt(1);
+ EXPECT_EQ(1U, item2next.menu_index);
+ EXPECT_EQ(newname1, item2next.name);
+}
+
+TEST_F(ProfileListChromeOSTest, ChangeOnNotify) {
+ string16 name1(ASCIIToUTF16("p1.com"));
+ string16 name2(ASCIIToUTF16("p2.com"));
+
+ AddProfile(name1, true);
+ AddProfile(name2, true);
+
+ AvatarMenu* menu = GetAvatarMenu();
+ EXPECT_EQ(2U, menu->GetNumberOfItems());
+
+ string16 name3(ASCIIToUTF16("p3.com"));
+ AddProfile(name3, true);
+
+ // Four changes happened via the call to CreateTestingProfile: adding the
+ // profile to the cache, setting the user name, rebuilding the list of
+ // profiles after the name change, and changing the avatar.
+ // TODO(michaelpg): Determine why actual change number does not match comment.
+ EXPECT_GE(change_count(), 4);
+ ASSERT_EQ(3U, menu->GetNumberOfItems());
+
+ const AvatarMenu::Item& item1 = menu->GetItemAt(0);
+ EXPECT_EQ(0U, item1.menu_index);
+ EXPECT_EQ(name1, item1.name);
+
+ const AvatarMenu::Item& item2 = menu->GetItemAt(1);
+ EXPECT_EQ(1U, item2.menu_index);
+ EXPECT_EQ(name2, item2.name);
+
+ const AvatarMenu::Item& item3 = menu->GetItemAt(2);
+ EXPECT_EQ(2U, item3.menu_index);
+ EXPECT_EQ(name3, item3.name);
+}
+
+TEST_F(ProfileListChromeOSTest, ShowAvatarMenu) {
+ string16 name1(ASCIIToUTF16("p1"));
+ string16 name2(ASCIIToUTF16("p2"));
+
+ AddProfile(name1, true);
+
+ // Should only show avatar menu with multiple users.
+ EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu());
+
+ AddProfile(name2, false);
+
+ EXPECT_TRUE(AvatarMenu::ShouldShowAvatarMenu());
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
index f66a0b5..a058e19 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
@@ -248,10 +248,10 @@
profile_test->AddProfile(kUserProfilePath, "user_hash");
service_test->AddService("stub_wifi2", "wifi2_PSK",
- flimflam::kTypeWifi, flimflam::kStateOnline,
+ shill::kTypeWifi, shill::kStateOnline,
true /* visible */, true /* watch */);
service_test->SetServiceProperty("stub_wifi2",
- flimflam::kGuidProperty,
+ shill::kGuidProperty,
base::StringValue("stub_wifi2"));
profile_test->AddService(kUserProfilePath, "stub_wifi2");
@@ -303,7 +303,7 @@
ASSERT_TRUE(network);
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
SetServiceProperty(network->path(),
- flimflam::kProxyConfigProperty,
+ shill::kProxyConfigProperty,
StringValue(proxy_config));
}
diff --git a/chrome/browser/chromeos/settings/cros_settings.cc b/chrome/browser/chromeos/settings/cros_settings.cc
index 901ebcf..9023c0a 100644
--- a/chrome/browser/chromeos/settings/cros_settings.cc
+++ b/chrome/browser/chromeos/settings/cros_settings.cc
@@ -10,15 +10,11 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/settings/device_settings_provider.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
#include "chrome/browser/chromeos/settings/system_settings_provider.h"
#include "chromeos/chromeos_switches.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
#include "google_apis/gaia/gaia_auth_util.h"
namespace chromeos {
@@ -262,52 +258,31 @@
return false;
}
-void CrosSettings::AddSettingsObserver(const char* path,
- content::NotificationObserver* obs) {
- DCHECK(path);
- DCHECK(obs);
+scoped_ptr<CrosSettings::ObserverSubscription>
+CrosSettings::AddSettingsObserver(const std::string& path,
+ const base::Closure& callback) {
+ DCHECK(!path.empty());
+ DCHECK(!callback.is_null());
DCHECK(CalledOnValidThread());
- if (!GetProvider(std::string(path))) {
+ if (!GetProvider(path)) {
NOTREACHED() << "Trying to add an observer for an unregistered setting: "
<< path;
- return;
+ return scoped_ptr<CrosSettings::ObserverSubscription>();
}
- // Get the settings observer list associated with the path.
- NotificationObserverList* observer_list = NULL;
+ // Get the callback registry associated with the path.
+ base::CallbackRegistry<void(void)>* registry = NULL;
SettingsObserverMap::iterator observer_iterator =
settings_observers_.find(path);
if (observer_iterator == settings_observers_.end()) {
- observer_list = new NotificationObserverList;
- settings_observers_[path] = observer_list;
+ registry = new base::CallbackRegistry<void(void)>;
+ settings_observers_[path] = registry;
} else {
- observer_list = observer_iterator->second;
+ registry = observer_iterator->second;
}
- // Verify that this observer doesn't already exist.
- NotificationObserverList::Iterator it(*observer_list);
- content::NotificationObserver* existing_obs;
- while ((existing_obs = it.GetNext()) != NULL) {
- if (existing_obs == obs)
- return;
- }
-
- // Ok, safe to add the pref observer.
- observer_list->AddObserver(obs);
-}
-
-void CrosSettings::RemoveSettingsObserver(const char* path,
- content::NotificationObserver* obs) {
- DCHECK(CalledOnValidThread());
-
- SettingsObserverMap::iterator observer_iterator =
- settings_observers_.find(path);
- if (observer_iterator == settings_observers_.end())
- return;
-
- NotificationObserverList* observer_list = observer_iterator->second;
- observer_list->RemoveObserver(obs);
+ return registry->Add(callback);
}
CrosSettingsProvider* CrosSettings::GetProvider(
@@ -326,13 +301,7 @@
if (observer_iterator == settings_observers_.end())
return;
- NotificationObserverList::Iterator it(*(observer_iterator->second));
- content::NotificationObserver* observer;
- while ((observer = it.GetNext()) != NULL) {
- observer->Observe(chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED,
- content::Source<CrosSettings>(this),
- content::Details<const std::string>(&path));
- }
+ observer_iterator->second->Notify();
}
ScopedTestCrosSettings::ScopedTestCrosSettings() {
diff --git a/chrome/browser/chromeos/settings/cros_settings.h b/chrome/browser/chromeos/settings/cros_settings.h
index e14b2be..77f8194 100644
--- a/chrome/browser/chromeos/settings/cros_settings.h
+++ b/chrome/browser/chromeos/settings/cros_settings.h
@@ -9,12 +9,12 @@
#include <vector>
#include "base/callback_forward.h"
+#include "base/callback_registry.h"
#include "base/containers/hash_tables.h"
-#include "base/observer_list.h"
+#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "chrome/browser/chromeos/settings/cros_settings_names.h"
#include "chrome/browser/chromeos/settings/cros_settings_provider.h"
-#include "content/public/browser/notification_observer.h"
namespace base {
class DictionaryValue;
@@ -93,12 +93,11 @@
bool AddSettingsProvider(CrosSettingsProvider* provider);
bool RemoveSettingsProvider(CrosSettingsProvider* provider);
- // If the pref at the given |path| changes, we call the observer's Observe
- // method with NOTIFICATION_SYSTEM_SETTING_CHANGED.
- void AddSettingsObserver(const char* path,
- content::NotificationObserver* obs);
- void RemoveSettingsObserver(const char* path,
- content::NotificationObserver* obs);
+ // Add an observer Callback for changes for the given |path|.
+ typedef base::CallbackRegistry<void(void)>::Subscription ObserverSubscription;
+ scoped_ptr<ObserverSubscription> AddSettingsObserver(
+ const std::string& path,
+ const base::Closure& callback);
// Returns the provider that handles settings with the |path| or prefix.
CrosSettingsProvider* GetProvider(const std::string& path) const;
@@ -106,7 +105,7 @@
private:
friend class CrosSettingsTest;
- // Fires system setting change notification.
+ // Fires system setting change callback.
void FireObservers(const std::string& path);
// List of ChromeOS system settings providers.
@@ -114,9 +113,7 @@
// A map from settings names to a list of observers. Observers get fired in
// the order they are added.
- typedef ObserverList<content::NotificationObserver, true>
- NotificationObserverList;
- typedef base::hash_map<std::string, NotificationObserverList*>
+ typedef base::hash_map<std::string, base::CallbackRegistry<void(void)>*>
SettingsObserverMap;
SettingsObserverMap settings_observers_;
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
index dbcf249..883720f 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
@@ -23,25 +23,25 @@
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. Additionally implements the Request interface, so that it
+// complete. Additionally derives from the RequestImpl, so that it
// can be passed back to the caller and directly deleted when cancelling
// the request.
class DeviceOAuth2TokenService::ValidatingConsumer
: public OAuth2TokenService::Consumer,
- public OAuth2TokenService::Request,
+ public OAuth2TokenService::RequestImpl,
public gaia::GaiaOAuthClient::Delegate {
public:
explicit ValidatingConsumer(DeviceOAuth2TokenService* token_service,
Consumer* consumer);
virtual ~ValidatingConsumer();
- void StartValidation(scoped_ptr<Request> request);
+ void StartValidation();
// OAuth2TokenService::Consumer
virtual void OnGetTokenSuccess(
@@ -76,11 +76,6 @@
bool token_validation_done_;
bool token_is_valid_;
- // The request instance returned by OAuth2TokenService, which we're
- // wrapping. If the this object is deleted, |request_| will also be
- // deleted and the OAuth2TokenService won't call back on this object.
- scoped_ptr<OAuth2TokenService::Request> request_;
-
// OAuth2TokenService::Consumer results
bool token_fetch_done_;
std::string access_token_;
@@ -91,7 +86,8 @@
DeviceOAuth2TokenService::ValidatingConsumer::ValidatingConsumer(
DeviceOAuth2TokenService* token_service,
Consumer* consumer)
- : token_service_(token_service),
+ : OAuth2TokenService::RequestImpl(this),
+ token_service_(token_service),
consumer_(consumer),
token_validation_done_(false),
token_is_valid_(false),
@@ -101,10 +97,8 @@
DeviceOAuth2TokenService::ValidatingConsumer::~ValidatingConsumer() {
}
-void DeviceOAuth2TokenService::ValidatingConsumer::StartValidation(
- scoped_ptr<Request> request) {
+void DeviceOAuth2TokenService::ValidatingConsumer::StartValidation() {
DCHECK(!gaia_oauth_client_);
- request_ = request.Pass();
gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(
g_browser_process->system_request_context()));
@@ -115,7 +109,7 @@
gaia_oauth_client_->RefreshToken(
client_info,
- token_service_->GetRefreshToken(),
+ token_service_->GetRefreshToken(token_service_->GetRobotAccountId()),
std::vector<std::string>(1, kServiceScopeGetUserInfo),
token_service_->max_refresh_token_validation_retries_,
this);
@@ -163,6 +157,7 @@
const Request* request,
const std::string& access_token,
const base::Time& expiration_time) {
+ DCHECK_EQ(request, this);
token_fetch_done_ = true;
access_token_ = access_token;
expiration_time_ = expiration_time;
@@ -173,6 +168,7 @@
void DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenFailure(
const Request* request,
const GoogleServiceAuthError& error) {
+ DCHECK_EQ(request, this);
token_fetch_done_ = true;
error_.reset(new GoogleServiceAuthError(error.state()));
if (token_validation_done_)
@@ -183,6 +179,7 @@
bool is_valid) {
token_validation_done_ = true;
token_is_valid_ = is_valid;
+ token_service_->OnValidationComplete(is_valid);
if (token_fetch_done_)
InformConsumer();
}
@@ -190,7 +187,7 @@
void DeviceOAuth2TokenService::ValidatingConsumer::InformConsumer() {
DCHECK(token_fetch_done_);
DCHECK(token_validation_done_);
- token_service_->OnValidationComplete(token_is_valid_);
+
// Note: this object (which is also the Request instance) may be deleted in
// these consumer callbacks, so the callbacks must be the last line executed.
// Also, make copies of the parameters passed to the consumer to avoid invalid
@@ -220,24 +217,6 @@
DeviceOAuth2TokenService::~DeviceOAuth2TokenService() {
}
-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 {
- scoped_ptr<ValidatingConsumer> validating_consumer(
- new ValidatingConsumer(this, consumer));
-
- scoped_ptr<Request> request = OAuth2TokenService::StartRequest(
- scopes, validating_consumer.get());
- validating_consumer->StartValidation(request.Pass());
- return validating_consumer.PassAs<Request>();
- }
-}
-
void DeviceOAuth2TokenService::OnValidationComplete(
bool refresh_token_is_valid) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -260,7 +239,9 @@
encrypted_refresh_token);
}
-std::string DeviceOAuth2TokenService::GetRefreshToken() {
+std::string DeviceOAuth2TokenService::GetRefreshToken(
+ const std::string& account_id) {
+ DCHECK_EQ(account_id, GetRobotAccountId());
if (refresh_token_.empty()) {
std::string encrypted_refresh_token =
local_state_->GetString(prefs::kDeviceRobotAnyApiRefreshToken);
@@ -283,4 +264,17 @@
return url_request_context_getter_.get();
}
+scoped_ptr<OAuth2TokenService::RequestImpl>
+DeviceOAuth2TokenService::CreateRequest(
+ OAuth2TokenService::Consumer* consumer) {
+ if (refresh_token_is_valid_)
+ return OAuth2TokenService::CreateRequest(consumer);
+
+ // Substitute our own consumer to wait for refresh token validation.
+ scoped_ptr<ValidatingConsumer> validating_consumer(
+ new ValidatingConsumer(this, consumer));
+ validating_consumer->StartValidation();
+ return validating_consumer.PassAs<RequestImpl>();
+}
+
} // 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 1ce6196..08d47d5 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.h
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.h
@@ -34,28 +34,30 @@
//
// See |OAuth2TokenService| for usage details.
//
+// When using DeviceOAuth2TokenSerivce, a value of |GetRobotAccountId| should
+// be used in places where API expects |account_id|.
+//
// 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);
static void RegisterPrefs(PrefRegistrySimple* registry);
- virtual std::string GetRefreshToken() OVERRIDE;
+ // Gets the refresh token used by the service. |account_id| is expected to be
+ // a value of |GetRobotAccountId|.
+ virtual std::string GetRefreshToken(const std::string& account_id) OVERRIDE;
- protected:
// Pull the robot account ID from device policy.
virtual std::string GetRobotAccountId();
+ protected:
// Implementation of OAuth2TokenService.
virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
+ virtual scoped_ptr<OAuth2TokenService::RequestImpl> CreateRequest(
+ OAuth2TokenService::Consumer* consumer) OVERRIDE;
private:
class ValidatingConsumer;
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 98fed4e..f9ad79a 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc
@@ -43,7 +43,6 @@
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_;
@@ -79,7 +78,9 @@
}
scoped_ptr<OAuth2TokenService::Request> StartTokenRequest() {
- return oauth2_service_.StartRequest(std::set<std::string>(), &consumer_);
+ return oauth2_service_.StartRequest(oauth2_service_.GetRobotAccountId(),
+ std::set<std::string>(),
+ &consumer_);
}
virtual void TearDown() OVERRIDE {
@@ -162,12 +163,15 @@
.Times(1)
.WillOnce(Return("test-token"));
- ASSERT_EQ("", oauth2_service_.GetRefreshToken());
+ ASSERT_EQ("", oauth2_service_.GetRefreshToken(
+ oauth2_service_.GetRobotAccountId()));
oauth2_service_.SetAndSaveRefreshToken("test-token");
- ASSERT_EQ("test-token", oauth2_service_.GetRefreshToken());
+ ASSERT_EQ("test-token", oauth2_service_.GetRefreshToken(
+ oauth2_service_.GetRobotAccountId()));
// 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(
+ oauth2_service_.GetRobotAccountId()));
}
TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_Success) {
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index 83306ad..6a6d720 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -744,9 +744,9 @@
new_values_cache->SetBoolean(
kAttestationForContentProtectionEnabled,
- !(policy.has_attestation_settings() &&
- policy.attestation_settings().has_content_protection_enabled() &&
- policy.attestation_settings().content_protection_enabled()));
+ policy.has_attestation_settings() &&
+ policy.attestation_settings().has_content_protection_enabled() &&
+ policy.attestation_settings().content_protection_enabled());
}
void DeviceSettingsProvider::UpdateValuesCache(
@@ -824,7 +824,7 @@
}
bool current_value;
if (!cellular->properties().GetBooleanWithoutPathExpansion(
- flimflam::kCellularAllowRoamingProperty, ¤t_value)) {
+ shill::kCellularAllowRoamingProperty, ¤t_value)) {
NET_LOG_ERROR("Could not get \"allow roaming\" property from cellular "
"device.", cellular->path());
return;
@@ -838,7 +838,7 @@
NetworkHandler::Get()->network_device_handler()->SetDeviceProperty(
cellular->path(),
- flimflam::kCellularAllowRoamingProperty,
+ shill::kCellularAllowRoamingProperty,
base::FundamentalValue(new_value),
base::Bind(&base::DoNothing),
base::Bind(&LogShillError));
diff --git a/chrome/browser/chromeos/status/data_promo_notification.cc b/chrome/browser/chromeos/status/data_promo_notification.cc
index 84f153d..e7b9bda 100644
--- a/chrome/browser/chromeos/status/data_promo_notification.cc
+++ b/chrome/browser/chromeos/status/data_promo_notification.cc
@@ -165,7 +165,7 @@
void DataPromoNotification::NetworkPropertiesUpdated(
const NetworkState* network) {
- if (!network || network->type() != flimflam::kTypeCellular)
+ if (!network || network->type() != shill::kTypeCellular)
return;
ShowOptionalMobileDataPromoNotification();
}
@@ -184,7 +184,7 @@
return;
const NetworkState* default_network =
NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
- if (!default_network || default_network->type() != flimflam::kTypeCellular)
+ if (!default_network || default_network->type() != shill::kTypeCellular)
return;
// When requesting a network connection, do not show the notification.
if (NetworkHandler::Get()->network_connection_handler()->
@@ -214,7 +214,7 @@
}
int icon_id;
- if (default_network->network_technology() == flimflam::kNetworkTechnologyLte)
+ if (default_network->network_technology() == shill::kNetworkTechnologyLte)
icon_id = IDR_AURA_UBER_TRAY_NOTIFICATION_LTE;
else
icon_id = IDR_AURA_UBER_TRAY_NOTIFICATION_3G;
diff --git a/chrome/browser/chromeos/status/network_menu.cc b/chrome/browser/chromeos/status/network_menu.cc
index a3be1ae..35869d9 100644
--- a/chrome/browser/chromeos/status/network_menu.cc
+++ b/chrome/browser/chromeos/status/network_menu.cc
@@ -317,9 +317,9 @@
owner_->delegate()->OnConnectToNetworkRequested(
menu_items_[index].service_path);
} else if (flags & FLAG_ADD_WIFI) {
- ShowOther(flimflam::kTypeWifi);
+ ShowOther(shill::kTypeWifi);
} else if (flags & FLAG_ADD_CELLULAR) {
- ShowOther(flimflam::kTypeCellular);
+ ShowOther(shill::kTypeCellular);
}
}
@@ -335,10 +335,10 @@
void NetworkMenuModel::ShowOther(const std::string& type) const {
gfx::NativeWindow native_window = owner_->delegate()->GetNativeWindow();
- if (type == flimflam::kTypeCellular)
+ if (type == shill::kTypeCellular)
ChooseMobileNetworkDialog::ShowDialog(native_window);
else
- NetworkConfigView::ShowForType(flimflam::kTypeWifi, native_window);
+ NetworkConfigView::ShowForType(shill::kTypeWifi, native_window);
}
////////////////////////////////////////////////////////////////////////////////
@@ -421,13 +421,13 @@
for (NetworkStateHandler::NetworkStateList::const_iterator iter =
network_list.begin(); iter != network_list.end(); ++iter) {
const NetworkState* network = *iter;
- if (network->type() != flimflam::kTypeCellular)
+ if (network->type() != shill::kTypeCellular)
continue;
std::string activation_state = network->activation_state();
// This is only used in the login screen; do not show unactivated
// networks.
- if (activation_state != flimflam::kActivationStateActivated)
+ if (activation_state != shill::kActivationStateActivated)
continue;
// Ampersand is a valid character in a network name, but menu2 uses it
@@ -459,7 +459,7 @@
if (cellular_device && cellular_device->support_network_scan()) {
const gfx::ImageSkia icon =
ash::network_icon::GetImageForDisconnectedNetwork(
- ash::network_icon::ICON_TYPE_LIST, flimflam::kTypeCellular);
+ ash::network_icon::ICON_TYPE_LIST, shill::kTypeCellular);
menu_items_.push_back(MenuItem(
ui::MenuModel::TYPE_COMMAND,
l10n_util::GetStringUTF16(
@@ -481,7 +481,7 @@
for (NetworkStateHandler::NetworkStateList::const_iterator iter =
network_list.begin(); iter != network_list.end(); ++iter) {
const NetworkState* network = *iter;
- if (network->type() != flimflam::kTypeWimax)
+ if (network->type() != shill::kTypeWimax)
continue;
AddWirelessNetworkMenuItem(network, FLAG_WIMAX);
}
@@ -496,7 +496,7 @@
for (NetworkStateHandler::NetworkStateList::const_iterator iter =
network_list.begin(); iter != network_list.end(); ++iter) {
const NetworkState* network = *iter;
- if (network->type() != flimflam::kTypeWifi)
+ if (network->type() != shill::kTypeWifi)
continue;
// Add 'Searching for Wi-Fi networks...' after connected networks.
if (scanning_msg && !network->IsConnectedState()) {
@@ -509,7 +509,7 @@
AddMessageItem(l10n_util::GetStringUTF16(scanning_msg));
const gfx::ImageSkia icon =
ash::network_icon::GetImageForConnectedNetwork(
- ash::network_icon::ICON_TYPE_LIST, flimflam::kTypeWifi);
+ ash::network_icon::ICON_TYPE_LIST, shill::kTypeWifi);
menu_items_.push_back(MenuItem(
ui::MenuModel::TYPE_COMMAND,
l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_WIFI_NETWORKS),
diff --git a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
index ba9fe96..a1ede89 100644
--- a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
+++ b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
@@ -256,20 +256,20 @@
return;
}
- if (network->type() == flimflam::kTypeWifi) {
+ if (network->type() == shill::kTypeWifi) {
// Only show the config view for secure networks, otherwise do nothing.
- if (network->security() != flimflam::kSecurityNone)
+ if (network->security() != shill::kSecurityNone)
NetworkConfigView::Show(service_path, parent_window);
return;
}
- if (network->type() == flimflam::kTypeWimax ||
- network->type() == flimflam::kTypeVPN) {
+ if (network->type() == shill::kTypeWimax ||
+ network->type() == shill::kTypeVPN) {
NetworkConfigView::Show(service_path, parent_window);
return;
}
- if (network->type() == flimflam::kTypeCellular) {
+ if (network->type() == shill::kTypeCellular) {
if (network->RequiresActivation()) {
ash::network_connect::ActivateCellular(service_path);
return;
@@ -872,11 +872,11 @@
}
virtual void ShowOtherWifi() OVERRIDE {
- NetworkConfigView::ShowForType(flimflam::kTypeWifi, GetNativeWindow());
+ NetworkConfigView::ShowForType(shill::kTypeWifi, GetNativeWindow());
}
virtual void ShowOtherVPN() OVERRIDE {
- NetworkConfigView::ShowForType(flimflam::kTypeVPN, GetNativeWindow());
+ NetworkConfigView::ShowForType(shill::kTypeVPN, GetNativeWindow());
}
virtual void ShowOtherCellular() OVERRIDE {
diff --git a/chrome/browser/chromeos/system_key_event_listener.cc b/chrome/browser/chromeos/system_key_event_listener.cc
index e992966..d148977 100644
--- a/chrome/browser/chromeos/system_key_event_listener.cc
+++ b/chrome/browser/chromeos/system_key_event_listener.cc
@@ -51,7 +51,7 @@
num_lock_mask_ = xkeyboard->GetNumLockMask();
xkeyboard->GetLockedModifiers(&caps_lock_is_on_, NULL);
- Display* display = ui::GetXDisplay();
+ XDisplay* display = gfx::GetXDisplay();
int xkb_major_version = XkbMajorVersion;
int xkb_minor_version = XkbMinorVersion;
if (!XkbQueryExtension(display,
diff --git a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc
index f368097..98759b1 100644
--- a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc
@@ -12,13 +12,19 @@
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/sync/about_sync_util.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_set.h"
#include "content/public/browser/browser_thread.h"
+namespace {
+
const char kSyncDataKey[] = "about_sync_data";
const char kExtensionsListKey[] = "extensions";
+const char kChromeVersionTag[] = "CHROME VERSION";
+
+} // namespace
namespace chromeos {
@@ -27,6 +33,10 @@
DCHECK(!callback.is_null());
SystemLogsResponse response;
+
+ chrome::VersionInfo version_info;
+ response[kChromeVersionTag] = version_info.CreateVersionString();
+
PopulateSyncLogs(&response);
PopulateExtensionInfoLogs(&response);
diff --git a/chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.cc b/chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.cc
index 8a00409..fd4d51e 100644
--- a/chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.cc
+++ b/chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.cc
@@ -22,7 +22,7 @@
int error;
if (!XQueryExtension(
- ui::GetXDisplay(), kExtensionName, &xi_opcode, &event, &error)) {
+ gfx::GetXDisplay(), kExtensionName, &xi_opcode, &event, &error)) {
VLOG(1) << "X Input extension not available: error=" << error;
return -1;
}
diff --git a/chrome/browser/component_updater/component_updater_configurator.cc b/chrome/browser/component_updater/component_updater_configurator.cc
index bc814f2..948e682 100644
--- a/chrome/browser/component_updater/component_updater_configurator.cc
+++ b/chrome/browser/component_updater/component_updater_configurator.cc
@@ -35,8 +35,6 @@
const char kSwitchOutOfProcess[] = "out-of-process";
// Add "testrequest=1" parameter to the update check query.
const char kSwitchRequestParam[] = "test-request";
-// Disables differential updates.
-const char kSwitchDisableDeltaUpdates[] = "disable-delta-updates";
// Disables pings. Pings are the requests sent to the update server that report
// the success or the failure of component install or update attempts.
extern const char kSwitchDisablePings[] = "disable-pings";
@@ -52,6 +50,11 @@
// The url to send the pings to.
const char kPingUrl[] = "http://tools.google.com/service/update2";
+#if defined(OS_WIN)
+// Disables differential updates.
+const char kSwitchDisableDeltaUpdates[] = "disable-delta-updates";
+#endif // defined(OS_WIN)
+
// 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())
diff --git a/chrome/browser/component_updater/default_component_installer.cc b/chrome/browser/component_updater/default_component_installer.cc
index 9c7e6e0..b610f2e 100644
--- a/chrome/browser/component_updater/default_component_installer.cc
+++ b/chrome/browser/component_updater/default_component_installer.cc
@@ -43,6 +43,19 @@
NOTREACHED() << "Component update error: " << error;
}
+bool DefaultComponentInstaller::InstallHelper(
+ const base::DictionaryValue& manifest,
+ const base::FilePath& unpack_path,
+ const base::FilePath& install_path) {
+ if (!base::Move(unpack_path, install_path))
+ return false;
+ if (!installer_traits_->OnCustomInstall(manifest, install_path))
+ return false;
+ if (!installer_traits_->VerifyInstallation(install_path))
+ return false;
+ return true;
+}
+
bool DefaultComponentInstaller::Install(const base::DictionaryValue& manifest,
const base::FilePath& unpack_path) {
std::string manifest_version;
@@ -54,13 +67,12 @@
return false;
base::FilePath install_path =
installer_traits_->GetBaseDirectory().AppendASCII(version.GetString());
- if (base::PathExists(install_path))
- return false;
- if (!base::Move(unpack_path, install_path))
- return false;
- if (!installer_traits_->OnCustomInstall(manifest, install_path))
- return false;
- if (!installer_traits_->VerifyInstallation(install_path)) {
+ if (base::PathExists(install_path)) {
+ if (!base::DeleteFile(install_path, true))
+ return false;
+ }
+ if (!InstallHelper(manifest, unpack_path, install_path)) {
+ base::DeleteFile(install_path, true);
return false;
}
current_version_ = version;
diff --git a/chrome/browser/component_updater/default_component_installer.h b/chrome/browser/component_updater/default_component_installer.h
index 037438e..10bdcc3 100644
--- a/chrome/browser/component_updater/default_component_installer.h
+++ b/chrome/browser/component_updater/default_component_installer.h
@@ -87,6 +87,9 @@
private:
base::FilePath GetInstallDirectory();
+ bool InstallHelper(const base::DictionaryValue& manifest,
+ const base::FilePath& unpack_path,
+ const base::FilePath& install_path);
void StartRegistration(ComponentUpdateService* cus);
void FinishRegistration(ComponentUpdateService* cus);
diff --git a/chrome/browser/component_updater/pepper_flash_component_installer.cc b/chrome/browser/component_updater/pepper_flash_component_installer.cc
index e463a8e..01a9da8 100644
--- a/chrome/browser/component_updater/pepper_flash_component_installer.cc
+++ b/chrome/browser/component_updater/pepper_flash_component_installer.cc
@@ -45,14 +45,20 @@
namespace {
+// File name of the Pepper Flash component manifest on different platforms.
+const char kPepperFlashManifestName[] = "Flapper";
+
+#if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX)
// CRX hash. The extension id is: mimojjlkmoijpicakmndhoigimigcmbb.
const uint8 kSha2Hash[] = {0xc8, 0xce, 0x99, 0xba, 0xce, 0x89, 0xf8, 0x20,
0xac, 0xd3, 0x7e, 0x86, 0x8c, 0x86, 0x2c, 0x11,
0xb9, 0x40, 0xc5, 0x55, 0xaf, 0x08, 0x63, 0x70,
0x54, 0xf9, 0x56, 0xd3, 0xe7, 0x88, 0xba, 0x8c};
-// File name of the Pepper Flash component manifest on different platforms.
-const char kPepperFlashManifestName[] = "Flapper";
+// If we don't have a Pepper Flash component, this is the version we claim.
+const char kNullVersion[] = "0.0.0.0";
+
+#endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX)
// Name of the Pepper Flash OS in the component manifest.
const char kPepperFlashOperatingSystem[] =
@@ -74,9 +80,6 @@
"???";
#endif
-// If we don't have a Pepper Flash component, this is the version we claim.
-const char kNullVersion[] = "0.0.0.0";
-
// The base directory on Windows looks like:
// <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\.
base::FilePath GetPepperFlashBaseDirectory() {
diff --git a/chrome/browser/component_updater/ppapi_utils.cc b/chrome/browser/component_updater/ppapi_utils.cc
index 6b43400..6f9638f 100644
--- a/chrome/browser/component_updater/ppapi_utils.cc
+++ b/chrome/browser/component_updater/ppapi_utils.cc
@@ -56,6 +56,8 @@
#include "ppapi/c/ppb_mouse_cursor.h"
#include "ppapi/c/ppb_mouse_lock.h"
#include "ppapi/c/ppb_net_address.h"
+#include "ppapi/c/ppb_network_list.h"
+#include "ppapi/c/ppb_network_monitor.h"
#include "ppapi/c/ppb_network_proxy.h"
#include "ppapi/c/ppb_opengles2.h"
#include "ppapi/c/ppb_tcp_socket.h"
@@ -85,8 +87,6 @@
#include "ppapi/c/private/ppb_flash_message_loop.h"
#include "ppapi/c/private/ppb_flash_print.h"
#include "ppapi/c/private/ppb_host_resolver_private.h"
-#include "ppapi/c/private/ppb_network_list_private.h"
-#include "ppapi/c/private/ppb_network_monitor_private.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/c/private/ppb_proxy_private.h"
#include "ppapi/c/private/ppb_talk_private.h"
diff --git a/chrome/browser/content_settings/content_settings_default_provider.cc b/chrome/browser/content_settings/content_settings_default_provider.cc
index 3a7c891..96f07fe 100644
--- a/chrome/browser/content_settings/content_settings_default_provider.cc
+++ b/chrome/browser/content_settings/content_settings_default_provider.cc
@@ -51,10 +51,12 @@
CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PPAPI_BROKER
CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MIDI_SYSEX
+ CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_SAVE_PASSWORD
#if defined(OS_WIN)
CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP
+#elif defined(OS_ANDROID)
+ CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
#endif
- CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_SAVE_PASSWORD
};
COMPILE_ASSERT(arraysize(kDefaultSettings) == CONTENT_SETTINGS_NUM_TYPES,
default_settings_incorrect_size);
diff --git a/chrome/browser/content_settings/content_settings_policy_provider.cc b/chrome/browser/content_settings/content_settings_policy_provider.cc
index b2dcdea..3858cc3 100644
--- a/chrome/browser/content_settings/content_settings_policy_provider.cc
+++ b/chrome/browser/content_settings/content_settings_policy_provider.cc
@@ -44,10 +44,12 @@
NULL, // No policy for default value of PPAPI broker
NULL, // No policy for default value of multiple automatic downloads
NULL, // No policy for default value of MIDI system exclusive requests
+ NULL, // No policy for default value of save password
#if defined(OS_WIN)
NULL, // No policy for default value of "switch to desktop"
+#elif defined(OS_ANDROID)
+ NULL, // No policy for default value of protected media identifier
#endif
- NULL, // No policy for default value of save password
};
COMPILE_ASSERT(arraysize(kPrefToManageType) == CONTENT_SETTINGS_NUM_TYPES,
managed_content_settings_pref_names_array_size_incorrect);
diff --git a/chrome/browser/content_settings/content_settings_utils.cc b/chrome/browser/content_settings/content_settings_utils.cc
index c95b907..5da1ec4 100644
--- a/chrome/browser/content_settings/content_settings_utils.cc
+++ b/chrome/browser/content_settings/content_settings_utils.cc
@@ -41,10 +41,12 @@
"ppapi-broker",
"multiple-automatic-downloads",
"midi-sysex",
+ "save-password",
#if defined(OS_WIN)
"metro-switch-to-desktop",
+#elif defined(OS_ANDROID)
+ "protected-media-identifier",
#endif
- "save-password",
};
COMPILE_ASSERT(arraysize(kTypeNames) == CONTENT_SETTINGS_NUM_TYPES,
type_names_incorrect_size);
diff --git a/chrome/browser/content_settings/permission_queue_controller.cc b/chrome/browser/content_settings/permission_queue_controller.cc
index 4da7228..cd2c5ac 100644
--- a/chrome/browser/content_settings/permission_queue_controller.cc
+++ b/chrome/browser/content_settings/permission_queue_controller.cc
@@ -21,6 +21,9 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
+#if defined(OS_ANDROID)
+#include "chrome/browser/media/protected_media_identifier_infobar_delegate.h"
+#endif
namespace {
@@ -110,6 +113,13 @@
GetInfoBarService(id_), controller, id_, requesting_frame_,
display_languages);
break;
+#if defined(OS_ANDROID)
+ case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
+ infobar_ = ProtectedMediaIdentifierInfoBarDelegate::Create(
+ GetInfoBarService(id_), controller, id_, requesting_frame_,
+ display_languages);
+ break;
+#endif
default:
NOTREACHED();
break;
diff --git a/chrome/browser/content_settings/tab_specific_content_settings.cc b/chrome/browser/content_settings/tab_specific_content_settings.cc
index ef49b78..af49c3c 100644
--- a/chrome/browser/content_settings/tab_specific_content_settings.cc
+++ b/chrome/browser/content_settings/tab_specific_content_settings.cc
@@ -278,11 +278,18 @@
// Media is different from other content setting types since it allows new
// setting to kick in without reloading the page, and the UI for media is
// always reflecting the newest permission setting.
- if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
- type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)
- content_allowed_[type] = false;
- else
- content_allowed_[type] = true;
+ switch (type) {
+ case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
+ case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
+#if defined(OS_ANDROID)
+ case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
+#endif
+ content_allowed_[type] = false;
+ break;
+ default:
+ content_allowed_[type] = true;
+ break;
+ }
// Unless UI for resource content settings is enabled, ignore the resource
// identifier.
@@ -296,7 +303,7 @@
if (!identifier.empty())
AddBlockedResource(type, identifier);
-#if defined (OS_ANDROID)
+#if defined(OS_ANDROID)
if (type == CONTENT_SETTINGS_TYPE_POPUPS) {
// For Android we do not have a persistent button that will always be
// visible for blocked popups. Instead we have info bars which could be
@@ -321,14 +328,21 @@
DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
<< "Geolocation settings handled by OnGeolocationPermissionSet";
bool access_changed = false;
- if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
- type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) {
- // The setting for media is overwritten here because media does not need to
- // reload the page to have the new setting kick in. See issue/175993.
- if (content_blocked_[type]) {
- content_blocked_[type] = false;
- access_changed = true;
- }
+ switch (type) {
+ case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
+ case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
+#if defined(OS_ANDROID)
+ case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
+#endif
+ // The setting for media is overwritten here because media does not need
+ // to reload the page to have the new setting kick in. See issue/175993.
+ if (content_blocked_[type]) {
+ content_blocked_[type] = false;
+ access_changed = true;
+ }
+ break;
+ default:
+ break;
}
if (!content_allowed_[type]) {
@@ -462,6 +476,19 @@
content::NotificationService::NoDetails());
}
+#if defined(OS_ANDROID)
+void TabSpecificContentSettings::OnProtectedMediaIdentifierPermissionSet(
+ const GURL& requesting_origin,
+ bool allowed) {
+ if (allowed) {
+ OnContentAllowed(CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER);
+ } else {
+ OnContentBlocked(CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
+ std::string());
+ }
+}
+#endif
+
void TabSpecificContentSettings::OnPasswordSubmitted(
PasswordFormManager* form_manager) {
form_manager_.reset(form_manager);
@@ -502,14 +529,18 @@
void TabSpecificContentSettings::OnMediaStreamPermissionSet(
const GURL& request_origin,
- const MediaStreamDevicesController::MediaStreamTypePermissionMap&
+ const MediaStreamDevicesController::MediaStreamTypeSettingsMap&
request_permissions) {
media_stream_access_origin_ = request_origin;
- MediaStreamDevicesController::MediaStreamTypePermissionMap::const_iterator
- it = request_permissions.find(content::MEDIA_DEVICE_AUDIO_CAPTURE);
+ MediaStreamDevicesController::MediaStreamTypeSettingsMap::const_iterator it =
+ request_permissions.find(content::MEDIA_DEVICE_AUDIO_CAPTURE);
if (it != request_permissions.end()) {
- switch (it->second) {
+ media_stream_requested_audio_device_ = it->second.requested_device_id;
+ switch (it->second.permission) {
+ case MediaStreamDevicesController::MEDIA_NONE:
+ NOTREACHED();
+ break;
case MediaStreamDevicesController::MEDIA_ALLOWED:
OnContentAllowed(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
break;
@@ -525,7 +556,11 @@
it = request_permissions.find(content::MEDIA_DEVICE_VIDEO_CAPTURE);
if (it != request_permissions.end()) {
- switch (it->second) {
+ media_stream_requested_video_device_ = it->second.requested_device_id;
+ switch (it->second.permission) {
+ case MediaStreamDevicesController::MEDIA_NONE:
+ NOTREACHED();
+ break;
case MediaStreamDevicesController::MEDIA_ALLOWED:
OnContentAllowed(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
break;
diff --git a/chrome/browser/content_settings/tab_specific_content_settings.h b/chrome/browser/content_settings/tab_specific_content_settings.h
index e9b06f3..c919f7c 100644
--- a/chrome/browser/content_settings/tab_specific_content_settings.h
+++ b/chrome/browser/content_settings/tab_specific_content_settings.h
@@ -200,6 +200,14 @@
return media_stream_access_origin_;
}
+ const std::string& media_stream_requested_audio_device() const {
+ return media_stream_requested_audio_device_;
+ }
+
+ const std::string& media_stream_requested_video_device() const {
+ return media_stream_requested_video_device_;
+ }
+
// Returns the state of the camera and microphone usage.
MicrophoneCameraState GetMicrophoneCameraState() const;
@@ -337,13 +345,17 @@
bool blocked_by_policy);
void OnGeolocationPermissionSet(const GURL& requesting_frame,
bool allowed);
+#if defined(OS_ANDROID)
+ void OnProtectedMediaIdentifierPermissionSet(const GURL& requesting_frame,
+ bool allowed);
+#endif
// This method is called to update the status about the microphone and
// camera stream access. |request_permissions| contains a list of requested
// media stream types and the permission for each type.
void OnMediaStreamPermissionSet(
const GURL& request_origin,
- const MediaStreamDevicesController::MediaStreamTypePermissionMap&
+ const MediaStreamDevicesController::MediaStreamTypeSettingsMap&
request_permissions);
// Called when the user submits a form containing login information, so we
@@ -433,6 +445,11 @@
// stored here. http://crbug.com/259794
GURL media_stream_access_origin_;
+ // The devices to be displayed in the media bubble when the media stream
+ // request is requesting certain specific devices.
+ std::string media_stream_requested_audio_device_;
+ std::string media_stream_requested_video_device_;
+
// Set by OnPasswordSubmitted() when the user submits a form containing login
// information. If the user responds to a subsequent "Do you want to save
// this password?" prompt, we ask this object to save or blacklist the
diff --git a/chrome/browser/content_settings/tab_specific_content_settings_unittest.cc b/chrome/browser/content_settings/tab_specific_content_settings_unittest.cc
index a149a49..b75a82e 100644
--- a/chrome/browser/content_settings/tab_specific_content_settings_unittest.cc
+++ b/chrome/browser/content_settings/tab_specific_content_settings_unittest.cc
@@ -206,9 +206,9 @@
// Request and allow microphone access.
GURL security_origin("http://google.com");
- MediaStreamDevicesController::MediaStreamTypePermissionMap
+ MediaStreamDevicesController::MediaStreamTypeSettingsMap
request_permissions;
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -221,7 +221,7 @@
// Request and allow camera access.
request_permissions.clear();
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -234,7 +234,7 @@
// Request and block microphone access.
request_permissions.clear();
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_BLOCKED_BY_USER;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -247,7 +247,7 @@
// Request and block camera access.
request_permissions.clear();
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_BLOCKED_BY_USER;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -259,9 +259,9 @@
content_settings->GetMicrophoneCameraState());
// Request and allow microphone and camera access.
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -277,9 +277,9 @@
content_settings->GetMicrophoneCameraState());
// Request and block microphone and camera access.
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_BLOCKED_BY_USER;
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_BLOCKED_BY_USER;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -295,7 +295,7 @@
content_settings->GetMicrophoneCameraState());
// Request microphone and camera access. Allow microphone, block camera.
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -311,9 +311,9 @@
content_settings->GetMicrophoneCameraState());
// Request microphone and camera access. Block microphone, allow camera.
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_BLOCKED_BY_USER;
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
diff --git a/chrome/browser/devtools/OWNERS b/chrome/browser/devtools/OWNERS
index 676e6d8..9793bcc 100644
--- a/chrome/browser/devtools/OWNERS
+++ b/chrome/browser/devtools/OWNERS
@@ -8,6 +8,5 @@
per-file devtools_embedder_message_dispatcher.*=cevans@chromium.org
per-file devtools_embedder_message_dispatcher.*=jln@chromium.org
per-file devtools_embedder_message_dispatcher.*=jschuh@chromium.org
-per-file devtools_embedder_message_dispatcher.*=palmer@chromium.org
per-file devtools_embedder_message_dispatcher.*=tsepez@chromium.org
per-file devtools_embedder_message_dispatcher.*=kenrb@chromium.org
diff --git a/chrome/browser/devtools/adb_client_socket.cc b/chrome/browser/devtools/adb_client_socket.cc
index 98e9065..e9d1959 100644
--- a/chrome/browser/devtools/adb_client_socket.cc
+++ b/chrome/browser/devtools/adb_client_socket.cc
@@ -18,7 +18,6 @@
namespace {
const int kBufferSize = 16 * 1024;
-const int kResponseBufferSize = 16;
const char kOkayResponse[] = "OKAY";
const char kHostTransportCommand[] = "host:transport:%s";
const char kLocalhost[] = "127.0.0.1";
diff --git a/chrome/browser/devtools/devtools_adb_bridge.cc b/chrome/browser/devtools/devtools_adb_bridge.cc
index ca2fcdf..f9f6617 100644
--- a/chrome/browser/devtools/devtools_adb_bridge.cc
+++ b/chrome/browser/devtools/devtools_adb_bridge.cc
@@ -41,31 +41,34 @@
namespace {
-static const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
-static const char kHostDevicesCommand[] = "host:devices";
-static const char kHostTransportCommand[] = "host:transport:%s|%s";
-static const char kLocalAbstractCommand[] = "localabstract:%s";
-static const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
-static const char kLocalChrome[] = "Local Chrome";
-static const char kChrome[] = "Chrome";
-static const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
-static const char kListProcessesCommand[] = "shell:ps";
-static const char kDumpsysCommand[] = "shell:dumpsys window policy";
-static const char kDumpsysScreenSizePrefix[] = "mStable=";
+const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
+const char kHostDevicesCommand[] = "host:devices";
+const char kHostTransportCommand[] = "host:transport:%s|%s";
+const char kLocalAbstractCommand[] = "localabstract:%s";
+const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
+const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
+const char kListProcessesCommand[] = "shell:ps";
+const char kDumpsysCommand[] = "shell:dumpsys window policy";
+const char kDumpsysScreenSizePrefix[] = "mStable=";
-static const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n";
-static const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n";
-static const char kClosePageRequest[] = "GET /json/close/%s HTTP/1.1\r\n\r\n";
-static const char kNewPageRequest[] = "GET /json/new HTTP/1.1\r\n\r\n";
-static const char kActivatePageRequest[] =
+const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n";
+const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n";
+const char kClosePageRequest[] = "GET /json/close/%s HTTP/1.1\r\n\r\n";
+const char kNewPageRequest[] = "GET /json/new HTTP/1.1\r\n\r\n";
+const char kActivatePageRequest[] =
"GET /json/activate/%s HTTP/1.1\r\n\r\n";
const int kAdbPort = 5037;
const int kBufferSize = 16 * 1024;
const int kAdbPollingIntervalMs = 1000;
-static const char kUrlParam[] = "url";
-static const char kPageReloadCommand[] = "Page.reload";
-static const char kPageNavigateCommand[] = "Page.navigate";
+const char kUrlParam[] = "url";
+const char kPageReloadCommand[] = "Page.reload";
+const char kPageNavigateCommand[] = "Page.navigate";
+
+#if defined(DEBUG_DEVTOOLS)
+const char kChrome[] = "Chrome";
+const char kLocalChrome[] = "Local Chrome";
+#endif // defined(DEBUG_DEVTOOLS)
typedef DevToolsAdbBridge::Callback Callback;
typedef std::vector<scoped_refptr<DevToolsAdbBridge::AndroidDevice> >
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index bb9e5bb..0066333 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -80,10 +80,6 @@
DISALLOW_COPY_AND_ASSIGN(BrowserClosedObserver);
};
-// The delay waited in some cases where we don't have a notifications for an
-// action we take.
-const int kActionDelayMs = 500;
-
const char kDebuggerTestPage[] = "files/devtools/debugger_test_page.html";
const char kPauseWhenLoadingDevTools[] =
"files/devtools/pause_when_loading_devtools.html";
diff --git a/chrome/browser/drive/drive_api_service.cc b/chrome/browser/drive/drive_api_service.cc
index b19efab..8d9b144 100644
--- a/chrome/browser/drive/drive_api_service.cc
+++ b/chrome/browser/drive/drive_api_service.cc
@@ -90,6 +90,26 @@
const int kMaxNumFilesResourcePerRequest = 500;
const int kMaxNumFilesResourcePerRequestForSearch = 50;
+// For performance, we declare all fields we use.
+const char kAboutResourceFields[] =
+ "kind,quotaBytesTotal,quotaBytesUsed,largestChangeId,rootFolderId";
+const char kFileResourceFields[] =
+ "kind,id,title,createdDate,sharedWithMeDate,downloadUrl,mimeType,"
+ "md5Checksum,fileSize,labels/trashed,etag,parents/parentLink,selfLink,"
+ "thumbnailLink,alternateLink,embedLink,modifiedDate,lastViewedByMeDate";
+const char kFileResourceOpenWithLinksFields[] =
+ "kind,id,openWithLinks/*";
+const char kFileListFields[] =
+ "kind,items(kind,id,title,createdDate,sharedWithMeDate,downloadUrl,"
+ "mimeType,md5Checksum,fileSize,labels/trashed,etag,parents/parentLink,"
+ "selfLink,thumbnailLink,alternateLink,embedLink,modifiedDate,"
+ "lastViewedByMeDate),nextLink";
+const char kChangeListFields[] =
+ "kind,items(file(kind,id,title,createdDate,sharedWithMeDate,downloadUrl,"
+ "mimeType,md5Checksum,fileSize,labels/trashed,etag,parents/parentLink,"
+ "selfLink,thumbnailLink,alternateLink,embedLink,modifiedDate,"
+ "lastViewedByMeDate),deleted,id,fileId),nextLink,largestChangeId";
+
// Callback invoked when the parsing of resource list is completed,
// regardless whether it is succeeded or not.
void DidConvertToResourceListOnBlockingPool(
@@ -271,7 +291,7 @@
sender_->auth_service()->RemoveObserver(this);
}
-void DriveAPIService::Initialize() {
+void DriveAPIService::Initialize(const std::string& account_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
std::vector<std::string> scopes;
@@ -283,11 +303,13 @@
scopes.push_back(util::kDriveAppsScope);
sender_.reset(new RequestSender(
- new google_apis::AuthService(
- oauth2_token_service_, url_request_context_getter_, scopes),
- url_request_context_getter_,
- blocking_task_runner_.get(),
- custom_user_agent_));
+ new google_apis::AuthService(oauth2_token_service_,
+ account_id,
+ url_request_context_getter_,
+ scopes),
+ url_request_context_getter_,
+ blocking_task_runner_.get(),
+ custom_user_agent_));
sender_->auth_service()->AddObserver(this);
}
@@ -324,6 +346,7 @@
blocking_task_runner_, callback));
request->set_max_results(kMaxNumFilesResourcePerRequest);
request->set_q("trashed = false"); // Exclude trashed files.
+ request->set_fields(kFileListFields);
return sender_->StartRequestWithRetry(request);
}
@@ -349,7 +372,7 @@
request->set_q(base::StringPrintf(
"'%s' in parents and trashed = false",
drive::util::EscapeQueryStringValue(directory_resource_id).c_str()));
-
+ request->set_fields(kFileListFields);
return sender_->StartRequestWithRetry(request);
}
@@ -366,7 +389,7 @@
blocking_task_runner_, callback));
request->set_max_results(kMaxNumFilesResourcePerRequestForSearch);
request->set_q(drive::util::TranslateQuery(search_query));
-
+ request->set_fields(kFileListFields);
return sender_->StartRequestWithRetry(request);
}
@@ -394,7 +417,7 @@
blocking_task_runner_, callback));
request->set_max_results(kMaxNumFilesResourcePerRequest);
request->set_q(query);
-
+ request->set_fields(kFileListFields);
return sender_->StartRequestWithRetry(request);
}
@@ -410,6 +433,7 @@
blocking_task_runner_, callback));
request->set_max_results(kMaxNumFilesResourcePerRequest);
request->set_start_change_id(start_changestamp);
+ request->set_fields(kChangeListFields);
return sender_->StartRequestWithRetry(request);
}
@@ -425,6 +449,7 @@
base::Bind(&ConvertChangeListToResourceListOnBlockingPoolAndRun,
blocking_task_runner_, callback));
request->set_next_link(next_link);
+ request->set_fields(kChangeListFields);
return sender_->StartRequestWithRetry(request);
}
@@ -440,6 +465,7 @@
base::Bind(&ConvertFileListToResourceListOnBlockingPoolAndRun,
blocking_task_runner_, callback));
request->set_next_link(next_link);
+ request->set_fields(kFileListFields);
return sender_->StartRequestWithRetry(request);
}
@@ -453,6 +479,7 @@
sender_.get(), url_generator_,
base::Bind(&ConvertFileEntryToResourceEntryAndRun, callback));
request->set_file_id(resource_id);
+ request->set_fields(kFileResourceFields);
return sender_->StartRequestWithRetry(request);
}
@@ -481,8 +508,10 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
- return sender_->StartRequestWithRetry(
- new AboutGetRequest(sender_.get(), url_generator_, callback));
+ AboutGetRequest* request =
+ new AboutGetRequest(sender_.get(), url_generator_, callback);
+ request->set_fields(kAboutResourceFields);
+ return sender_->StartRequestWithRetry(request);
}
CancelCallback DriveAPIService::GetAppList(const AppListCallback& callback) {
@@ -524,6 +553,7 @@
sender_.get(), url_generator_,
base::Bind(&EntryActionCallbackAdapter, callback));
request->set_file_id(resource_id);
+ request->set_fields(kFileResourceFields);
return sender_->StartRequestWithRetry(request);
}
@@ -540,6 +570,7 @@
request->set_mime_type(kFolderMimeType);
request->add_parent(parent_resource_id);
request->set_title(directory_title);
+ request->set_fields(kFileResourceFields);
return sender_->StartRequestWithRetry(request);
}
@@ -547,6 +578,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
@@ -557,6 +589,8 @@
request->set_file_id(resource_id);
request->add_parent(parent_resource_id);
request->set_title(new_title);
+ request->set_modified_date(last_modified);
+ request->set_fields(kFileResourceFields);
return sender_->StartRequestWithRetry(request);
}
@@ -572,6 +606,7 @@
base::Bind(&ConvertFileEntryToResourceEntryAndRun, callback));
request->set_file_id(resource_id);
request->set_title(new_title);
+ request->set_fields(kFileResourceFields);
return sender_->StartRequestWithRetry(request);
}
@@ -579,6 +614,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
@@ -590,6 +626,11 @@
request->set_title(new_title);
if (!parent_resource_id.empty())
request->add_parent(parent_resource_id);
+ if (!last_modified.is_null()) {
+ request->set_set_modified_date(true);
+ request->set_modified_date(last_modified);
+ }
+ request->set_fields(kFileResourceFields);
return sender_->StartRequestWithRetry(request);
}
@@ -605,6 +646,7 @@
base::Bind(&EntryActionCallbackAdapter, callback));
request->set_file_id(resource_id);
request->set_title(new_title);
+ request->set_fields(kFileResourceFields);
return sender_->StartRequestWithRetry(request);
}
@@ -630,6 +672,7 @@
request->set_modified_date(modified_date);
request->set_last_viewed_by_me_date(last_viewed_by_me_date);
+ request->set_fields(kFileResourceFields);
return sender_->StartRequestWithRetry(request);
}
@@ -753,6 +796,7 @@
sender_.get(), url_generator_,
base::Bind(&ExtractOpenUrlAndRun, app_id, callback));
request->set_file_id(resource_id);
+ request->set_fields(kFileResourceOpenWithLinksFields);
return sender_->StartRequestWithRetry(request);
}
diff --git a/chrome/browser/drive/drive_api_service.h b/chrome/browser/drive/drive_api_service.h
index 8da990f..0944179 100644
--- a/chrome/browser/drive/drive_api_service.h
+++ b/chrome/browser/drive/drive_api_service.h
@@ -62,7 +62,7 @@
virtual ~DriveAPIService();
// DriveServiceInterface Overrides
- virtual void Initialize() OVERRIDE;
+ virtual void Initialize(const std::string& account_id) OVERRIDE;
virtual void AddObserver(DriveServiceObserver* observer) OVERRIDE;
virtual void RemoveObserver(DriveServiceObserver* observer) OVERRIDE;
virtual bool CanSendRequest() const OVERRIDE;
@@ -120,6 +120,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
virtual google_apis::CancelCallback CopyHostedDocument(
const std::string& resource_id,
@@ -129,6 +130,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
virtual google_apis::CancelCallback RenameResource(
const std::string& resource_id,
diff --git a/chrome/browser/drive/drive_api_util.cc b/chrome/browser/drive/drive_api_util.cc
index 8606dc2..776ea5c 100644
--- a/chrome/browser/drive/drive_api_util.cc
+++ b/chrome/browser/drive/drive_api_util.cc
@@ -28,11 +28,8 @@
// Google Apps MIME types:
const char kGoogleDocumentMimeType[] = "application/vnd.google-apps.document";
const char kGoogleDrawingMimeType[] = "application/vnd.google-apps.drawing";
-const char kGoogleFormMimeType[] = "application/vnd.google-apps.form";
const char kGooglePresentationMimeType[] =
"application/vnd.google-apps.presentation";
-const char kGoogleScriptMimeType[] = "application/vnd.google-apps.script";
-const char kGoogleSiteMimeType[] = "application/vnd.google-apps.site";
const char kGoogleSpreadsheetMimeType[] =
"application/vnd.google-apps.spreadsheet";
const char kGoogleTableMimeType[] = "application/vnd.google-apps.table";
diff --git a/chrome/browser/drive/drive_service_interface.h b/chrome/browser/drive/drive_service_interface.h
index fcb20c5..9ff3be6 100644
--- a/chrome/browser/drive/drive_service_interface.h
+++ b/chrome/browser/drive/drive_service_interface.h
@@ -41,8 +41,8 @@
// Common service:
- // Initializes the documents service.
- virtual void Initialize() = 0;
+ // Initializes the documents service with |account_id|.
+ virtual void Initialize(const std::string& account_id) = 0;
// Adds an observer.
virtual void AddObserver(DriveServiceObserver* observer) = 0;
@@ -201,6 +201,8 @@
// Makes a copy of a resource with |resource_id|.
// The new resource will be put under a directory with |parent_resource_id|,
// and it'll be named |new_title|.
+ // If |last_modified| is not null, the modified date of the resource on the
+ // server will be set to the date.
// This request is supported only on DriveAPIService, because GData WAPI
// doesn't support the function unfortunately.
// Upon completion, invokes |callback| with results on the calling thread.
@@ -209,6 +211,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) = 0;
// Makes a copy of a hosted document identified by its |resource_id|.
@@ -226,6 +229,8 @@
// Moves a resource with |resource_id| to the directory of
// |parent_resource_id| with renaming to |new_title|.
+ // If |last_modified| is not null, the modified date of the resource on the
+ // server will be set to the date.
// This request is supported only on DriveAPIService, because GData WAPI
// doesn't support the function unfortunately.
// Upon completion, invokes |callback| with results on the calling thread.
@@ -234,6 +239,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) = 0;
// Renames a document or collection identified by its |resource_id|
diff --git a/chrome/browser/drive/dummy_drive_service.cc b/chrome/browser/drive/dummy_drive_service.cc
index b9a46ae..de84f86 100644
--- a/chrome/browser/drive/dummy_drive_service.cc
+++ b/chrome/browser/drive/dummy_drive_service.cc
@@ -34,7 +34,7 @@
DummyDriveService::~DummyDriveService() {}
-void DummyDriveService::Initialize() {}
+void DummyDriveService::Initialize(const std::string& account_id) {}
void DummyDriveService::AddObserver(DriveServiceObserver* observer) {}
@@ -121,6 +121,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const GetResourceEntryCallback& callback) { return CancelCallback(); }
CancelCallback DummyDriveService::CopyHostedDocument(
@@ -132,6 +133,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) {
return CancelCallback();
}
diff --git a/chrome/browser/drive/dummy_drive_service.h b/chrome/browser/drive/dummy_drive_service.h
index e361a18..76e58b4 100644
--- a/chrome/browser/drive/dummy_drive_service.h
+++ b/chrome/browser/drive/dummy_drive_service.h
@@ -18,7 +18,7 @@
virtual ~DummyDriveService();
// DriveServiceInterface Overrides
- virtual void Initialize() OVERRIDE;
+ virtual void Initialize(const std::string& account_id) OVERRIDE;
virtual void AddObserver(DriveServiceObserver* observer) OVERRIDE;
virtual void RemoveObserver(DriveServiceObserver* observer) OVERRIDE;
virtual bool CanSendRequest() const OVERRIDE;
@@ -76,6 +76,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
virtual google_apis::CancelCallback CopyHostedDocument(
const std::string& resource_id,
@@ -85,6 +86,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
virtual google_apis::CancelCallback RenameResource(
const std::string& resource_id,
diff --git a/chrome/browser/drive/fake_drive_service.cc b/chrome/browser/drive/fake_drive_service.cc
index cc74539..e6611ef 100644
--- a/chrome/browser/drive/fake_drive_service.cc
+++ b/chrome/browser/drive/fake_drive_service.cc
@@ -278,7 +278,7 @@
return GURL("https://fake_server/" + net::EscapePath(resource_id));
}
-void FakeDriveService::Initialize() {
+void FakeDriveService::Initialize(const std::string& account_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
@@ -691,6 +691,7 @@
const std::string& resource_id,
const std::string& in_parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
@@ -737,6 +738,12 @@
link->SetString("href", GetFakeLinkUrl(parent_resource_id).spec());
links->Append(link);
+ if (!last_modified.is_null()) {
+ copied_entry->SetString(
+ "updated.$t",
+ google_apis::util::FormatTimeAsString(last_modified));
+ }
+
AddNewChangestampAndETag(copied_entry.get());
// Parse the new entry.
@@ -769,13 +776,15 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
- return CopyResource(resource_id, std::string(), new_title, callback);
+ return CopyResource(
+ resource_id, std::string(), new_title, base::Time(), callback);
}
CancelCallback FakeDriveService::MoveResource(
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
@@ -821,6 +830,12 @@
links->Append(link);
}
+ if (!last_modified.is_null()) {
+ entry->SetString(
+ "updated.$t",
+ google_apis::util::FormatTimeAsString(last_modified));
+ }
+
AddNewChangestampAndETag(entry);
// Parse the new entry.
@@ -847,7 +862,7 @@
DCHECK(!callback.is_null());
return MoveResource(
- resource_id, std::string(), new_title,
+ resource_id, std::string(), new_title, base::Time(),
base::Bind(&EntryActionCallbackAdapter, callback));
}
diff --git a/chrome/browser/drive/fake_drive_service.h b/chrome/browser/drive/fake_drive_service.h
index 5e71516..9da4b6e 100644
--- a/chrome/browser/drive/fake_drive_service.h
+++ b/chrome/browser/drive/fake_drive_service.h
@@ -103,7 +103,7 @@
static GURL GetFakeLinkUrl(const std::string& resource_id);
// DriveServiceInterface Overrides
- virtual void Initialize() OVERRIDE;
+ virtual void Initialize(const std::string& account_id) OVERRIDE;
virtual void AddObserver(DriveServiceObserver* observer) OVERRIDE;
virtual void RemoveObserver(DriveServiceObserver* observer) OVERRIDE;
virtual bool CanSendRequest() const OVERRIDE;
@@ -163,6 +163,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
// The new resource ID for the copied document will look like
// |resource_id| + "_copied".
@@ -174,6 +175,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
virtual google_apis::CancelCallback RenameResource(
const std::string& resource_id,
diff --git a/chrome/browser/drive/fake_drive_service_unittest.cc b/chrome/browser/drive/fake_drive_service_unittest.cc
index ec38d27..453a914 100644
--- a/chrome/browser/drive/fake_drive_service_unittest.cc
+++ b/chrome/browser/drive/fake_drive_service_unittest.cc
@@ -959,6 +959,8 @@
}
TEST_F(FakeDriveServiceTest, CopyResource) {
+ const base::Time::Exploded kModifiedDate = {2012, 7, 0, 19, 15, 59, 13, 123};
+
ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
"gdata/root_feed.json"));
ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
@@ -974,6 +976,7 @@
kResourceId,
kParentResourceId,
"new title",
+ base::Time::FromUTCExploded(kModifiedDate),
test_util::CreateCopyResultCallback(&error, &resource_entry));
base::RunLoop().RunUntilIdle();
@@ -982,6 +985,8 @@
// The copied entry should have the new resource ID and the title.
EXPECT_EQ(kResourceId + "_copied", resource_entry->resource_id());
EXPECT_EQ("new title", resource_entry->title());
+ EXPECT_EQ(base::Time::FromUTCExploded(kModifiedDate),
+ resource_entry->updated_time());
EXPECT_TRUE(HasParent(resource_entry->resource_id(), kParentResourceId));
// Should be incremented as a new hosted document was created.
EXPECT_EQ(old_largest_change_id + 1, fake_service_.largest_changestamp());
@@ -999,6 +1004,7 @@
kResourceId,
"folder:1_folder_resource_id",
"new title",
+ base::Time(),
test_util::CreateCopyResultCallback(&error, &resource_entry));
base::RunLoop().RunUntilIdle();
@@ -1020,6 +1026,7 @@
kResourceId,
std::string(),
"new title",
+ base::Time(),
test_util::CreateCopyResultCallback(&error, &resource_entry));
base::RunLoop().RunUntilIdle();
@@ -1046,6 +1053,7 @@
kResourceId,
"folder:1_folder_resource_id",
"new title",
+ base::Time(),
test_util::CreateCopyResultCallback(&error, &resource_entry));
base::RunLoop().RunUntilIdle();
@@ -1115,6 +1123,8 @@
}
TEST_F(FakeDriveServiceTest, MoveResource) {
+ const base::Time::Exploded kModifiedDate = {2012, 7, 0, 19, 15, 59, 13, 123};
+
ASSERT_TRUE(fake_service_.LoadResourceListForWapi(
"gdata/root_feed.json"));
ASSERT_TRUE(fake_service_.LoadAccountMetadataForWapi(
@@ -1130,6 +1140,7 @@
kResourceId,
kParentResourceId,
"new title",
+ base::Time::FromUTCExploded(kModifiedDate),
test_util::CreateCopyResultCallback(&error, &resource_entry));
base::RunLoop().RunUntilIdle();
@@ -1138,6 +1149,8 @@
// The copied entry should have the new resource ID and the title.
EXPECT_EQ(kResourceId, resource_entry->resource_id());
EXPECT_EQ("new title", resource_entry->title());
+ EXPECT_EQ(base::Time::FromUTCExploded(kModifiedDate),
+ resource_entry->updated_time());
EXPECT_TRUE(HasParent(kResourceId, kParentResourceId));
// Should be incremented as a new hosted document was created.
EXPECT_EQ(old_largest_change_id + 1, fake_service_.largest_changestamp());
@@ -1155,6 +1168,7 @@
kResourceId,
"folder:1_folder_resource_id",
"new title",
+ base::Time(),
test_util::CreateCopyResultCallback(&error, &resource_entry));
base::RunLoop().RunUntilIdle();
@@ -1180,6 +1194,7 @@
kResourceId,
std::string(),
"new title",
+ base::Time(),
test_util::CreateCopyResultCallback(&error, &resource_entry));
base::RunLoop().RunUntilIdle();
@@ -1206,6 +1221,7 @@
kResourceId,
"folder:1_folder_resource_id",
"new title",
+ base::Time(),
test_util::CreateCopyResultCallback(&error, &resource_entry));
base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/drive/gdata_wapi_service.cc b/chrome/browser/drive/gdata_wapi_service.cc
index 5acad45..c1fb7be 100644
--- a/chrome/browser/drive/gdata_wapi_service.cc
+++ b/chrome/browser/drive/gdata_wapi_service.cc
@@ -148,7 +148,7 @@
sender_->auth_service()->RemoveObserver(this);
}
-void GDataWapiService::Initialize() {
+void GDataWapiService::Initialize(const std::string& account_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
std::vector<std::string> scopes;
@@ -158,8 +158,10 @@
// Drive App scope is required for even WAPI v3 apps access.
scopes.push_back(util::kDriveAppsScope);
sender_.reset(new RequestSender(
- new AuthService(
- oauth2_token_service_, url_request_context_getter_, scopes),
+ new AuthService(oauth2_token_service_,
+ account_id,
+ url_request_context_getter_,
+ scopes),
url_request_context_getter_,
blocking_task_runner_.get(),
custom_user_agent_));
@@ -404,6 +406,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
@@ -435,6 +438,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
diff --git a/chrome/browser/drive/gdata_wapi_service.h b/chrome/browser/drive/gdata_wapi_service.h
index 5e80983..ecae566 100644
--- a/chrome/browser/drive/gdata_wapi_service.h
+++ b/chrome/browser/drive/gdata_wapi_service.h
@@ -58,7 +58,7 @@
virtual ~GDataWapiService();
// DriveServiceInterface Overrides
- virtual void Initialize() OVERRIDE;
+ virtual void Initialize(const std::string& account_id) OVERRIDE;
virtual void AddObserver(DriveServiceObserver* observer) OVERRIDE;
virtual void RemoveObserver(DriveServiceObserver* observer) OVERRIDE;
virtual bool CanSendRequest() const OVERRIDE;
@@ -116,6 +116,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
virtual google_apis::CancelCallback CopyHostedDocument(
const std::string& resource_id,
@@ -125,6 +126,7 @@
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
+ const base::Time& last_modified,
const google_apis::GetResourceEntryCallback& callback) OVERRIDE;
virtual google_apis::CancelCallback RenameResource(
const std::string& resource_id,
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index 2eda4bd..f1a0877 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -36,6 +36,10 @@
#include "third_party/re2/re2/re2.h"
#include "url/gurl.h"
+#if !defined(OS_ANDROID)
+#include "chrome/browser/extensions/activity_log/uma_policy.h"
+#endif
+
namespace constants = activity_log_constants;
namespace {
@@ -329,8 +333,9 @@
// Use GetInstance instead of directly creating an ActivityLog.
ActivityLog::ActivityLog(Profile* profile)
- : policy_(NULL),
- policy_type_(ActivityLogPolicy::POLICY_INVALID),
+ : database_policy_(NULL),
+ database_policy_type_(ActivityLogPolicy::POLICY_INVALID),
+ uma_policy_(NULL),
profile_(profile),
db_enabled_(false),
testing_mode_(false),
@@ -363,11 +368,21 @@
ExtensionSystem::Get(profile_)->ready().Post(
FROM_HERE,
base::Bind(&ActivityLog::InitInstallTracker, base::Unretained(this)));
- ChooseDefaultPolicy();
+
+// None of this should run on Android since the AL is behind ENABLE_EXTENSION
+// checks. However, UmaPolicy can't even compile on Android because it uses
+// BrowserList and related classes that aren't compiled for Android.
+#if !defined(OS_ANDROID)
+ if (!profile->IsOffTheRecord())
+ uma_policy_ = new UmaPolicy(profile_);
+#endif
+
+ ChooseDatabasePolicy();
}
-void ActivityLog::SetDefaultPolicy(ActivityLogPolicy::PolicyType policy_type) {
- if (policy_type == policy_type_)
+void ActivityLog::SetDatabasePolicy(
+ ActivityLogPolicy::PolicyType policy_type) {
+ if (database_policy_type_ == policy_type)
return;
if (!IsDatabaseEnabled() && !IsWatchdogAppActive())
return;
@@ -380,20 +395,20 @@
//
// However, changing policies at runtime is still not recommended, and
// likely only should be done for unit tests.
- if (policy_)
- policy_->Close();
+ if (database_policy_)
+ database_policy_->Close();
switch (policy_type) {
case ActivityLogPolicy::POLICY_FULLSTREAM:
- policy_ = new FullStreamUIPolicy(profile_);
+ database_policy_ = new FullStreamUIPolicy(profile_);
break;
case ActivityLogPolicy::POLICY_COUNTS:
- policy_ = new CountingPolicy(profile_);
+ database_policy_ = new CountingPolicy(profile_);
break;
default:
NOTREACHED();
}
- policy_type_ = policy_type;
+ database_policy_type_ = policy_type;
}
// SHUT DOWN. ------------------------------------------------------------------
@@ -403,8 +418,10 @@
}
ActivityLog::~ActivityLog() {
- if (policy_)
- policy_->Close();
+ if (uma_policy_)
+ uma_policy_->Close();
+ if (database_policy_)
+ database_policy_->Close();
}
// MAINTAIN STATUS. ------------------------------------------------------------
@@ -414,13 +431,13 @@
tracker_->AddObserver(this);
}
-void ActivityLog::ChooseDefaultPolicy() {
+void ActivityLog::ChooseDatabasePolicy() {
if (!(IsDatabaseEnabled() || IsWatchdogAppActive()))
return;
if (testing_mode_)
- SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
+ SetDatabasePolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
else
- SetDefaultPolicy(ActivityLogPolicy::POLICY_COUNTS);
+ SetDatabasePolicy(ActivityLogPolicy::POLICY_COUNTS);
}
bool ActivityLog::IsDatabaseEnabled() {
@@ -445,7 +462,7 @@
watchdog_app_active_ = true;
profile_->GetPrefs()->SetBoolean(prefs::kWatchdogExtensionActive, true);
}
- ChooseDefaultPolicy();
+ ChooseDatabasePolicy();
}
void ActivityLog::OnExtensionUnloaded(const Extension* extension) {
@@ -462,7 +479,7 @@
}
void ActivityLog::OnExtensionUninstalled(const Extension* extension) {
- if (!policy_)
+ if (!database_policy_)
return;
// If the extension has been uninstalled but not disabled, we delete the
// database.
@@ -472,7 +489,7 @@
DeleteDatabase();
}
} else {
- policy_->RemoveExtensionData(extension->id());
+ database_policy_->RemoveExtensionData(extension->id());
}
}
@@ -503,8 +520,10 @@
// mask out incognito URLs if appropriate.
ExtractUrls(action, profile_);
- if (IsDatabaseEnabled() && policy_)
- policy_->ProcessAction(action);
+ if (uma_policy_)
+ uma_policy_->ProcessAction(action);
+ if (IsDatabaseEnabled() && database_policy_)
+ database_policy_->ProcessAction(action);
if (IsWatchdogAppActive())
observers_->Notify(&Observer::OnExtensionActivity, action);
if (testing_mode_)
@@ -568,8 +587,8 @@
const int daysAgo,
const base::Callback
<void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) {
- if (policy_) {
- policy_->ReadFilteredData(
+ if (database_policy_) {
+ database_policy_->ReadFilteredData(
extension_id, type, api_name, page_url, arg_url, daysAgo, callback);
}
}
@@ -577,13 +596,13 @@
// DELETE ACTIONS. -------------------------------------------------------------
void ActivityLog::RemoveURLs(const std::vector<GURL>& restrict_urls) {
- if (!policy_)
+ if (!database_policy_)
return;
- policy_->RemoveURLs(restrict_urls);
+ database_policy_->RemoveURLs(restrict_urls);
}
void ActivityLog::RemoveURLs(const std::set<GURL>& restrict_urls) {
- if (!policy_)
+ if (!database_policy_)
return;
std::vector<GURL> urls;
@@ -591,7 +610,7 @@
it != restrict_urls.end(); ++it) {
urls.push_back(*it);
}
- policy_->RemoveURLs(urls);
+ database_policy_->RemoveURLs(urls);
}
void ActivityLog::RemoveURL(const GURL& url) {
@@ -603,9 +622,9 @@
}
void ActivityLog::DeleteDatabase() {
- if (!policy_)
+ if (!database_policy_)
return;
- policy_->DeleteDatabase();
+ database_policy_->DeleteDatabase();
}
} // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/activity_log.h b/chrome/browser/extensions/activity_log/activity_log.h
index 1869e7f..8c93e1a 100644
--- a/chrome/browser/extensions/activity_log/activity_log.h
+++ b/chrome/browser/extensions/activity_log/activity_log.h
@@ -150,21 +150,26 @@
// These methods are used to choose and set the most appropriate policy.
// Changing policies at runtime is not recommended, and likely only should be
// done for unit tests.
- void ChooseDefaultPolicy();
- void SetDefaultPolicy(ActivityLogPolicy::PolicyType policy_type);
+ void ChooseDatabasePolicy();
+ void SetDatabasePolicy(ActivityLogPolicy::PolicyType policy_type);
typedef ObserverListThreadSafe<Observer> ObserverList;
scoped_refptr<ObserverList> observers_;
- // The policy object takes care of data summarization, compression, and
- // logging. The policy object is owned by the ActivityLog, but this cannot
- // be a scoped_ptr since some cleanup work must happen on the database
- // thread. Calling policy_->Close() will free the object; see the comments
- // on the ActivityDatabase class for full details.
- ActivityLogPolicy* policy_;
+ // Policy objects are owned by the ActivityLog, but cannot be scoped_ptrs
+ // since they may need to do some cleanup work on the database thread.
+ // Calling policy->Close() will free the object; see the comments on the
+ // ActivityDatabase class for full details.
- // TODO(dbabic,felt) change this into a list of policy types later.
- ActivityLogPolicy::PolicyType policy_type_;
+ // The database policy object takes care of recording & looking up data:
+ // data summarization, compression, and logging. There should only be a
+ // database_policy_ if the Watchdog app is installed or flag is set.
+ ActivityLogDatabasePolicy* database_policy_;
+ ActivityLogPolicy::PolicyType database_policy_type_;
+
+ // The UMA policy is used for recording statistics about extension behavior.
+ // This policy is always in use, except for Incognito profiles.
+ ActivityLogPolicy* uma_policy_;
Profile* profile_;
bool db_enabled_; // Whether logging to disk is currently enabled.
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy.h b/chrome/browser/extensions/activity_log/activity_log_policy.h
index c97cb40..00ac27f 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy.h
+++ b/chrome/browser/extensions/activity_log/activity_log_policy.h
@@ -8,6 +8,7 @@
#include <map>
#include <set>
#include <string>
+#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -75,30 +76,6 @@
// state to memory every 5 min.
virtual void ProcessAction(scoped_refptr<Action> action) = 0;
- // Gets all actions that match the specified fields. URLs are treated like
- // prefixes; other fields are exact matches. Empty strings are not matched to
- // anything. For the date: 0 = today, 1 = yesterday, etc.; if the data is
- // negative, it will be treated as missing.
- virtual void ReadFilteredData(
- const std::string& extension_id,
- const Action::ActionType type,
- const std::string& api_name,
- const std::string& page_url,
- const std::string& arg_url,
- const int days_ago,
- const base::Callback
- <void(scoped_ptr<Action::ActionVector>)>& callback) = 0;
-
- // Clean the relevant URL data. The cleaning may need to be different for
- // different policies. If restrict_urls is empty then all URLs are removed.
- virtual void RemoveURLs(const std::vector<GURL>& restrict_urls) = 0;
-
- // Remove all rows relating to a given extension.
- virtual void RemoveExtensionData(const std::string& extension_id) = 0;
-
- // Deletes everything in the database.
- virtual void DeleteDatabase() = 0;
-
// For unit testing only.
void SetClockForTesting(scoped_ptr<base::Clock> clock);
@@ -182,6 +159,30 @@
// on the database thread.
virtual void Flush();
+ // Gets all actions that match the specified fields. URLs are treated like
+ // prefixes; other fields are exact matches. Empty strings are not matched to
+ // anything. For the date: 0 = today, 1 = yesterday, etc.; if the data is
+ // negative, it will be treated as missing.
+ virtual void ReadFilteredData(
+ const std::string& extension_id,
+ const Action::ActionType type,
+ const std::string& api_name,
+ const std::string& page_url,
+ const std::string& arg_url,
+ const int days_ago,
+ const base::Callback
+ <void(scoped_ptr<Action::ActionVector>)>& callback) = 0;
+
+ // Clean the relevant URL data. The cleaning may need to be different for
+ // different policies. If restrict_urls is empty then all URLs are removed.
+ virtual void RemoveURLs(const std::vector<GURL>& restrict_urls) = 0;
+
+ // Remove all rows relating to a given extension.
+ virtual void RemoveExtensionData(const std::string& extension_id) = 0;
+
+ // Deletes everything in the database.
+ virtual void DeleteDatabase() = 0;
+
protected:
// The Schedule methods dispatch the calls to the database on a
// separate thread.
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
index 3652d2e..d198069 100644
--- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -76,9 +76,9 @@
void SetPolicy(bool log_arguments) {
ActivityLog* activity_log = ActivityLog::GetInstance(profile());
if (log_arguments)
- activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
+ activity_log->SetDatabasePolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
else
- activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_COUNTS);
+ activity_log->SetDatabasePolicy(ActivityLogPolicy::POLICY_COUNTS);
}
bool GetDatabaseEnabled() {
@@ -110,13 +110,24 @@
static void RetrieveActions_ArgUrlExtraction(
scoped_ptr<std::vector<scoped_refptr<Action> > > i) {
- ASSERT_EQ(2U, i->size());
+ ASSERT_EQ(3U, i->size());
scoped_refptr<Action> action = i->at(0);
- ASSERT_EQ("[\"GET\",\"\\u003Carg_url\\u003E\"]",
+ ASSERT_EQ("XMLHttpRequest.open", action->api_name());
+ ASSERT_EQ("[\"POST\",\"\\u003Carg_url\\u003E\"]",
ActivityLogPolicy::Util::Serialize(action->args()));
- ASSERT_EQ("http://www.google.com/", action->arg_url().spec());
+ ASSERT_EQ("http://api.google.com/", action->arg_url().spec());
action = i->at(1);
+ ASSERT_EQ("XMLHttpRequest.open", action->api_name());
+ ASSERT_EQ("[\"POST\",\"/api/\"]",
+ ActivityLogPolicy::Util::Serialize(action->args()));
+ ASSERT_FALSE(action->arg_url().is_valid());
+ // TODO(mvrable): If we are able to resolve relative URLs, then the test
+ // case should produce:
+ // ASSERT_EQ("http://www.google.com/api/", action->arg_url().spec());
+
+ action = i->at(2);
+ ASSERT_EQ("windows.create", action->api_name());
ASSERT_EQ("[{\"url\":\"\\u003Carg_url\\u003E\"}]",
ActivityLogPolicy::Util::Serialize(action->args()));
ASSERT_EQ("http://www.google.co.uk/", action->arg_url().spec());
@@ -224,13 +235,25 @@
now,
Action::ACTION_DOM_ACCESS,
"XMLHttpRequest.open");
- action->mutable_args()->AppendString("GET");
- action->mutable_args()->AppendString("http://www.google.com/");
+ action->set_page_url(GURL("http://www.google.com/"));
+ action->mutable_args()->AppendString("POST");
+ action->mutable_args()->AppendString("http://api.google.com/");
+ activity_log->LogAction(action);
+
+ // Submit a DOM API call with a relative URL, which cannot (currently) be
+ // handled.
+ action = new Action(kExtensionId,
+ now - base::TimeDelta::FromSeconds(1),
+ Action::ACTION_DOM_ACCESS,
+ "XMLHttpRequest.open");
+ action->set_page_url(GURL("http://www.google.com/"));
+ action->mutable_args()->AppendString("POST");
+ action->mutable_args()->AppendString("/api/");
activity_log->LogAction(action);
// Submit an API call with an embedded URL.
action = new Action(kExtensionId,
- now - base::TimeDelta::FromSeconds(1),
+ now - base::TimeDelta::FromSeconds(2),
Action::ACTION_API_CALL,
"windows.create");
action->set_args(
diff --git a/chrome/browser/extensions/activity_log/counting_policy.cc b/chrome/browser/extensions/activity_log/counting_policy.cc
index 7286d09..fb9a0cb 100644
--- a/chrome/browser/extensions/activity_log/counting_policy.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy.cc
@@ -80,7 +80,6 @@
{Action::ACTION_CONTENT_SCRIPT, ""},
{Action::ACTION_DOM_ACCESS, "Document.createElement"},
{Action::ACTION_DOM_ACCESS, "Document.createElementNS"},
- {Action::ACTION_DOM_ACCESS, "XMLHttpRequest.open"},
};
// Columns in the main database table. See the file-level comment for a
diff --git a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
index 6315b8d..8d6fa70 100644
--- a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
@@ -10,6 +10,7 @@
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/test_timeouts.h"
#include "chrome/browser/extensions/activity_log/activity_log.h"
#include "chrome/browser/extensions/activity_log/counting_policy.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -73,7 +74,7 @@
// A wrapper function for CheckReadFilteredData, so that we don't need to
// enter empty string values for parameters we don't care about.
void CheckReadData(
- ActivityLogPolicy* policy,
+ ActivityLogDatabasePolicy* policy,
const std::string& extension_id,
int day,
const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) {
@@ -84,7 +85,7 @@
// A helper function to call ReadFilteredData on a policy object and wait for
// the results to be processed.
void CheckReadFilteredData(
- ActivityLogPolicy* policy,
+ ActivityLogDatabasePolicy* policy,
const std::string& extension_id,
const Action::ActionType type,
const std::string& api_name,
@@ -106,12 +107,12 @@
checker,
base::MessageLoop::current()->QuitClosure()));
- // Set up a timeout that will trigger after 8 seconds; if we haven't
- // received any results by then assume that the test is broken.
+ // Set up a timeout for receiving results; if we haven't received anything
+ // when the timeout triggers then assume that the test is broken.
base::CancelableClosure timeout(
base::Bind(&CountingPolicyTest::TimeoutCallback));
base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(8));
+ FROM_HERE, timeout.callback(), TestTimeouts::action_timeout());
// Wait for results; either the checker or the timeout callbacks should
// cause the main loop to exit.
@@ -303,7 +304,7 @@
};
TEST_F(CountingPolicyTest, Construct) {
- ActivityLogPolicy* policy = new CountingPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new CountingPolicy(profile_.get());
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
@@ -323,7 +324,7 @@
}
TEST_F(CountingPolicyTest, LogWithStrippedArguments) {
- ActivityLogPolicy* policy = new CountingPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new CountingPolicy(profile_.get());
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
@@ -466,7 +467,7 @@
}
TEST_F(CountingPolicyTest, LogAndFetchFilteredActions) {
- ActivityLogPolicy* policy = new CountingPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new CountingPolicy(profile_.get());
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
@@ -809,7 +810,7 @@
}
TEST_F(CountingPolicyTest, RemoveAllURLs) {
- ActivityLogPolicy* policy = new CountingPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new CountingPolicy(profile_.get());
// Use a mock clock to ensure that events are not recorded on the wrong day
// when the test is run close to local midnight.
@@ -851,7 +852,7 @@
}
TEST_F(CountingPolicyTest, RemoveSpecificURLs) {
- ActivityLogPolicy* policy = new CountingPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new CountingPolicy(profile_.get());
// Use a mock clock to ensure that events are not recorded on the wrong day
// when the test is run close to local midnight.
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 37dec65..19713ea 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -9,6 +9,7 @@
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/test_timeouts.h"
#include "chrome/browser/extensions/activity_log/activity_log.h"
#include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -64,7 +65,7 @@
// A wrapper function for CheckReadFilteredData, so that we don't need to
// enter empty string values for parameters we don't care about.
void CheckReadData(
- ActivityLogPolicy* policy,
+ ActivityLogDatabasePolicy* policy,
const std::string& extension_id,
int day,
const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) {
@@ -75,7 +76,7 @@
// A helper function to call ReadFilteredData on a policy object and wait for
// the results to be processed.
void CheckReadFilteredData(
- ActivityLogPolicy* policy,
+ ActivityLogDatabasePolicy* policy,
const std::string& extension_id,
const Action::ActionType type,
const std::string& api_name,
@@ -97,12 +98,12 @@
checker,
base::MessageLoop::current()->QuitClosure()));
- // Set up a timeout that will trigger after 8 seconds; if we haven't
- // received any results by then assume that the test is broken.
+ // Set up a timeout for receiving results; if we haven't received anything
+ // when the timeout triggers then assume that the test is broken.
base::CancelableClosure timeout(
base::Bind(&FullStreamUIPolicyTest::TimeoutCallback));
base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(8));
+ FROM_HERE, timeout.callback(), TestTimeouts::action_timeout());
// Wait for results; either the checker or the timeout callbacks should
// cause the main loop to exit.
@@ -235,7 +236,7 @@
};
TEST_F(FullStreamUIPolicyTest, Construct) {
- ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get());
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
@@ -255,7 +256,7 @@
}
TEST_F(FullStreamUIPolicyTest, LogAndFetchActions) {
- ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get());
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
@@ -292,7 +293,7 @@
}
TEST_F(FullStreamUIPolicyTest, LogAndFetchFilteredActions) {
- ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get());
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
@@ -389,7 +390,7 @@
}
TEST_F(FullStreamUIPolicyTest, LogWithArguments) {
- ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get());
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
@@ -417,7 +418,7 @@
}
TEST_F(FullStreamUIPolicyTest, GetTodaysActions) {
- ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get());
// Use a mock clock to ensure that events are not recorded on the wrong day
// when the test is run close to local midnight. Note: Ownership is passed
@@ -465,7 +466,7 @@
// Check that we can read back less recent actions in the db.
TEST_F(FullStreamUIPolicyTest, GetOlderActions) {
- ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get());
// Use a mock clock to ensure that events are not recorded on the wrong day
// when the test is run close to local midnight.
@@ -517,7 +518,7 @@
}
TEST_F(FullStreamUIPolicyTest, RemoveAllURLs) {
- ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get());
// Use a mock clock to ensure that events are not recorded on the wrong day
// when the test is run close to local midnight.
@@ -559,7 +560,7 @@
}
TEST_F(FullStreamUIPolicyTest, RemoveSpecificURLs) {
- ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get());
// Use a mock clock to ensure that events are not recorded on the wrong day
// when the test is run close to local midnight.
@@ -725,7 +726,7 @@
}
TEST_F(FullStreamUIPolicyTest, DeleteActions) {
- ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
+ ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get());
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
diff --git a/chrome/browser/extensions/activity_log/uma_policy.cc b/chrome/browser/extensions/activity_log/uma_policy.cc
new file mode 100644
index 0000000..0e4e917
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/uma_policy.cc
@@ -0,0 +1,363 @@
+// Copyright 2013 The Chromium 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/activity_log/uma_policy.h"
+
+#include "base/metrics/histogram.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
+#include "chrome/browser/sessions/session_id.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/extensions/dom_action_types.h"
+#include "content/public/browser/web_contents.h"
+
+namespace {
+
+// For convenience.
+const int kNoStatus = extensions::UmaPolicy::NONE;
+const int kContentScript = 1 << extensions::UmaPolicy::CONTENT_SCRIPT;
+const int kReadDom = 1 << extensions::UmaPolicy::READ_DOM;
+const int kModifiedDom = 1 << extensions::UmaPolicy::MODIFIED_DOM;
+const int kDomMethod = 1 << extensions::UmaPolicy::DOM_METHOD;
+const int kDocumentWrite = 1 << extensions::UmaPolicy::DOCUMENT_WRITE;
+const int kInnerHtml = 1 << extensions::UmaPolicy::INNER_HTML;
+const int kCreatedScript = 1 << extensions::UmaPolicy::CREATED_SCRIPT;
+const int kCreatedIframe = 1 << extensions::UmaPolicy::CREATED_IFRAME;
+const int kCreatedDiv = 1 << extensions::UmaPolicy::CREATED_DIV;
+const int kCreatedLink = 1 << extensions::UmaPolicy::CREATED_LINK;
+const int kCreatedInput = 1 << extensions::UmaPolicy::CREATED_INPUT;
+const int kCreatedEmbed = 1 << extensions::UmaPolicy::CREATED_EMBED;
+const int kCreatedObject = 1 << extensions::UmaPolicy::CREATED_OBJECT;
+
+} // namespace
+
+namespace extensions {
+
+// Class constants, also used in testing. --------------------------------------
+
+const char UmaPolicy::kNumberOfTabs[] = "num_tabs";
+const size_t UmaPolicy::kMaxTabsTracked = 50;
+
+// Setup and shutdown. ---------------------------------------------------------
+
+UmaPolicy::UmaPolicy(Profile* profile)
+ : ActivityLogPolicy(profile), profile_(profile) {
+ DCHECK(!profile->IsOffTheRecord());
+ BrowserList::AddObserver(this);
+}
+
+UmaPolicy::~UmaPolicy() {
+ BrowserList::RemoveObserver(this);
+}
+
+// Unlike the other policies, UmaPolicy can commit suicide directly because it
+// doesn't have a dependency on a database.
+void UmaPolicy::Close() {
+ delete this;
+}
+
+// Process actions. ------------------------------------------------------------
+
+void UmaPolicy::ProcessAction(scoped_refptr<Action> action) {
+ if (!action->page_url().is_valid() && !action->arg_url().is_valid())
+ return;
+ if (action->page_incognito() || action->arg_incognito())
+ return;
+ std::string url;
+ int status = MatchActionToStatus(action);
+ if (action->page_url().is_valid()) {
+ url = CleanURL(action->page_url());
+ } else if (status & kContentScript) {
+ // This is for the tabs.executeScript case.
+ url = CleanURL(action->arg_url());
+ }
+ if (url.empty())
+ return;
+
+ SiteMap::iterator site_lookup = url_status_.find(url);
+ if (site_lookup != url_status_.end())
+ site_lookup->second[action->extension_id()] |= status;
+}
+
+int UmaPolicy::MatchActionToStatus(scoped_refptr<Action> action) {
+ if (action->action_type() == Action::ACTION_CONTENT_SCRIPT) {
+ return kContentScript;
+ } else if (action->action_type() == Action::ACTION_API_CALL &&
+ action->api_name() == "tabs.executeScript") {
+ return kContentScript;
+ } else if (action->action_type() != Action::ACTION_DOM_ACCESS) {
+ return kNoStatus;
+ }
+
+ int dom_verb;
+ if (!action->other() ||
+ !action->other()->GetIntegerWithoutPathExpansion(
+ activity_log_constants::kActionDomVerb, &dom_verb)) {
+ return kNoStatus;
+ }
+
+ int ret_bit = kNoStatus;
+ DomActionType::Type dom_type = static_cast<DomActionType::Type>(dom_verb);
+ if (dom_type == DomActionType::GETTER)
+ return kReadDom;
+ if (dom_type == DomActionType::SETTER) {
+ ret_bit |= kModifiedDom;
+ } else if (dom_type == DomActionType::METHOD) {
+ ret_bit |= kDomMethod;
+ } else {
+ return kNoStatus;
+ }
+
+ if (action->api_name() == "HTMLDocument.write" ||
+ action->api_name() == "HTMLDocument.writeln") {
+ ret_bit |= kDocumentWrite;
+ } else if (action->api_name() == "HTMLElement.innerHTML") {
+ ret_bit |= kInnerHtml;
+ } else if (action->api_name() == "Document.createElement") {
+ std::string arg;
+ action->args()->GetString(0, &arg);
+ if (arg == "script") {
+ ret_bit |= kCreatedScript;
+ } else if (arg == "iframe") {
+ ret_bit |= kCreatedIframe;
+ } else if (arg == "div") {
+ ret_bit |= kCreatedDiv;
+ } else if (arg == "a") {
+ ret_bit |= kCreatedLink;
+ } else if (arg == "input") {
+ ret_bit |= kCreatedInput;
+ } else if (arg == "embed") {
+ ret_bit |= kCreatedEmbed;
+ } else if (arg == "object") {
+ ret_bit |= kCreatedObject;
+ }
+ }
+ return ret_bit;
+}
+
+void UmaPolicy::HistogramOnClose(const std::string& url) {
+ // Let's try to avoid histogramming useless URLs.
+ if (url == "about:blank" || url.empty() || url == "chrome://newtab/")
+ return;
+
+ int statuses[MAX_STATUS-1];
+ std::memset(statuses, 0, sizeof(statuses));
+
+ SiteMap::iterator site_lookup = url_status_.find(url);
+ ExtensionMap exts = site_lookup->second;
+ ExtensionMap::iterator ext_iter;
+ for (ext_iter = exts.begin(); ext_iter != exts.end(); ++ext_iter) {
+ if (ext_iter->first == kNumberOfTabs)
+ continue;
+ for (int i = NONE + 1; i < MAX_STATUS; ++i) {
+ if (ext_iter->second & (1 << i))
+ statuses[i-1]++;
+ }
+ }
+
+ std::string prefix = "ExtensionActivity.";
+ if (GURL(url).host() != "www.google.com") {
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CONTENT_SCRIPT),
+ statuses[CONTENT_SCRIPT - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(READ_DOM),
+ statuses[READ_DOM - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(MODIFIED_DOM),
+ statuses[MODIFIED_DOM - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(DOM_METHOD),
+ statuses[DOM_METHOD - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(DOCUMENT_WRITE),
+ statuses[DOCUMENT_WRITE - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(INNER_HTML),
+ statuses[INNER_HTML - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_SCRIPT),
+ statuses[CREATED_SCRIPT - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_IFRAME),
+ statuses[CREATED_IFRAME - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_DIV),
+ statuses[CREATED_DIV - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_LINK),
+ statuses[CREATED_LINK - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_INPUT),
+ statuses[CREATED_INPUT - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_EMBED),
+ statuses[CREATED_EMBED - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_OBJECT),
+ statuses[CREATED_OBJECT - 1]);
+ } else {
+ prefix += "Google.";
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CONTENT_SCRIPT),
+ statuses[CONTENT_SCRIPT - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(READ_DOM),
+ statuses[READ_DOM - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(MODIFIED_DOM),
+ statuses[MODIFIED_DOM - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(DOM_METHOD),
+ statuses[DOM_METHOD - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(DOCUMENT_WRITE),
+ statuses[DOCUMENT_WRITE - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(INNER_HTML),
+ statuses[INNER_HTML - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_SCRIPT),
+ statuses[CREATED_SCRIPT - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_IFRAME),
+ statuses[CREATED_IFRAME - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_DIV),
+ statuses[CREATED_DIV - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_LINK),
+ statuses[CREATED_LINK - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_INPUT),
+ statuses[CREATED_INPUT - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_EMBED),
+ statuses[CREATED_EMBED - 1]);
+ UMA_HISTOGRAM_COUNTS_100(prefix + GetHistogramName(CREATED_OBJECT),
+ statuses[CREATED_OBJECT - 1]);
+ }
+}
+
+// Handle tab tracking. --------------------------------------------------------
+
+void UmaPolicy::OnBrowserAdded(Browser* browser) {
+ if (!profile_->IsSameProfile(browser->profile()))
+ return;
+ browser->tab_strip_model()->AddObserver(this);
+}
+
+void UmaPolicy::OnBrowserRemoved(Browser* browser) {
+ if (!profile_->IsSameProfile(browser->profile()))
+ return;
+ browser->tab_strip_model()->RemoveObserver(this);
+}
+
+// Use the value from SessionID::IdForTab, *not* |index|. |index| will be
+// duplicated across tabs in a session, whereas IdForTab uniquely identifies
+// each tab.
+void UmaPolicy::TabChangedAt(content::WebContents* contents,
+ int index,
+ TabChangeType change_type) {
+ if (change_type != TabStripModelObserver::LOADING_ONLY)
+ return;
+ if (!contents)
+ return;
+
+ std::string url = CleanURL(contents->GetLastCommittedURL());
+ int32 tab_id = SessionID::IdForTab(contents);
+
+ std::map<int32, std::string>::iterator tab_it = tab_list_.find(tab_id);
+
+ // Ignore tabs that haven't changed status.
+ if (tab_it != tab_list_.end() && tab_it->second == url)
+ return;
+
+ // Is this an existing tab whose URL has changed.
+ if (tab_it != tab_list_.end()) {
+ CleanupClosedPage(tab_it->second);
+ tab_list_.erase(tab_id);
+ }
+
+ // Check that tab_list_ isn't over the kMaxTabsTracked budget.
+ if (tab_list_.size() >= kMaxTabsTracked)
+ return;
+
+ // Set up the new entries.
+ tab_list_[tab_id] = url;
+ SetupOpenedPage(url);
+}
+
+// Use the value from SessionID::IdForTab, *not* |index|. |index| will be
+// duplicated across tabs in a session, whereas IdForTab uniquely identifies
+// each tab.
+void UmaPolicy::TabClosingAt(TabStripModel* tab_strip_model,
+ content::WebContents* contents,
+ int index) {
+ if (!contents)
+ return;
+ std::string url = CleanURL(contents->GetLastCommittedURL());
+ int32 tab_id = SessionID::IdForTab(contents);
+ std::map<int, std::string>::iterator tab_it = tab_list_.find(tab_id);
+ if (tab_it != tab_list_.end())
+ tab_list_.erase(tab_id);
+
+ CleanupClosedPage(url);
+}
+
+void UmaPolicy::SetupOpenedPage(const std::string& url) {
+ url_status_[url][kNumberOfTabs]++;
+}
+
+void UmaPolicy::CleanupClosedPage(const std::string& url) {
+ SiteMap::iterator old_site_lookup = url_status_.find(url);
+ if (old_site_lookup == url_status_.end())
+ return;
+ old_site_lookup->second[kNumberOfTabs]--;
+ if (old_site_lookup->second[kNumberOfTabs] == 0) {
+ HistogramOnClose(url);
+ url_status_.erase(url);
+ }
+}
+
+// Helpers. --------------------------------------------------------------------
+
+// We don't want to treat # ref navigations as if they were new pageloads.
+// So we get rid of the ref if it has it.
+// We convert to a string in the hopes that this is faster than Replacements.
+std::string UmaPolicy::CleanURL(const GURL& gurl) {
+ if (gurl.spec().empty())
+ return GURL("about:blank").spec();
+ if (!gurl.is_valid())
+ return gurl.spec();
+ if (!gurl.has_ref())
+ return gurl.spec();
+ std::string port = "";
+ if (gurl.has_port())
+ port = ":" + gurl.port();
+ std::string query = "";
+ if (gurl.has_query())
+ query = "?" + gurl.query();
+ return base::StringPrintf("%s://%s%s%s%s",
+ gurl.scheme().c_str(),
+ gurl.host().c_str(),
+ port.c_str(),
+ gurl.path().c_str(),
+ query.c_str());
+}
+
+const char* UmaPolicy::GetHistogramName(PageStatus status) {
+ switch (status) {
+ case CONTENT_SCRIPT:
+ return "ContentScript";
+ case READ_DOM:
+ return "ReadDom";
+ case MODIFIED_DOM:
+ return "ModifiedDom";
+ case DOM_METHOD:
+ return "InvokedDomMethod";
+ case DOCUMENT_WRITE:
+ return "DocumentWrite";
+ case INNER_HTML:
+ return "InnerHtml";
+ case CREATED_SCRIPT:
+ return "CreatedScript";
+ case CREATED_IFRAME:
+ return "CreatedIframe";
+ case CREATED_DIV:
+ return "CreatedDiv";
+ case CREATED_LINK:
+ return "CreatedLink";
+ case CREATED_INPUT:
+ return "CreatedInput";
+ case CREATED_EMBED:
+ return "CreatedEmbed";
+ case CREATED_OBJECT:
+ return "CreatedObject";
+ case NONE:
+ case MAX_STATUS:
+ default:
+ NOTREACHED();
+ return "";
+ }
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/uma_policy.h b/chrome/browser/extensions/activity_log/uma_policy.h
new file mode 100644
index 0000000..71794f2
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/uma_policy.h
@@ -0,0 +1,123 @@
+// Copyright 2013 The Chromium 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_ACTIVITY_LOG_UMA_POLICY_H_
+#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_UMA_POLICY_H_
+
+#include <map>
+#include <string>
+
+#include "chrome/browser/extensions/activity_log/activity_log_policy.h"
+
+#include "chrome/browser/ui/browser_list_observer.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
+#include "url/gurl.h"
+
+namespace extensions {
+
+// The UmaPolicy keeps track of how many extensions have read from or modified
+// a given pageload. UmaPolicy records to a histogram when a given tab is
+// closed. Caveats:
+// * If multiple tabs are open for the same URL at the same time, UmaPolicy
+// treats them as if they are the same.
+// * UmaPolicy does not record statistics for incognito tabs. (For privacy.)
+// * If the number of tabs open exceeds 50, UmaPolicy stops recording stats
+// for tabs 51+. (For memory.)
+// * UmaPolicy only handles top frames; stats are not recorded for iframes.
+class UmaPolicy : public ActivityLogPolicy,
+ public TabStripModelObserver,
+ public chrome::BrowserListObserver {
+ public:
+ // The possible status bits for a pageload. If you alter this, make sure to
+ // also update GetHistogramName.
+ enum PageStatus {
+ NONE = 0,
+ CONTENT_SCRIPT = 1,
+ READ_DOM,
+ MODIFIED_DOM,
+ DOM_METHOD,
+ DOCUMENT_WRITE,
+ INNER_HTML,
+ CREATED_SCRIPT,
+ CREATED_IFRAME,
+ CREATED_DIV,
+ CREATED_LINK,
+ CREATED_INPUT,
+ CREATED_EMBED,
+ CREATED_OBJECT,
+ MAX_STATUS // Insert new page statuses right before this one.
+ };
+
+ explicit UmaPolicy(Profile* profile);
+
+ virtual void ProcessAction(scoped_refptr<Action> action) OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ // Gets the histogram name associated with each PageStatus.
+ static const char* GetHistogramName(PageStatus status);
+
+ protected:
+ // Run when Close() is called.
+ virtual ~UmaPolicy();
+
+ private:
+ // Used as a special key in the ExtensionMap.
+ static const char kNumberOfTabs[];
+
+ // The max number of tabs we track at a time.
+ static const size_t kMaxTabsTracked;
+
+ typedef std::map<std::string, int> ExtensionMap;
+ typedef std::map<std::string, ExtensionMap> SiteMap;
+
+ // BrowserListObserver
+ virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
+ virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
+
+ // TabStripModelObserver
+ // Fired when a page loads, either as a new tab or replacing the contents of
+ // an older tab.
+ virtual void TabChangedAt(content::WebContents* contents,
+ int index,
+ TabChangeType change_type) OVERRIDE;
+ // Fired when a tab closes.
+ virtual void TabClosingAt(TabStripModel* tab_strip_model,
+ content::WebContents* contents,
+ int index) OVERRIDE;
+
+ // Assign a status bitmask based on the action's properties.
+ int MatchActionToStatus(scoped_refptr<Action> action);
+
+ // When a page is opened, add it to the SiteMap url_status_.
+ void SetupOpenedPage(const std::string& url);
+
+ // When a page is closing, remove it from the SiteMap url_status_.
+ void CleanupClosedPage(const std::string& url);
+
+ // When a page is closing, save statistics about the page to histograms.
+ void HistogramOnClose(const std::string& url);
+
+ // Standardizes the way URLs are treated.
+ static std::string CleanURL(const GURL& gurl);
+
+ // Used by UmaPolicyTest.ProcessActionTest.
+ SiteMap url_status() { return url_status_; }
+
+ Profile* profile_;
+
+ // URL -> extension id -> page status.
+ SiteMap url_status_;
+
+ // tab index -> URL.
+ std::map<int32, std::string> tab_list_;
+
+ FRIEND_TEST_ALL_PREFIXES(UmaPolicyTest, CleanURLTest);
+ FRIEND_TEST_ALL_PREFIXES(UmaPolicyTest, MatchActionToStatusTest);
+ FRIEND_TEST_ALL_PREFIXES(UmaPolicyTest, ProcessActionTest);
+ FRIEND_TEST_ALL_PREFIXES(UmaPolicyTest, SiteUrlTest);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_UMA_POLICY_H_
diff --git a/chrome/browser/extensions/activity_log/uma_policy_browsertest.cc b/chrome/browser/extensions/activity_log/uma_policy_browsertest.cc
new file mode 100644
index 0000000..dd1d934
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/uma_policy_browsertest.cc
@@ -0,0 +1,302 @@
+// Copyright 2013 The Chromium 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/metrics/histogram.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/extensions/activity_log/uma_policy.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/test_extension_dir.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/common/extensions/extension_file_util.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "extensions/common/manifest_constants.h"
+#include "net/dns/mock_host_resolver.h"
+
+using extensions::UmaPolicy;
+
+const char* kGooglePrefix = "ExtensionActivity.Google";
+const char* kNonGooglePrefix = "ExtensionActivity";
+
+// These tests need to ensure that all of the extension JavaScript completes
+// before the histograms are checked. To accomplish this, the test relies on
+// some JavaScript in chrome/test/data/extensions/api_test/uma_policy/:
+// * When the test navigates to opener.com, opener.js will use window.open() to
+// pop open a new window with the appropriate URL for the test case. This
+// ensures that the testing framework never reuses a window that's still
+// running a previous test case.
+// * The test extension code in content_script.js tells background.js when it's
+// done. When it's finished, background.js closes the blocker.com window. So
+// blocker.com will remain open (and block) until the tests complete.
+class ActivityLogUmaPolicyTest : public ExtensionApiTest {
+};
+
+std::string ConcatNames(const char* prefix, int status_num) {
+ return base::StringPrintf(
+ "%s.%s",
+ prefix,
+ extensions::UmaPolicy::GetHistogramName(
+ static_cast<extensions::UmaPolicy::PageStatus>(status_num)));
+}
+
+// TODO(felt): These are disabled due to crbug.com/294500, since they fail
+// due to a blink bug. The fix went in to Blink on Thursday and should roll
+// on Monday 9/23.
+// These are all sequential navigations, so they should each be logged
+// independently.
+IN_PROC_BROWSER_TEST_F(ActivityLogUmaPolicyTest, DISABLED_SequentialNavs) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ StartEmbeddedTestServer();
+
+ const extensions::Extension* ext =
+ LoadExtension(test_data_dir_.AppendASCII("uma_policy"));
+ ASSERT_TRUE(ext);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#google"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#google?q=a"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#google?q=b"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#cnn?q=a"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#cnn?q=b"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+
+ for (int i = UmaPolicy::NONE + 1; i < UmaPolicy::MAX_STATUS - 2; ++i) {
+ base::HistogramBase* google_histogram = base::Histogram::FactoryGet(
+ ConcatNames(kGooglePrefix, i),
+ 1, 100, 50, base::HistogramBase::kNoFlags);
+ scoped_ptr<base::HistogramSamples> google_samples =
+ google_histogram->SnapshotSamples();
+ EXPECT_EQ(3, google_samples->TotalCount());
+ EXPECT_EQ(3, google_samples->GetCount(1));
+
+ base::HistogramBase* cnn_histogram = base::Histogram::FactoryGet(
+ ConcatNames(kNonGooglePrefix, i),
+ 1, 100, 50, base::HistogramBase::kNoFlags);
+ scoped_ptr<base::HistogramSamples> cnn_samples =
+ cnn_histogram->SnapshotSamples();
+ if (ConcatNames(kNonGooglePrefix, i) != "ExtensionActivity.ContentScript" &&
+ ConcatNames(kNonGooglePrefix, i) != "ExtensionActivity.ReadDom") {
+ // There's a content script on opener.com that checks the location.
+ // The test is not set up to accurately record opener.com histograms due
+ // to the possibility of race conditions in the testing framework, so we
+ // can't check those values.
+ EXPECT_EQ(2, cnn_samples->GetCount(1));
+ }
+ }
+}
+
+// Two windows are open at once with the same google.com TLD.
+// However, they should be treated separately because they have different URLs.
+IN_PROC_BROWSER_TEST_F(
+ ActivityLogUmaPolicyTest, DISABLED_ParallelDistinctNavs) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ StartEmbeddedTestServer();
+
+ const extensions::Extension* ext =
+ LoadExtension(test_data_dir_.AppendASCII("uma_policy"));
+ ASSERT_TRUE(ext);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#google?p=a"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#google?p=b"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+
+ for (int i = UmaPolicy::NONE + 1; i < UmaPolicy::MAX_STATUS - 2; ++i) {
+ base::HistogramBase* google_histogram = base::Histogram::FactoryGet(
+ ConcatNames(kGooglePrefix, i),
+ 1, 100, 50, base::HistogramBase::kNoFlags);
+ scoped_ptr<base::HistogramSamples> google_samples =
+ google_histogram->SnapshotSamples();
+ EXPECT_EQ(2, google_samples->GetCount(1));
+ }
+}
+
+// Two windows are open at once with the same Google URLs.
+// They should be treated the same.
+IN_PROC_BROWSER_TEST_F(ActivityLogUmaPolicyTest, DISABLED_Google_ParallelSame) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ StartEmbeddedTestServer();
+
+ const extensions::Extension* ext =
+ LoadExtension(test_data_dir_.AppendASCII("uma_policy"));
+ ASSERT_TRUE(ext);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#googlea"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#googleb"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+
+ for (int i = UmaPolicy::NONE + 1; i < UmaPolicy::MAX_STATUS - 2; ++i) {
+ base::HistogramBase* google_histogram = base::Histogram::FactoryGet(
+ ConcatNames(kGooglePrefix, i),
+ 1, 100, 50, base::HistogramBase::kNoFlags);
+ scoped_ptr<base::HistogramSamples> google_samples =
+ google_histogram->SnapshotSamples();
+ EXPECT_EQ(1, google_samples->GetCount(1));
+ }
+}
+
+// Two windows are open at once with the same non-Google URLs.
+// They should be treated the same.
+IN_PROC_BROWSER_TEST_F(ActivityLogUmaPolicyTest,
+ DISABLED_NonGoogle_ParallelSame) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ StartEmbeddedTestServer();
+
+ const extensions::Extension* ext =
+ LoadExtension(test_data_dir_.AppendASCII("uma_policy"));
+ ASSERT_TRUE(ext);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#cnna"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#cnnb"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+
+ for (int i = UmaPolicy::NONE + 1; i < UmaPolicy::MAX_STATUS - 2; ++i) {
+ base::HistogramBase* cnn_histogram = base::Histogram::FactoryGet(
+ ConcatNames(kNonGooglePrefix, i),
+ 1, 100, 50, base::HistogramBase::kNoFlags);
+ scoped_ptr<base::HistogramSamples> cnn_samples =
+ cnn_histogram->SnapshotSamples();
+ if (ConcatNames(kNonGooglePrefix, i) != "ExtensionActivity.ContentScript" &&
+ ConcatNames(kNonGooglePrefix, i) != "ExtensionActivity.ReadDom") {
+ // There's a content script on opener.com that checks the location.
+ // The test is not set up to accurately record opener.com histograms due
+ // to the possibility of race conditions in the testing framework, so we
+ // can't check those values.
+ EXPECT_EQ(1, cnn_samples->GetCount(1));
+ }
+ }
+}
+
+// This runs with multiple extensions installed.
+IN_PROC_BROWSER_TEST_F(ActivityLogUmaPolicyTest, DISABLED_MultipleExtensions) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ StartEmbeddedTestServer();
+
+ const extensions::Extension* ext =
+ LoadExtension(test_data_dir_.AppendASCII("uma_policy"));
+ ASSERT_TRUE(ext);
+
+ const char* script2 =
+ "document.createElement('script');"
+ "document.createElement('iframe');"
+ "document.createElement('div');"
+ "document.createElement('embed');"
+ "document.createElement('object');";
+
+ const char* manifest =
+ "{"
+ " \"name\": \"Activity Log UMA Policy Test Extension\","
+ " \"version\": \"0.%s\","
+ " \"description\": \"Testing the histogramming\","
+ " \"content_scripts\": ["
+ " {"
+ " \"matches\": "
+ " [\"http://www.google.com/*\","
+ " \"http://www.cnn.com/*\"],"
+ " \"js\": [\"content_script.js\"]"
+ " }"
+ " ],"
+ " \"manifest_version\": 2"
+ "}";
+
+ extensions::TestExtensionDir dir2;
+ dir2.WriteManifest(base::StringPrintf(manifest, "2"));
+ dir2.WriteFile(FILE_PATH_LITERAL("content_script.js"), script2);
+ LoadExtension(dir2.unpacked_path());
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#google"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), GURL("http://www.opener.com/#cnn?q=b"), NEW_WINDOW,
+ ui_test_utils::BROWSER_TEST_NONE);
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
+ browser(), GURL("http://www.blocker.com"), 2);
+
+ const char* subset_one[] = {
+ "CreatedLink",
+ "InnerHtml",
+ "DocumentWrite"
+ };
+
+ const char* subset_two[] = {
+ "ContentScript",
+ "CreatedScript",
+ "CreatedIframe",
+ "CreatedDiv",
+ "CreatedEmbed",
+ "CreatedObject",
+ "InvokedDomMethod"
+ };
+
+ // These were only touched by one of the scripts.
+ for (size_t i = 0; i < arraysize(subset_one); ++i) {
+ base::HistogramBase* google_histogram = base::Histogram::FactoryGet(
+ std::string(kGooglePrefix) + "." + std::string(subset_one[i]),
+ 1, 100, 50, base::HistogramBase::kNoFlags);
+ scoped_ptr<base::HistogramSamples> google_samples =
+ google_histogram->SnapshotSamples();
+ EXPECT_EQ(1, google_samples->GetCount(1));
+
+ base::HistogramBase* cnn_histogram = base::Histogram::FactoryGet(
+ std::string(kNonGooglePrefix) + "." + std::string(subset_one[i]),
+ 1, 100, 50, base::HistogramBase::kNoFlags);
+ scoped_ptr<base::HistogramSamples> cnn_samples =
+ cnn_histogram->SnapshotSamples();
+ EXPECT_EQ(1, cnn_samples->GetCount(1));
+ }
+
+ // These were touched by both scripts.
+ for (size_t i = 0; i < arraysize(subset_two); ++i) {
+ base::HistogramBase* google_histogram = base::Histogram::FactoryGet(
+ std::string(kGooglePrefix) + "." + std::string(subset_two[i]),
+ 1, 100, 50, base::HistogramBase::kNoFlags);
+ scoped_ptr<base::HistogramSamples> google_samples =
+ google_histogram->SnapshotSamples();
+ EXPECT_EQ(1, google_samples->GetCount(2));
+
+ base::HistogramBase* cnn_histogram = base::Histogram::FactoryGet(
+ std::string(kNonGooglePrefix) + "." + std::string(subset_two[i]),
+ 1, 100, 50, base::HistogramBase::kNoFlags);
+ scoped_ptr<base::HistogramSamples> cnn_samples =
+ cnn_histogram->SnapshotSamples();
+ EXPECT_EQ(1, cnn_samples->GetCount(2));
+ }
+
+}
diff --git a/chrome/browser/extensions/activity_log/uma_policy_unittest.cc b/chrome/browser/extensions/activity_log/uma_policy_unittest.cc
new file mode 100644
index 0000000..3fb421a
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/uma_policy_unittest.cc
@@ -0,0 +1,225 @@
+// Copyright 2013 The Chromium 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/time/time.h"
+#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
+#include "chrome/browser/extensions/activity_log/uma_policy.h"
+#include "chrome/common/extensions/dom_action_types.h"
+#include "chrome/test/base/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+class UmaPolicyTest : public testing::Test {
+ public:
+ UmaPolicyTest() {
+ profile_.reset(new TestingProfile());
+ }
+
+ protected:
+ scoped_ptr<TestingProfile> profile_;
+};
+
+TEST_F(UmaPolicyTest, Construct) {
+ ActivityLogPolicy* policy = new UmaPolicy(profile_.get());
+ policy->Close();
+}
+
+TEST_F(UmaPolicyTest, MatchActionToStatusTest) {
+ UmaPolicy* policy = new UmaPolicy(profile_.get());
+
+ scoped_refptr<Action> action = new Action(
+ "id", base::Time::Now(), Action::ACTION_API_CALL, "extension.connect");
+ ASSERT_EQ(UmaPolicy::NONE, policy->MatchActionToStatus(action));
+
+ action = new Action(
+ "id", base::Time::Now(), Action::ACTION_API_CALL, "tabs.executeScript");
+ ASSERT_EQ(
+ (1 << UmaPolicy::CONTENT_SCRIPT), policy->MatchActionToStatus(action));
+
+ action = new Action(
+ "id", base::Time::Now(), Action::ACTION_CONTENT_SCRIPT, "");
+ ASSERT_TRUE(
+ (1 << UmaPolicy::CONTENT_SCRIPT) & policy->MatchActionToStatus(action));
+ ASSERT_EQ(
+ (1 << UmaPolicy::CONTENT_SCRIPT), policy->MatchActionToStatus(action));
+
+ action = new Action(
+ "id", base::Time::Now(), Action::ACTION_DOM_ACCESS, "Document.location");
+ action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
+ DomActionType::GETTER);
+ ASSERT_TRUE((1 << UmaPolicy::READ_DOM) & policy->MatchActionToStatus(action));
+ ASSERT_EQ((1 << UmaPolicy::READ_DOM), policy->MatchActionToStatus(action));
+
+ action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
+ DomActionType::SETTER);
+ ASSERT_TRUE(
+ (1 << UmaPolicy::MODIFIED_DOM) & policy->MatchActionToStatus(action));
+ ASSERT_EQ(
+ (1 << UmaPolicy::MODIFIED_DOM), policy->MatchActionToStatus(action));
+
+ action = new Action(
+ "id", base::Time::Now(), Action::ACTION_DOM_ACCESS, "HTMLDocument.write");
+ action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
+ DomActionType::METHOD);
+ ASSERT_TRUE(
+ (1 << UmaPolicy::DOCUMENT_WRITE) & policy->MatchActionToStatus(action));
+ ASSERT_TRUE(
+ (1 << UmaPolicy::DOM_METHOD) & policy->MatchActionToStatus(action));
+
+ action = new Action("id",
+ base::Time::Now(),
+ Action::ACTION_DOM_ACCESS,
+ "Document.createElement");
+ scoped_ptr<base::ListValue> args(new base::ListValue());
+ args->Set(0, new base::StringValue("script"));
+ action->set_args(args.Pass());
+ ASSERT_EQ(UmaPolicy::NONE, policy->MatchActionToStatus(action));
+ action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
+ DomActionType::METHOD);
+ ASSERT_TRUE(
+ (1 << UmaPolicy::CREATED_SCRIPT) & policy->MatchActionToStatus(action));
+ ASSERT_TRUE(
+ (1 << UmaPolicy::DOM_METHOD) & policy->MatchActionToStatus(action));
+
+ policy->Close();
+}
+
+TEST_F(UmaPolicyTest, SiteUrlTest) {
+ UmaPolicy* policy = new UmaPolicy(profile_.get());
+
+ const std::string site0 = "http://www.zzz.com";
+ const std::string site1 = "http://www.foo.com";
+ const std::string site2 = "http://www.google.com#a";
+ const std::string site3 = "http://www.google.com#bb";
+
+ // Record some opened sites.
+ policy->SetupOpenedPage(site1);
+ policy->SetupOpenedPage(site2);
+ policy->SetupOpenedPage(site2);
+ policy->SetupOpenedPage(site3);
+ policy->SetupOpenedPage(site3);
+ policy->SetupOpenedPage(site3);
+
+ // Check that site1, site2, and site3 were recorded.
+ ASSERT_EQ(3u, policy->url_status().size());
+ ASSERT_EQ(1, policy->url_status()[site1][UmaPolicy::kNumberOfTabs]);
+ ASSERT_EQ(2, policy->url_status()[site2][UmaPolicy::kNumberOfTabs]);
+ ASSERT_EQ(3, policy->url_status()[site3][UmaPolicy::kNumberOfTabs]);
+
+ // Remove some sites.
+ policy->CleanupClosedPage(site0);
+ policy->CleanupClosedPage(site2);
+ policy->CleanupClosedPage(site2);
+ policy->CleanupClosedPage(site3);
+
+ // Check that the removal worked.
+ ASSERT_EQ(2u, policy->url_status().size());
+ ASSERT_EQ(1, policy->url_status()[site1][UmaPolicy::kNumberOfTabs]);
+ ASSERT_EQ(2, policy->url_status()[site3][UmaPolicy::kNumberOfTabs]);
+
+ policy->Close();
+}
+
+TEST_F(UmaPolicyTest, ProcessActionTest) {
+ const std::string site_a = "http://www.zzz.com/";
+ const std::string site_b = "http://www.foo.com/";
+ const std::string ext_a = "a";
+ const std::string ext_b = "b";
+ UmaPolicy* policy = new UmaPolicy(profile_.get());
+
+ // Populate with a few different pages.
+ policy->SetupOpenedPage(site_a);
+ policy->SetupOpenedPage(site_b);
+
+ // Process a few actions for site_a.
+ scoped_refptr<Action> action1 = new Action(
+ ext_a, base::Time::Now(), Action::ACTION_CONTENT_SCRIPT, "");
+ action1->set_page_url(GURL(site_a));
+ policy->ProcessAction(action1);
+
+ scoped_refptr<Action> action2 = new Action(
+ ext_a, base::Time::Now(), Action::ACTION_CONTENT_SCRIPT, "");
+ action2->set_page_url(GURL(site_a));
+ policy->ProcessAction(action2);
+
+ scoped_refptr<Action> action3 = new Action(
+ ext_b, base::Time::Now(), Action::ACTION_DOM_ACCESS, "Document.location");
+ action3->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
+ DomActionType::GETTER);
+ action3->set_page_url(GURL(site_a));
+ policy->ProcessAction(action3);
+
+ // Process an action for site_b.
+ scoped_refptr<Action> action4 = new Action(
+ ext_a, base::Time::Now(), Action::ACTION_DOM_ACCESS, "Document.location");
+ action4->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
+ DomActionType::SETTER);
+ action4->set_page_url(GURL(site_b));
+ policy->ProcessAction(action4);
+
+ scoped_refptr<Action> action5 = new Action(
+ ext_b, base::Time::Now(), Action::ACTION_DOM_ACCESS, "Document.location");
+ action5->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
+ DomActionType::SETTER);
+ action5->set_page_url(GURL(site_b));
+ policy->ProcessAction(action5);
+
+ scoped_refptr<Action> action6 = new Action(
+ ext_b, base::Time::Now(), Action::ACTION_API_CALL, "tabs.executeScript");
+ action6->set_arg_url(GURL(site_b));
+ policy->ProcessAction(action6);
+
+ // Now check what's been recorded.
+ ASSERT_EQ(2u, policy->url_status().size());
+
+ ASSERT_EQ(3u, policy->url_status()[site_a].size());
+ ASSERT_TRUE(
+ (1 << UmaPolicy::CONTENT_SCRIPT) & policy->url_status()[site_a][ext_a]);
+ ASSERT_FALSE(
+ (1 << UmaPolicy::CONTENT_SCRIPT) & policy->url_status()[site_a][ext_b]);
+ ASSERT_TRUE((1 << UmaPolicy::READ_DOM) & policy->url_status()[site_a][ext_b]);
+ ASSERT_FALSE(
+ (1 << UmaPolicy::READ_DOM) & policy->url_status()[site_a][ext_a]);
+
+ ASSERT_EQ(3u, policy->url_status()[site_b].size());
+ ASSERT_TRUE(
+ (1 << UmaPolicy::MODIFIED_DOM) & policy->url_status()[site_b][ext_a]);
+ ASSERT_TRUE(
+ (1 << UmaPolicy::MODIFIED_DOM) & policy->url_status()[site_b][ext_b]);
+ ASSERT_TRUE(
+ (1 << UmaPolicy::CONTENT_SCRIPT) & policy->url_status()[site_b][ext_b]);
+
+ policy->Close();
+}
+
+TEST_F(UmaPolicyTest, CleanURLTest) {
+ ASSERT_EQ("http://www.google.com/",
+ UmaPolicy::CleanURL(GURL("http://www.google.com/")));
+ ASSERT_EQ("http://www.google.com/",
+ UmaPolicy::CleanURL(GURL("http://www.google.com")));
+ ASSERT_EQ("http://www.google.com:8080/a.html",
+ UmaPolicy::CleanURL(GURL("http://www.google.com:8080/a.html")));
+ ASSERT_EQ("http://www.google.com/",
+ UmaPolicy::CleanURL(GURL("http://www.google.com/#a")));
+ ASSERT_EQ("http://www.google.com/",
+ UmaPolicy::CleanURL(GURL("http://www.google.com/#aaaa")));
+ ASSERT_EQ("http://www.google.com/?q=a",
+ UmaPolicy::CleanURL(GURL("http://www.google.com/?q=a")));
+
+ ASSERT_EQ("http://www.cnn.com/",
+ UmaPolicy::CleanURL(GURL("http://www.cnn.com/")));
+ ASSERT_EQ("http://www.cnn.com:8080/a.html",
+ UmaPolicy::CleanURL(GURL("http://www.cnn.com:8080/a.html")));
+ ASSERT_EQ("http://www.cnn.com/",
+ UmaPolicy::CleanURL(GURL("http://www.cnn.com")));
+ ASSERT_EQ("http://www.cnn.com/",
+ UmaPolicy::CleanURL(GURL("http://www.cnn.com/#a")));
+ ASSERT_EQ("http://www.cnn.com/",
+ UmaPolicy::CleanURL(GURL("http://www.cnn.com/#aaaa")));
+ ASSERT_EQ("http://www.cnn.com/?q=a",
+ UmaPolicy::CleanURL(GURL("http://www.cnn.com/?q=a")));
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/api_resource_manager.h b/chrome/browser/extensions/api/api_resource_manager.h
index a7c1624..586ce63 100644
--- a/chrome/browser/extensions/api/api_resource_manager.h
+++ b/chrome/browser/extensions/api/api_resource_manager.h
@@ -10,6 +10,7 @@
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
#include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
#include "base/threading/non_thread_safe.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/profile_keyed_api_factory.h"
@@ -22,6 +23,12 @@
#include "content/public/browser/notification_service.h"
namespace extensions {
+namespace api {
+class UDPSocketEventDispatcher;
+}
+}
+
+namespace extensions {
// An ApiResourceManager manages the lifetime of a set of resources that
// ApiFunctions use. Examples are sockets or USB connections.
@@ -83,7 +90,7 @@
content::BrowserThread::ID thread_id) {
ApiResourceManager* manager = new ApiResourceManager<T>(profile);
manager->thread_id_ = thread_id;
- manager->data_.reset(new ApiResourceData(thread_id));
+ manager->data_ = new ApiResourceData(thread_id);
return manager;
}
@@ -94,7 +101,7 @@
"the thread message loop needed for that kind of resource. "
"Please ensure that the appropriate message loop is operational.";
- content::BrowserThread::DeleteSoon(thread_id_, FROM_HERE, data_.release());
+ data_->InititateCleanup();
}
// ProfileKeyedAPI implementation.
@@ -146,6 +153,7 @@
private:
friend class ProfileKeyedAPIFactory<ApiResourceManager<T> >;
+ friend class api::UDPSocketEventDispatcher;
// ProfileKeyedAPI implementation.
static const char* service_name() {
return T::service_name();
@@ -155,7 +163,7 @@
// ApiResourceData class handles resource bookkeeping on a thread
// where resource lifetime is handled.
- class ApiResourceData {
+ class ApiResourceData : public base::RefCountedThreadSafe<ApiResourceData> {
public:
typedef std::map<int, linked_ptr<T> > ApiResourceMap;
// Lookup map from extension id's to allocated resource id's.
@@ -208,16 +216,25 @@
void InitiateExtensionUnloadedCleanup(const std::string& extension_id) {
content::BrowserThread::PostTask(thread_id_, FROM_HERE,
base::Bind(&ApiResourceData::CleanupResourcesFromUnloadedExtension,
- base::Unretained(this), extension_id));
+ this, extension_id));
}
void InitiateExtensionSuspendedCleanup(const std::string& extension_id) {
content::BrowserThread::PostTask(thread_id_, FROM_HERE,
base::Bind(&ApiResourceData::CleanupResourcesFromSuspendedExtension,
- base::Unretained(this), extension_id));
+ this, extension_id));
+ }
+
+ void InititateCleanup() {
+ content::BrowserThread::PostTask(thread_id_, FROM_HERE,
+ base::Bind(&ApiResourceData::Cleanup, this));
}
private:
+ friend class base::RefCountedThreadSafe<ApiResourceData>;
+
+ virtual ~ApiResourceData() {}
+
T* GetOwnedResource(const std::string& extension_id,
int api_resource_id) {
linked_ptr<T> ptr = api_resource_map_[api_resource_id];
@@ -284,6 +301,13 @@
}
}
+ void Cleanup() {
+ DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
+
+ api_resource_map_.clear();
+ extension_resource_map_.clear();
+ }
+
int GenerateId() {
return next_id_++;
}
@@ -296,7 +320,7 @@
content::BrowserThread::ID thread_id_;
content::NotificationRegistrar registrar_;
- scoped_ptr<ApiResourceData> data_;
+ scoped_refptr<ApiResourceData> data_;
};
} // namespace extensions
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 8aa550d..3852e0b 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
@@ -12,6 +12,7 @@
#include "chrome/common/extensions/api/app_current_window_internal.h"
#include "chrome/common/extensions/api/app_window.h"
#include "chrome/common/extensions/features/feature_channel.h"
+#include "chrome/common/extensions/features/simple_feature.h"
#include "extensions/common/switches.h"
#include "third_party/skia/include/core/SkRegion.h"
@@ -151,7 +152,18 @@
bool AppCurrentWindowInternalSetInputRegionFunction::RunWithWindow(
ShellWindow* window) {
- if (GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV) {
+
+ const char* whitelist[] = {
+ "2775E568AC98F9578791F1EAB65A1BF5F8CEF414",
+ "4AA3C5D69A4AECBD236CAD7884502209F0F5C169",
+ "E410CDAB2C6E6DD408D731016CECF2444000A912",
+ "9E930B2B5EABA6243AE6C710F126E54688E8FAF6"
+ };
+ if (GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV &&
+ !SimpleFeature::IsIdInWhitelist(
+ GetExtension()->id(),
+ std::set<std::string>(whitelist,
+ whitelist + arraysize(whitelist)))) {
error_ = kDevChannelOnly;
return false;
}
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 97b52f2..0be1b4d 100644
--- a/chrome/browser/extensions/api/app_window/app_window_api.cc
+++ b/chrome/browser/extensions/api/app_window/app_window_api.cc
@@ -31,7 +31,6 @@
#if defined(USE_ASH)
#include "ash/shell.h"
-#include "ash/wm/property_util.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#endif
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 28b0f9b..2d152b7 100644
--- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
@@ -13,6 +13,8 @@
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/session_manager_client.h"
#endif
namespace extensions {
@@ -96,6 +98,15 @@
return true;
}
+bool AutotestPrivateLockScreenFunction::RunImpl() {
+ DVLOG(1) << "AutotestPrivateLockScreenFunction";
+#if defined(OS_CHROMEOS)
+ chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
+ RequestLockScreen();
+#endif
+ return true;
+}
+
static int AccessArray(const volatile int arr[], const volatile int *index) {
return arr[*index];
}
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
index 176cc20..8c3e117 100644
--- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
+++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
@@ -51,6 +51,16 @@
virtual bool RunImpl() OVERRIDE;
};
+class AutotestPrivateLockScreenFunction: public SyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("autotestPrivate.lockScreen",
+ AUTOTESTPRIVATE_LOCKSCREEN)
+
+ private:
+ virtual ~AutotestPrivateLockScreenFunction() {}
+ virtual bool RunImpl() OVERRIDE;
+};
+
class AutotestPrivateSimulateAsanMemoryBugFunction
: public SyncExtensionFunction {
public:
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
index 9532f61..d48d2e8 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
@@ -51,8 +51,6 @@
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[] =
"This profile has already been registered";
const char kProfileNotFound[] = "Profile not found: invalid uuid";
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 62ca111..2e56f57 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
@@ -13,6 +13,7 @@
#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_stats.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api_constants.h"
#include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h"
@@ -520,7 +521,7 @@
}
bool BookmarkManagerPrivateRecordLaunchFunction::RunImpl() {
- bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_MANAGER);
+ RecordBookmarkLaunch(BOOKMARK_LAUNCH_LOCATION_MANAGER);
return true;
}
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
index 4ab1194..0fe8566 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
+++ b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
@@ -134,7 +134,7 @@
}
void BrailleControllerImpl::PokeSocketDirForTesting() {
- OnSocketDirChanged(base::FilePath(), false /*error*/);
+ OnSocketDirChangedOnIOThread();
}
void BrailleControllerImpl::StartConnecting() {
@@ -146,26 +146,44 @@
if (!libbrlapi_loader_.loaded()) {
return;
}
- base::FilePath brlapi_dir(BRLAPI_SOCKETPATH);
- if (!file_path_watcher_.Watch(
- brlapi_dir, false, base::Bind(
- &BrailleControllerImpl::OnSocketDirChanged,
- base::Unretained(this)))) {
- LOG(WARNING) << "Couldn't watch brlapi directory " << BRLAPI_SOCKETPATH;
- return;
- }
+ // One could argue that there is a race condition between starting to
+ // watch the socket asynchonously and trying to connect. While this is true,
+ // we are actually retrying to connect for a while, so this doesn't matter
+ // in practice.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE, base::Bind(
+ &BrailleControllerImpl::StartWatchingSocketDirOnFileThread,
+ base::Unretained(this)));
ResetRetryConnectHorizon();
TryToConnect();
}
-void BrailleControllerImpl::OnSocketDirChanged(const base::FilePath& path,
- bool error) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(libbrlapi_loader_.loaded());
+void BrailleControllerImpl::StartWatchingSocketDirOnFileThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ base::FilePath brlapi_dir(BRLAPI_SOCKETPATH);
+ if (!file_path_watcher_.Watch(
+ brlapi_dir, false, base::Bind(
+ &BrailleControllerImpl::OnSocketDirChangedOnFileThread,
+ base::Unretained(this)))) {
+ LOG(WARNING) << "Couldn't watch brlapi directory " << BRLAPI_SOCKETPATH;
+ }
+}
+
+void BrailleControllerImpl::OnSocketDirChangedOnFileThread(
+ const base::FilePath& path, bool error) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (error) {
LOG(ERROR) << "Error watching brlapi directory: " << path.value();
return;
}
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE, base::Bind(
+ &BrailleControllerImpl::OnSocketDirChangedOnIOThread,
+ base::Unretained(this)));
+}
+
+void BrailleControllerImpl::OnSocketDirChangedOnIOThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
LOG(INFO) << "BrlAPI directory changed";
// Every directory change resets the max retry time to the appropriate delay
// into the future.
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
index ff8cf3a..20fbf9d 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
+++ b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
@@ -52,7 +52,9 @@
// Tries to connect and starts watching for new brlapi servers.
// No-op if already called.
void StartConnecting();
- void OnSocketDirChanged(const base::FilePath& path, bool error);
+ void StartWatchingSocketDirOnFileThread();
+ void OnSocketDirChangedOnFileThread(const base::FilePath& path, bool error);
+ void OnSocketDirChangedOnIOThread();
void TryToConnect();
void ResetRetryConnectHorizon();
void ScheduleTryToConnect();
@@ -63,12 +65,11 @@
void DispatchKeyEvent(scoped_ptr<KeyEvent> event);
void DispatchOnDisplayStateChanged(scoped_ptr<DisplayState> new_state);
- LibBrlapiLoader libbrlapi_loader_;
CreateBrlapiConnectionFunction create_brlapi_connection_function_;
// Manipulated on the IO thread.
+ LibBrlapiLoader libbrlapi_loader_;
scoped_ptr<BrlapiConnection> connection_;
- base::FilePathWatcher file_path_watcher_;
bool started_connecting_;
bool connect_scheduled_;
base::Time retry_connect_horizon_;
@@ -76,6 +77,9 @@
// Manipulated on the UI thread.
ObserverList<BrailleObserver> observers_;
+ // Manipulated on the FILE thread.
+ base::FilePathWatcher file_path_watcher_;
+
friend struct DefaultSingletonTraits<BrailleControllerImpl>;
DISALLOW_COPY_AND_ASSIGN(BrailleControllerImpl);
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc b/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
index 88ce9b6..436ea52 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
+++ b/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
@@ -88,7 +88,7 @@
return true;
}
- virtual int ReadKey(brlapi_keyCode_t* key_code) {
+ virtual int ReadKey(brlapi_keyCode_t* key_code) OVERRIDE {
if (!data_->pending_keys.empty()) {
int queued_key_code = data_->pending_keys.front();
data_->pending_keys.pop_front();
@@ -120,7 +120,7 @@
class BrailleDisplayPrivateApiTest : public ExtensionApiTest {
public:
- virtual void SetUpInProcessBrowserTestFixture() {
+ virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
ExtensionApiTest::SetUpInProcessBrowserTestFixture();
connection_data_.connected = false;
connection_data_.display_size = 0;
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 4b31801..66afc3b 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry_with_cache.cc
+++ b/chrome/browser/extensions/api/declarative/rules_registry_with_cache.cc
@@ -306,21 +306,13 @@
chrome::NOTIFICATION_EXTENSION_LOADED,
content::Source<Profile>(profile_->GetOriginalProfile()));
- if (profile_->IsOffTheRecord()) {
+ if (profile_->IsOffTheRecord())
log_storage_init_delay_ = false;
- ExtensionService* extension_service = system.extension_service();
- DCHECK(extension_service->is_ready());
- const ExtensionSet* extensions = extension_service->extensions();
- for (ExtensionSet::const_iterator i = extensions->begin();
- i != extensions->end();
- ++i) {
- if (((*i)->HasAPIPermission(APIPermission::kDeclarativeContent) ||
- (*i)->HasAPIPermission(APIPermission::kDeclarativeWebRequest)) &&
- extension_service->IsIncognitoEnabled((*i)->id()))
- ReadFromStorage((*i)->id());
- }
- }
+ system.ready().Post(
+ FROM_HERE,
+ base::Bind(&RuleStorageOnUI::ReadRulesForInstalledExtensions,
+ GetWeakPtr()));
system.ready().Post(FROM_HERE,
base::Bind(&RuleStorageOnUI::CheckIfReady, GetWeakPtr()));
}
@@ -382,6 +374,31 @@
notified_registry_ = true;
}
+void
+RulesRegistryWithCache::RuleStorageOnUI::ReadRulesForInstalledExtensions() {
+ ExtensionSystem& system = *ExtensionSystem::Get(profile_);
+ ExtensionService* extension_service = system.extension_service();
+ DCHECK(extension_service);
+ // In an OTR profile, we start on top of a normal profile already, so the
+ // extension service should be ready.
+ DCHECK(!profile_->IsOffTheRecord() || extension_service->is_ready());
+ if (extension_service->is_ready()) {
+ const ExtensionSet* extensions = extension_service->extensions();
+ for (ExtensionSet::const_iterator i = extensions->begin();
+ i != extensions->end();
+ ++i) {
+ bool needs_apis_storing_rules =
+ (*i)->HasAPIPermission(APIPermission::kDeclarativeContent) ||
+ (*i)->HasAPIPermission(APIPermission::kDeclarativeWebRequest);
+ bool respects_off_the_record =
+ !(profile_->IsOffTheRecord()) ||
+ extension_service->IsIncognitoEnabled((*i)->id());
+ if (needs_apis_storing_rules && respects_off_the_record)
+ ReadFromStorage((*i)->id());
+ }
+ }
+}
+
void RulesRegistryWithCache::RuleStorageOnUI::ReadFromStorage(
const std::string& extension_id) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
diff --git a/chrome/browser/extensions/api/declarative/rules_registry_with_cache.h b/chrome/browser/extensions/api/declarative/rules_registry_with_cache.h
index 6c55c75..6e0005a 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry_with_cache.h
+++ b/chrome/browser/extensions/api/declarative/rules_registry_with_cache.h
@@ -80,6 +80,10 @@
// exactly once.
void CheckIfReady();
+ // Schedules retrieving rules for already loaded extensions where
+ // appropriate.
+ void ReadRulesForInstalledExtensions();
+
// Read/write a list of rules serialized to Values.
void ReadFromStorage(const std::string& extension_id);
void ReadFromStorageCallback(const std::string& extension_id,
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 3c19cc2..a6e55c6 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
@@ -12,8 +12,11 @@
#include "base/message_loop/message_loop.h"
#include "chrome/browser/extensions/api/declarative/test_rules_registry.h"
#include "chrome/browser/extensions/extension_prefs.h"
+#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/value_store/testing_value_store.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,12 +27,14 @@
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#endif
+using extension_test_util::LoadManifestUnchecked;
+
namespace {
-// The |extension_id| needs to pass the Extension::IdIsValid test.
-const char extension_id[] = "abcdefghijklmnopabcdefghijklmnop";
-const char extension2_id[] = "ponmlkjihgfedcbaponmlkjihgfedcba";
-const char rule_id[] = "rule";
-const char rule2_id[] = "rule2";
+// The |kExtensionId| needs to pass the Extension::IdIsValid test.
+const char kExtensionId[] = "abcdefghijklmnopabcdefghijklmnop";
+const char kExtension2Id[] = "ponmlkjihgfedcbaponmlkjihgfedcba";
+const char kRuleId[] = "rule";
+const char kRule2Id[] = "rule2";
}
namespace extensions {
@@ -51,27 +56,38 @@
}
std::string AddRule(const std::string& extension_id,
- const std::string rule_id) {
+ const std::string& rule_id,
+ TestRulesRegistry* registry) {
std::vector<linked_ptr<extensions::RulesRegistry::Rule> > add_rules;
add_rules.push_back(make_linked_ptr(new extensions::RulesRegistry::Rule));
add_rules[0]->id.reset(new std::string(rule_id));
- return registry_->AddRules(extension_id, add_rules);
+ return registry->AddRules(extension_id, add_rules);
+ }
+
+ std::string AddRule(const std::string& extension_id,
+ const std::string& rule_id) {
+ return AddRule(extension_id, rule_id, registry_.get());
}
std::string RemoveRule(const std::string& extension_id,
- const std::string rule_id) {
+ const std::string& rule_id) {
std::vector<std::string> remove_rules;
remove_rules.push_back(rule_id);
return registry_->RemoveRules(extension_id, remove_rules);
}
- int GetNumberOfRules(const std::string& extension_id) {
+ int GetNumberOfRules(const std::string& extension_id,
+ TestRulesRegistry* registry) {
std::vector<linked_ptr<extensions::RulesRegistry::Rule> > get_rules;
- std::string error = registry_->GetAllRules(extension_id, &get_rules);
+ std::string error = registry->GetAllRules(extension_id, &get_rules);
EXPECT_EQ("", error);
return get_rules.size();
}
+ int GetNumberOfRules(const std::string& extension_id) {
+ return GetNumberOfRules(extension_id, registry_.get());
+ }
+
protected:
base::MessageLoop message_loop_;
content::TestBrowserThread ui_thread_;
@@ -88,113 +104,113 @@
// Check that nothing happens if the concrete RulesRegistry refuses to insert
// the rules.
registry_->SetResult("Error");
- EXPECT_EQ("Error", AddRule(extension_id, rule_id));
- EXPECT_EQ(0, GetNumberOfRules(extension_id));
+ EXPECT_EQ("Error", AddRule(kExtensionId, kRuleId));
+ EXPECT_EQ(0, GetNumberOfRules(kExtensionId));
registry_->SetResult(std::string());
// Check that rules can be inserted.
- EXPECT_EQ("", AddRule(extension_id, rule_id));
- EXPECT_EQ(1, GetNumberOfRules(extension_id));
+ EXPECT_EQ("", AddRule(kExtensionId, kRuleId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtensionId));
- // Check that rules cannot be inserted twice with the same rule_id.
- EXPECT_NE("", AddRule(extension_id, rule_id));
- EXPECT_EQ(1, GetNumberOfRules(extension_id));
+ // Check that rules cannot be inserted twice with the same kRuleId.
+ EXPECT_NE("", AddRule(kExtensionId, kRuleId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtensionId));
- // Check that different extensions may use the same rule_id.
- EXPECT_EQ("", AddRule(extension2_id, rule_id));
- EXPECT_EQ(1, GetNumberOfRules(extension_id));
- EXPECT_EQ(1, GetNumberOfRules(extension2_id));
+ // Check that different extensions may use the same kRuleId.
+ EXPECT_EQ("", AddRule(kExtension2Id, kRuleId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtensionId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtension2Id));
}
TEST_F(RulesRegistryWithCacheTest, RemoveRules) {
// Prime registry.
- EXPECT_EQ("", AddRule(extension_id, rule_id));
- EXPECT_EQ("", AddRule(extension2_id, rule_id));
- EXPECT_EQ(1, GetNumberOfRules(extension_id));
- EXPECT_EQ(1, GetNumberOfRules(extension2_id));
+ EXPECT_EQ("", AddRule(kExtensionId, kRuleId));
+ EXPECT_EQ("", AddRule(kExtension2Id, kRuleId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtensionId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtension2Id));
// Check that nothing happens if the concrete RuleRegistry refuses to remove
// the rules.
registry_->SetResult("Error");
- EXPECT_EQ("Error", RemoveRule(extension_id, rule_id));
- EXPECT_EQ(1, GetNumberOfRules(extension_id));
+ EXPECT_EQ("Error", RemoveRule(kExtensionId, kRuleId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtensionId));
registry_->SetResult(std::string());
// Check that nothing happens if a rule does not exist.
- EXPECT_EQ("", RemoveRule(extension_id, "unknown_rule"));
- EXPECT_EQ(1, GetNumberOfRules(extension_id));
+ EXPECT_EQ("", RemoveRule(kExtensionId, "unknown_rule"));
+ EXPECT_EQ(1, GetNumberOfRules(kExtensionId));
// Check that rules may be removed and only for the correct extension.
- EXPECT_EQ("", RemoveRule(extension_id, rule_id));
- EXPECT_EQ(0, GetNumberOfRules(extension_id));
- EXPECT_EQ(1, GetNumberOfRules(extension2_id));
+ EXPECT_EQ("", RemoveRule(kExtensionId, kRuleId));
+ EXPECT_EQ(0, GetNumberOfRules(kExtensionId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtension2Id));
}
TEST_F(RulesRegistryWithCacheTest, RemoveAllRules) {
// Prime registry.
- EXPECT_EQ("", AddRule(extension_id, rule_id));
- EXPECT_EQ("", AddRule(extension_id, rule2_id));
- EXPECT_EQ("", AddRule(extension2_id, rule_id));
- EXPECT_EQ(2, GetNumberOfRules(extension_id));
- EXPECT_EQ(1, GetNumberOfRules(extension2_id));
+ EXPECT_EQ("", AddRule(kExtensionId, kRuleId));
+ EXPECT_EQ("", AddRule(kExtensionId, kRule2Id));
+ EXPECT_EQ("", AddRule(kExtension2Id, kRuleId));
+ EXPECT_EQ(2, GetNumberOfRules(kExtensionId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtension2Id));
// Check that nothing happens if the concrete RuleRegistry refuses to remove
// the rules.
registry_->SetResult("Error");
- EXPECT_EQ("Error", registry_->RemoveAllRules(extension_id));
- EXPECT_EQ(2, GetNumberOfRules(extension_id));
+ EXPECT_EQ("Error", registry_->RemoveAllRules(kExtensionId));
+ EXPECT_EQ(2, GetNumberOfRules(kExtensionId));
registry_->SetResult(std::string());
// Check that rules may be removed and only for the correct extension.
- EXPECT_EQ("", registry_->RemoveAllRules(extension_id));
- EXPECT_EQ(0, GetNumberOfRules(extension_id));
- EXPECT_EQ(1, GetNumberOfRules(extension2_id));
+ EXPECT_EQ("", registry_->RemoveAllRules(kExtensionId));
+ EXPECT_EQ(0, GetNumberOfRules(kExtensionId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtension2Id));
}
TEST_F(RulesRegistryWithCacheTest, GetRules) {
// Prime registry.
- EXPECT_EQ("", AddRule(extension_id, rule_id));
- EXPECT_EQ("", AddRule(extension_id, rule2_id));
- EXPECT_EQ("", AddRule(extension2_id, rule_id));
+ EXPECT_EQ("", AddRule(kExtensionId, kRuleId));
+ EXPECT_EQ("", AddRule(kExtensionId, kRule2Id));
+ EXPECT_EQ("", AddRule(kExtension2Id, kRuleId));
// Check that we get the correct rule and unknown rules are ignored.
std::vector<std::string> rules_to_get;
- rules_to_get.push_back(rule_id);
+ rules_to_get.push_back(kRuleId);
rules_to_get.push_back("unknown_rule");
std::vector<linked_ptr<extensions::RulesRegistry::Rule> > gotten_rules;
- EXPECT_EQ("", registry_->GetRules(extension_id, rules_to_get, &gotten_rules));
+ EXPECT_EQ("", registry_->GetRules(kExtensionId, rules_to_get, &gotten_rules));
ASSERT_EQ(1u, gotten_rules.size());
ASSERT_TRUE(gotten_rules[0]->id.get());
- EXPECT_EQ(rule_id, *(gotten_rules[0]->id));
+ EXPECT_EQ(kRuleId, *(gotten_rules[0]->id));
}
TEST_F(RulesRegistryWithCacheTest, GetAllRules) {
// Prime registry.
- EXPECT_EQ("", AddRule(extension_id, rule_id));
- EXPECT_EQ("", AddRule(extension_id, rule2_id));
- EXPECT_EQ("", AddRule(extension2_id, rule_id));
+ EXPECT_EQ("", AddRule(kExtensionId, kRuleId));
+ EXPECT_EQ("", AddRule(kExtensionId, kRule2Id));
+ EXPECT_EQ("", AddRule(kExtension2Id, kRuleId));
// Check that we get the correct rules.
std::vector<linked_ptr<extensions::RulesRegistry::Rule> > gotten_rules;
- EXPECT_EQ("", registry_->GetAllRules(extension_id, &gotten_rules));
+ EXPECT_EQ("", registry_->GetAllRules(kExtensionId, &gotten_rules));
EXPECT_EQ(2u, gotten_rules.size());
ASSERT_TRUE(gotten_rules[0]->id.get());
ASSERT_TRUE(gotten_rules[1]->id.get());
- EXPECT_TRUE( (rule_id == *(gotten_rules[0]->id) &&
- rule2_id == *(gotten_rules[1]->id)) ||
- (rule_id == *(gotten_rules[1]->id) &&
- rule2_id == *(gotten_rules[0]->id)) );
+ EXPECT_TRUE( (kRuleId == *(gotten_rules[0]->id) &&
+ kRule2Id == *(gotten_rules[1]->id)) ||
+ (kRuleId == *(gotten_rules[1]->id) &&
+ kRule2Id == *(gotten_rules[0]->id)) );
}
TEST_F(RulesRegistryWithCacheTest, OnExtensionUnloaded) {
// Prime registry.
- EXPECT_EQ("", AddRule(extension_id, rule_id));
- EXPECT_EQ("", AddRule(extension2_id, rule_id));
+ EXPECT_EQ("", AddRule(kExtensionId, kRuleId));
+ EXPECT_EQ("", AddRule(kExtension2Id, kRuleId));
// Check that the correct rules are removed.
- registry_->OnExtensionUnloaded(extension_id);
- EXPECT_EQ(0, GetNumberOfRules(extension_id));
- EXPECT_EQ(1, GetNumberOfRules(extension2_id));
+ registry_->OnExtensionUnloaded(kExtensionId);
+ EXPECT_EQ(0, GetNumberOfRules(kExtensionId));
+ EXPECT_EQ(1, GetNumberOfRules(kExtension2Id));
}
TEST_F(RulesRegistryWithCacheTest, DeclarativeRulesStored) {
@@ -217,58 +233,97 @@
// 1. Test the handling of preferences.
// Default value is always true.
- EXPECT_TRUE(ui_part->GetDeclarativeRulesStored(extension_id));
+ EXPECT_TRUE(ui_part->GetDeclarativeRulesStored(kExtensionId));
extension_prefs->UpdateExtensionPref(
- extension_id,
+ kExtensionId,
RulesRegistryWithCache::RuleStorageOnUI::kRulesStoredKey,
new base::FundamentalValue(false));
- EXPECT_FALSE(ui_part->GetDeclarativeRulesStored(extension_id));
+ EXPECT_FALSE(ui_part->GetDeclarativeRulesStored(kExtensionId));
extension_prefs->UpdateExtensionPref(
- extension_id,
+ kExtensionId,
RulesRegistryWithCache::RuleStorageOnUI::kRulesStoredKey,
new base::FundamentalValue(true));
- EXPECT_TRUE(ui_part->GetDeclarativeRulesStored(extension_id));
+ EXPECT_TRUE(ui_part->GetDeclarativeRulesStored(kExtensionId));
// 2. Test writing behavior.
int write_count = store->write_count();
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));
+ ui_part->WriteToStorage(kExtensionId, value.PassAs<base::Value>());
+ EXPECT_TRUE(ui_part->GetDeclarativeRulesStored(kExtensionId));
message_loop_.RunUntilIdle();
EXPECT_EQ(write_count + 1, store->write_count());
write_count = store->write_count();
value.reset(new base::ListValue);
- ui_part->WriteToStorage(extension_id, value.PassAs<base::Value>());
- EXPECT_FALSE(ui_part->GetDeclarativeRulesStored(extension_id));
+ ui_part->WriteToStorage(kExtensionId, value.PassAs<base::Value>());
+ EXPECT_FALSE(ui_part->GetDeclarativeRulesStored(kExtensionId));
message_loop_.RunUntilIdle();
// No rules currently, but previously there were, so we expect a write.
EXPECT_EQ(write_count + 1, store->write_count());
write_count = store->write_count();
value.reset(new base::ListValue);
- ui_part->WriteToStorage(extension_id, value.PassAs<base::Value>());
- EXPECT_FALSE(ui_part->GetDeclarativeRulesStored(extension_id));
+ ui_part->WriteToStorage(kExtensionId, value.PassAs<base::Value>());
+ EXPECT_FALSE(ui_part->GetDeclarativeRulesStored(kExtensionId));
message_loop_.RunUntilIdle();
EXPECT_EQ(write_count, store->write_count());
// 3. Test reading behavior.
int read_count = store->read_count();
- ui_part->SetDeclarativeRulesStored(extension_id, false);
- ui_part->ReadFromStorage(extension_id);
+ ui_part->SetDeclarativeRulesStored(kExtensionId, false);
+ ui_part->ReadFromStorage(kExtensionId);
message_loop_.RunUntilIdle();
EXPECT_EQ(read_count, store->read_count());
read_count = store->read_count();
- ui_part->SetDeclarativeRulesStored(extension_id, true);
- ui_part->ReadFromStorage(extension_id);
+ ui_part->SetDeclarativeRulesStored(kExtensionId, true);
+ ui_part->ReadFromStorage(kExtensionId);
message_loop_.RunUntilIdle();
EXPECT_EQ(read_count + 1, store->read_count());
}
+TEST_F(RulesRegistryWithCacheTest, RulesPreservedAcrossRestart) {
+ // This test makes sure that rules are restored from the rule store
+ // on registry (in particular, browser) restart.
+
+ TestingProfile profile;
+ extensions::TestExtensionSystem* system =
+ static_cast<extensions::TestExtensionSystem*>(
+ extensions::ExtensionSystem::Get(&profile));
+ ExtensionService* extension_service = system->CreateExtensionService(
+ CommandLine::ForCurrentProcess(), base::FilePath(), false);
+
+ // 1. Add an extension, before rules registry gets created.
+ std::string error;
+ scoped_refptr<Extension> extension(
+ LoadManifestUnchecked("permissions",
+ "web_request_all_host_permissions.json",
+ Manifest::INVALID_LOCATION,
+ Extension::NO_FLAGS,
+ kExtensionId,
+ &error));
+ ASSERT_TRUE(error.empty());
+ extension_service->AddExtension(extension.get());
+ system->SetReady();
+
+ // 2. First run, adding a rule for the extension.
+ scoped_ptr<RulesRegistryWithCache::RuleStorageOnUI> ui_part;
+ scoped_refptr<TestRulesRegistry> registry(new TestRulesRegistry(
+ &profile, "testEvent", content::BrowserThread::UI, &ui_part));
+ AddRule(kExtensionId, kRuleId, registry.get());
+ message_loop_.RunUntilIdle(); // Posted tasks store the added rule.
+ EXPECT_EQ(1, GetNumberOfRules(kExtensionId, registry.get()));
+
+ // 3. Restart the TestRulesRegistry and see the rule still there.
+ registry = new TestRulesRegistry(
+ &profile, "testEvent", content::BrowserThread::UI, &ui_part);
+ message_loop_.RunUntilIdle(); // Posted tasks retrieve the stored rule.
+ EXPECT_EQ(1, GetNumberOfRules(kExtensionId, registry.get()));
+}
+
} // namespace extensions
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.cc
index 45ff85f..fcee907 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.cc
@@ -38,7 +38,6 @@
namespace {
// Error messages.
-const char kUnknownConditionAttribute[] = "Unknown matching condition: '*'";
const char kInvalidValue[] = "Condition '*' has an invalid value";
struct WebRequestConditionAttributeFactory {
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc
index a0849c3..533017f 100644
--- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc
+++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc
@@ -16,8 +16,6 @@
namespace {
-const char kNotImplementedError[] =
- "Desktop Capture API is not yet implemented for this platform.";
const char kInvalidSourceNameError[] = "Invalid source type specified.";
const char kEmptySourcesListError[] =
"At least one source type must be specified.";
@@ -94,12 +92,15 @@
screen_capturer.Pass(), window_capturer.Pass());
picker_ = g_picker_factory->CreatePicker();
} else {
- // DesktopMediaPicker is not implented for all platforms yet.
-#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
+ // DesktopMediaPicker is implemented only for Windows, OSX and
+ // Aura Linux builds.
+#if (defined(TOOLKIT_VIEWS) && !defined(OS_CHROMEOS)) || defined(OS_MACOSX)
model.reset(new DesktopMediaPickerModelImpl(
screen_capturer.Pass(), window_capturer.Pass()));
picker_ = DesktopMediaPicker::Create();
#else
+ const char kNotImplementedError[] =
+ "Desktop Capture API is not yet implemented for this platform.";
error_ = kNotImplementedError;
return false;
#endif
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 39a5672..3f594d6 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -58,8 +58,10 @@
#include "extensions/common/switches.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
#include "net/base/net_util.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/webui/web_ui_util.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_operation.h"
@@ -83,6 +85,45 @@
return profile->GetExtensionService()->updater();
}
+GURL GetImageURLFromData(std::string contents) {
+ std::string contents_base64;
+ if (!base::Base64Encode(contents, &contents_base64))
+ return GURL();
+
+ // TODO(dvh): make use of chrome::kDataScheme. Filed as crbug/297301.
+ const char kDataURLPrefix[] = "data:image;base64,";
+ return GURL(kDataURLPrefix + contents_base64);
+}
+
+GURL GetDefaultImageURL(developer_private::ItemType type) {
+ int icon_resource_id;
+ switch (type) {
+ case developer::ITEM_TYPE_LEGACY_PACKAGED_APP:
+ case developer::ITEM_TYPE_HOSTED_APP:
+ case developer::ITEM_TYPE_PACKAGED_APP:
+ icon_resource_id = IDR_APP_DEFAULT_ICON;
+ break;
+ default:
+ icon_resource_id = IDR_EXTENSION_DEFAULT_ICON;
+ break;
+ }
+
+ return GetImageURLFromData(
+ ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
+ icon_resource_id, ui::SCALE_FACTOR_100P).as_string());
+}
+
+// TODO(dvh): This code should be refactored and moved to
+// extensions::ImageLoader. Also a resize should be performed to avoid
+// potential huge URLs: crbug/297298.
+GURL ToDataURL(const base::FilePath& path, developer_private::ItemType type) {
+ std::string contents;
+ if (path.empty() || !base::ReadFileToString(path, &contents))
+ return GetDefaultImageURL(type);
+
+ return GetImageURLFromData(contents);
+}
+
std::vector<base::FilePath> ListFolder(const base::FilePath path) {
base::FileEnumerator files(path, false,
base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES);
@@ -271,14 +312,6 @@
info->version = item.VersionString();
info->description = item.description();
- GURL url =
- ExtensionIconSource::GetIconURL(&item,
- extension_misc::EXTENSION_ICON_MEDIUM,
- ExtensionIconSet::MATCH_BIGGER,
- false,
- NULL);
- info->icon_url = url.spec();
-
if (item.is_app()) {
if (item.is_legacy_packaged_app())
info->type = developer::ITEM_TYPE_LEGACY_PACKAGED_APP;
@@ -341,6 +374,27 @@
return info.Pass();
}
+void DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread(
+ ItemInfoList item_list,
+ const std::map<std::string, ExtensionResource> idToIcon) {
+ for (ItemInfoList::iterator iter = item_list.begin();
+ iter != item_list.end(); ++iter) {
+ developer_private::ItemInfo* info = iter->get();
+ std::map<std::string, ExtensionResource>::const_iterator resource_ptr
+ = idToIcon.find(info->id);
+ if (resource_ptr != idToIcon.end()) {
+ info->icon_url =
+ ToDataURL(resource_ptr->second.GetFilePath(), info->type).spec();
+ }
+ }
+
+ results_ = developer::GetItemsInfo::Results::Create(item_list);
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&DeveloperPrivateGetItemsInfoFunction::SendResponse,
+ this,
+ true));
+}
+
void DeveloperPrivateGetItemsInfoFunction::
GetInspectablePagesForExtensionProcess(
const Extension* extension,
@@ -500,12 +554,19 @@
items.InsertAll(*service->terminated_extensions());
}
+ std::map<std::string, ExtensionResource> id_to_icon;
ItemInfoList item_list;
for (ExtensionSet::const_iterator iter = items.begin();
iter != items.end(); ++iter) {
const Extension& item = *iter->get();
+ ExtensionResource item_resource =
+ IconsInfo::GetIconResource(&item,
+ extension_misc::EXTENSION_ICON_MEDIUM,
+ ExtensionIconSet::MATCH_BIGGER);
+ id_to_icon[item.id()] = item_resource;
+
// Don't show component extensions and invisible apps.
if (item.ShouldNotBeVisible())
continue;
@@ -515,8 +576,11 @@
item, service->IsExtensionEnabled(item.id())).release()));
}
- results_ = developer::GetItemsInfo::Results::Create(item_list);
- SendResponse(true);
+ content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread,
+ this,
+ item_list,
+ id_to_icon));
return true;
}
diff --git a/chrome/browser/extensions/api/diagnostics/diagnostics_api_chromeos.cc b/chrome/browser/extensions/api/diagnostics/diagnostics_api_chromeos.cc
index 55f2cb0..9ae0f18 100644
--- a/chrome/browser/extensions/api/diagnostics/diagnostics_api_chromeos.cc
+++ b/chrome/browser/extensions/api/diagnostics/diagnostics_api_chromeos.cc
@@ -31,27 +31,27 @@
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;
+ // 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;
+ base::DictionaryValue* result = NULL;
+ if (!parsed_value->GetAsDictionary(&result) || result->size() != 1)
+ return false;
- // Returns the first item.
- base::DictionaryValue::Iterator iterator(*result);
+ // Returns the first item.
+ base::DictionaryValue::Iterator iterator(*result);
- const base::DictionaryValue* info;
- if (!iterator.value().GetAsDictionary(&info))
- return false;
+ const base::DictionaryValue* info;
+ if (!iterator.value().GetAsDictionary(&info))
+ return false;
- if (info->GetDouble("avg", latency))
- return false;
+ if (!info->GetDouble("avg", latency))
+ return false;
- *ip = iterator.key();
- return true;
+ *ip = iterator.key();
+ return true;
}
void OnTestICMPCompleted(
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
index f9785f8..0601780 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -59,9 +59,9 @@
bool ImagesAreEqualAtScale(const gfx::ImageSkia& i1,
const gfx::ImageSkia& i2,
- ui::ScaleFactor scale_factor) {
- SkBitmap bitmap1 = i1.GetRepresentation(scale_factor).sk_bitmap();
- SkBitmap bitmap2 = i2.GetRepresentation(scale_factor).sk_bitmap();
+ float scale) {
+ SkBitmap bitmap1 = i1.GetRepresentation(scale).sk_bitmap();
+ SkBitmap bitmap2 = i2.GetRepresentation(scale).sk_bitmap();
return gfx::BitmapsAreEqual(bitmap1, bitmap2);
}
@@ -136,7 +136,7 @@
std::vector<ui::ScaleFactor> supported_scale_factors;
supported_scale_factors.push_back(ui::SCALE_FACTOR_100P);
supported_scale_factors.push_back(ui::SCALE_FACTOR_200P);
- ui::test::SetSupportedScaleFactors(supported_scale_factors);
+ ui::SetSupportedScaleFactors(supported_scale_factors);
#endif
// We should not be creating icons asynchronously, so we don't need an
@@ -171,13 +171,12 @@
EXPECT_GT(action_icon_current_id, action_icon_last_id);
action_icon_last_id = action_icon_current_id;
- EXPECT_FALSE(
- action_icon.ToImageSkia()->HasRepresentation(ui::SCALE_FACTOR_200P));
+ EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
EXPECT_TRUE(ImagesAreEqualAtScale(
AddBackgroundForViews(*action_icon.ToImageSkia()),
*GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
- ui::SCALE_FACTOR_100P));
+ 1.0f));
// Tell the extension to update the icon using path.
GetBrowserActionsBar().Press(0);
@@ -190,12 +189,12 @@
action_icon_last_id = action_icon_current_id;
EXPECT_FALSE(
- action_icon.ToImageSkia()->HasRepresentation(ui::SCALE_FACTOR_200P));
+ action_icon.ToImageSkia()->HasRepresentation(2.0f));
EXPECT_TRUE(ImagesAreEqualAtScale(
AddBackgroundForViews(*action_icon.ToImageSkia()),
*GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
- ui::SCALE_FACTOR_100P));
+ 1.0f));
// Tell the extension to update the icon using dictionary of ImageData
// objects.
@@ -208,13 +207,12 @@
EXPECT_GT(action_icon_current_id, action_icon_last_id);
action_icon_last_id = action_icon_current_id;
- EXPECT_TRUE(
- action_icon.ToImageSkia()->HasRepresentation(ui::SCALE_FACTOR_200P));
+ EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
EXPECT_TRUE(ImagesAreEqualAtScale(
AddBackgroundForViews(*action_icon.ToImageSkia()),
*GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
- ui::SCALE_FACTOR_100P));
+ 1.0f));
// Tell the extension to update the icon using dictionary of paths.
GetBrowserActionsBar().Press(0);
@@ -226,13 +224,12 @@
EXPECT_GT(action_icon_current_id, action_icon_last_id);
action_icon_last_id = action_icon_current_id;
- EXPECT_TRUE(
- action_icon.ToImageSkia()->HasRepresentation(ui::SCALE_FACTOR_200P));
+ EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
EXPECT_TRUE(ImagesAreEqualAtScale(
AddBackgroundForViews(*action_icon.ToImageSkia()),
*GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
- ui::SCALE_FACTOR_100P));
+ 1.0f));
// Tell the extension to update the icon using dictionary of ImageData
// objects, but setting only size 19.
@@ -245,13 +242,12 @@
EXPECT_GT(action_icon_current_id, action_icon_last_id);
action_icon_last_id = action_icon_current_id;
- EXPECT_FALSE(
- action_icon.ToImageSkia()->HasRepresentation(ui::SCALE_FACTOR_200P));
+ EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
EXPECT_TRUE(ImagesAreEqualAtScale(
AddBackgroundForViews(*action_icon.ToImageSkia()),
*GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
- ui::SCALE_FACTOR_100P));
+ 1.0f));
// Tell the extension to update the icon using dictionary of paths, but
// setting only size 19.
@@ -264,13 +260,12 @@
EXPECT_GT(action_icon_current_id, action_icon_last_id);
action_icon_last_id = action_icon_current_id;
- EXPECT_FALSE(
- action_icon.ToImageSkia()->HasRepresentation(ui::SCALE_FACTOR_200P));
+ EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
EXPECT_TRUE(ImagesAreEqualAtScale(
AddBackgroundForViews(*action_icon.ToImageSkia()),
*GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
- ui::SCALE_FACTOR_100P));
+ 1.0f));
// Tell the extension to update the icon using dictionary of ImageData
// objects, but setting only size 38.
@@ -281,8 +276,8 @@
const gfx::ImageSkia* action_icon_skia = action_icon.ToImageSkia();
- EXPECT_FALSE(action_icon_skia->HasRepresentation(ui::SCALE_FACTOR_100P));
- EXPECT_TRUE(action_icon_skia->HasRepresentation(ui::SCALE_FACTOR_200P));
+ EXPECT_FALSE(action_icon_skia->HasRepresentation(1.0f));
+ EXPECT_TRUE(action_icon_skia->HasRepresentation(2.0f));
action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
EXPECT_GT(action_icon_current_id, action_icon_last_id);
@@ -290,12 +285,12 @@
EXPECT_TRUE(gfx::BitmapsAreEqual(
*action_icon.ToSkBitmap(),
- action_icon_skia->GetRepresentation(ui::SCALE_FACTOR_200P).sk_bitmap()));
+ action_icon_skia->GetRepresentation(2.0f).sk_bitmap()));
EXPECT_TRUE(ImagesAreEqualAtScale(
AddBackgroundForViews(*action_icon_skia),
*GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
- ui::SCALE_FACTOR_200P));
+ 2.0f));
// Try setting icon with empty dictionary of ImageData objects.
GetBrowserActionsBar().Press(0);
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 3d4c46d..488e852 100644
--- a/chrome/browser/extensions/api/extension_action/extension_action_api.cc
+++ b/chrome/browser/extensions/api/extension_action/extension_action_api.cc
@@ -100,8 +100,7 @@
}
// Conversion function for reading/writing to storage.
-std::string RepresentationToString(const gfx::ImageSkia& image,
- ui::ScaleFactor scale) {
+std::string RepresentationToString(const gfx::ImageSkia& image, float scale) {
SkBitmap bitmap = image.GetRepresentation(scale).sk_bitmap();
IPC::Message bitmap_pickle;
// Clear the header values so they don't vary in serialization.
@@ -144,7 +143,8 @@
if (icon_value->GetString(kIconSizes[i].size_string, &str_value) &&
StringToSkBitmap(str_value, &bitmap)) {
CHECK(!bitmap.isNull());
- icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, kIconSizes[i].scale));
+ float scale = ui::GetImageScale(kIconSizes[i].scale);
+ icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
}
}
action->SetIcon(kTabId, gfx::Image(icon));
@@ -172,10 +172,11 @@
if (!icon.isNull()) {
base::DictionaryValue* icon_value = new base::DictionaryValue();
for (size_t i = 0; i < arraysize(kIconSizes); i++) {
- if (icon.HasRepresentation(kIconSizes[i].scale)) {
+ float scale = ui::GetImageScale(kIconSizes[i].scale);
+ if (icon.HasRepresentation(scale)) {
icon_value->SetString(
kIconSizes[i].size_string,
- RepresentationToString(icon, kIconSizes[i].scale));
+ RepresentationToString(icon, scale));
}
}
dict->Set(kIconStorageKey, icon_value);
@@ -696,7 +697,8 @@
SkBitmap bitmap;
EXTENSION_FUNCTION_VALIDATE(IPC::ReadParam(&pickle, &iter, &bitmap));
CHECK(!bitmap.isNull());
- icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, kIconSizes[i].scale));
+ float scale = ui::GetImageScale(kIconSizes[i].scale);
+ icon.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
}
}
diff --git a/chrome/browser/extensions/api/feedback_private/blob_reader.cc b/chrome/browser/extensions/api/feedback_private/blob_reader.cc
index 3f2ee23..4ee07c9 100644
--- a/chrome/browser/extensions/api/feedback_private/blob_reader.cc
+++ b/chrome/browser/extensions/api/feedback_private/blob_reader.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/api/feedback_private/blob_reader.h"
+#include "base/strings/string_util.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_fetcher.h"
@@ -11,12 +12,20 @@
#include "net/url_request/url_request_context_getter.h"
BlobReader::BlobReader(Profile* profile,
- const GURL& blob_url,
+ const std::string& blob_uuid,
BlobReadCallback callback)
: callback_(callback) {
- fetcher_ = net::URLFetcher::Create(
+ GURL blob_url;
+ if (StartsWithASCII(blob_uuid, "blob:blobinternal", true)) {
+ // TODO(michaeln): remove support for deprecated blob urls
+ blob_url = GURL(blob_uuid);
+ } else {
+ blob_url = GURL(std::string("blob:uuid/") + blob_uuid);
+ }
+ DCHECK(blob_url.is_valid());
+ fetcher_.reset(net::URLFetcher::Create(
blob_url, net::URLFetcher::GET,
- this);
+ this));
fetcher_->SetRequestContext(profile->GetRequestContext());
}
diff --git a/chrome/browser/extensions/api/feedback_private/blob_reader.h b/chrome/browser/extensions/api/feedback_private/blob_reader.h
index 6c05b20..455d2c0 100644
--- a/chrome/browser/extensions/api/feedback_private/blob_reader.h
+++ b/chrome/browser/extensions/api/feedback_private/blob_reader.h
@@ -25,7 +25,7 @@
BlobReadCallback;
BlobReader(Profile* profile,
- const GURL& blob_url,
+ const std::string& blob_uuid,
BlobReadCallback callback);
virtual ~BlobReader();
@@ -36,7 +36,7 @@
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
BlobReadCallback callback_;
- net::URLFetcher* fetcher_;
+ scoped_ptr<net::URLFetcher> fetcher_;
DISALLOW_COPY_AND_ASSIGN(BlobReader);
};
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
index 6685eeb..e9d0c7d 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/extensions/api/feedback_private/feedback_service.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/feedback/tracing_manager.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/webui/web_ui_util.h"
@@ -50,21 +51,17 @@
void FeedbackPrivateAPI::RequestFeedback(
const std::string& description_template,
const std::string& category_tag,
- const GURL& page_url,
- const gfx::Rect& screen_size) {
+ const GURL& page_url) {
if (profile_ && ExtensionSystem::Get(profile_)->event_router()) {
FeedbackInfo info;
info.description = description_template;
info.category_tag = make_scoped_ptr(new std::string(category_tag));
info.page_url = make_scoped_ptr(new std::string(page_url.spec()));
info.system_information.reset(new SystemInformationList);
-
- FeedbackService::PopulateSystemInfo(
- info.system_information.get(), FeedbackData::kScreensizeHeightKey,
- base::IntToString(screen_size.height()));
- FeedbackService::PopulateSystemInfo(
- info.system_information.get(), FeedbackData::kScreensizeWidthKey,
- base::IntToString(screen_size.width()));
+ // The manager is only available if tracing is enabled.
+ if (TracingManager* manager = TracingManager::Get()) {
+ info.trace_id.reset(new int(manager->RequestTrace()));
+ }
scoped_ptr<base::ListValue> args(new base::ListValue());
args->Append(info.ToValue().release());
@@ -95,6 +92,8 @@
SET_STRING("cancel", IDS_CANCEL);
SET_STRING("no-description", IDS_FEEDBACK_NO_DESCRIPTION);
SET_STRING("privacy-note", IDS_FEEDBACK_PRIVACY_NOTE);
+ SET_STRING("performance-trace",
+ IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX);
#undef SET_STRING
webui::SetFontAndTextDirection(dict);
@@ -135,14 +134,15 @@
const FeedbackInfo &feedback_info = params->feedback;
- std::string attached_file_url, screenshot_url;
- if (feedback_info.attached_file_blob_url.get() &&
- !feedback_info.attached_file_blob_url->empty())
- attached_file_url = *feedback_info.attached_file_blob_url;
+ std::string attached_file_uuid;
+ if (feedback_info.attached_file_blob_uuid.get() &&
+ !feedback_info.attached_file_blob_uuid->empty())
+ attached_file_uuid = *feedback_info.attached_file_blob_uuid;
- if (feedback_info.screenshot_blob_url.get() &&
- !feedback_info.screenshot_blob_url->empty())
- screenshot_url = *feedback_info.screenshot_blob_url;
+ std::string screenshot_uuid;
+ if (feedback_info.screenshot_blob_uuid.get() &&
+ !feedback_info.screenshot_blob_uuid->empty())
+ screenshot_uuid = *feedback_info.screenshot_blob_uuid;
// Populate feedback data.
scoped_refptr<FeedbackData> feedback_data(new FeedbackData());
@@ -156,14 +156,18 @@
if (feedback_info.email.get())
feedback_data->set_user_email(*feedback_info.email.get());
- if (!attached_file_url.empty()) {
+ if (!attached_file_uuid.empty()) {
feedback_data->set_attached_filename(
(*feedback_info.attached_file.get()).name);
- feedback_data->set_attached_file_url(GURL(attached_file_url));
+ feedback_data->set_attached_file_uuid(attached_file_uuid);
}
- if (!screenshot_url.empty())
- feedback_data->set_screenshot_url(GURL(screenshot_url));
+ if (!screenshot_uuid.empty())
+ feedback_data->set_screenshot_uuid(screenshot_uuid);
+
+ if (feedback_info.trace_id.get()) {
+ feedback_data->set_trace_id(*feedback_info.trace_id.get());
+ }
scoped_ptr<FeedbackData::SystemLogsMap> sys_logs(
new FeedbackData::SystemLogsMap);
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_private_api.h b/chrome/browser/extensions/api/feedback_private/feedback_private_api.h
index 278bba0..bfdc000 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_private_api.h
+++ b/chrome/browser/extensions/api/feedback_private/feedback_private_api.h
@@ -24,8 +24,7 @@
FeedbackService* GetService() const;
void RequestFeedback(const std::string& description_template,
const std::string& category_tag,
- const GURL& page_url,
- const gfx::Rect& screen_size);
+ const GURL& page_url);
// ProfileKeyedAPI implementation.
static ProfileKeyedAPIFactory<FeedbackPrivateAPI>* GetFactoryInstance();
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_private_apitest.cc b/chrome/browser/extensions/api/feedback_private/feedback_private_apitest.cc
index 322601d..c6ab4c7 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_private_apitest.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_private_apitest.cc
@@ -2,25 +2,21 @@
// 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 "chrome/browser/extensions/api/audio/audio_api.h"
+#include "base/message_loop/message_loop.h"
+#include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/extension_test_message_listener.h"
-#include "chrome/common/chrome_switches.h"
namespace extensions {
-class AudioApiTest: public ExtensionApiTest {
+class FeedbackApiTest: public ExtensionApiTest {
public:
- AudioApiTest() {}
- virtual ~AudioApiTest() {}
+ FeedbackApiTest() {}
+ virtual ~FeedbackApiTest() {}
};
-#if defined(OS_CHROMEOS)
-IN_PROC_BROWSER_TEST_F(AudioApiTest, Audio) {
- EXPECT_TRUE(RunExtensionTest("audio")) << message_;
+// Falis on buildbots. crbug.com/297414
+IN_PROC_BROWSER_TEST_F(FeedbackApiTest, DISABLED_Basic) {
+ EXPECT_TRUE(RunExtensionTest("feedback_private/basic")) << message_;
}
-#endif
} // namespace extensions
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service.cc b/chrome/browser/extensions/api/feedback_private/feedback_service.cc
index a4102ed..b16f1ad 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_service.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_service.cc
@@ -42,19 +42,19 @@
send_feedback_callback_ = callback;
feedback_data_ = feedback_data;
- if (feedback_data_->attached_file_url().is_valid()) {
+ if (!feedback_data_->attached_file_uuid().empty()) {
// Self-deleting object.
BlobReader* attached_file_reader = new BlobReader(
- profile, feedback_data_->attached_file_url(),
+ profile, feedback_data_->attached_file_uuid(),
base::Bind(&FeedbackService::AttachedFileCallback,
GetWeakPtr()));
attached_file_reader->Start();
}
- if (feedback_data_->screenshot_url().is_valid()) {
+ if (!feedback_data_->screenshot_uuid().empty()) {
// Self-deleting object.
BlobReader* screenshot_reader = new BlobReader(
- profile, feedback_data_->screenshot_url(),
+ profile, feedback_data_->screenshot_uuid(),
base::Bind(&FeedbackService::ScreenshotCallback,
GetWeakPtr()));
screenshot_reader->Start();
@@ -65,7 +65,7 @@
void FeedbackService::AttachedFileCallback(scoped_ptr<std::string> data) {
if (!data.get())
- feedback_data_->set_attached_file_url(GURL());
+ feedback_data_->set_attached_file_uuid(std::string());
else
feedback_data_->set_attached_filedata(data.Pass());
@@ -74,7 +74,7 @@
void FeedbackService::ScreenshotCallback(scoped_ptr<std::string> data) {
if (!data.get())
- feedback_data_->set_screenshot_url(GURL());
+ feedback_data_->set_screenshot_uuid(std::string());
else
feedback_data_->set_image(data.Pass());
@@ -90,10 +90,10 @@
// and the read callback has updated the associated data on the feedback
// object.
bool attached_file_completed =
- !feedback_data_->attached_file_url().is_valid() ||
+ feedback_data_->attached_file_uuid().empty() ||
feedback_data_->attached_filedata();
bool screenshot_completed =
- !feedback_data_->screenshot_url().is_valid() ||
+ !feedback_data_->screenshot_uuid().empty() ||
feedback_data_->image();
if (screenshot_completed && attached_file_completed) {
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc b/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc
index d4c2f19..53afb1c 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc
@@ -49,7 +49,8 @@
if (!manager)
return std::string();
else
- return manager->GetLoggedInUser()->display_email();}
+ return manager->GetLoggedInUser()->display_email();
+}
void FeedbackServiceImpl::GetSystemInformation(
const GetSystemInformationCallback& callback) {
diff --git a/chrome/browser/extensions/api/history/history_api.cc b/chrome/browser/extensions/api/history/history_api.cc
index 8faa056..1b8b962 100644
--- a/chrome/browser/extensions/api/history/history_api.cc
+++ b/chrome/browser/extensions/api/history/history_api.cc
@@ -57,7 +57,6 @@
namespace {
-const char kInvalidIdError[] = "History item id is invalid.";
const char kInvalidUrlError[] = "Url is invalid.";
const char kDeleteProhibitedError[] = "Browsing history is not allowed to be "
"deleted.";
diff --git a/chrome/browser/extensions/api/identity/experimental_identity_api.cc b/chrome/browser/extensions/api/identity/experimental_identity_api.cc
index 4920f55..5839991 100644
--- a/chrome/browser/extensions/api/identity/experimental_identity_api.cc
+++ b/chrome/browser/extensions/api/identity/experimental_identity_api.cc
@@ -235,7 +235,8 @@
if (chromeos::UserManager::Get()->GetAppModeChromeClientOAuthInfo(
&app_client_id, &app_client_secret)) {
login_token_request_ =
- service->StartRequestForClient(app_client_id,
+ service->StartRequestForClient(service->GetPrimaryAccountId(),
+ app_client_id,
app_client_secret,
OAuth2TokenService::ScopeSet(),
this);
@@ -243,8 +244,8 @@
}
}
#endif
- login_token_request_ = service->StartRequest(OAuth2TokenService::ScopeSet(),
- this);
+ login_token_request_ = service->StartRequest(
+ service->GetPrimaryAccountId(), OAuth2TokenService::ScopeSet(), this);
}
void ExperimentalIdentityGetAuthTokenFunction::StartGaiaRequest(
@@ -288,8 +289,10 @@
}
bool ExperimentalIdentityGetAuthTokenFunction::HasLoginToken() const {
- return ProfileOAuth2TokenServiceFactory::GetForProfile(profile())->
- RefreshTokenIsAvailable();
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
+ return token_service->RefreshTokenIsAvailable(
+ token_service->GetPrimaryAccountId());
}
ExperimentalIdentityLaunchWebAuthFlowFunction::
diff --git a/chrome/browser/extensions/api/identity/experimental_identity_apitest.cc b/chrome/browser/extensions/api/identity/experimental_identity_apitest.cc
index 7d5c0cb..613171d 100644
--- a/chrome/browser/extensions/api/identity/experimental_identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/experimental_identity_apitest.cc
@@ -37,8 +37,7 @@
namespace errors = identity_constants;
namespace utils = extension_function_test_utils;
-static const char kAccessToken[] = "auth_token";
-static const char kExtensionId[] = "ext_id";
+const char kAccessToken[] = "auth_token";
// This helps us be able to wait until an AsyncExtensionFunction calls
// SendResponse.
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index c7707b4..5726c65 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -219,9 +219,12 @@
IsEnterpriseManaged()) {
OAuth2TokenService::ScopeSet scope_set(oauth2_info.scopes.begin(),
oauth2_info.scopes.end());
+ chromeos::DeviceOAuth2TokenService* token_service =
+ chromeos::DeviceOAuth2TokenServiceFactory::Get();
device_token_request_ =
- chromeos::DeviceOAuth2TokenServiceFactory::Get()->StartRequest(
- scope_set, this);
+ token_service->StartRequest(token_service->GetRobotAccountId(),
+ scope_set,
+ this);
} else {
gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE;
StartLoginAccessTokenRequest();
@@ -424,7 +427,8 @@
if (chromeos::UserManager::Get()->GetAppModeChromeClientOAuthInfo(
&app_client_id, &app_client_secret)) {
login_token_request_ =
- service->StartRequestForClient(app_client_id,
+ service->StartRequestForClient(service->GetPrimaryAccountId(),
+ app_client_id,
app_client_secret,
OAuth2TokenService::ScopeSet(),
this);
@@ -432,8 +436,8 @@
}
}
#endif
- login_token_request_ = service->StartRequest(OAuth2TokenService::ScopeSet(),
- this);
+ login_token_request_ = service->StartRequest(
+ service->GetPrimaryAccountId(), OAuth2TokenService::ScopeSet(), this);
}
void IdentityGetAuthTokenFunction::StartGaiaRequest(
@@ -477,8 +481,10 @@
}
bool IdentityGetAuthTokenFunction::HasLoginToken() const {
- return ProfileOAuth2TokenServiceFactory::GetForProfile(profile())->
- RefreshTokenIsAvailable();
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
+ return token_service->RefreshTokenIsAvailable(
+ token_service->GetPrimaryAccountId());
}
std::string IdentityGetAuthTokenFunction::MapOAuth2ErrorToDescription(
@@ -619,6 +625,10 @@
const std::string& token, base::TimeDelta time_to_live)
: status_(CACHE_STATUS_TOKEN),
token_(token) {
+ // Remove 20 minutes from the ttl so cached tokens will have some time
+ // to live any time they are returned.
+ time_to_live -= base::TimeDelta::FromMinutes(20);
+
base::TimeDelta zero_delta;
if (time_to_live < zero_delta)
time_to_live = zero_delta;
diff --git a/chrome/browser/extensions/api/image_writer_private/error_messages.cc b/chrome/browser/extensions/api/image_writer_private/error_messages.cc
index ad92476..0f193da 100644
--- a/chrome/browser/extensions/api/image_writer_private/error_messages.cc
+++ b/chrome/browser/extensions/api/image_writer_private/error_messages.cc
@@ -19,10 +19,10 @@
const char kDownloadMD5[] = "Failed to calculate MD5 sum for download.";
const char kEmptyUnzip[] = "Unzipped image contained no files.";
const char kFileOperationsNotImplemented[] = "Write-from file not implemented.";
+const char kImageBurnerError[] = "Error contacting Image Burner process.";
const char kImageMD5[] = "Failed to calculate MD5 sum for unzipped image.";
const char kImageNotFound[] = "Unpacked image not found.";
const char kImageSize[] = "Could not determine image size.";
-const char kInvalidFileEntry[] = "Invalid file entry.";
const char kInvalidUrl[] = "Invalid URL provided.";
const char kMultiFileZip[] = "More than one file in zip."
" Unsure how to proceed.";
diff --git a/chrome/browser/extensions/api/image_writer_private/error_messages.h b/chrome/browser/extensions/api/image_writer_private/error_messages.h
index 0042426..a45c775 100644
--- a/chrome/browser/extensions/api/image_writer_private/error_messages.h
+++ b/chrome/browser/extensions/api/image_writer_private/error_messages.h
@@ -20,6 +20,7 @@
extern const char kDownloadMD5[];
extern const char kEmptyUnzip[];
extern const char kFileOperationsNotImplemented[];
+extern const char kImageBurnerError[];
extern const char kImageMD5[];
extern const char kImageNotFound[];
extern const char kImageSize[];
diff --git a/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc b/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
index 0fb3b97..a9834be 100644
--- a/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
+++ b/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
@@ -30,10 +30,16 @@
return false;
}
+#if defined(OS_CHROMEOS)
+ // The Chrome OS temporary partition is too small for Chrome OS images, thus
+ // we must always use the downloads folder.
+ bool save_image_as_download = true;
+#else
bool save_image_as_download = false;
if (params->options.get() && params->options->save_as_download.get()) {
save_image_as_download = true;
}
+#endif
std::string hash;
if (params->options.get() && params->options->image_hash.get()) {
diff --git a/chrome/browser/extensions/api/image_writer_private/operation.cc b/chrome/browser/extensions/api/image_writer_private/operation.cc
index 510030c..711badb 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation.cc
@@ -16,10 +16,17 @@
using content::BrowserThread;
-const int kBurningBlockSize = 8 * 1024; // 8 KiB
+namespace {
+
const int kMD5BufferSize = 1024;
-Operation::Operation(OperationManager* manager,
+void RemoveTempDirectory(const base::FilePath path) {
+ base::DeleteFile(path, true);
+}
+
+} // namespace
+
+Operation::Operation(base::WeakPtr<OperationManager> manager,
const ExtensionId& extension_id,
const std::string& storage_unit_id)
: manager_(manager),
@@ -36,55 +43,129 @@
DVLOG(1) << "Cancelling image writing operation for ext: " << extension_id_;
stage_ = image_writer_api::STAGE_NONE;
+
+ CleanUp();
}
void Operation::Abort() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
Error(error::kAborted);
}
void Operation::Error(const std::string& error_message) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
+ BrowserThread::PostTask(BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&Operation::Error, this, error_message));
+ return;
+ }
+
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&OperationManager::OnError,
- manager_->AsWeakPtr(),
+ manager_,
extension_id_,
stage_,
progress_,
error_message));
+
+ CleanUp();
}
-void Operation::SendProgress() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+void Operation::SetProgress(int progress) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&Operation::SetProgress,
+ this,
+ progress));
+ return;
+ }
+
+ if (IsCancelled()) {
+ return;
+ }
+
+ progress_ = progress;
+
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&OperationManager::OnProgress,
- manager_->AsWeakPtr(),
+ manager_,
+ extension_id_,
+ stage_,
+ progress_));
+}
+
+void Operation::SetStage(image_writer_api::Stage stage) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&Operation::SetStage,
+ this,
+ stage));
+ return;
+ }
+
+ if (IsCancelled()) {
+ return;
+ }
+
+ stage_ = stage;
+ progress_ = 0;
+
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&OperationManager::OnProgress,
+ manager_,
extension_id_,
stage_,
progress_));
}
void Operation::Finish() {
+ if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
+ BrowserThread::PostTask(BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&Operation::Finish, this));
+ }
DVLOG(1) << "Write operation complete.";
- stage_ = image_writer_api::STAGE_NONE;
- progress_ = 0;
+ CleanUp();
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&OperationManager::OnComplete,
- manager_->AsWeakPtr(),
+ manager_,
extension_id_));
}
bool Operation::IsCancelled() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
return stage_ == image_writer_api::STAGE_NONE;
}
+void Operation::AddCleanUpFunction(base::Closure callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ cleanup_functions_.push_back(callback);
+}
+
+void Operation::CleanUp() {
+ for (std::vector<base::Closure>::iterator it = cleanup_functions_.begin();
+ it != cleanup_functions_.end();
+ ++it) {
+ it->Run();
+ }
+ cleanup_functions_.clear();
+}
+
void Operation::UnzipStart(scoped_ptr<base::FilePath> zip_file) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (IsCancelled()) {
@@ -93,17 +174,18 @@
DVLOG(1) << "Starting unzip stage for " << zip_file->value();
- stage_ = image_writer_api::STAGE_UNZIP;
- progress_ = 0;
-
- SendProgress();
+ SetStage(image_writer_api::STAGE_UNZIP);
base::FilePath tmp_dir;
- if (!file_util::CreateNewTempDirectory(FILE_PATH_LITERAL(""), &tmp_dir)) {
+ if (!file_util::CreateTemporaryDirInDir(zip_file->DirName(),
+ FILE_PATH_LITERAL("image_writer"),
+ &tmp_dir)) {
Error(error::kTempDir);
return;
}
+ AddCleanUpFunction(base::Bind(&RemoveTempDirectory, tmp_dir));
+
if (!zip::Unzip(*zip_file, tmp_dir)) {
Error(error::kUnzip);
return;
@@ -128,8 +210,7 @@
DVLOG(1) << "Successfully unzipped as " << unzipped_file->value();
- progress_ = 100;
- SendProgress();
+ SetProgress(kProgressComplete);
image_path_ = *unzipped_file;
@@ -197,14 +278,13 @@
if (len > 0) {
base::MD5Update(&md5_context_, base::StringPiece(buffer, len));
- int percent_prev = (bytes_processed * progress_scale + progress_offset)
- / (bytes_total);
- int percent_curr = ((bytes_processed + len) * progress_scale
- + progress_offset) / (bytes_total);
- progress_ = percent_curr;
-
+ int percent_prev = (bytes_processed * progress_scale + progress_offset) /
+ (bytes_total);
+ int percent_curr = ((bytes_processed + len) * progress_scale +
+ progress_offset) /
+ (bytes_total);
if (percent_curr > percent_prev) {
- SendProgress();
+ SetProgress(progress_);
}
BrowserThread::PostTask(BrowserThread::FILE,
@@ -234,5 +314,5 @@
}
}
-} // namespace image_writer
-} // namespace extensions
+} // namespace image_writer
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/image_writer_private/operation.h b/chrome/browser/extensions/api/image_writer_private/operation.h
index 5cc06f2..17a88e9 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation.h
+++ b/chrome/browser/extensions/api/image_writer_private/operation.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/md5.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "chrome/browser/extensions/api/image_writer_private/image_writer_utils.h"
#include "chrome/common/cancelable_task_tracker.h"
@@ -16,14 +17,14 @@
namespace image_writer_api = extensions::api::image_writer_private;
namespace base {
-
class FilePath;
-
-} // namespace base
+} // namespace base
namespace extensions {
namespace image_writer {
+const int kProgressComplete = 100;
+
class OperationManager;
// Encapsulates an operation being run on behalf of the
@@ -43,7 +44,7 @@
typedef base::Callback<void(bool, const std::string&)> CancelWriteCallback;
typedef std::string ExtensionId;
- Operation(OperationManager* manager,
+ Operation(base::WeakPtr<OperationManager> manager,
const ExtensionId& extension_id,
const std::string& storage_unit_id);
@@ -52,12 +53,11 @@
// Cancel the operation. This must be called to clean up internal state and
// cause the the operation to actually stop. It will not be destroyed until
- // all callbacks have completed. This method may be overridden to provide
- // subclass cancelling. It should still call the superclass method.
- virtual void Cancel();
+ // all callbacks have completed.
+ void Cancel();
// Aborts the operation, cancelling it and generating an error.
- virtual void Abort();
+ void Abort();
protected:
virtual ~Operation();
@@ -65,12 +65,21 @@
// |error_message| is used to create an OnWriteError event which is
// sent to the extension
virtual void Error(const std::string& error_message);
- // Sends a progress notification.
- void SendProgress();
+
+ // Set |progress_| and send an event. Progress should be in the interval
+ // [0,100]
+ void SetProgress(int progress);
+ // Change to a new |stage_| and set |progress_| to zero.
+ void SetStage(image_writer_api::Stage stage);
// Can be queried to safely determine if the operation has been cancelled.
bool IsCancelled();
+ // Adds a callback that will be called during clean-up, whether the operation
+ // is aborted, encounters and error, or finishes successfully. These
+ // functions will be run on the FILE thread.
+ void AddCleanUpFunction(base::Closure);
+
void UnzipStart(scoped_ptr<base::FilePath> zip_file);
void WriteStart();
void VerifyWriteStart();
@@ -89,34 +98,21 @@
int progress_scale,
const base::Callback<void(scoped_ptr<std::string>)>& callback);
- OperationManager* manager_;
+ base::WeakPtr<OperationManager> manager_;
const ExtensionId extension_id_;
- // This field is owned by the UI thread.
- image_writer_api::Stage stage_;
-
- // The amount of work completed for the current stage as a percentage. This
- // variable may be modified by both the FILE and UI threads, but it is only
- // modified by the basic activity flow of the operation which is logically
- // single threaded. Progress events will read this variable from the UI
- // thread which has the potential to read a value newer than when the event
- // was posted. However, the stage is never advanced except on the UI thread
- // and so will be later in the queue than those progress events. Thus
- // progress events may report higher progress numbers than when queued, but
- // will never report the wrong stage and appear to move backwards.
- int progress_;
-
base::FilePath image_path_;
const std::string storage_unit_id_;
private:
friend class base::RefCountedThreadSafe<Operation>;
+ // TODO(haven): Clean up these switches. http://crbug.com/292956
#if defined(OS_LINUX) && !defined(CHROMEOS)
void WriteRun();
void WriteChunk(scoped_ptr<image_writer_utils::ImageReader> reader,
scoped_ptr<image_writer_utils::ImageWriter> writer,
int64 bytes_written);
- bool WriteCleanup(scoped_ptr<image_writer_utils::ImageReader> reader,
+ bool WriteCleanUp(scoped_ptr<image_writer_utils::ImageReader> reader,
scoped_ptr<image_writer_utils::ImageWriter> writer);
void WriteComplete();
@@ -125,6 +121,18 @@
scoped_ptr<std::string> device_hash);
#endif
+#if defined(OS_CHROMEOS)
+ void StartWriteOnUIThread();
+
+ void OnBurnFinished(const std::string& target_path,
+ bool success,
+ const std::string& error);
+ void OnBurnProgress(const std::string& target_path,
+ int64 num_bytes_burnt,
+ int64 total_size);
+ void OnBurnError();
+#endif
+
void MD5Chunk(scoped_ptr<image_writer_utils::ImageReader> reader,
int64 bytes_processed,
int64 bytes_total,
@@ -132,13 +140,24 @@
int progress_scale,
const base::Callback<void(scoped_ptr<std::string>)>& callback);
+ // Runs all cleanup functions.
+ void CleanUp();
+
+ // |stage_| and |progress_| are owned by the FILE thread, use |SetStage| and
+ // |SetProgress| to update. Progress should be in the interval [0,100]
+ image_writer_api::Stage stage_;
+ int progress_;
+
// MD5 contexts don't play well with smart pointers. Just going to allocate
// memory here. This requires that we only do one MD5 sum at a time.
base::MD5Context md5_context_;
+ // CleanUp operations that must be run. All these functions are run on the
+ // FILE thread.
+ std::vector<base::Closure> cleanup_functions_;
};
-} // namespace image_writer
-} // namespace extensions
+} // namespace image_writer
+} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_OPERATION_H_
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc b/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
index 5aeb7f5..067614d 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
@@ -4,17 +4,84 @@
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
#include "chrome/browser/extensions/api/image_writer_private/operation.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/image_burner_client.h"
+#include "content/public/browser/browser_thread.h"
namespace extensions {
namespace image_writer {
+using chromeos::ImageBurnerClient;
+using content::BrowserThread;
+
+namespace {
+
+void ClearImageBurner() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ chromeos::DBusThreadManager::Get()->
+ GetImageBurnerClient()->
+ ResetEventHandlers();
+}
+
+void CleanUpImageBurner() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&ClearImageBurner));
+}
+
+} // namespace
+
void Operation::WriteStart() {
- Error(error::kUnsupportedOperation);
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ SetStage(image_writer_api::STAGE_WRITE);
+
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&Operation::StartWriteOnUIThread, this));
+
+ AddCleanUpFunction(base::Bind(&CleanUpImageBurner));
}
-void Operation::VerifyWriteStart() {
- Error(error::kUnsupportedOperation);
+void Operation::StartWriteOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DVLOG(1) << "Starting burn.";
+
+ ImageBurnerClient* burner =
+ chromeos::DBusThreadManager::Get()->GetImageBurnerClient();
+
+ burner->SetEventHandlers(
+ base::Bind(&Operation::OnBurnFinished, this),
+ base::Bind(&Operation::OnBurnProgress, this));
+
+ burner->BurnImage(image_path_.value(),
+ storage_unit_id_,
+ base::Bind(&Operation::OnBurnError, this));
}
-} // namespace image_writer
-} // namespace extensions
+void Operation::OnBurnFinished(const std::string& target_path,
+ bool success,
+ const std::string& error) {
+ DVLOG(1) << "Burn finished: " << success;
+
+ if (success) {
+ SetProgress(kProgressComplete);
+ Finish();
+ } else {
+ Error(error);
+ }
+}
+
+void Operation::OnBurnProgress(const std::string& target_path,
+ int64 num_bytes_burnt,
+ int64 total_size) {
+ int progress = kProgressComplete * num_bytes_burnt / total_size;
+ SetProgress(progress);
+}
+
+void Operation::OnBurnError() {
+ Error(error::kImageBurnerError);
+}
+
+} // namespace image_writer
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_linux.cc b/chrome/browser/extensions/api/image_writer_private/operation_linux.cc
index 1945053..8250363 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_linux.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_linux.cc
@@ -32,9 +32,7 @@
DVLOG(1) << "Starting write of " << image_path_.value()
<< " to " << storage_unit_id_;
- stage_ = image_writer_api::STAGE_WRITE;
- progress_ = 0;
- SendProgress();
+ SetStage(image_writer_api::STAGE_WRITE);
// TODO (haven): Unmount partitions before writing. http://crbug.com/284834
@@ -70,7 +68,7 @@
scoped_ptr<image_writer_utils::ImageWriter> writer,
int64 bytes_written) {
if (IsCancelled()) {
- WriteCleanup(reader.Pass(), writer.Pass());
+ WriteCleanUp(reader.Pass(), writer.Pass());
return;
}
@@ -80,12 +78,11 @@
if (len > 0) {
if (writer->Write(buffer, len) == len) {
- int percent_prev = bytes_written * 100 / image_size;
- int percent_curr = (bytes_written + len) * 100 / image_size;
- progress_ = (bytes_written + len) * 100 / image_size;
+ int percent_prev = kProgressComplete * bytes_written / image_size;
+ int percent_curr = kProgressComplete * (bytes_written + len) / image_size;
if (percent_curr > percent_prev) {
- SendProgress();
+ SetProgress(percent_curr);
}
BrowserThread::PostTask(
@@ -97,12 +94,12 @@
base::Passed(&writer),
bytes_written + len));
} else {
- WriteCleanup(reader.Pass(), writer.Pass());
+ WriteCleanUp(reader.Pass(), writer.Pass());
Error(error::kWriteImage);
}
} else if (len == 0) {
if (bytes_written == image_size) {
- if (WriteCleanup(reader.Pass(), writer.Pass())) {
+ if (WriteCleanUp(reader.Pass(), writer.Pass())) {
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
@@ -110,16 +107,16 @@
this));
}
} else {
- WriteCleanup(reader.Pass(), writer.Pass());
+ WriteCleanUp(reader.Pass(), writer.Pass());
Error(error::kPrematureEndOfFile);
}
} else { // len < 0
- WriteCleanup(reader.Pass(), writer.Pass());
+ WriteCleanUp(reader.Pass(), writer.Pass());
Error(error::kReadImage);
}
}
-bool Operation::WriteCleanup(
+bool Operation::WriteCleanUp(
scoped_ptr<image_writer_utils::ImageReader> reader,
scoped_ptr<image_writer_utils::ImageWriter> writer) {
@@ -139,8 +136,7 @@
void Operation::WriteComplete() {
DVLOG(2) << "Completed write of " << image_path_.value();
- progress_ = 100;
- SendProgress();
+ SetProgress(kProgressComplete);
BrowserThread::PostTask(
BrowserThread::FILE,
@@ -157,9 +153,7 @@
DVLOG(1) << "Starting verification stage.";
- stage_ = image_writer_api::STAGE_VERIFYWRITE;
- progress_ = 0;
- SendProgress();
+ SetStage(image_writer_api::STAGE_VERIFYWRITE);
scoped_ptr<base::FilePath> image_path(new base::FilePath(image_path_));
@@ -206,10 +200,10 @@
DVLOG(2) << "Completed write verification of " << image_path_.value();
- progress_ = 100;
- SendProgress();
+ SetProgress(kProgressComplete);
+
Finish();
}
-} // namespace image_writer
-} // namespace extensions
+} // namespace image_writer
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
index 3f34675..c6d8c85 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
@@ -27,7 +27,8 @@
using content::BrowserThread;
OperationManager::OperationManager(Profile* profile)
- : profile_(profile) {
+ : profile_(profile),
+ weak_factory_(this) {
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
content::Source<Profile>(profile_));
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
@@ -71,8 +72,12 @@
}
scoped_refptr<Operation> operation(
- new WriteFromUrlOperation(this, extension_id, rvh, url,
- hash, saveImageAsDownload,
+ new WriteFromUrlOperation(weak_factory_.GetWeakPtr(),
+ extension_id,
+ rvh,
+ url,
+ hash,
+ saveImageAsDownload,
storage_unit_id));
operations_[extension_id] = operation;
@@ -101,6 +106,9 @@
if (existing_operation == NULL) {
callback.Run(false, error::kNoOperationInProgress);
} else {
+ BrowserThread::PostTask(BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&Operation::Cancel, existing_operation));
DeleteOperation(extension_id);
callback.Run(true, "");
}
@@ -148,7 +156,6 @@
DLOG(ERROR) << "ImageWriter error: " << error_message;
// TODO(haven): Set up error messages. http://crbug.com/284880
-
info.stage = stage;
info.percent_complete = progress;
@@ -174,10 +181,6 @@
void OperationManager::DeleteOperation(const ExtensionId& extension_id) {
OperationMap::iterator existing_operation = operations_.find(extension_id);
if (existing_operation != operations_.end()) {
- BrowserThread::PostTask(BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&Operation::Cancel,
- existing_operation->second));
operations_.erase(existing_operation);
}
}
@@ -229,5 +232,5 @@
}
-} // namespace image_writer
-} // namespace extensions
+} // namespace image_writer
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_manager.h b/chrome/browser/extensions/api/image_writer_private/operation_manager.h
index f959745..d801e86 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_manager.h
+++ b/chrome/browser/extensions/api/image_writer_private/operation_manager.h
@@ -102,10 +102,12 @@
OperationMap operations_;
content::NotificationRegistrar registrar_;
+ base::WeakPtrFactory<OperationManager> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(OperationManager);
};
-} // namespace image_writer
-} // namespace extensions
+} // namespace image_writer
+} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_OPERATION_MANAGER_H_
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.cc b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.cc
index 73ecece..ddcf032 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.cc
@@ -10,7 +10,7 @@
namespace image_writer {
WriteFromFileOperation::WriteFromFileOperation(
- OperationManager* manager,
+ base::WeakPtr<OperationManager> manager,
const ExtensionId& extension_id,
const base::FilePath& path,
const std::string& storage_unit_id)
@@ -25,5 +25,5 @@
Error(error::kUnsupportedOperation);
}
-} // namespace image_writer
-} // namespace extensions
+} // namespace image_writer
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.h b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.h
index 478ae85..702bdf2 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.h
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.h
@@ -13,7 +13,7 @@
// Encapsulates a write of an image from a local file.
class WriteFromFileOperation : public Operation {
public:
- WriteFromFileOperation(OperationManager* manager,
+ WriteFromFileOperation(base::WeakPtr<OperationManager> manager,
const ExtensionId& extension_id,
const base::FilePath& path,
const std::string& storage_unit_id);
@@ -24,7 +24,7 @@
const base::FilePath path_;
};
-} // namespace image_writer
-} // namespace extensions
+} // namespace image_writer
+} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_WRITE_FROM_FILE_OPERATION_H_
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
index ad446ea..dec61bf 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
@@ -21,7 +21,7 @@
using content::BrowserThread;
WriteFromUrlOperation::WriteFromUrlOperation(
- OperationManager* manager,
+ base::WeakPtr<OperationManager> manager,
const ExtensionId& extension_id,
content::RenderViewHost* rvh,
GURL url,
@@ -33,20 +33,17 @@
url_(url),
hash_(hash),
saveImageAsDownload_(saveImageAsDownload),
- download_(NULL){
+ download_stopped_(false),
+ download_(NULL) {
}
WriteFromUrlOperation::~WriteFromUrlOperation() {
- if (stage_ == image_writer_api::STAGE_DOWNLOAD && download_) {
- download_->RemoveObserver(this);
- download_->Cancel(false);
- }
}
+
void WriteFromUrlOperation::Start() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- stage_ = image_writer_api::STAGE_DOWNLOAD;
- progress_ = 0;
+ SetStage(image_writer_api::STAGE_DOWNLOAD);
if (saveImageAsDownload_){
BrowserThread::PostTask(
@@ -59,16 +56,8 @@
FROM_HERE,
base::Bind(&WriteFromUrlOperation::CreateTempFile, this));
}
-}
-void WriteFromUrlOperation::Cancel() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- if (stage_ == image_writer_api::STAGE_DOWNLOAD && download_) {
- download_->RemoveObserver(this);
- download_->Cancel(true);
- }
-
- Operation::Cancel();
+ AddCleanUpFunction(base::Bind(&WriteFromUrlOperation::DownloadCleanUp, this));
}
void WriteFromUrlOperation::CreateTempFile() {
@@ -91,14 +80,12 @@
// The downloader runs on the UI thread.
void WriteFromUrlOperation::DownloadStart() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DVLOG(1) << "Starting download of URL: " << url_;
- if (IsCancelled()) {
+ if (download_stopped_) {
return;
}
- stage_ = image_writer_api::STAGE_DOWNLOAD;
- progress_ = 0;
+ DVLOG(1) << "Starting download of URL: " << url_;
Profile* current_profile = manager_->profile();
@@ -124,6 +111,14 @@
void WriteFromUrlOperation::OnDownloadStarted(content::DownloadItem* item,
net::Error error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (download_stopped_) {
+ // At this point DownloadCleanUp was called but the |download_| wasn't
+ // stored yet and still hasn't been cancelled.
+ item->Cancel(true);
+ return;
+ }
+
if (item) {
DCHECK_EQ(net::OK, error);
@@ -142,20 +137,14 @@
}
// Always called from the UI thread.
-void WriteFromUrlOperation::OnDownloadUpdated(
- content::DownloadItem* download) {
+void WriteFromUrlOperation::OnDownloadUpdated(content::DownloadItem* download) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (IsCancelled()) {
- download->Cancel(false);
+ if (download_stopped_) {
return;
}
- progress_ = download->PercentComplete();
-
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&WriteFromUrlOperation::SendProgress, this));
+ SetProgress(download->PercentComplete());
if (download->GetState() == content::DownloadItem::COMPLETE) {
download_path_ = download_->GetTargetFilePath();
@@ -176,15 +165,35 @@
}
void WriteFromUrlOperation::DownloadComplete() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
DVLOG(1) << "Download complete.";
- progress_ = 100;
- SendProgress();
+ SetProgress(kProgressComplete);
VerifyDownloadStart();
}
+void WriteFromUrlOperation::DownloadCleanUp() {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&WriteFromUrlOperation::DownloadCleanUp, this));
+ return;
+ }
+
+ download_stopped_ = true;
+
+ if (download_) {
+ download_->RemoveObserver(this);
+ download_->Cancel(true);
+ download_ = NULL;
+ }
+}
+
void WriteFromUrlOperation::VerifyDownloadStart() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
if (IsCancelled()) {
return;
}
@@ -199,10 +208,7 @@
DVLOG(1) << "Download verification started.";
- stage_ = image_writer_api::STAGE_VERIFYDOWNLOAD;
- progress_ = 0;
-
- SendProgress();
+ SetStage(image_writer_api::STAGE_VERIFYDOWNLOAD);
BrowserThread::PostTask(
BrowserThread::FILE,
@@ -211,17 +217,19 @@
}
void WriteFromUrlOperation::VerifyDownloadRun() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
scoped_ptr<base::FilePath> download_path(new base::FilePath(download_path_));
GetMD5SumOfFile(
download_path.Pass(),
0,
0,
- 100,
+ kProgressComplete,
base::Bind(&WriteFromUrlOperation::VerifyDownloadCompare, this));
}
void WriteFromUrlOperation::VerifyDownloadCompare(
scoped_ptr<std::string> download_hash) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (*download_hash != hash_) {
Error(error::kDownloadHash);
return;
@@ -234,14 +242,14 @@
}
void WriteFromUrlOperation::VerifyDownloadComplete() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (IsCancelled()) {
return;
}
DVLOG(1) << "Download verification complete.";
- progress_ = 100;
- SendProgress();
+ SetProgress(kProgressComplete);
scoped_ptr<base::FilePath> download_path(new base::FilePath(download_path_));
UnzipStart(download_path.Pass());
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
index 8ae0aa2..95e5574 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
@@ -26,14 +26,13 @@
class WriteFromUrlOperation : public Operation,
public content::DownloadItem::Observer {
public:
- WriteFromUrlOperation(OperationManager* manager,
+ WriteFromUrlOperation(base::WeakPtr<OperationManager> manager,
const ExtensionId& extension_id,
content::RenderViewHost* rvh,
GURL url,
const std::string& hash,
bool saveImageAsDownload,
const std::string& storage_unit_id);
- virtual void Cancel() OVERRIDE;
virtual void Start() OVERRIDE;
private:
virtual ~WriteFromUrlOperation();
@@ -43,19 +42,23 @@
void OnDownloadStarted(content::DownloadItem*, net::Error);
virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE;
void DownloadComplete();
+ void DownloadCleanUp();
void VerifyDownloadStart();
void VerifyDownloadRun();
void VerifyDownloadCompare(scoped_ptr<std::string> download_hash);
void VerifyDownloadComplete();
+ // Arguments
content::RenderViewHost* rvh_;
GURL url_;
const std::string hash_;
const bool saveImageAsDownload_;
- scoped_ptr<base::FilePath> tmp_file_;
- content::DownloadItem* download_;
+ // Local state
+ scoped_ptr<base::FilePath> tmp_file_;
+ bool download_stopped_;
+ content::DownloadItem* download_;
base::FilePath download_path_;
};
diff --git a/chrome/browser/extensions/api/input/input.cc b/chrome/browser/extensions/api/input/input.cc
index ca2adfc..c695bf1 100644
--- a/chrome/browser/extensions/api/input/input.cc
+++ b/chrome/browser/extensions/api/input/input.cc
@@ -26,7 +26,7 @@
namespace extensions {
-bool InsertTextFunction::RunImpl() {
+bool VirtualKeyboardPrivateInsertTextFunction::RunImpl() {
#if defined(USE_ASH)
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -39,7 +39,7 @@
return false;
}
-bool MoveCursorFunction::RunImpl() {
+bool VirtualKeyboardPrivateMoveCursorFunction::RunImpl() {
#if defined(USE_ASH)
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -55,7 +55,7 @@
return false;
}
-bool SendKeyEventFunction::RunImpl() {
+bool VirtualKeyboardPrivateSendKeyEventFunction::RunImpl() {
#if defined(USE_ASH)
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -83,7 +83,7 @@
return false;
}
-bool HideKeyboardFunction::RunImpl() {
+bool VirtualKeyboardPrivateHideKeyboardFunction::RunImpl() {
#if defined(USE_ASH)
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -97,12 +97,6 @@
}
InputAPI::InputAPI(Profile* profile) {
- ExtensionFunctionRegistry* registry =
- ExtensionFunctionRegistry::GetInstance();
- registry->RegisterFunction<InsertTextFunction>();
- registry->RegisterFunction<MoveCursorFunction>();
- registry->RegisterFunction<SendKeyEventFunction>();
- registry->RegisterFunction<HideKeyboardFunction>();
}
InputAPI::~InputAPI() {
diff --git a/chrome/browser/extensions/api/input/input.h b/chrome/browser/extensions/api/input/input.h
index c0d516c..8116ca0 100644
--- a/chrome/browser/extensions/api/input/input.h
+++ b/chrome/browser/extensions/api/input/input.h
@@ -13,51 +13,53 @@
namespace extensions {
-class InsertTextFunction : public SyncExtensionFunction {
+class VirtualKeyboardPrivateInsertTextFunction : public SyncExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("virtualKeyboardPrivate.insertText",
VIRTUALKEYBOARDPRIVATE_INSERTTEXT);
protected:
- virtual ~InsertTextFunction() {}
+ virtual ~VirtualKeyboardPrivateInsertTextFunction() {}
// ExtensionFunction:
virtual bool RunImpl() OVERRIDE;
};
-class MoveCursorFunction : public SyncExtensionFunction {
+class VirtualKeyboardPrivateMoveCursorFunction : public SyncExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("virtualKeyboardPrivate.moveCursor",
VIRTUALKEYBOARDPRIVATE_MOVECURSOR);
protected:
- virtual ~MoveCursorFunction() {}
+ virtual ~VirtualKeyboardPrivateMoveCursorFunction() {}
// ExtensionFunction.
virtual bool RunImpl() OVERRIDE;
};
-class SendKeyEventFunction : public SyncExtensionFunction {
+class VirtualKeyboardPrivateSendKeyEventFunction
+ : public SyncExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION(
"virtualKeyboardPrivate.sendKeyEvent",
VIRTUALKEYBOARDPRIVATE_SENDKEYEVENT);
protected:
- virtual ~SendKeyEventFunction() {}
+ virtual ~VirtualKeyboardPrivateSendKeyEventFunction() {}
// ExtensionFunction:
virtual bool RunImpl() OVERRIDE;
};
-class HideKeyboardFunction : public SyncExtensionFunction {
+class VirtualKeyboardPrivateHideKeyboardFunction
+ : public SyncExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION(
"virtualKeyboardPrivate.hideKeyboard",
VIRTUALKEYBOARDPRIVATE_HIDEKEYBOARD);
protected:
- virtual ~HideKeyboardFunction() {}
+ virtual ~VirtualKeyboardPrivateHideKeyboardFunction() {}
// ExtensionFunction:
virtual bool RunImpl() OVERRIDE;
diff --git a/chrome/browser/extensions/api/management/management_browsertest.cc b/chrome/browser/extensions/api/management/management_browsertest.cc
index 999ae85..ad12efc 100644
--- a/chrome/browser/extensions/api/management/management_browsertest.cc
+++ b/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -273,9 +273,7 @@
ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", extension->id());
ASSERT_EQ("1.0", extension->VersionString());
- // We don't want autoupdate blacklist checks.
extensions::ExtensionUpdater::CheckParams params;
- params.check_blacklist = false;
params.callback =
base::Bind(&NotificationListener::OnFinished,
base::Unretained(¬ification_listener));
@@ -361,9 +359,7 @@
ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", extension->id());
ASSERT_EQ("1.0", extension->VersionString());
- // We don't want autoupdate blacklist checks.
extensions::ExtensionUpdater::CheckParams params;
- params.check_blacklist = false;
params.callback =
base::Bind(&NotificationListener::OnFinished,
base::Unretained(¬ification_listener));
@@ -405,9 +401,7 @@
ExtensionService* service = extensions::ExtensionSystem::Get(
browser()->profile())->extension_service();
const char* kExtensionId = "ogjcoiohnmldgjemafoockdghcjciccf";
- // We don't want autoupdate blacklist checks.
extensions::ExtensionUpdater::CheckParams params;
- params.check_blacklist = false;
base::FilePath basedir = test_data_dir_.AppendASCII("autoupdate");
@@ -491,9 +485,6 @@
ExtensionService* service = extensions::ExtensionSystem::Get(
browser()->profile())->extension_service();
const char* kExtensionId = "ogjcoiohnmldgjemafoockdghcjciccf";
- // We don't want autoupdate blacklist checks.
- extensions::ExtensionUpdater::CheckParams params;
- params.check_blacklist = false;
base::FilePath basedir = test_data_dir_.AppendASCII("autoupdate");
@@ -566,7 +557,6 @@
browser()->profile())->extension_service();
const char* kExtensionId = "ogjcoiohnmldgjemafoockdghcjciccf";
extensions::ExtensionUpdater::CheckParams params;
- params.check_blacklist = false;
service->updater()->set_default_check_params(params);
const size_t size_before = service->extensions()->size();
base::FilePath basedir = test_data_dir_.AppendASCII("autoupdate");
diff --git a/chrome/browser/extensions/api/mdns/dns_sd_device_lister.cc b/chrome/browser/extensions/api/mdns/dns_sd_device_lister.cc
index 9d3bd3d..fdb7fe4 100644
--- a/chrome/browser/extensions/api/mdns/dns_sd_device_lister.cc
+++ b/chrome/browser/extensions/api/mdns/dns_sd_device_lister.cc
@@ -7,15 +7,14 @@
#include <utility>
#include "base/bind.h"
-#include "chrome/browser/local_discovery/service_discovery_host_client.h"
+#include "chrome/browser/local_discovery/service_discovery_shared_client.h"
#include "chrome/common/extensions/api/mdns.h"
-#include "chrome/common/local_discovery/service_discovery_client.h"
#include "net/base/net_util.h"
using local_discovery::ServiceDescription;
+using local_discovery::ServiceDiscoverySharedClient;
using local_discovery::ServiceResolver;
using local_discovery::ServiceWatcher;
-using local_discovery::ServiceDiscoverySharedClient;
namespace extensions {
@@ -25,7 +24,10 @@
DnsSdService* service) {
service->service_name = service_description.service_name;
service->service_host_port = service_description.address.ToString();
- service->ip_address = net::IPAddressToString(service_description.ip_address);
+ if (!service_description.ip_address.empty()) {
+ service->ip_address = net::IPAddressToString(
+ service_description.ip_address);
+ }
service->service_data = service_description.metadata;
DVLOG(1) << "Found " << service->service_name << ", "
@@ -102,6 +104,7 @@
DnsSdService service;
FillServiceInfo(service_description, &service);
+ resolvers_.erase(service_description.service_name);
delegate_->ServiceChanged(service_type_, added, service);
}
diff --git a/chrome/browser/extensions/api/mdns/dns_sd_device_lister.h b/chrome/browser/extensions/api/mdns/dns_sd_device_lister.h
index 3e747ca..4c6f49c 100644
--- a/chrome/browser/extensions/api/mdns/dns_sd_device_lister.h
+++ b/chrome/browser/extensions/api/mdns/dns_sd_device_lister.h
@@ -12,7 +12,11 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/api/mdns/dns_sd_delegate.h"
-#include "chrome/browser/local_discovery/service_discovery_host_client.h"
+#include "chrome/common/local_discovery/service_discovery_client.h"
+
+namespace local_discovery {
+class ServiceDiscoverySharedClient;
+} // local_discovery
namespace extensions {
diff --git a/chrome/browser/extensions/api/mdns/dns_sd_registry.cc b/chrome/browser/extensions/api/mdns/dns_sd_registry.cc
index f613a70..6a72fc5 100644
--- a/chrome/browser/extensions/api/mdns/dns_sd_registry.cc
+++ b/chrome/browser/extensions/api/mdns/dns_sd_registry.cc
@@ -6,8 +6,9 @@
#include "base/stl_util.h"
#include "chrome/browser/extensions/api/mdns/dns_sd_device_lister.h"
-#include "chrome/browser/local_discovery/service_discovery_host_client.h"
+#include "chrome/browser/local_discovery/service_discovery_shared_client.h"
+using local_discovery::ServiceDiscoveryClient;
using local_discovery::ServiceDiscoverySharedClient;
namespace extensions {
@@ -24,10 +25,8 @@
private:
const DnsSdService& service_;
};
-
} // namespace
-
DnsSdRegistry::ServiceTypeData::ServiceTypeData(
scoped_ptr<DnsSdDeviceLister> lister)
: ref_count(1), lister_(lister.Pass()) {}
@@ -80,7 +79,7 @@
}
DnsSdRegistry::DnsSdRegistry() {
-#if defined(ENABLE_MDNS)
+#if defined(ENABLE_MDNS) || defined(OS_MACOSX)
service_discovery_client_ = ServiceDiscoverySharedClient::GetInstance();
#endif
}
@@ -89,8 +88,7 @@
service_discovery_client_ = client;
}
-DnsSdRegistry::~DnsSdRegistry() {
-}
+DnsSdRegistry::~DnsSdRegistry() {}
void DnsSdRegistry::AddObserver(DnsSdObserver* observer) {
observers_.AddObserver(observer);
@@ -112,7 +110,7 @@
return;
if (service_data_map_.find(service_type) != service_data_map_.end()) {
- service_data_map_[service_type].get()->ListenerAdded();
+ service_data_map_[service_type]->ListenerAdded();
DispatchApiEvent(service_type);
return;
}
@@ -132,7 +130,7 @@
if (it == service_data_map_.end())
return;
- if (service_data_map_[service_type].get()->ListenerRemoved())
+ if (service_data_map_[service_type]->ListenerRemoved())
service_data_map_.erase(it);
}
@@ -142,7 +140,7 @@
if (service_data_map_.find(service_type) == service_data_map_.end())
return;
- if (service_data_map_[service_type].get()->UpdateService(added, service)) {
+ if (service_data_map_[service_type]->UpdateService(added, service)) {
DispatchApiEvent(service_type);
} else {
DVLOG(1) << "Failed to find existing service to update: "
@@ -155,7 +153,7 @@
if (service_data_map_.find(service_type) == service_data_map_.end())
return;
- if (service_data_map_[service_type].get()->RemoveService(service_name)) {
+ if (service_data_map_[service_type]->RemoveService(service_name)) {
DispatchApiEvent(service_type);
} else {
DVLOG(1) << "Failed to remove service: " << service_name;
@@ -164,7 +162,7 @@
void DnsSdRegistry::DispatchApiEvent(const std::string& service_type) {
FOR_EACH_OBSERVER(DnsSdObserver, observers_, OnDnsSdEvent(
- service_type, service_data_map_[service_type].get()->GetServiceList()));
+ service_type, service_data_map_[service_type]->GetServiceList()));
}
} // namespace extensions
diff --git a/chrome/browser/extensions/api/mdns/dns_sd_registry.h b/chrome/browser/extensions/api/mdns/dns_sd_registry.h
index 3cb1086..79d8988 100644
--- a/chrome/browser/extensions/api/mdns/dns_sd_registry.h
+++ b/chrome/browser/extensions/api/mdns/dns_sd_registry.h
@@ -17,6 +17,7 @@
namespace local_discovery {
class ServiceDiscoverySharedClient;
+class ServiceDiscoveryClient;
}
namespace extensions {
diff --git a/chrome/browser/extensions/api/mdns/mdns_api.cc b/chrome/browser/extensions/api/mdns/mdns_api.cc
index 237ecb6..1832372 100644
--- a/chrome/browser/extensions/api/mdns/mdns_api.cc
+++ b/chrome/browser/extensions/api/mdns/mdns_api.cc
@@ -19,10 +19,12 @@
// Whitelisted mDNS service types.
const char kCastServiceType[] = "_googlecast._tcp.local";
+const char kPrivetServiceType[] = "_privet._tcp.local";
const char kTestServiceType[] = "_testing._tcp.local";
bool IsServiceTypeWhitelisted(const std::string& service_type) {
return service_type == kCastServiceType ||
+ service_type == kPrivetServiceType ||
service_type == kTestServiceType;
}
@@ -125,8 +127,6 @@
void MDnsAPI::OnDnsSdEvent(const std::string& service_type,
const DnsSdRegistry::DnsSdServiceList& services) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (services.size() == 0)
- return;
std::vector<linked_ptr<mdns::MDnsService> > args;
for (DnsSdRegistry::DnsSdServiceList::const_iterator it = services.begin();
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 42a6b49..fe8a857 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
@@ -20,6 +20,7 @@
#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_histograms.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/storage_monitor/storage_monitor.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
@@ -81,6 +82,7 @@
if (!ApiIsAccessible(&error_))
return false;
+ media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS);
scoped_ptr<GetMediaFileSystems::Params> params(
GetMediaFileSystems::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
@@ -205,6 +207,7 @@
}
void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() {
+ media_galleries::UsageCount(media_galleries::SHOW_DIALOG);
WebContents* contents = WebContents::FromRenderViewHost(render_view_host());
WebContentsModalDialogManager* web_contents_modal_dialog_manager =
WebContentsModalDialogManager::FromWebContents(contents);
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
index 8d8b341..811ba90 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
@@ -2,26 +2,23 @@
// 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/bind_helpers.h"
-#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/strings/stringprintf.h"
+#include "base/json/json_writer.h"
+#include "base/path_service.h"
+#include "base/safe_numerics.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "chrome/browser/apps/app_browsertest_util.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/media_galleries/media_file_system_registry.h"
#include "chrome/browser/media_galleries/media_galleries_preferences.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/ui/browser.h"
-#include "content/public/browser/render_view_host.h"
+#include "chrome/common/chrome_paths.h"
#include "content/public/test/test_utils.h"
-#include "extensions/common/switches.h"
using extensions::PlatformAppBrowserTest;
@@ -36,8 +33,6 @@
base::FilePath::CharType kDevicePath[] = FILE_PATH_LITERAL("/qux");
#endif
-const char kTestGalleries[] = "testGalleries(%d)";
-
} // namespace
// This function is to ensure at least one (fake) media gallery exists for
@@ -66,18 +61,36 @@
class MediaGalleriesPlatformAppBrowserTest : public PlatformAppBrowserTest {
protected:
- // Since ExtensionTestMessageListener does not work with RunPlatformAppTest(),
- // This helper method can be used to run additional media gallery tests.
- void RunSecondTestPhase(const string16& command) {
- const extensions::Extension* extension = GetSingleLoadedExtension();
- extensions::ExtensionHost* host =
- extensions::ExtensionSystem::Get(browser()->profile())->
- process_manager()->GetBackgroundHostForExtension(extension->id());
- ASSERT_TRUE(host);
+ MediaGalleriesPlatformAppBrowserTest() : test_jpg_size_(0) {}
+ virtual ~MediaGalleriesPlatformAppBrowserTest() {}
- ResultCatcher catcher;
- host->render_view_host()->ExecuteJavascriptInWebFrame(string16(), command);
- EXPECT_TRUE(catcher.GetNextResult()) << message_;
+ virtual void SetUpOnMainThread() OVERRIDE {
+ PlatformAppBrowserTest::SetUpOnMainThread();
+ ensure_media_directories_exist_.reset(new EnsureMediaDirectoriesExists);
+ PopulatePicturesDirectoryTestData();
+ }
+
+ virtual void TearDownOnMainThread() OVERRIDE {
+ ensure_media_directories_exist_.reset();
+ PlatformAppBrowserTest::TearDownOnMainThread();
+ }
+
+ bool RunMediaGalleriesTest(const std::string& extension_name) {
+ base::ListValue empty_list_value;
+ return RunMediaGalleriesTestWithArg(extension_name, empty_list_value);
+ }
+
+ bool RunMediaGalleriesTestWithArg(const std::string& extension_name,
+ const base::ListValue& custom_arg_value) {
+ const char* custom_arg = NULL;
+ std::string json_string;
+ if (!custom_arg_value.empty()) {
+ base::JSONWriter::Write(&custom_arg_value, &json_string);
+ custom_arg = json_string.c_str();
+ }
+
+ const char kTestDir[] = "api_test/media_galleries/";
+ return RunPlatformAppTestWithArg(kTestDir + extension_name, custom_arg);
}
void AttachFakeDevice() {
@@ -85,8 +98,9 @@
StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM, kDeviceId);
StorageMonitor::GetInstance()->receiver()->ProcessAttach(
- StorageInfo(device_id_, string16(), kDevicePath,
- ASCIIToUTF16(kDeviceName), string16(), string16(), 0));
+ StorageInfo(device_id_, base::string16(), kDevicePath,
+ ASCIIToUTF16(kDeviceName), base::string16(),
+ base::string16(), 0));
content::RunAllPendingInMessageLoop();
}
@@ -95,81 +109,102 @@
content::RunAllPendingInMessageLoop();
}
+ void PopulatePicturesDirectoryTestData() {
+ if (ensure_media_directories_exist_->num_galleries() == 0)
+ return;
+
+ base::FilePath test_data_path =
+ test_data_dir_.AppendASCII("api_test")
+ .AppendASCII("media_galleries")
+ .AppendASCII("common");
+ base::FilePath write_path;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_USER_PICTURES, &write_path));
+
+ // Valid file, should show up in JS as a FileEntry.
+ ASSERT_TRUE(base::CopyFile(test_data_path.AppendASCII("test.jpg"),
+ write_path.AppendASCII("test.jpg")));
+
+ // Invalid file, should not show up as a FileEntry in JS at all.
+ ASSERT_TRUE(base::CopyFile(test_data_path.AppendASCII("test.txt"),
+ write_path.AppendASCII("test.txt")));
+
+ int64 file_size;
+ ASSERT_TRUE(file_util::GetFileSize(test_data_path.AppendASCII("test.jpg"),
+ &file_size));
+ test_jpg_size_ = base::checked_numeric_cast<int>(file_size);
+ }
+
+ int num_galleries() const {
+ return ensure_media_directories_exist_->num_galleries();
+ }
+
+ int test_jpg_size() const { return test_jpg_size_; }
+
private:
std::string device_id_;
+ int test_jpg_size_;
+ scoped_ptr<EnsureMediaDirectoriesExists> ensure_media_directories_exist_;
};
IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
MediaGalleriesNoAccess) {
- EnsureMediaDirectoriesExists media_directories;
- ASSERT_TRUE(RunPlatformAppTest("api_test/media_galleries/no_access"))
+ base::ListValue custom_args;
+ custom_args.AppendInteger(num_galleries());
+
+ ASSERT_TRUE(RunMediaGalleriesTestWithArg("no_access", custom_args))
<< message_;
- RunSecondTestPhase(base::UTF8ToUTF16(base::StringPrintf(
- kTestGalleries, media_directories.num_galleries())));
}
IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, NoGalleriesRead) {
- EnsureMediaDirectoriesExists media_directories;
- ASSERT_TRUE(RunPlatformAppTest("api_test/media_galleries/no_galleries"))
- << message_;
+ ASSERT_TRUE(RunMediaGalleriesTest("no_galleries")) << message_;
}
IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
NoGalleriesCopyTo) {
- EnsureMediaDirectoriesExists media_directories;
- ASSERT_TRUE(RunPlatformAppTest(
- "api_test/media_galleries/no_galleries_copy_to")) << message_;
+ ASSERT_TRUE(RunMediaGalleriesTest("no_galleries_copy_to")) << message_;
}
IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
MediaGalleriesRead) {
- EnsureMediaDirectoriesExists media_directories;
- ASSERT_TRUE(RunPlatformAppTest("api_test/media_galleries/read_access"))
+ base::ListValue custom_args;
+ custom_args.AppendInteger(num_galleries());
+ custom_args.AppendInteger(test_jpg_size());
+
+ ASSERT_TRUE(RunMediaGalleriesTestWithArg("read_access", custom_args))
<< message_;
- RunSecondTestPhase(base::UTF8ToUTF16(base::StringPrintf(
- kTestGalleries, media_directories.num_galleries())));
}
IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
MediaGalleriesCopyTo) {
- EnsureMediaDirectoriesExists media_directories;
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
MakeFakeMediaGalleryForTest(browser()->profile(), temp_dir.path());
- ASSERT_TRUE(RunPlatformAppTest("api_test/media_galleries/copy_to_access"))
- << message_;
+ ASSERT_TRUE(RunMediaGalleriesTest("copy_to_access")) << message_;
}
IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
MediaGalleriesCopyToNoAccess) {
- EnsureMediaDirectoriesExists media_directories;
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
MakeFakeMediaGalleryForTest(browser()->profile(), temp_dir.path());
- ASSERT_TRUE(RunPlatformAppTest(
- "api_test/media_galleries/copy_to_access/no_access"))
- << message_;
+ ASSERT_TRUE(RunMediaGalleriesTest("copy_to_access/no_access")) << message_;
}
IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
MediaGalleriesAccessAttached) {
- EnsureMediaDirectoriesExists media_directories;
-
AttachFakeDevice();
- ASSERT_TRUE(RunPlatformAppTest("api_test/media_galleries/access_attached"))
- << message_;
+ base::ListValue custom_args;
+ custom_args.AppendInteger(num_galleries() + 1);
+ custom_args.AppendString(kDeviceName);
- RunSecondTestPhase(ASCIIToUTF16(base::StringPrintf(
- "testGalleries(%d, \"%s\")",
- media_directories.num_galleries() + 1, kDeviceName)));
+ ASSERT_TRUE(RunMediaGalleriesTestWithArg("access_attached", custom_args))
+ << message_;
DetachFakeDevice();
}
IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
GetFilesystemMetadata) {
- EnsureMediaDirectoriesExists media_directories;
- ASSERT_TRUE(RunPlatformAppTest("api_test/media_galleries/metadata"))
- << message_;
+ ASSERT_TRUE(RunMediaGalleriesTest("metadata")) << message_;
}
diff --git a/chrome/browser/extensions/api/media_galleries_private/media_galleries_watch_apitest.cc b/chrome/browser/extensions/api/media_galleries_private/media_galleries_watch_apitest.cc
index 6a2c75d..bc98bb1 100644
--- a/chrome/browser/extensions/api/media_galleries_private/media_galleries_watch_apitest.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/media_galleries_watch_apitest.cc
@@ -27,35 +27,41 @@
const char kTestExtensionPath[] = "media_galleries_private/gallerywatch";
// JS commands.
-const char kAddGalleryChangedListenerCmd[] = "addGalleryChangedListener()";
const char kGetAllWatchedGalleryIdsCmd[] = "getAllWatchedGalleryIds()";
const char kGetMediaFileSystemsCmd[] = "getMediaFileSystems()";
+const char kSetupWatchOnValidGalleriesCmd[] = "setupWatchOnValidGalleries()";
+#if defined(OS_WIN)
+const char kAddGalleryChangedListenerCmd[] = "addGalleryChangedListener()";
const char kRemoveAllGalleryWatchCmd[] = "removeAllGalleryWatch()";
const char kRemoveGalleryChangedListenerCmd[] =
"removeGalleryChangedListener()";
const char kRemoveGalleryWatchCmd[] = "removeGalleryWatch()";
-const char kSetupWatchOnValidGalleriesCmd[] = "setupWatchOnValidGalleries()";
const char kSetupWatchOnInvalidGalleryCmd[] = "setupWatchOnInvalidGallery()";
+#endif // defined(OS_WIN)
// And JS reply messages.
const char kAddGalleryWatchOK[] = "add_gallery_watch_ok";
-const char kAddGalleryChangedListenerOK[] = "add_gallery_changed_listener_ok";
const char kGetAllGalleryWatchOK[] = "get_all_gallery_watch_ok";
-const char kGetMediaFileSystemsOK[] = "get_media_file_systems_ok";
const char kGetMediaFileSystemsCallbackOK[] =
"get_media_file_systems_callback_ok";
+const char kGetMediaFileSystemsOK[] = "get_media_file_systems_ok";
+#if defined(OS_WIN)
+const char kAddGalleryChangedListenerOK[] = "add_gallery_changed_listener_ok";
const char kRemoveAllGalleryWatchOK[] = "remove_all_gallery_watch_ok";
const char kRemoveGalleryChangedListenerOK[] =
"remove_gallery_changed_listener_ok";
const char kRemoveGalleryWatchOK[] = "remove_gallery_watch_ok";
+#endif // defined(OS_WIN)
// Test reply messages.
-const char kAddGalleryWatchRequestSucceeded[] = "add_watch_request_succeeded";
-const char kAddGalleryWatchRequestFailed[] = "add_watch_request_failed";
-const char kGalleryChangedEventReceived[] = "gallery_changed_event_received";
const char kGetAllGalleryWatchResultA[] = "gallery_watchers_does_not_exists";
+const char kAddGalleryWatchRequestFailed[] = "add_watch_request_failed";
+#if defined(OS_WIN)
+const char kAddGalleryWatchRequestSucceeded[] = "add_watch_request_succeeded";
+const char kGalleryChangedEventReceived[] = "gallery_changed_event_received";
const char kGetAllGalleryWatchResultB[] =
"watchers_for_galleries_{1, 2, 3}_found";
+#endif // defined(OS_WIN)
} // namespace
diff --git a/chrome/browser/extensions/api/messaging/message_service.cc b/chrome/browser/extensions/api/messaging/message_service.cc
index be6d2fe..cd29d98 100644
--- a/chrome/browser/extensions/api/messaging/message_service.cc
+++ b/chrome/browser/extensions/api/messaging/message_service.cc
@@ -27,6 +27,7 @@
#include "chrome/common/extensions/background_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_messages.h"
+#include "chrome/common/extensions/features/simple_feature.h"
#include "chrome/common/extensions/incognito_handler.h"
#include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
#include "content/public/browser/browser_thread.h"
@@ -57,14 +58,10 @@
namespace extensions {
-namespace {
const char kReceivingEndDoesntExistError[] =
"Could not establish connection. Receiving end does not exist.";
const char kMissingPermissionError[] =
"Access to native messaging requires nativeMessaging permission.";
-const char kNativeMessagingNotSupportedError[] =
- "Native Messaging is not supported on this platform.";
-}
struct MessageService::MessageChannel {
scoped_ptr<MessagePort> opener;
@@ -210,9 +207,17 @@
if (profile->IsOffTheRecord() &&
!extension_service->IsIncognitoEnabled(target_extension_id)) {
- DispatchOnDisconnect(
- source, receiver_port_id, kReceivingEndDoesntExistError);
- return;
+ // Allow the security token apps (normal, dev) to be connectable from
+ // incognito profiles. See http://crbug.com/295845.
+ std::set<std::string> incognito_whitelist;
+ incognito_whitelist.insert("E4FCC42F7C7776C0985996DAED74F630C4F0A785");
+ incognito_whitelist.insert("D3D12919F7F00FE553E8A573AAA7147C51DD65C9");
+ if (!extensions::SimpleFeature::IsIdInWhitelist(target_extension_id,
+ incognito_whitelist)) {
+ DispatchOnDisconnect(
+ source, receiver_port_id, kReceivingEndDoesntExistError);
+ return;
+ }
}
if (source_extension_id != target_extension_id) {
@@ -349,6 +354,8 @@
AddChannel(channel.release(), receiver_port_id);
#else // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX))
+ const char kNativeMessagingNotSupportedError[] =
+ "Native Messaging is not supported on this platform.";
DispatchOnDisconnect(
source, receiver_port_id, kNativeMessagingNotSupportedError);
#endif // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX))
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
index 0f8992e..46ae624 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -24,9 +24,11 @@
namespace {
+#if defined(OS_WIN)
// Name of the command line switch used to pass handle of the native view to
// the native messaging host.
const char kParentWindowSwitchName[] = "parent-window";
+#endif // defined(OS_WIN)
base::FilePath GetHostManifestPathFromCommandLine(
const std::string& native_host_name) {
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 9913f5f..d019580 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
@@ -128,12 +128,8 @@
string16 command_line_string = command_line.GetCommandLineString();
- // 'start' command has a moronic syntax: if first argument is quoted then it
- // interprets it as a command title. Host path may need to be in quotes, so
- // we always need to specify the title as the first argument.
string16 command = base::StringPrintf(
- L"%ls /c start \"Chrome Native Messaging Host\" /b "
- L"%ls < %ls > %ls",
+ L"%ls /c %ls < %ls > %ls",
comspec.get(), command_line_string.c_str(),
in_pipe_name.c_str(), out_pipe_name.c_str());
@@ -158,19 +154,6 @@
return false;
}
- // Check that cmd.exe has completed with 0 exit code to make sure it was
- // able to connect IO pipes.
- int error_code;
- if (!base::WaitForExitCodeWithTimeout(
- cmd_handle, &error_code,
- base::TimeDelta::FromMilliseconds(kTimeoutMs)) ||
- error_code != 0) {
- LOG(ERROR) << "cmd.exe did not exit cleanly";
- base::KillProcess(cmd_handle, 0, false);
- base::CloseProcessHandle(cmd_handle);
- return false;
- }
-
base::CloseProcessHandle(cmd_handle);
*read_file = stdout_pipe.Take();
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_chromeos.cc b/chrome/browser/extensions/api/music_manager_private/device_id_chromeos.cc
index e1e0dac..0dbbf6e 100644
--- a/chrome/browser/extensions/api/music_manager_private/device_id_chromeos.cc
+++ b/chrome/browser/extensions/api/music_manager_private/device_id_chromeos.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/api/music_manager_private/device_id.h"
+#include "base/message_loop/message_loop.h"
#include "chromeos/cryptohome/cryptohome_library.h"
namespace extensions {
@@ -14,6 +15,15 @@
void DeviceId::GetMachineId(const IdCallback& callback) {
chromeos::CryptohomeLibrary* c_home = chromeos::CryptohomeLibrary::Get();
std::string result = c_home->GetSystemSalt();
+ if (result.empty()) {
+ // cryptohome must not be running; re-request after a delay.
+ const int64 kRequestSystemSaltDelayMs = 500;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&DeviceId::GetMachineId, callback),
+ base::TimeDelta::FromMilliseconds(kRequestSystemSaltDelayMs));
+ return;
+ }
callback.Run(result);
}
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
index ead08cb..56c6fb9 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
@@ -35,12 +35,11 @@
namespace chromeos {
-namespace {
-
+#if defined(OS_CHROMEOS)
const char kUser1ProfilePath[] = "/profile/user1/shill";
const char kUserIdStubHashSuffix[] = "-hash";
+#endif // defined(OS_CHROMEOS)
-} // namespace
class ExtensionNetworkingPrivateApiTest :
public ExtensionApiTest,
@@ -120,45 +119,45 @@
profile_test->AddProfile(kUser1ProfilePath, userhash_);
device_test->AddDevice("/device/stub_wifi_device1",
- flimflam::kTypeWifi, "stub_wifi_device1");
+ shill::kTypeWifi, "stub_wifi_device1");
device_test->AddDevice("/device/stub_cellular_device1",
- flimflam::kTypeCellular, "stub_cellular_device1");
+ shill::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,
+ shill::kTypeEthernet, shill::kStateOnline,
add_to_visible, add_to_watchlist);
service_test->AddService("stub_wifi1", "wifi1",
- flimflam::kTypeWifi, flimflam::kStateOnline,
+ shill::kTypeWifi, shill::kStateOnline,
add_to_visible, add_to_watchlist);
service_test->SetServiceProperty("stub_wifi1",
- flimflam::kSecurityProperty,
- base::StringValue(flimflam::kSecurityWep));
+ shill::kSecurityProperty,
+ base::StringValue(shill::kSecurityWep));
base::ListValue frequencies1;
frequencies1.AppendInteger(2400);
service_test->SetServiceProperty("stub_wifi1",
shill::kWifiFrequencyListProperty,
frequencies1);
service_test->SetServiceProperty("stub_wifi1",
- flimflam::kWifiFrequency,
+ shill::kWifiFrequency,
base::FundamentalValue(2400));
service_test->AddService("stub_wifi2", "wifi2_PSK",
- flimflam::kTypeWifi, flimflam::kStateIdle,
+ shill::kTypeWifi, shill::kStateIdle,
add_to_visible, add_to_watchlist);
service_test->SetServiceProperty("stub_wifi2",
- flimflam::kGuidProperty,
+ shill::kGuidProperty,
base::StringValue("stub_wifi2"));
service_test->SetServiceProperty("stub_wifi2",
- flimflam::kSecurityProperty,
- base::StringValue(flimflam::kSecurityPsk));
+ shill::kSecurityProperty,
+ base::StringValue(shill::kSecurityPsk));
service_test->SetServiceProperty("stub_wifi2",
- flimflam::kSignalStrengthProperty,
+ shill::kSignalStrengthProperty,
base::FundamentalValue(80));
service_test->SetServiceProperty("stub_wifi2",
- flimflam::kConnectableProperty,
+ shill::kConnectableProperty,
base::FundamentalValue(true));
base::ListValue frequencies2;
@@ -168,32 +167,32 @@
shill::kWifiFrequencyListProperty,
frequencies2);
service_test->SetServiceProperty("stub_wifi2",
- flimflam::kWifiFrequency,
+ shill::kWifiFrequency,
base::FundamentalValue(5000));
service_test->SetServiceProperty("stub_wifi2",
- flimflam::kProfileProperty,
+ shill::kProfileProperty,
base::StringValue(kUser1ProfilePath));
profile_test->AddService(kUser1ProfilePath, "stub_wifi2");
service_test->AddService("stub_cellular1", "cellular1",
- flimflam::kTypeCellular, flimflam::kStateIdle,
+ shill::kTypeCellular, shill::kStateIdle,
add_to_visible, add_to_watchlist);
service_test->SetServiceProperty(
"stub_cellular1",
- flimflam::kNetworkTechnologyProperty,
- base::StringValue(flimflam::kNetworkTechnologyGsm));
+ shill::kNetworkTechnologyProperty,
+ base::StringValue(shill::kNetworkTechnologyGsm));
service_test->SetServiceProperty(
"stub_cellular1",
- flimflam::kActivationStateProperty,
- base::StringValue(flimflam::kActivationStateNotActivated));
+ shill::kActivationStateProperty,
+ base::StringValue(shill::kActivationStateNotActivated));
service_test->SetServiceProperty(
"stub_cellular1",
- flimflam::kRoamingStateProperty,
- base::StringValue(flimflam::kRoamingStateHome));
+ shill::kRoamingStateProperty,
+ base::StringValue(shill::kRoamingStateHome));
service_test->AddService("stub_vpn1", "vpn1",
- flimflam::kTypeVPN,
- flimflam::kStateOnline,
+ shill::kTypeVPN,
+ shill::kStateOnline,
add_to_visible, add_to_watchlist);
manager_test->SortManagerServices();
@@ -294,10 +293,10 @@
" }"
"}";
service_test->SetServiceProperty("stub_wifi2",
- flimflam::kUIDataProperty,
+ shill::kUIDataProperty,
base::StringValue(uidata_blob));
service_test->SetServiceProperty("stub_wifi2",
- flimflam::kAutoConnectProperty,
+ shill::kAutoConnectProperty,
base::FundamentalValue(false));
ShillProfileClient::TestInterface* profile_test =
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc
index e78798e..af0b67d 100644
--- a/chrome/browser/extensions/api/notifications/notifications_api.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -36,7 +36,6 @@
namespace {
-const char kResultKey[] = "result";
const char kMissingRequiredPropertiesForCreateNotification[] =
"Some of the required properties are missing: type, iconUrl, title and "
"message.";
@@ -102,8 +101,7 @@
}
// TODO(dewittj): Handle HiDPI images.
- ui::ScaleFactor scale_factor(ui::SCALE_FACTOR_100P);
- gfx::ImageSkia skia(gfx::ImageSkiaRep(bitmap, scale_factor));
+ gfx::ImageSkia skia(gfx::ImageSkiaRep(bitmap, 1.0f));
*return_image = gfx::Image(skia);
return true;
}
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api.cc b/chrome/browser/extensions/api/omnibox/omnibox_api.cc
index 585b39e..55c7da8 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_api.cc
+++ b/chrome/browser/extensions/api/omnibox/omnibox_api.cc
@@ -36,12 +36,6 @@
namespace {
const char kSuggestionContent[] = "content";
-const char kSuggestionDescription[] = "description";
-const char kSuggestionDescriptionStyles[] = "descriptionStyles";
-const char kSuggestionDescriptionStylesRaw[] = "descriptionStylesRaw";
-const char kDescriptionStylesType[] = "type";
-const char kDescriptionStylesOffset[] = "offset";
-const char kDescriptionStylesLength[] = "length";
const char kCurrentTabDisposition[] = "currentTab";
const char kForegroundTabDisposition[] = "newForegroundTab";
const char kBackgroundTabDisposition[] = "newBackgroundTab";
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 d9fdf77..cae3129 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
@@ -37,14 +37,11 @@
using content::BrowserThread;
-namespace {
const char kChannelIdSeparator[] = "/";
const char kUserNotSignedIn[] = "The user is not signed in.";
const char kUserAccessTokenFailure[] =
"Cannot obtain access token for the user.";
-const char kTokenServiceNotAvailable[] = "Failed to get token service.";
const int kObfuscatedGaiaIdTimeoutInDays = 30;
-}
namespace extensions {
@@ -126,9 +123,10 @@
std::vector<std::string> scope_vector =
extensions::ObfuscatedGaiaIdFetcher::GetScopes();
OAuth2TokenService::ScopeSet scopes(scope_vector.begin(), scope_vector.end());
- fetcher_access_token_request_ =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile())
- ->StartRequest(scopes, this);
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
+ fetcher_access_token_request_ = token_service->StartRequest(
+ token_service->GetPrimaryAccountId(), scopes, this);
}
void PushMessagingGetChannelIdFunction::OnRefreshTokenAvailable(
@@ -189,8 +187,10 @@
// Check if the user is logged in.
bool PushMessagingGetChannelIdFunction::IsUserLoggedIn() const {
- return ProfileOAuth2TokenServiceFactory::GetForProfile(profile())
- ->RefreshTokenIsAvailable();
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
+ return token_service->RefreshTokenIsAvailable(
+ token_service->GetPrimaryAccountId());
}
void PushMessagingGetChannelIdFunction::ReportResult(
diff --git a/chrome/browser/extensions/api/rtc_private/rtc_private_api.cc b/chrome/browser/extensions/api/rtc_private/rtc_private_api.cc
deleted file mode 100644
index 2fe759d..0000000
--- a/chrome/browser/extensions/api/rtc_private/rtc_private_api.cc
+++ /dev/null
@@ -1,113 +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/extensions/api/rtc_private/rtc_private_api.h"
-
-#include "base/json/json_writer.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "base/value_conversions.h"
-#include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/chromeos/contacts/contact.pb.h"
-#include "chrome/browser/extensions/event_router.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/state_store.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/extensions/api/rtc_private.h"
-#include "content/public/browser/notification_service.h"
-
-using base::DictionaryValue;
-using base::ListValue;
-using base::Value;
-using contacts::Contact;
-using contacts::Contact_EmailAddress;
-using contacts::Contact_PhoneNumber;
-
-namespace extensions {
-
-namespace rtc_private = api::rtc_private;
-
-namespace {
-
-// Web intent data payload mimetype.
-const char kMimeTypeJson[] = "application/vnd.chromium.contact";
-// Web intent data structure fields.
-const char kNameIntentField[] = "name";
-const char kPhoneIntentField[] = "phone";
-const char kEmailIntentField[] = "email";
-
-// Returns the ActionType of intent action.
-api::rtc_private::ActionType GetLaunchAction(
- RtcPrivateEventRouter::LaunchAction action) {
- switch (action) {
- case RtcPrivateEventRouter::LAUNCH_ACTIVATE:
- return api::rtc_private::ACTION_TYPE_NONE;
- case RtcPrivateEventRouter::LAUNCH_CHAT:
- return api::rtc_private::ACTION_TYPE_CHAT;
- case RtcPrivateEventRouter::LAUNCH_VOICE:
- return api::rtc_private::ACTION_TYPE_VOICE;
- case RtcPrivateEventRouter::LAUNCH_VIDEO:
- return api::rtc_private::ACTION_TYPE_VIDEO;
- }
- return api::rtc_private::ACTION_TYPE_NONE;
-}
-
-// Creates JSON payload string for contact web intent data.
-void GetContactIntentData(const Contact& contact,
- DictionaryValue* dict) {
- // TODO(derat): This might require more name extraction magic than this.
- dict->SetString(kNameIntentField, contact.full_name());
-
- ListValue* phone_list = new base::ListValue();
- dict->Set(kPhoneIntentField, phone_list);
- for (int i = 0; i < contact.phone_numbers_size(); i++) {
- const Contact_PhoneNumber& phone_number = contact.phone_numbers(i);
- StringValue* value = new base::StringValue(phone_number.number());
- if (phone_number.primary())
- CHECK(phone_list->Insert(0, value));
- else
- phone_list->Append(value);
- }
-
- ListValue* email_list = new base::ListValue();
- dict->Set(kEmailIntentField, email_list);
- for (int i = 0; i < contact.email_addresses_size(); i++) {
- const Contact_EmailAddress& email_address = contact.email_addresses(i);
- StringValue* value = new base::StringValue(email_address.address());
- if (email_address.primary())
- CHECK(email_list->Insert(0, value));
- else
- email_list->Append(value);
- }
-}
-
-} // namespace
-
-void RtcPrivateEventRouter::DispatchLaunchEvent(
- Profile* profile, LaunchAction action, const Contact* contact) {
- if (action == RtcPrivateEventRouter::LAUNCH_ACTIVATE) {
- scoped_ptr<Event> event(new Event(
- rtc_private::OnLaunch::kEventName, make_scoped_ptr(new ListValue())));
- event->restrict_to_profile = profile;
- ExtensionSystem::Get(profile)->event_router()->BroadcastEvent(event.Pass());
- } else {
- DCHECK(contact);
- extensions::api::rtc_private::LaunchData launch_data;
- launch_data.intent.action = GetLaunchAction(action);
- GetContactIntentData(*contact,
- &launch_data.intent.data.additional_properties);
- launch_data.intent.type = kMimeTypeJson;
- scoped_ptr<Event> event(new Event(
- rtc_private::OnLaunch::kEventName,
- api::rtc_private::OnLaunch::Create(launch_data)));
- event->restrict_to_profile = profile;
- ExtensionSystem::Get(profile)->event_router()->BroadcastEvent(event.Pass());
- }
-}
-
-} // namespace extensions
diff --git a/chrome/browser/extensions/api/rtc_private/rtc_private_api.h b/chrome/browser/extensions/api/rtc_private/rtc_private_api.h
deleted file mode 100644
index 2431cbc..0000000
--- a/chrome/browser/extensions/api/rtc_private/rtc_private_api.h
+++ /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.
-#ifndef CHROME_BROWSER_EXTENSIONS_API_RTC_PRIVATE_RTC_PRIVATE_API_H_
-#define CHROME_BROWSER_EXTENSIONS_API_RTC_PRIVATE_RTC_PRIVATE_API_H_
-
-class Profile;
-
-namespace contacts {
-class Contact;
-}
-
-namespace extensions {
-
-// Implementation of chrome.rtcPrivate API.
-class RtcPrivateEventRouter {
- public:
- // Contact launch intent action.
- enum LaunchAction {
- LAUNCH_ACTIVATE,
- LAUNCH_CHAT,
- LAUNCH_VIDEO,
- LAUNCH_VOICE,
- };
-
- // Raises chrome.rtcPrivate.onLaunch event which is used to launch the default
- // RTC application in ChromeOS. |action| defines the context of the launch
- // event. Optional |contact| information is passed as event payload if launch
- // event is related to a particilar contact.
- static void DispatchLaunchEvent(Profile* profile,
- LaunchAction action,
- const contacts::Contact* contact);
-};
-
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_RTC_PRIVATE_RTC_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/rtc_private/rtc_private_apitest.cc b/chrome/browser/extensions/api/rtc_private/rtc_private_apitest.cc
deleted file mode 100644
index ba0cf57..0000000
--- a/chrome/browser/extensions/api/rtc_private/rtc_private_apitest.cc
+++ /dev/null
@@ -1,93 +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/contacts/contact.pb.h"
-#include "chrome/browser/extensions/api/rtc_private/rtc_private_api.h"
-#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_test_message_listener.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/test/browser_test_utils.h"
-#include "url/gurl.h"
-
-namespace {
-
-// Id of test extension from
-// chrome/test/data/extensions/api_test/rtc_private/events.
-const char kTestRtcExtensionId[] = "jdaiaafaoeaejklkkbndacnggmgmpkpa";
-// Test contact data.
-const char kContactFullName[] = "Test Contact";
-const char kTestEmail_1[] = "test_1@something.com";
-const char kTestEmail_2[] = "test_2@something.com";
-const char kTestPhone_1[] = "(555) 111-2222";
-const char kTestPhone_2[] = "(555) 333-4444";
-
-} // namespace
-
-class RtcPrivateApiTest : public ExtensionApiTest {
- protected:
- // ExtensionApiTest overrides.
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- ExtensionApiTest::SetUpCommandLine(command_line);
- command_line->AppendSwitchASCII(switches::kWhitelistedExtensionID,
- kTestRtcExtensionId);
- command_line->AppendSwitch(switches::kEnableContacts);
- }
-
- static contacts::Contact* CreateTestContact() {
- contacts::Contact* contact = new contacts::Contact();
- contact->set_full_name(kContactFullName);
- contacts::Contact_EmailAddress* address_1 =
- contact->mutable_email_addresses()->Add();
- address_1->set_address(kTestEmail_1);
- contacts::Contact_EmailAddress* address_2 =
- contact->mutable_email_addresses()->Add();
- address_2->set_address(kTestEmail_2);
-
- contacts::Contact_PhoneNumber* number_1 =
- contact->mutable_phone_numbers()->Add();
- number_1->set_number(kTestPhone_1);
- contacts::Contact_PhoneNumber* number_2 =
- contact->mutable_phone_numbers()->Add();
- number_2->set_number(kTestPhone_2);
- return contact;
- }
-};
-
-IN_PROC_BROWSER_TEST_F(RtcPrivateApiTest, LaunchEvents) {
- // Load test RTC extension.
- const extensions::Extension* extension = LoadExtension(
- test_data_dir_.AppendASCII("rtc_private/events"));
- ASSERT_TRUE(extension);
-
- ExtensionTestMessageListener discovery_started("received_all", false);
-
- // Raise all RTC-related events.
- scoped_ptr<contacts::Contact> contact(CreateTestContact());
- extensions::RtcPrivateEventRouter::DispatchLaunchEvent(
- browser()->profile(),
- extensions::RtcPrivateEventRouter::LAUNCH_ACTIVATE,
- contact.get());
-
- extensions::RtcPrivateEventRouter::DispatchLaunchEvent(
- browser()->profile(),
- extensions::RtcPrivateEventRouter::LAUNCH_CHAT,
- contact.get());
-
- extensions::RtcPrivateEventRouter::DispatchLaunchEvent(
- browser()->profile(),
- extensions::RtcPrivateEventRouter::LAUNCH_VIDEO,
- contact.get());
-
- extensions::RtcPrivateEventRouter::DispatchLaunchEvent(
- browser()->profile(),
- extensions::RtcPrivateEventRouter::LAUNCH_VOICE,
- contact.get());
-
- EXPECT_TRUE(discovery_started.WaitUntilSatisfied());
-}
diff --git a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.cc b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.cc
index caadd4d..db37fd5 100644
--- a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.cc
+++ b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.cc
@@ -5,8 +5,10 @@
#include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.h"
#include <string>
+#include <vector>
#include "base/lazy_instance.h"
+#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/values.h"
@@ -30,6 +32,19 @@
using browser_sync::DeviceInfo;
namespace extensions {
+namespace {
+void FillDeviceInfo(const DeviceInfo& device_info,
+ api::signed_in_devices::DeviceInfo* api_device_info) {
+ api_device_info->id = device_info.public_id();
+ api_device_info->name = device_info.client_name();
+ api_device_info->os = api::signed_in_devices::ParseOS(
+ device_info.GetOSString());
+ api_device_info->type = api::signed_in_devices::ParseDeviceType(
+ device_info.GetDeviceTypeString());
+ api_device_info->chrome_version = device_info.chrome_version();
+}
+} // namespace
+
SignedInDevicesChangeObserver::SignedInDevicesChangeObserver(
const std::string& extension_id,
Profile* profile) : extension_id_(extension_id),
@@ -54,14 +69,19 @@
ScopedVector<DeviceInfo> devices = GetAllSignedInDevices(extension_id_,
profile_);
- scoped_ptr<base::ListValue> result(new base::ListValue());
+ std::vector<linked_ptr<api::signed_in_devices::DeviceInfo> > args;
for (ScopedVector<DeviceInfo>::const_iterator it = devices.begin();
it != devices.end();
++it) {
- result->Append((*it)->ToValue());
+ linked_ptr<api::signed_in_devices::DeviceInfo> api_device =
+ make_linked_ptr(new api::signed_in_devices::DeviceInfo);
+ FillDeviceInfo(*(*it), api_device.get());
+ args.push_back(api_device);
}
+ scoped_ptr<base::ListValue> result =
+ api::signed_in_devices::OnDeviceInfoChange::Create(args);
scoped_ptr<Event> event(new Event(
api::signed_in_devices::OnDeviceInfoChange::kEventName,
result.Pass()));
diff --git a/chrome/browser/extensions/api/sockets_udp/sockets_udp_api.cc b/chrome/browser/extensions/api/sockets_udp/sockets_udp_api.cc
index c7a6e81..295594e 100644
--- a/chrome/browser/extensions/api/sockets_udp/sockets_udp_api.cc
+++ b/chrome/browser/extensions/api/sockets_udp/sockets_udp_api.cc
@@ -6,8 +6,7 @@
#include "chrome/browser/extensions/api/socket/udp_socket.h"
#include "chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.h"
-#include "chrome/common/extensions/permissions/permissions_data.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
+#include "chrome/common/extensions/api/sockets/sockets_handler.h"
#include "content/public/common/socket_permission_request.h"
#include "net/base/net_errors.h"
@@ -131,14 +130,22 @@
results_ = sockets_udp::Update::Results::Create();
}
-SocketsUdpBindFunction::SocketsUdpBindFunction() {}
+SocketsUdpBindFunction::SocketsUdpBindFunction()
+ : socket_event_dispatcher_(NULL) {
+}
SocketsUdpBindFunction::~SocketsUdpBindFunction() {}
bool SocketsUdpBindFunction::Prepare() {
params_ = sockets_udp::Bind::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params_.get());
- return true;
+
+ socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(profile());
+ DCHECK(socket_event_dispatcher_) << "There is no socket event dispatcher. "
+ "If this assertion is failing during a test, then it is likely that "
+ "TestExtensionSystem is failing to provide an instance of "
+ "UDPSocketEventDispatcher.";
+ return socket_event_dispatcher_ != NULL;
}
void SocketsUdpBindFunction::Work() {
@@ -148,20 +155,19 @@
return;
}
- SocketPermission::CheckParam param(
- SocketPermissionRequest::UDP_BIND, params_->address, params_->port);
- if (!PermissionsData::CheckAPIPermissionWithParam(
- GetExtension(),
- APIPermission::kSocket,
- ¶m)) {
+ content::SocketPermissionRequest param(
+ SocketPermissionRequest::UDP_BIND,
+ params_->address,
+ params_->port);
+ if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
error_ = kPermissionError;
return;
}
int net_result = socket->Bind(params_->address, params_->port);
if (net_result == net::OK) {
- UDPSocketEventDispatcher::Get(profile())->OnSocketBind(extension_->id(),
- params_->socket_id);
+ socket_event_dispatcher_->OnSocketBind(extension_->id(),
+ params_->socket_id);
}
if (net_result != net::OK)
@@ -190,14 +196,11 @@
return;
}
- SocketPermission::CheckParam param(
+ content::SocketPermissionRequest param(
SocketPermissionRequest::UDP_SEND_TO,
params_->address,
params_->port);
- if (!PermissionsData::CheckAPIPermissionWithParam(
- GetExtension(),
- APIPermission::kSocket,
- ¶m)) {
+ if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
error_ = kPermissionError;
AsyncWorkCompleted();
return;
@@ -333,13 +336,11 @@
return;
}
- SocketPermission::CheckParam param(
+ content::SocketPermissionRequest param(
SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
kWildcardAddress,
kWildcardPort);
-
- if (!PermissionsData::CheckAPIPermissionWithParam(
- GetExtension(), APIPermission::kSocket, ¶m)) {
+ if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
error_ = kPermissionError;
return;
}
@@ -367,13 +368,11 @@
return;
}
- SocketPermission::CheckParam param(
+ content::SocketPermissionRequest param(
SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
kWildcardAddress,
kWildcardPort);
- if (!PermissionsData::CheckAPIPermissionWithParam(GetExtension(),
- APIPermission::kSocket,
- ¶m)) {
+ if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
error_ = kPermissionError;
return;
}
@@ -451,14 +450,11 @@
return;
}
- SocketPermission::CheckParam param(
+ content::SocketPermissionRequest param(
SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
kWildcardAddress,
kWildcardPort);
- if (!PermissionsData::CheckAPIPermissionWithParam(
- GetExtension(),
- APIPermission::kSocket,
- ¶m)) {
+ if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
error_ = kPermissionError;
return;
}
diff --git a/chrome/browser/extensions/api/sockets_udp/sockets_udp_api.h b/chrome/browser/extensions/api/sockets_udp/sockets_udp_api.h
index b971c4f..60fbe3b 100644
--- a/chrome/browser/extensions/api/sockets_udp/sockets_udp_api.h
+++ b/chrome/browser/extensions/api/sockets_udp/sockets_udp_api.h
@@ -15,6 +15,8 @@
namespace extensions {
namespace api {
+class UDPSocketEventDispatcher;
+
class UDPSocketAsyncApiFunction : public SocketAsyncApiFunction {
protected:
virtual ~UDPSocketAsyncApiFunction();
@@ -86,6 +88,7 @@
private:
scoped_ptr<sockets_udp::Bind::Params> params_;
+ UDPSocketEventDispatcher* socket_event_dispatcher_;
};
class SocketsUdpSendFunction : public UDPSocketExtensionWithDnsLookupFunction {
diff --git a/chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.cc b/chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.cc
index 2331417..47e86b8 100644
--- a/chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.cc
+++ b/chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.cc
@@ -4,14 +4,19 @@
#include "chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/socket/udp_socket.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "net/base/net_errors.h"
namespace extensions {
namespace api {
+using content::BrowserThread;
+
static base::LazyInstance<ProfileKeyedAPIFactory<UDPSocketEventDispatcher> >
g_factory = LAZY_INSTANCE_INITIALIZER;
@@ -23,6 +28,8 @@
// static
UDPSocketEventDispatcher* UDPSocketEventDispatcher::Get(Profile* profile) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
return ProfileKeyedAPIFactory<UDPSocketEventDispatcher>::GetForProfile(
profile);
}
@@ -30,67 +37,70 @@
UDPSocketEventDispatcher::UDPSocketEventDispatcher(Profile* profile)
: thread_id_(Socket::kThreadId),
profile_(profile) {
-}
-
-UDPSocketEventDispatcher::~UDPSocketEventDispatcher() {
-}
-
-ResumableUDPSocket* UDPSocketEventDispatcher::GetUdpSocket(
- const std::string& extension_id,
- int socket_id) {
- DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
-
ApiResourceManager<ResumableUDPSocket>* manager =
- ApiResourceManager<ResumableUDPSocket>::Get(profile_);
+ ApiResourceManager<ResumableUDPSocket>::Get(profile);
DCHECK(manager) << "There is no socket manager. "
"If this assertion is failing during a test, then it is likely that "
"TestExtensionSystem is failing to provide an instance of "
"ApiResourceManager<ResumableUDPSocket>.";
-
- return manager->Get(extension_id, socket_id);
+ sockets_ = manager->data_;
}
+UDPSocketEventDispatcher::~UDPSocketEventDispatcher() {}
+
+UDPSocketEventDispatcher::ReceiveParams::ReceiveParams() {}
+
+UDPSocketEventDispatcher::ReceiveParams::~ReceiveParams() {}
+
void UDPSocketEventDispatcher::OnSocketBind(const std::string& extension_id,
- int socket_id) {
- DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
- StartReceive(extension_id, socket_id);
+ int socket_id) {
+ DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+
+ ReceiveParams params;
+ params.thread_id = thread_id_;
+ params.profile_id = profile_;
+ params.extension_id = extension_id;
+ params.sockets = sockets_;
+ params.socket_id = socket_id;
+
+ StartReceive(params);
}
-void UDPSocketEventDispatcher::StartReceive(const std::string& extension_id,
- int socket_id) {
- DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
- ResumableUDPSocket* socket = GetUdpSocket(extension_id, socket_id);
+/* static */
+void UDPSocketEventDispatcher::StartReceive(const ReceiveParams& params) {
+ DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+
+ ResumableUDPSocket* socket =
+ params.sockets->Get(params.extension_id, params.socket_id);
if (socket == NULL) {
// This can happen if the socket is closed while our callback is active.
return;
}
- DCHECK(extension_id == socket->owner_extension_id())
+ DCHECK(params.extension_id == socket->owner_extension_id())
<< "Socket has wrong owner.";
int buffer_size = (socket->buffer_size() <= 0 ? 4096 : socket->buffer_size());
socket->RecvFrom(buffer_size,
base::Bind(&UDPSocketEventDispatcher::ReceiveCallback,
- AsWeakPtr(),
- extension_id,
- socket_id));
+ params));
}
+/* static */
void UDPSocketEventDispatcher::ReceiveCallback(
- const std::string& extension_id,
- const int socket_id,
+ const ReceiveParams& params,
int bytes_read,
scoped_refptr<net::IOBuffer> io_buffer,
const std::string& address,
int port) {
- DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
+ DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
// Note: if "bytes_read" < 0, there was a network error, and "bytes_read" is
// a value from "net::ERR_".
if (bytes_read >= 0) {
- // Dispatch event.
+ // Dispatch "onReceive" event.
sockets_udp::ReceiveInfo receive_info;
- receive_info.socket_id = socket_id;
+ receive_info.socket_id = params.socket_id;
receive_info.data = std::string(io_buffer->data(), bytes_read);
receive_info.remote_address = address;
receive_info.remote_port = port;
@@ -98,28 +108,54 @@
sockets_udp::OnReceive::Create(receive_info);
scoped_ptr<Event> event(
new Event(sockets_udp::OnReceive::kEventName, args.Pass()));
- ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
- extension_id, event.Pass());
+ PostEvent(params, event.Pass());
// Post a task to delay the read until the socket is available, as
// calling StartReceive at this point would error with ERR_IO_PENDING.
- content::BrowserThread::PostTask(thread_id_, FROM_HERE,
- base::Bind(&UDPSocketEventDispatcher::StartReceive,
- AsWeakPtr(), extension_id, socket_id));
+ BrowserThread::PostTask(
+ params.thread_id, FROM_HERE,
+ base::Bind(&UDPSocketEventDispatcher::StartReceive, params));
} else {
- // Dispatch event but don't start another read to avoid infinite read if
- // we have a persistent network error.
+ // Dispatch "onReceiveError" event but don't start another read to avoid
+ // potential infinite reads if we have a persistent network error.
sockets_udp::ReceiveErrorInfo receive_error_info;
- receive_error_info.socket_id = socket_id;
+ receive_error_info.socket_id = params.socket_id;
receive_error_info.result = bytes_read;
scoped_ptr<base::ListValue> args =
sockets_udp::OnReceiveError::Create(receive_error_info);
scoped_ptr<Event> event(
new Event(sockets_udp::OnReceiveError::kEventName, args.Pass()));
- ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
- extension_id, event.Pass());
+ PostEvent(params, event.Pass());
}
}
+/* static */
+void UDPSocketEventDispatcher::PostEvent(const ReceiveParams& params,
+ scoped_ptr<Event> event) {
+ DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DispatchEvent,
+ params.profile_id,
+ params.extension_id,
+ base::Passed(event.Pass())));
+}
+
+/*static*/
+void UDPSocketEventDispatcher::DispatchEvent(void* profile_id,
+ const std::string& extension_id,
+ scoped_ptr<Event> event) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ Profile* profile = reinterpret_cast<Profile*>(profile_id);
+ if (!g_browser_process->profile_manager()->IsValidProfile(profile))
+ return;
+
+ EventRouter* router = ExtensionSystem::Get(profile)->event_router();
+ if (router)
+ router->DispatchEventToExtension(extension_id, event.Pass());
+}
+
} // namespace api
} // namespace extensions
diff --git a/chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.h b/chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.h
index c5672a9..8468624 100644
--- a/chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.h
+++ b/chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.h
@@ -5,9 +5,11 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_SOCKETS_UDP_UDP_SOCKET_EVENT_DISPATCHER_H_
#define CHROME_BROWSER_EXTENSIONS_API_SOCKETS_UDP_UDP_SOCKET_EVENT_DISPATCHER_H_
+#include "chrome/browser/extensions/api/api_resource_manager.h"
#include "chrome/browser/extensions/api/sockets_udp/sockets_udp_api.h"
namespace extensions {
+struct Event;
class ResumableUDPSocket;
}
@@ -33,31 +35,50 @@
static UDPSocketEventDispatcher* Get(Profile* profile);
private:
+ typedef ApiResourceManager<ResumableUDPSocket>::ApiResourceData SocketData;
friend class ProfileKeyedAPIFactory<UDPSocketEventDispatcher>;
-
- ResumableUDPSocket* GetUdpSocket(const std::string& extension_id,
- int socket_id);
-
- // Start a receive and register a callback.
- void StartReceive(const std::string& extension_id, int socket_id);
-
- // Called when socket receive data.
- void ReceiveCallback(const std::string& extension_id,
- const int socket_id,
- int bytes_read,
- scoped_refptr<net::IOBuffer> io_buffer,
- const std::string& address,
- int port);
-
// ProfileKeyedAPI implementation.
static const char* service_name() {
return "UDPSocketEventDispatcher";
}
static const bool kServiceHasOwnInstanceInIncognito = true;
+ static const bool kServiceIsNULLWhileTesting = true;
+
+ // base::Bind supports methods with up to 6 parameters. ReceiveParams is used
+ // as a workaround that limitation for invoking StartReceive.
+ struct ReceiveParams {
+ ReceiveParams();
+ ~ReceiveParams();
+
+ content::BrowserThread::ID thread_id;
+ void* profile_id;
+ std::string extension_id;
+ scoped_refptr<SocketData> sockets;
+ int socket_id;
+ };
+
+ // Start a receive and register a callback.
+ static void StartReceive(const ReceiveParams& params);
+
+ // Called when socket receive data.
+ static void ReceiveCallback(const ReceiveParams& params,
+ int bytes_read,
+ scoped_refptr<net::IOBuffer> io_buffer,
+ const std::string& address,
+ int port);
+
+ // Post an extension event from IO to UI thread
+ static void PostEvent(const ReceiveParams& params, scoped_ptr<Event> event);
+
+ // Dispatch an extension event on to EventRouter instance on UI thread.
+ static void DispatchEvent(void* profile_id,
+ const std::string& extension_id,
+ scoped_ptr<Event> event);
// Usually IO thread (except for unit testing).
- content::BrowserThread::ID thread_id_;
+ content::BrowserThread::ID thread_id_;
Profile* const profile_;
+ scoped_refptr<SocketData> sockets_;
};
} // namespace api
diff --git a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
index 13a5fde..05e6ebb 100644
--- a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
+++ b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
@@ -27,11 +27,12 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_set.h"
#include "chrome/common/extensions/permissions/api_permission.h"
-#include "components/policy/core/common/policy_schema.h"
+#include "components/policy/core/common/schema.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
+#include "extensions/common/constants.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
@@ -137,10 +138,10 @@
std::string schema_file;
if (!(*it)->manifest()->GetString(
manifest_keys::kStorageManagedSchema, &schema_file)) {
- // TODO(joaodasilva): Remove this for M30. http://crbug.com/240704
+ // TODO(joaodasilva): Remove this for M32. http://crbug.com/240704
if ((*it)->HasAPIPermission(APIPermission::kStorage)) {
descriptor->RegisterComponent((*it)->id(),
- scoped_ptr<policy::PolicySchema>());
+ scoped_ptr<policy::SchemaOwner>());
} else {
NOTREACHED();
}
@@ -149,7 +150,7 @@
// The extension should have been validated, so assume the schema exists
// and is valid.
std::string error;
- scoped_ptr<policy::PolicySchema> schema =
+ scoped_ptr<policy::SchemaOwner> schema =
StorageSchemaManifestHandler::GetSchema(it->get(), &error);
CHECK(schema) << error;
descriptor->RegisterComponent((*it)->id(), schema.Pass());
@@ -178,7 +179,7 @@
storage_factory_(factory),
observers_(observers),
base_path_(profile->GetPath().AppendASCII(
- ExtensionService::kManagedSettingsDirectoryName)) {
+ extensions::kManagedSettingsDirectoryName)) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// |event_router_| can be NULL on unit_tests.
if (event_router_)
diff --git a/chrome/browser/extensions/api/storage/sync_or_local_value_store_cache.cc b/chrome/browser/extensions/api/storage/sync_or_local_value_store_cache.cc
index 607beb2..da38155 100644
--- a/chrome/browser/extensions/api/storage/sync_or_local_value_store_cache.cc
+++ b/chrome/browser/extensions/api/storage/sync_or_local_value_store_cache.cc
@@ -12,11 +12,11 @@
#include "chrome/browser/extensions/api/storage/settings_frontend.h"
#include "chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.h"
#include "chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.h"
-#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/sync/glue/sync_start_util.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/permissions/api_permission.h"
#include "content/public/browser/browser_thread.h"
+#include "extensions/common/constants.h"
using content::BrowserThread;
@@ -103,11 +103,11 @@
DCHECK(!extension_backend_.get());
const bool local = settings_namespace_ == settings_namespace::LOCAL;
const base::FilePath app_path = profile_path.AppendASCII(
- local ? ExtensionService::kLocalAppSettingsDirectoryName
- : ExtensionService::kSyncAppSettingsDirectoryName);
+ local ? extensions::kLocalAppSettingsDirectoryName
+ : extensions::kSyncAppSettingsDirectoryName);
const base::FilePath extension_path = profile_path.AppendASCII(
- local ? ExtensionService::kLocalExtensionSettingsDirectoryName
- : ExtensionService::kSyncExtensionSettingsDirectoryName);
+ local ? extensions::kLocalExtensionSettingsDirectoryName
+ : extensions::kSyncExtensionSettingsDirectoryName);
app_backend_.reset(new SettingsBackend(
factory, app_path, syncer::APP_SETTINGS,
sync_start_util::GetFlareForSyncableService(profile_path),
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 51f95ec..6dc8125 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
@@ -42,7 +42,6 @@
// Error messages.
const char kFileError[] = "File error %d.";
-const char kQuotaError[] = "Quota error %d.";
const char kUnsupportedConflictResolutionPolicy[] =
"Policy %s is not supported.";
diff --git a/chrome/browser/extensions/api/system_display/system_display_api.cc b/chrome/browser/extensions/api/system_display/system_display_api.cc
index 36dd2f2..775a429 100644
--- a/chrome/browser/extensions/api/system_display/system_display_api.cc
+++ b/chrome/browser/extensions/api/system_display/system_display_api.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/extensions/api/system_display/system_display_api.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h"
+#include "chrome/common/extensions/manifest_handlers/kiosk_mode_info.h"
namespace extensions {
@@ -37,7 +37,7 @@
SetError("Function available only on ChromeOS.");
return false;
#else
- if (!KioskEnabledInfo::IsKioskEnabled(GetExtension())) {
+ if (!KioskModeInfo::IsKioskEnabled(GetExtension())) {
SetError("The extension needs to be kiosk enabled to use the function.");
return false;
}
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 ec42006..4a5654b 100644
--- a/chrome/browser/extensions/api/system_private/system_private_api.cc
+++ b/chrome/browser/extensions/api/system_private/system_private_api.cc
@@ -39,9 +39,12 @@
// System update states.
const char kNotAvailableState[] = "NotAvailable";
-const char kUpdatingState[] = "Updating";
const char kNeedRestartState[] = "NeedRestart";
+#if defined(OS_CHROMEOS)
+const char kUpdatingState[] = "Updating";
+#endif // defined(OS_CHROMEOS)
+
// Dispatches an extension event with |argument|
void DispatchEvent(const std::string& event_name, base::Value* argument) {
scoped_ptr<base::ListValue> list_args(new base::ListValue());
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
index 2890c06..4b3b165 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
@@ -41,7 +41,6 @@
const char kCapturingSameTab[] = "Cannot capture a tab with an active stream.";
const char kFindingTabError[] = "Error finding tab to capture.";
const char kNoAudioOrVideo[] = "Capture failed. No audio or video requested.";
-const char kPermissionError[] = "Tab Capture API flag is not enabled.";
const char kGrantError[] =
"Extension has not been invoked for the current page (see activeTab "
"permission). Chrome pages cannot be captured.";
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 d100fe2..df18d25 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -246,7 +246,6 @@
ResourceType::Type resource_type,
int child_id,
int route_id,
- bool is_continuation_of_transferred_request,
ScopedVector<content::ResourceThrottle>* throttles) OVERRIDE {
ChromeResourceDispatcherHostDelegate::RequestBeginning(
request,
@@ -255,7 +254,6 @@
resource_type,
child_id,
route_id,
- is_continuation_of_transferred_request,
throttles);
content::ResourceThrottle* throttle =
test_navigation_listener_->CreateResourceThrottle(request->url(),
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 ccf2655..c98ceea 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
@@ -515,7 +515,7 @@
element_readers.push_back(
new net::UploadBytesElementReader(&(bytes_2[0]), bytes_2.size()));
request.set_upload(make_scoped_ptr(
- new net::UploadDataStream(&element_readers, 0)));
+ new net::UploadDataStream(element_readers.Pass(), 0)));
ipc_sender_.PushTask(base::Bind(&base::DoNothing));
request.Start();
}
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/OWNERS b/chrome/browser/extensions/api/webrtc_logging_private/OWNERS
new file mode 100644
index 0000000..67620a2
--- /dev/null
+++ b/chrome/browser/extensions/api/webrtc_logging_private/OWNERS
@@ -0,0 +1 @@
+grunell@chromium.org
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
new file mode 100644
index 0000000..16819e7
--- /dev/null
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.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/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h"
+
+#include "base/logging.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace extensions {
+
+namespace SetMetaData = api::webrtc_logging_private::SetMetaData;
+namespace SetUploadOnRenderClose =
+ api::webrtc_logging_private::SetUploadOnRenderClose;
+
+WebrtcLoggingPrivateSetMetaDataFunction::
+WebrtcLoggingPrivateSetMetaDataFunction() {}
+
+WebrtcLoggingPrivateSetMetaDataFunction::
+~WebrtcLoggingPrivateSetMetaDataFunction() {}
+
+bool WebrtcLoggingPrivateSetMetaDataFunction::RunImpl() {
+ scoped_ptr<SetMetaData::Params> params(SetMetaData::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+WebrtcLoggingPrivateStartFunction::WebrtcLoggingPrivateStartFunction() {}
+
+WebrtcLoggingPrivateStartFunction::~WebrtcLoggingPrivateStartFunction() {}
+
+bool WebrtcLoggingPrivateStartFunction::RunImpl() {
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void WebrtcLoggingPrivateStartFunction::StartCallback(bool success) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ // TODO(grunell): Implement set lastError.
+ NOTIMPLEMENTED();
+ SendResponse(success);
+}
+
+WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::
+WebrtcLoggingPrivateSetUploadOnRenderCloseFunction() {}
+
+WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::
+~WebrtcLoggingPrivateSetUploadOnRenderCloseFunction() {}
+
+bool WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::RunImpl() {
+ scoped_ptr<SetUploadOnRenderClose::Params> params(
+ SetUploadOnRenderClose::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+WebrtcLoggingPrivateStopFunction::WebrtcLoggingPrivateStopFunction() {}
+
+WebrtcLoggingPrivateStopFunction::~WebrtcLoggingPrivateStopFunction() {}
+
+bool WebrtcLoggingPrivateStopFunction::RunImpl() {
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void WebrtcLoggingPrivateStopFunction::StopCallback(bool success) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ // TODO(grunell): Implement set lastError.
+ NOTIMPLEMENTED();
+ SendResponse(success);
+}
+
+WebrtcLoggingPrivateUploadFunction::WebrtcLoggingPrivateUploadFunction() {}
+
+WebrtcLoggingPrivateUploadFunction::~WebrtcLoggingPrivateUploadFunction() {}
+
+bool WebrtcLoggingPrivateUploadFunction::RunImpl() {
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void WebrtcLoggingPrivateUploadFunction::UploadCallback(
+ bool success, std::string report_id) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ api::webrtc_logging_private::UploadResult result;
+ result.report_id = report_id;
+ // TODO(grunell): Implement set lastError.
+ NOTIMPLEMENTED();
+ SendResponse(success);
+}
+
+WebrtcLoggingPrivateDiscardFunction::WebrtcLoggingPrivateDiscardFunction() {}
+
+WebrtcLoggingPrivateDiscardFunction::~WebrtcLoggingPrivateDiscardFunction() {}
+
+bool WebrtcLoggingPrivateDiscardFunction::RunImpl() {
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void WebrtcLoggingPrivateDiscardFunction::DiscardCallback(bool success) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ // TODO(grunell): Implement set lastError.
+ NOTIMPLEMENTED();
+ SendResponse(success);
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h
new file mode 100644
index 0000000..1d16f97
--- /dev/null
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h
@@ -0,0 +1,109 @@
+// Copyright 2013 The Chromium 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_WEBRTC_LOGGING_PRIVATE_WEBRTC_LOGGING_PRIVATE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_WEBRTC_LOGGING_PRIVATE_WEBRTC_LOGGING_PRIVATE_API_H_
+
+#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/common/extensions/api/webrtc_logging_private.h"
+
+namespace extensions {
+
+class WebrtcLoggingPrivateSetMetaDataFunction : public AsyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("webrtcLoggingPrivate.setMetaData",
+ WEBRTCLOGGINGPRIVATE_SETMETADATA)
+ WebrtcLoggingPrivateSetMetaDataFunction();
+
+ private:
+ virtual ~WebrtcLoggingPrivateSetMetaDataFunction();
+
+ // ExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ // Must be called on UI thread.
+ void SetMetaDataCallback(bool success);
+};
+
+class WebrtcLoggingPrivateStartFunction : public AsyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("webrtcLoggingPrivate.start",
+ WEBRTCLOGGINGPRIVATE_START)
+ WebrtcLoggingPrivateStartFunction();
+
+ private:
+ virtual ~WebrtcLoggingPrivateStartFunction();
+
+ // ExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ // Must be called on UI thread.
+ void StartCallback(bool success);
+};
+
+class WebrtcLoggingPrivateSetUploadOnRenderCloseFunction
+ : public AsyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("webrtcLoggingPrivate.setUploadOnRenderClose",
+ WEBRTCLOGGINGPRIVATE_SETUPLOADONRENDERCLOSE)
+ WebrtcLoggingPrivateSetUploadOnRenderCloseFunction();
+
+ private:
+ virtual ~WebrtcLoggingPrivateSetUploadOnRenderCloseFunction();
+
+ // ExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+};
+
+class WebrtcLoggingPrivateStopFunction : public AsyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("webrtcLoggingPrivate.stop",
+ WEBRTCLOGGINGPRIVATE_STOP)
+ WebrtcLoggingPrivateStopFunction();
+
+ private:
+ virtual ~WebrtcLoggingPrivateStopFunction();
+
+ // ExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ // Must be called on UI thread.
+ void StopCallback(bool success);
+};
+
+class WebrtcLoggingPrivateUploadFunction : public AsyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("webrtcLoggingPrivate.upload",
+ WEBRTCLOGGINGPRIVATE_UPLOAD)
+ WebrtcLoggingPrivateUploadFunction();
+
+ private:
+ virtual ~WebrtcLoggingPrivateUploadFunction();
+
+ // ExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ // Must be called on UI thread.
+ void UploadCallback(bool success, std::string report_id);
+};
+
+class WebrtcLoggingPrivateDiscardFunction : public AsyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("webrtcLoggingPrivate.discard",
+ WEBRTCLOGGINGPRIVATE_DISCARD)
+ WebrtcLoggingPrivateDiscardFunction();
+
+ private:
+ virtual ~WebrtcLoggingPrivateDiscardFunction();
+
+ // ExtensionFunction overrides.
+ virtual bool RunImpl() OVERRIDE;
+
+ // Must be called on UI thread.
+ void DiscardCallback(bool success);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_WEBRTC_LOGGING_PRIVATE_WEBRTC_LOGGING_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc
new file mode 100644
index 0000000..a7bed87
--- /dev/null
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.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.
+//
+// Stub implementation used when WebRTC is not enabled.
+
+#include "chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h"
+
+namespace extensions {
+
+namespace {
+
+const char kErrorNotSupported[] = "Not supported";
+
+} // namespace
+
+WebrtcLoggingPrivateSetMetaDataFunction::
+WebrtcLoggingPrivateSetMetaDataFunction() {}
+
+WebrtcLoggingPrivateSetMetaDataFunction::
+~WebrtcLoggingPrivateSetMetaDataFunction() {}
+
+bool WebrtcLoggingPrivateSetMetaDataFunction::RunImpl() {
+ SetError(kErrorNotSupported);
+ SendResponse(false);
+ return false;
+}
+
+WebrtcLoggingPrivateStartFunction::WebrtcLoggingPrivateStartFunction() {}
+
+WebrtcLoggingPrivateStartFunction::~WebrtcLoggingPrivateStartFunction() {}
+
+bool WebrtcLoggingPrivateStartFunction::RunImpl() {
+ SetError(kErrorNotSupported);
+ SendResponse(false);
+ return false;
+}
+
+void WebrtcLoggingPrivateStartFunction::StartCallback(bool success) {}
+
+WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::
+WebrtcLoggingPrivateSetUploadOnRenderCloseFunction() {}
+
+WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::
+~WebrtcLoggingPrivateSetUploadOnRenderCloseFunction() {}
+
+bool WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::RunImpl() {
+ SetError(kErrorNotSupported);
+ SendResponse(false);
+ return false;
+}
+
+WebrtcLoggingPrivateStopFunction::WebrtcLoggingPrivateStopFunction() {}
+
+WebrtcLoggingPrivateStopFunction::~WebrtcLoggingPrivateStopFunction() {}
+
+bool WebrtcLoggingPrivateStopFunction::RunImpl() {
+ SetError(kErrorNotSupported);
+ SendResponse(false);
+ return false;
+}
+
+void WebrtcLoggingPrivateStopFunction::StopCallback(bool success) {}
+
+WebrtcLoggingPrivateUploadFunction::WebrtcLoggingPrivateUploadFunction() {}
+
+WebrtcLoggingPrivateUploadFunction::~WebrtcLoggingPrivateUploadFunction() {}
+
+bool WebrtcLoggingPrivateUploadFunction::RunImpl() {
+ SetError(kErrorNotSupported);
+ SendResponse(false);
+ return false;
+}
+
+void WebrtcLoggingPrivateUploadFunction::UploadCallback(
+ bool success, std::string report_id) {
+}
+
+WebrtcLoggingPrivateDiscardFunction::WebrtcLoggingPrivateDiscardFunction() {}
+
+WebrtcLoggingPrivateDiscardFunction::~WebrtcLoggingPrivateDiscardFunction() {}
+
+bool WebrtcLoggingPrivateDiscardFunction::RunImpl() {
+ SetError(kErrorNotSupported);
+ SendResponse(false);
+ return false;
+}
+
+void WebrtcLoggingPrivateDiscardFunction::DiscardCallback(bool success) {}
+
+} // namespace extensions
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 cea24d6..90c64ae 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -553,7 +553,8 @@
scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
profile(), this,
&(dispatcher()->delegate()->GetAssociatedWebContents()->GetController()),
- params->expected_id, approval_.Pass(), WebstoreInstaller::FLAG_NONE);
+ params->expected_id, approval_.Pass(),
+ WebstoreInstaller::INSTALL_SOURCE_OTHER);
installer->Start();
return true;
diff --git a/chrome/browser/extensions/api/webview/webview_api.cc b/chrome/browser/extensions/api/webview/webview_api.cc
index 935e3bd..d7a402d 100644
--- a/chrome/browser/extensions/api/webview/webview_api.cc
+++ b/chrome/browser/extensions/api/webview/webview_api.cc
@@ -269,6 +269,28 @@
return true;
}
+WebviewOverrideUserAgentFunction::WebviewOverrideUserAgentFunction() {
+}
+
+WebviewOverrideUserAgentFunction::~WebviewOverrideUserAgentFunction() {
+}
+
+bool WebviewOverrideUserAgentFunction::RunImpl() {
+ scoped_ptr<extensions::api::webview::OverrideUserAgent::Params> params(
+ extensions::api::webview::OverrideUserAgent::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+ int instance_id = params->instance_id;
+ std::string user_agent_override = params->user_agent_override;
+
+ WebViewGuest* guest = WebViewGuest::From(
+ render_view_host()->GetProcess()->GetID(), instance_id);
+ if (!guest)
+ return false;
+
+ guest->SetUserAgentOverride(user_agent_override);
+ return true;
+}
+
WebviewStopFunction::WebviewStopFunction() {
}
diff --git a/chrome/browser/extensions/api/webview/webview_api.h b/chrome/browser/extensions/api/webview/webview_api.h
index 59f9d97..95f0f6d 100644
--- a/chrome/browser/extensions/api/webview/webview_api.h
+++ b/chrome/browser/extensions/api/webview/webview_api.h
@@ -140,6 +140,23 @@
DISALLOW_COPY_AND_ASSIGN(WebviewSetPermissionFunction);
};
+class WebviewOverrideUserAgentFunction: public AsyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("webview.overrideUserAgent",
+ WEBVIEW_OVERRIDEUSERAGENT);
+
+ WebviewOverrideUserAgentFunction();
+
+ protected:
+ virtual ~WebviewOverrideUserAgentFunction();
+
+ // ExtensionFunction implementation.
+ virtual bool RunImpl() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebviewOverrideUserAgentFunction);
+};
+
class WebviewStopFunction : public AsyncExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("webview.stop", WEBVIEW_STOP);
diff --git a/chrome/browser/extensions/app_icon_loader_impl.cc b/chrome/browser/extensions/app_icon_loader_impl.cc
index 4eb0fc2..1172b2b 100644
--- a/chrome/browser/extensions/app_icon_loader_impl.cc
+++ b/chrome/browser/extensions/app_icon_loader_impl.cc
@@ -67,7 +67,7 @@
// Triggers image loading now instead of depending on paint message. This
// makes the temp blank image be shown for shorter time and improves user
// experience. See http://crbug.com/146114.
- image->image_skia().EnsureRepsForSupportedScaleFactors();
+ image->image_skia().EnsureRepsForSupportedScales();
}
void AppIconLoaderImpl::ClearImage(const std::string& id) {
diff --git a/chrome/browser/extensions/app_sync_bundle.cc b/chrome/browser/extensions/app_sync_bundle.cc
index 8038fed..32dc919 100644
--- a/chrome/browser/extensions/app_sync_bundle.cc
+++ b/chrome/browser/extensions/app_sync_bundle.cc
@@ -81,16 +81,6 @@
return result;
}
-void AppSyncBundle::SyncChangeIfNeeded(const Extension& extension) {
- AppSyncData app_sync_data = extension_service_->GetAppSyncData(extension);
-
- syncer::SyncChangeList sync_change_list(1, app_sync_data.GetSyncChange(
- HasExtensionId(extension.id()) ?
- syncer::SyncChange::ACTION_UPDATE : syncer::SyncChange::ACTION_ADD));
- sync_processor_->ProcessSyncChanges(FROM_HERE, sync_change_list);
- MarkPendingAppSynced(extension.id());
-}
-
void AppSyncBundle::ProcessSyncChange(AppSyncData app_sync_data) {
if (app_sync_data.uninstalled())
RemoveApp(app_sync_data.id());
@@ -123,6 +113,16 @@
return sync_processor_ != NULL;
}
+void AppSyncBundle::SyncChangeIfNeeded(const Extension& extension) {
+ AppSyncData app_sync_data = extension_service_->GetAppSyncData(extension);
+
+ syncer::SyncChangeList sync_change_list(1, app_sync_data.GetSyncChange(
+ HasExtensionId(extension.id()) ?
+ syncer::SyncChange::ACTION_UPDATE : syncer::SyncChange::ACTION_ADD));
+ sync_processor_->ProcessSyncChanges(FROM_HERE, sync_change_list);
+ MarkPendingAppSynced(extension.id());
+}
+
std::vector<AppSyncData> AppSyncBundle::GetPendingData() const {
std::vector<AppSyncData> pending_apps;
for (std::map<std::string, AppSyncData>::const_iterator
diff --git a/chrome/browser/extensions/app_sync_bundle.h b/chrome/browser/extensions/app_sync_bundle.h
index d5172ff..b613a13 100644
--- a/chrome/browser/extensions/app_sync_bundle.h
+++ b/chrome/browser/extensions/app_sync_bundle.h
@@ -13,6 +13,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/app_sync_data.h"
+#include "chrome/browser/extensions/sync_bundle.h"
#include "sync/api/syncable_service.h"
class ExtensionService;
@@ -28,7 +29,7 @@
class Extension;
// Bundle of app specific sync stuff.
-class AppSyncBundle {
+class AppSyncBundle : public SyncBundle {
public:
explicit AppSyncBundle(ExtensionService* extension_service);
virtual ~AppSyncBundle();
@@ -55,9 +56,6 @@
// Get all the sync data contained in this bundle.
syncer::SyncDataList GetAllSyncData() const;
- // Sync a newly-installed application or change an existing one.
- void SyncChangeIfNeeded(const Extension& extension);
-
// Process the given sync change and apply it.
void ProcessSyncChange(AppSyncData app_sync_data);
@@ -80,8 +78,12 @@
const ExtensionSet& extensions,
std::vector<extensions::AppSyncData>* sync_data_list) const;
+ // Overrides for SyncBundle.
// Returns true if SetupSync has been called, false otherwise.
- bool IsSyncing() const;
+ virtual bool IsSyncing() const OVERRIDE;
+
+ // Sync a newly-installed application or change an existing one.
+ virtual void SyncChangeIfNeeded(const Extension& extension) OVERRIDE;
private:
// Add a synced app.
diff --git a/chrome/browser/extensions/app_sync_data_unittest.cc b/chrome/browser/extensions/app_sync_data_unittest.cc
index c32a56d..f81f07c 100644
--- a/chrome/browser/extensions/app_sync_data_unittest.cc
+++ b/chrome/browser/extensions/app_sync_data_unittest.cc
@@ -11,16 +11,10 @@
namespace extensions {
-namespace {
-
const char kValidId[] = "abcdefghijklmnopabcdefghijklmnop";
const char kName[] = "MyExtension";
const char kValidVersion[] = "0.0.0.0";
-const char kValidUpdateUrl[] =
- "http://clients2.google.com/service/update2/crx";
-const char kOAuthClientId[] = "1234abcd";
-
-} // namespace
+const char kValidUpdateUrl[] = "http://clients2.google.com/service/update2/crx";
class AppSyncDataTest : public testing::Test {
public:
diff --git a/chrome/browser/extensions/blacklist.cc b/chrome/browser/extensions/blacklist.cc
index 905b67a..d69f1d9 100644
--- a/chrome/browser/extensions/blacklist.cc
+++ b/chrome/browser/extensions/blacklist.cc
@@ -141,22 +141,26 @@
SetDatabaseManager(original_);
}
-Blacklist::Blacklist(ExtensionPrefs* prefs) : prefs_(prefs) {
+Blacklist::Blacklist(ExtensionPrefs* prefs) {
scoped_refptr<SafeBrowsingDatabaseManager> database_manager =
g_database_manager.Get().get();
- if (database_manager.get()) {
+ if (database_manager) {
registrar_.Add(
this,
chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
content::Source<SafeBrowsingDatabaseManager>(database_manager.get()));
}
- // TODO(kalman): Delete anything from the pref blacklist that is in the
- // safebrowsing blacklist (of course, only entries for which the extension
- // hasn't been installed).
+ // Clear out the old prefs-backed blacklist, stored as empty extension entries
+ // with just a "blacklisted" property.
//
- // Or maybe just wait until we're able to delete the pref blacklist
- // altogether (when we're sure it's a strict subset of the safebrowsing one).
+ // TODO(kalman): Delete this block of code, see http://crbug.com/295882.
+ std::set<std::string> blacklisted = prefs->GetBlacklistedExtensions();
+ for (std::set<std::string>::iterator it = blacklisted.begin();
+ it != blacklisted.end(); ++it) {
+ if (!prefs->GetInstalledExtensionInfo(*it))
+ prefs->DeleteExtensionPrefs(*it);
+ }
}
Blacklist::~Blacklist() {
@@ -166,35 +170,15 @@
const GetBlacklistedIDsCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (ids.empty()) {
+ if (ids.empty() || !g_database_manager.Get().get().get()) {
base::MessageLoopProxy::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, std::set<std::string>()));
- return;
- }
-
- // The blacklisted IDs are the union of those blacklisted in prefs and
- // those blacklisted from safe browsing.
- std::set<std::string> pref_blacklisted_ids;
- for (std::set<std::string>::const_iterator it = ids.begin();
- it != ids.end(); ++it) {
- if (prefs_->IsExtensionBlacklisted(*it))
- pref_blacklisted_ids.insert(*it);
- }
-
- if (!g_database_manager.Get().get().get()) {
- base::MessageLoopProxy::current()->PostTask(
- FROM_HERE, base::Bind(callback, pref_blacklisted_ids));
+ FROM_HERE, base::Bind(callback, std::set<std::string>()));
return;
}
// Constructing the SafeBrowsingClientImpl begins the process of asking
// safebrowsing for the blacklisted extensions.
- new SafeBrowsingClientImpl(
- ids,
- base::Bind(&Blacklist::OnSafeBrowsingResponse, AsWeakPtr(),
- pref_blacklisted_ids,
- callback));
+ new SafeBrowsingClientImpl(ids, callback);
}
void Blacklist::IsBlacklisted(const std::string& extension_id,
@@ -204,43 +188,6 @@
GetBlacklistedIDs(check, base::Bind(&IsNotEmpty, callback));
}
-void Blacklist::SetFromUpdater(const std::vector<std::string>& ids,
- const std::string& version) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- std::set<std::string> ids_as_set;
- for (std::vector<std::string>::const_iterator it = ids.begin();
- it != ids.end(); ++it) {
- if (Extension::IdIsValid(*it))
- ids_as_set.insert(*it);
- else
- LOG(WARNING) << "Got invalid extension ID \"" << *it << "\"";
- }
-
- std::set<std::string> from_prefs = prefs_->GetBlacklistedExtensions();
-
- std::set<std::string> no_longer_blacklisted =
- base::STLSetDifference<std::set<std::string> >(from_prefs,
- ids_as_set);
- std::set<std::string> not_yet_blacklisted =
- base::STLSetDifference<std::set<std::string> >(ids_as_set,
- from_prefs);
-
- for (std::set<std::string>::iterator it = no_longer_blacklisted.begin();
- it != no_longer_blacklisted.end(); ++it) {
- prefs_->SetExtensionBlacklisted(*it, false);
- }
- for (std::set<std::string>::iterator it = not_yet_blacklisted.begin();
- it != not_yet_blacklisted.end(); ++it) {
- prefs_->SetExtensionBlacklisted(*it, true);
- }
-
- prefs_->pref_service()->SetString(prefs::kExtensionBlacklistUpdateVersion,
- version);
-
- FOR_EACH_OBSERVER(Observer, observers_, OnBlacklistUpdated());
-}
-
void Blacklist::AddObserver(Observer* observer) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
observers_.AddObserver(observer);
@@ -262,19 +209,6 @@
return g_database_manager.Get().get();
}
-void Blacklist::OnSafeBrowsingResponse(
- const std::set<std::string>& pref_blacklisted_ids,
- const GetBlacklistedIDsCallback& callback,
- const std::set<std::string>& safebrowsing_blacklisted_ids) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- std::set<std::string> blacklist = pref_blacklisted_ids;
- blacklist.insert(safebrowsing_blacklisted_ids.begin(),
- safebrowsing_blacklisted_ids.end());
-
- callback.Run(blacklist);
-}
-
void Blacklist::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
diff --git a/chrome/browser/extensions/blacklist.h b/chrome/browser/extensions/blacklist.h
index ed7acf4..f005eaf 100644
--- a/chrome/browser/extensions/blacklist.h
+++ b/chrome/browser/extensions/blacklist.h
@@ -21,7 +21,7 @@
class Extension;
class ExtensionPrefs;
-// A blacklist of extensions.
+// The blacklist of extensions backed by safe browsing.
class Blacklist : public content::NotificationObserver,
public base::SupportsWeakPtr<Blacklist> {
public:
@@ -62,7 +62,6 @@
typedef base::Callback<void(BlacklistState)> IsBlacklistedCallback;
- // |prefs_| must outlive this.
explicit Blacklist(ExtensionPrefs* prefs);
virtual ~Blacklist();
@@ -80,10 +79,6 @@
void IsBlacklisted(const std::string& extension_id,
const IsBlacklistedCallback& callback);
- // Sets the blacklist from the updater to contain the extension IDs in |ids|
- void SetFromUpdater(const std::vector<std::string>& ids,
- const std::string& version);
-
// Adds/removes an observer to the blacklist.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
@@ -94,14 +89,6 @@
scoped_refptr<SafeBrowsingDatabaseManager> database_manager);
static scoped_refptr<SafeBrowsingDatabaseManager> GetDatabaseManager();
- // Handles the |safebrowsing_blacklisted_ids| response from querying the
- // safebrowsing blacklist, given that we know |pref_blacklisted_ids| are
- // already blacklisted. Responds to |callback| with the union.
- void OnSafeBrowsingResponse(
- const std::set<std::string>& pref_blacklisted_ids,
- const GetBlacklistedIDsCallback& callback,
- const std::set<std::string>& safebrowsing_blacklisted_ids);
-
// content::NotificationObserver
virtual void Observe(int type,
const content::NotificationSource& source,
@@ -109,10 +96,6 @@
ObserverList<Observer> observers_;
- ExtensionPrefs* const prefs_;
-
- std::set<std::string> prefs_blacklist_;
-
content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(Blacklist);
diff --git a/chrome/browser/extensions/blacklist_unittest.cc b/chrome/browser/extensions/blacklist_unittest.cc
index 1ccaf4c..1ebf5e2 100644
--- a/chrome/browser/extensions/blacklist_unittest.cc
+++ b/chrome/browser/extensions/blacklist_unittest.cc
@@ -10,194 +10,156 @@
#include "chrome/browser/extensions/fake_safe_browsing_database_manager.h"
#include "chrome/browser/extensions/test_blacklist.h"
#include "chrome/browser/extensions/test_extension_prefs.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"
namespace extensions {
namespace {
+std::set<std::string> Set(const std::string& a) {
+ std::set<std::string> set;
+ set.insert(a);
+ return set;
+}
+std::set<std::string> Set(const std::string& a, const std::string& b) {
+ std::set<std::string> set = Set(a);
+ set.insert(b);
+ return set;
+}
+std::set<std::string> Set(const std::string& a,
+ const std::string& b,
+ const std::string& c) {
+ std::set<std::string> set = Set(a, b);
+ set.insert(c);
+ return set;
+}
+std::set<std::string> Set(const std::string& a,
+ const std::string& b,
+ const std::string& d,
+ const std::string& c) {
+ std::set<std::string> set = Set(a, b, c);
+ set.insert(d);
+ return set;
+}
+
class BlacklistTest : public testing::Test {
public:
BlacklistTest()
- : prefs_(message_loop_.message_loop_proxy().get()),
- ui_thread_(content::BrowserThread::UI, &message_loop_),
- io_thread_(content::BrowserThread::IO, &message_loop_),
- safe_browsing_database_manager_(new FakeSafeBrowsingDatabaseManager()),
- scoped_blacklist_database_manager_(safe_browsing_database_manager_),
- blacklist_(prefs_.prefs()) {}
-
- bool IsBlacklisted(const Extension* extension) {
- return TestBlacklist(&blacklist_).IsBlacklisted(extension->id());
- }
+ : test_prefs_(base::MessageLoopProxy::current()),
+ blacklist_db_(new FakeSafeBrowsingDatabaseManager(false)),
+ scoped_blacklist_db_(blacklist_db_) {}
protected:
- base::MessageLoop message_loop_;
+ ExtensionPrefs* prefs() {
+ return test_prefs_.prefs();
+ }
- TestExtensionPrefs prefs_;
+ FakeSafeBrowsingDatabaseManager* blacklist_db() {
+ return blacklist_db_.get();
+ }
- content::TestBrowserThread ui_thread_;
- content::TestBrowserThread io_thread_;
+ std::string AddExtension(const std::string& id) {
+ return test_prefs_.AddExtension(id)->id();
+ }
- scoped_refptr<FakeSafeBrowsingDatabaseManager>
- safe_browsing_database_manager_;
- Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_database_manager_;
+ private:
+ content::TestBrowserThreadBundle browser_thread_bundle_;
- Blacklist blacklist_;
+ TestExtensionPrefs test_prefs_;
+
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db_;
+
+ Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db_;
};
-TEST_F(BlacklistTest, SetFromUpdater) {
- scoped_refptr<const Extension> extension_a = prefs_.AddExtension("a");
- scoped_refptr<const Extension> extension_b = prefs_.AddExtension("b");
- scoped_refptr<const Extension> extension_c = prefs_.AddExtension("c");
- scoped_refptr<const Extension> extension_d = prefs_.AddExtension("d");
-
- // c, d, start blacklisted.
- prefs_.prefs()->SetExtensionBlacklisted(extension_c->id(), true);
- prefs_.prefs()->SetExtensionBlacklisted(extension_d->id(), true);
-
- EXPECT_FALSE(IsBlacklisted(extension_a.get()));
- EXPECT_FALSE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsBlacklisted(extension_c.get()));
- EXPECT_TRUE(IsBlacklisted(extension_d.get()));
-
- // Mix up the blacklist.
- {
- std::vector<std::string> blacklist;
- blacklist.push_back(extension_b->id());
- blacklist.push_back(extension_c->id());
- blacklist_.SetFromUpdater(blacklist, "1");
- }
- EXPECT_FALSE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsBlacklisted(extension_c.get()));
- EXPECT_FALSE(IsBlacklisted(extension_d.get()));
-
- // No-op, just in case.
- {
- std::vector<std::string> blacklist;
- blacklist.push_back(extension_b->id());
- blacklist.push_back(extension_c->id());
- blacklist_.SetFromUpdater(blacklist, "2");
- }
- EXPECT_FALSE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsBlacklisted(extension_c.get()));
- EXPECT_FALSE(IsBlacklisted(extension_d.get()));
-
- // Strictly increase the blacklist.
- {
- std::vector<std::string> blacklist;
- blacklist.push_back(extension_a->id());
- blacklist.push_back(extension_b->id());
- blacklist.push_back(extension_c->id());
- blacklist.push_back(extension_d->id());
- blacklist_.SetFromUpdater(blacklist, "3");
- }
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsBlacklisted(extension_c.get()));
- EXPECT_TRUE(IsBlacklisted(extension_d.get()));
-
- // Strictly decrease the blacklist.
- {
- std::vector<std::string> blacklist;
- blacklist.push_back(extension_a->id());
- blacklist.push_back(extension_b->id());
- blacklist_.SetFromUpdater(blacklist, "4");
- }
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_FALSE(IsBlacklisted(extension_c.get()));
- EXPECT_FALSE(IsBlacklisted(extension_d.get()));
-
- // Clear the blacklist.
- {
- std::vector<std::string> blacklist;
- blacklist_.SetFromUpdater(blacklist, "5");
- }
- EXPECT_FALSE(IsBlacklisted(extension_a.get()));
- EXPECT_FALSE(IsBlacklisted(extension_b.get()));
- EXPECT_FALSE(IsBlacklisted(extension_c.get()));
- EXPECT_FALSE(IsBlacklisted(extension_d.get()));
-}
-
void Assign(std::set<std::string> *to, const std::set<std::string>& from) {
*to = from;
}
TEST_F(BlacklistTest, OnlyIncludesRequestedIDs) {
- scoped_refptr<const Extension> extension_a = prefs_.AddExtension("a");
- scoped_refptr<const Extension> extension_b = prefs_.AddExtension("b");
- scoped_refptr<const Extension> extension_c = prefs_.AddExtension("c");
+ std::string a = AddExtension("a");
+ std::string b = AddExtension("b");
+ std::string c = AddExtension("c");
- {
- std::vector<std::string> blacklist;
- blacklist.push_back(extension_a->id());
- blacklist.push_back(extension_b->id());
- blacklist_.SetFromUpdater(blacklist, "1");
- base::RunLoop().RunUntilIdle();
- }
+ Blacklist blacklist(prefs());
+ TestBlacklist tester(&blacklist);
- std::set<std::string> blacklist_actual;
- {
- std::set<std::string> blacklist_query;
- blacklist_query.insert(extension_a->id());
- blacklist_query.insert(extension_c->id());
- blacklist_.GetBlacklistedIDs(blacklist_query,
- base::Bind(&Assign, &blacklist_actual));
- base::RunLoop().RunUntilIdle();
- }
+ blacklist_db()->Enable();
+ blacklist_db()->SetUnsafe(a, b);
- std::set<std::string> blacklist_expected;
- blacklist_expected.insert(extension_a->id());
- EXPECT_EQ(blacklist_expected, blacklist_actual);
+ EXPECT_TRUE(tester.IsBlacklisted(a));
+ EXPECT_TRUE(tester.IsBlacklisted(b));
+ EXPECT_FALSE(tester.IsBlacklisted(c));
+
+ std::set<std::string> blacklisted_ids;
+ blacklist.GetBlacklistedIDs(Set(a, c), base::Bind(&Assign, &blacklisted_ids));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(Set(a), blacklisted_ids);
}
-TEST_F(BlacklistTest, PrefsVsSafeBrowsing) {
- scoped_refptr<const Extension> extension_a = prefs_.AddExtension("a");
- scoped_refptr<const Extension> extension_b = prefs_.AddExtension("b");
- scoped_refptr<const Extension> extension_c = prefs_.AddExtension("c");
+TEST_F(BlacklistTest, SafeBrowsing) {
+ std::string a = AddExtension("a");
- // Prefs have a and b blacklisted, safebrowsing has b and c.
- prefs_.prefs()->SetExtensionBlacklisted(extension_a->id(), true);
- prefs_.prefs()->SetExtensionBlacklisted(extension_b->id(), true);
- {
- std::set<std::string> bc;
- bc.insert(extension_b->id());
- bc.insert(extension_c->id());
- safe_browsing_database_manager_->set_unsafe_ids(bc);
- }
+ Blacklist blacklist(prefs());
+ TestBlacklist tester(&blacklist);
- // The manager is still disabled at this point, so c won't be blacklisted.
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_FALSE(IsBlacklisted(extension_c.get()));
+ EXPECT_FALSE(tester.IsBlacklisted(a));
+ blacklist_db()->SetUnsafe(a);
+ // The manager is still disabled at this point, so it won't be blacklisted.
+ EXPECT_FALSE(tester.IsBlacklisted(a));
+
+ blacklist_db()->Enable().NotifyUpdate();
+ base::RunLoop().RunUntilIdle();
// Now it should be.
- safe_browsing_database_manager_->set_enabled(true);
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsBlacklisted(extension_c.get()));
+ EXPECT_TRUE(tester.IsBlacklisted(a));
- // Corner case: nothing in safebrowsing (but still enabled).
- safe_browsing_database_manager_->set_unsafe_ids(std::set<std::string>());
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_FALSE(IsBlacklisted(extension_c.get()));
-
- // Corner case: nothing in prefs.
- prefs_.prefs()->SetExtensionBlacklisted(extension_a->id(), false);
- prefs_.prefs()->SetExtensionBlacklisted(extension_b->id(), false);
- {
- std::set<std::string> bc;
- bc.insert(extension_b->id());
- bc.insert(extension_c->id());
- safe_browsing_database_manager_->set_unsafe_ids(bc);
- }
- EXPECT_FALSE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsBlacklisted(extension_c.get()));
+ blacklist_db()->ClearUnsafe().NotifyUpdate();
+ // Safe browsing blacklist empty, now enabled.
+ EXPECT_FALSE(tester.IsBlacklisted(a));
}
-} // namespace extensions
+// Tests that Blacklist clears the old prefs blacklist on startup.
+TEST_F(BlacklistTest, ClearsPreferencesBlacklist) {
+ std::string a = AddExtension("a");
+ std::string b = AddExtension("b");
+
+ // Blacklist an installed extension.
+ prefs()->SetExtensionBlacklisted(a, true);
+
+ // Blacklist some non-installed extensions. This is what the old preferences
+ // blacklist looked like.
+ std::string c = "cccccccccccccccccccccccccccccccc";
+ std::string d = "dddddddddddddddddddddddddddddddd";
+ prefs()->SetExtensionBlacklisted(c, true);
+ prefs()->SetExtensionBlacklisted(d, true);
+
+ EXPECT_EQ(Set(a, c, d), prefs()->GetBlacklistedExtensions());
+
+ Blacklist blacklist(prefs());
+ TestBlacklist tester(&blacklist);
+
+ // Blacklist has been cleared. Only the installed extension "a" left.
+ EXPECT_EQ(Set(a), prefs()->GetBlacklistedExtensions());
+ EXPECT_TRUE(prefs()->GetInstalledExtensionInfo(a).get());
+ EXPECT_TRUE(prefs()->GetInstalledExtensionInfo(b).get());
+
+ // "a" won't actually be *blacklisted* since it doesn't appear in
+ // safebrowsing. Blacklist no longer reads from prefs. This is purely a
+ // concern of somebody else (currently, ExtensionService).
+ std::set<std::string> blacklisted_ids;
+ blacklist.GetBlacklistedIDs(Set(a, b, c, d),
+ base::Bind(&Assign, &blacklisted_ids));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(std::set<std::string>(), blacklisted_ids);
+
+ // Prefs are still unaffected for installed extensions, though.
+ EXPECT_TRUE(prefs()->IsExtensionBlacklisted(a));
+ EXPECT_FALSE(prefs()->IsExtensionBlacklisted(b));
+ EXPECT_FALSE(prefs()->IsExtensionBlacklisted(c));
+ EXPECT_FALSE(prefs()->IsExtensionBlacklisted(d));
+}
+
} // namespace
+} // namespace extensions
diff --git a/chrome/browser/extensions/bundle_installer.cc b/chrome/browser/extensions/bundle_installer.cc
index 1c42d58..ec8b8e5 100644
--- a/chrome/browser/extensions/bundle_installer.cc
+++ b/chrome/browser/extensions/bundle_installer.cc
@@ -171,7 +171,7 @@
controller,
i->first,
approval.Pass(),
- WebstoreInstaller::FLAG_NONE);
+ WebstoreInstaller::INSTALL_SOURCE_OTHER);
installer->Start();
}
}
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 2f793a2..2205608 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -38,6 +38,7 @@
#include "chrome/common/extensions/extension_file_util.h"
#include "chrome/common/extensions/extension_icon_set.h"
#include "chrome/common/extensions/feature_switch.h"
+#include "chrome/common/extensions/manifest_handlers/kiosk_mode_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/permission_set.h"
@@ -55,6 +56,10 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/user_manager.h"
+#endif
+
using content::BrowserThread;
using content::UserMetricsAction;
using extensions::SharedModuleInfo;
@@ -512,6 +517,19 @@
if (!service || service->browser_terminating())
return;
+ if (KioskModeInfo::IsKioskOnly(installer_.extension())) {
+ bool in_kiosk_mode = false;
+#if defined(OS_CHROMEOS)
+ chromeos::UserManager* user_manager = chromeos::UserManager::Get();
+ in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp();
+#endif
+ if (!in_kiosk_mode) {
+ ReportFailureFromUIThread(CrxInstallerError(
+ l10n_util::GetStringUTF16(
+ IDS_EXTENSION_INSTALL_KIOSK_MODE_ONLY)));
+ }
+ }
+
string16 error = installer_.CheckManagementPolicy();
if (!error.empty()) {
// We don't want to show the error infobar for installs from the WebStore,
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index 8ebbfbe..a916842 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/fake_safe_browsing_database_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
@@ -24,6 +25,11 @@
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/fake_user_manager.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#endif
+
class SkBitmap;
namespace extensions {
@@ -447,13 +453,11 @@
}
IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Blacklist) {
- extensions::Blacklist* blacklist =
- ExtensionSystem::Get(profile())->blacklist();
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
+ new FakeSafeBrowsingDatabaseManager(true));
+ Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
- // Fake the blacklisting of the extension we're about to install by
- // pretending that we get a blacklist update which includes it.
- const std::string kId = "gllekhaobjnhgeagipipnkpmmmpchacm";
- blacklist->SetFromUpdater(std::vector<std::string>(1, kId), "some-version");
+ blacklist_db->SetUnsafe("gllekhaobjnhgeagipipnkpmmmpchacm");
base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx")
.AppendASCII("theme_hidpi.crx");
@@ -478,4 +482,20 @@
EXPECT_TRUE(mock_prompt->did_succeed());
}
+IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, KioskOnlyTest) {
+ base::FilePath crx_path =
+ test_data_dir_.AppendASCII("kiosk/kiosk_only.crx");
+ EXPECT_FALSE(InstallExtension(crx_path, 0));
+#if defined(OS_CHROMEOS)
+ // Simulate ChromeOS kiosk mode. |scoped_user_manager| will take over
+ // lifetime of |user_manager|.
+ chromeos::FakeUserManager* fake_user_manager =
+ new chromeos::FakeUserManager();
+ fake_user_manager->AddKioskAppUser("example@example.com");
+ fake_user_manager->LoginUser("example@example.com");
+ chromeos::ScopedUserManagerEnabler scoped_user_manager(fake_user_manager);
+ EXPECT_TRUE(InstallExtension(crx_path, 1));
+#endif
+}
+
} // namespace extensions
diff --git a/chrome/browser/extensions/extension_action.cc b/chrome/browser/extensions/extension_action.cc
index ccce0ca..50ac185 100644
--- a/chrome/browser/extensions/extension_action.cc
+++ b/chrome/browser/extensions/extension_action.cc
@@ -39,13 +39,12 @@
: icon_(icon) {}
// gfx::ImageSkiaSource overrides:
- virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor)
- OVERRIDE {
- gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor);
+ virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale);
color_utils::HSL shift = {-1, 0, 0.5};
return gfx::ImageSkiaRep(
SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift),
- icon_rep.scale_factor());
+ icon_rep.scale());
}
private:
@@ -68,7 +67,7 @@
private:
virtual ~AnimatedIconImageSource() {}
- virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale) OVERRIDE {
+ virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
gfx::ImageSkiaRep original_rep = image_.GetRepresentation(scale);
if (!animation_.get())
return original_rep;
@@ -77,8 +76,7 @@
// factor passed to this method. We want to use the former (since we are
// using bitmap for that scale).
return gfx::ImageSkiaRep(
- animation_->Apply(original_rep.sk_bitmap()),
- original_rep.scale_factor());
+ animation_->Apply(original_rep.sk_bitmap()), original_rep.scale());
}
gfx::ImageSkia image_;
diff --git a/chrome/browser/extensions/extension_action_icon_factory_unittest.cc b/chrome/browser/extensions/extension_action_icon_factory_unittest.cc
index 3eadffa..649ac62 100644
--- a/chrome/browser/extensions/extension_action_icon_factory_unittest.cc
+++ b/chrome/browser/extensions/extension_action_icon_factory_unittest.cc
@@ -38,7 +38,7 @@
bool ImageRepsAreEqual(const gfx::ImageSkiaRep& image_rep1,
const gfx::ImageSkiaRep& image_rep2) {
- return image_rep1.scale_factor() == image_rep2.scale_factor() &&
+ return image_rep1.scale() == image_rep2.scale() &&
gfx::BitmapsAreEqual(image_rep1.sk_bitmap(), image_rep2.sk_bitmap());
}
@@ -53,15 +53,14 @@
return gfx::Image::CreateFrom1xBitmap(resized);
}
-gfx::ImageSkiaRep CreateBlankRep(int size_dip, ui::ScaleFactor scale_factor) {
- SkBitmap bitmap;
- const float scale = ui::GetScaleFactorScale(scale_factor);
- bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- static_cast<int>(size_dip * scale),
- static_cast<int>(size_dip * scale));
- bitmap.allocPixels();
- bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
- return gfx::ImageSkiaRep(bitmap, scale_factor);
+gfx::ImageSkiaRep CreateBlankRep(int size_dip, float scale) {
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ static_cast<int>(size_dip * scale),
+ static_cast<int>(size_dip * scale));
+ bitmap.allocPixels();
+ bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
+ return gfx::ImageSkiaRep(bitmap, scale);
}
gfx::Image LoadIcon(const std::string& filename) {
@@ -203,8 +202,8 @@
gfx::Image icon = icon_factory.GetIcon(0);
EXPECT_TRUE(ImageRepsAreEqual(
- favicon.GetRepresentation(ui::SCALE_FACTOR_100P),
- icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
+ favicon.GetRepresentation(1.0f),
+ icon.ToImageSkia()->GetRepresentation(1.0f)));
}
// If the icon has been set using |SetIcon|, the factory should return that
@@ -234,15 +233,15 @@
gfx::Image icon = icon_factory.GetIcon(0);
EXPECT_TRUE(ImageRepsAreEqual(
- set_icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P),
- icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
+ set_icon.ToImageSkia()->GetRepresentation(1.0f),
+ icon.ToImageSkia()->GetRepresentation(1.0f)));
// It should still return favicon for another tabs.
icon = icon_factory.GetIcon(1);
EXPECT_TRUE(ImageRepsAreEqual(
- GetFavicon().GetRepresentation(ui::SCALE_FACTOR_100P),
- icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
+ GetFavicon().GetRepresentation(1.0f),
+ icon.ToImageSkia()->GetRepresentation(1.0f)));
}
// If there is a default icon, and the icon has not been set using |SetIcon|,
@@ -277,8 +276,8 @@
// The icon should be loaded asynchronously. Initially a transparent icon
// should be returned.
EXPECT_TRUE(ImageRepsAreEqual(
- CreateBlankRep(19, ui::SCALE_FACTOR_100P),
- icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
+ CreateBlankRep(19, 1.0f),
+ icon.ToImageSkia()->GetRepresentation(1.0f)));
WaitForIconUpdate();
@@ -286,15 +285,15 @@
// The default icon representation should be loaded at this point.
EXPECT_TRUE(ImageRepsAreEqual(
- default_icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P),
- icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
+ default_icon.ToImageSkia()->GetRepresentation(1.0f),
+ icon.ToImageSkia()->GetRepresentation(1.0f)));
// The same icon should be returned for the other tabs.
icon = icon_factory.GetIcon(1);
EXPECT_TRUE(ImageRepsAreEqual(
- default_icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P),
- icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
+ default_icon.ToImageSkia()->GetRepresentation(1.0f),
+ icon.ToImageSkia()->GetRepresentation(1.0f)));
}
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc
index d2b9284..07e4ea6 100644
--- a/chrome/browser/extensions/extension_apitest.cc
+++ b/chrome/browser/extensions/extension_apitest.cc
@@ -218,12 +218,13 @@
test_config_.reset(NULL);
}
-bool ExtensionApiTest::RunExtensionTest(const char* extension_name) {
+bool ExtensionApiTest::RunExtensionTest(const std::string& extension_name) {
return RunExtensionTestImpl(
extension_name, std::string(), NULL, kFlagEnableFileAccess);
}
-bool ExtensionApiTest::RunExtensionTestIncognito(const char* extension_name) {
+bool ExtensionApiTest::RunExtensionTestIncognito(
+ const std::string& extension_name) {
return RunExtensionTestImpl(extension_name,
std::string(),
NULL,
@@ -231,13 +232,13 @@
}
bool ExtensionApiTest::RunExtensionTestIgnoreManifestWarnings(
- const char* extension_name) {
+ const std::string& extension_name) {
return RunExtensionTestImpl(
extension_name, std::string(), NULL, kFlagIgnoreManifestWarnings);
}
bool ExtensionApiTest::RunExtensionTestAllowOldManifestVersion(
- const char* extension_name) {
+ const std::string& extension_name) {
return RunExtensionTestImpl(
extension_name,
std::string(),
@@ -245,7 +246,8 @@
kFlagEnableFileAccess | kFlagAllowOldManifestVersions);
}
-bool ExtensionApiTest::RunComponentExtensionTest(const char* extension_name) {
+bool ExtensionApiTest::RunComponentExtensionTest(
+ const std::string& extension_name) {
return RunExtensionTestImpl(extension_name,
std::string(),
NULL,
@@ -253,22 +255,22 @@
}
bool ExtensionApiTest::RunExtensionTestNoFileAccess(
- const char* extension_name) {
+ const std::string& extension_name) {
return RunExtensionTestImpl(extension_name, std::string(), NULL, kFlagNone);
}
bool ExtensionApiTest::RunExtensionTestIncognitoNoFileAccess(
- const char* extension_name) {
+ const std::string& extension_name) {
return RunExtensionTestImpl(
extension_name, std::string(), NULL, kFlagEnableIncognito);
}
-bool ExtensionApiTest::RunExtensionSubtest(const char* extension_name,
+bool ExtensionApiTest::RunExtensionSubtest(const std::string& extension_name,
const std::string& page_url) {
return RunExtensionSubtest(extension_name, page_url, kFlagEnableFileAccess);
}
-bool ExtensionApiTest::RunExtensionSubtest(const char* extension_name,
+bool ExtensionApiTest::RunExtensionSubtest(const std::string& extension_name,
const std::string& page_url,
int flags) {
DCHECK(!page_url.empty()) << "Argument page_url is required.";
@@ -282,28 +284,28 @@
bool ExtensionApiTest::RunPageTest(const std::string& page_url) {
- return RunExtensionSubtest("", page_url);
+ return RunExtensionSubtest(std::string(), page_url);
}
bool ExtensionApiTest::RunPageTest(const std::string& page_url,
int flags) {
- return RunExtensionSubtest("", page_url, flags);
+ return RunExtensionSubtest(std::string(), page_url, flags);
}
-bool ExtensionApiTest::RunPlatformAppTest(const char* extension_name) {
+bool ExtensionApiTest::RunPlatformAppTest(const std::string& extension_name) {
return RunExtensionTestImpl(
extension_name, std::string(), NULL, kFlagLaunchPlatformApp);
}
bool ExtensionApiTest::RunPlatformAppTestWithArg(
- const char* extension_name, const char* custom_arg) {
+ const std::string& extension_name, const char* custom_arg) {
return RunExtensionTestImpl(
extension_name, std::string(), custom_arg, kFlagLaunchPlatformApp);
}
// Load |extension_name| extension and/or |page_url| and wait for
// PASSED or FAILED notification.
-bool ExtensionApiTest::RunExtensionTestImpl(const char* extension_name,
+bool ExtensionApiTest::RunExtensionTestImpl(const std::string& extension_name,
const std::string& page_url,
const char* custom_arg,
int flags) {
@@ -311,15 +313,15 @@
bool launch_platform_app = (flags & kFlagLaunchPlatformApp) != 0;
bool use_incognito = (flags & kFlagUseIncognito) != 0;
- if (custom_arg)
+ if (custom_arg && custom_arg[0])
test_config_->SetString(kTestCustomArg, custom_arg);
ResultCatcher catcher;
- DCHECK(!std::string(extension_name).empty() || !page_url.empty()) <<
+ DCHECK(!extension_name.empty() || !page_url.empty()) <<
"extension_name and page_url cannot both be empty";
const extensions::Extension* extension = NULL;
- if (!std::string(extension_name).empty()) {
+ if (!extension_name.empty()) {
base::FilePath extension_path = test_data_dir_.AppendASCII(extension_name);
if (load_as_component) {
extension = LoadExtensionAsComponent(extension_path);
@@ -351,7 +353,7 @@
// may lack a scheme & host and thus be a relative url within the loaded
// extension.
if (!url.is_valid()) {
- DCHECK(!std::string(extension_name).empty()) <<
+ DCHECK(!extension_name.empty()) <<
"Relative page_url given with no extension_name";
url = extension->GetResourceURL(page_url);
@@ -361,7 +363,6 @@
ui_test_utils::OpenURLOffTheRecord(browser()->profile(), url);
else
ui_test_utils::NavigateToURL(browser(), url);
-
} else if (launch_platform_app) {
chrome::AppLaunchParams params(browser()->profile(), extension,
extension_misc::LAUNCH_NONE,
@@ -373,9 +374,9 @@
if (!catcher.GetNextResult()) {
message_ = catcher.message();
return false;
- } else {
- return true;
}
+
+ return true;
}
// Test that exactly one extension is loaded, and return it.
diff --git a/chrome/browser/extensions/extension_apitest.h b/chrome/browser/extensions/extension_apitest.h
index 12827ad..1e79880 100644
--- a/chrome/browser/extensions/extension_apitest.h
+++ b/chrome/browser/extensions/extension_apitest.h
@@ -109,37 +109,39 @@
// Load |extension_name| and wait for pass / fail notification.
// |extension_name| is a directory in "test/data/extensions/api_test".
- bool RunExtensionTest(const char* extension_name);
+ bool RunExtensionTest(const std::string& extension_name);
// Same as RunExtensionTest, but enables the extension for incognito mode.
- bool RunExtensionTestIncognito(const char* extension_name);
+ bool RunExtensionTestIncognito(const std::string& extension_name);
// Same as RunExtensionTest, but ignores any warnings in the manifest.
- bool RunExtensionTestIgnoreManifestWarnings(const char* extension_name);
+ bool RunExtensionTestIgnoreManifestWarnings(
+ const std::string& extension_name);
// Same as RunExtensionTest, allow old manifest ersions.
- bool RunExtensionTestAllowOldManifestVersion(const char* extension_name);
+ bool RunExtensionTestAllowOldManifestVersion(
+ const std::string& extension_name);
// Same as RunExtensionTest, but loads extension as component.
- bool RunComponentExtensionTest(const char* extension_name);
+ bool RunComponentExtensionTest(const std::string& extension_name);
// Same as RunExtensionTest, but disables file access.
- bool RunExtensionTestNoFileAccess(const char* extension_name);
+ bool RunExtensionTestNoFileAccess(const std::string& extension_name);
// Same as RunExtensionTestIncognito, but disables file access.
- bool RunExtensionTestIncognitoNoFileAccess(const char* extension_name);
+ bool RunExtensionTestIncognitoNoFileAccess(const std::string& extension_name);
// If not empty, Load |extension_name|, load |page_url| and wait for pass /
// fail notification from the extension API on the page. Note that if
// |page_url| is not a valid url, it will be treated as a resource within
// the extension. |extension_name| is a directory in
// "test/data/extensions/api_test".
- bool RunExtensionSubtest(const char* extension_name,
+ bool RunExtensionSubtest(const std::string& extension_name,
const std::string& page_url);
// Same as RunExtensionSubtest, except run with the specific |flags|
// (as defined in the Flags enum).
- bool RunExtensionSubtest(const char* extension_name,
+ bool RunExtensionSubtest(const std::string& extension_name,
const std::string& page_url,
int flags);
@@ -150,11 +152,12 @@
// Similar to RunExtensionTest, except used for running tests in platform app
// shell windows.
- bool RunPlatformAppTest(const char* extension_name);
+ bool RunPlatformAppTest(const std::string& extension_name);
+
// Similar to RunPlatformAppTest, except sets an additional string argument
// |customArg| to the test config object.
bool RunPlatformAppTestWithArg(
- const char* extension_name, const char* custom_arg);
+ const std::string& extension_name, const char* custom_arg);
// Start the test server, and store details of its state. Those details
// will be available to javascript tests using chrome.test.getConfig().
@@ -176,7 +179,7 @@
std::string message_;
private:
- bool RunExtensionTestImpl(const char* extension_name,
+ bool RunExtensionTestImpl(const std::string& extension_name,
const std::string& test_page,
const char* custom_arg,
int flags);
diff --git a/chrome/browser/extensions/extension_blacklist_browsertest.cc b/chrome/browser/extensions/extension_blacklist_browsertest.cc
deleted file mode 100644
index 3f57cb6..0000000
--- a/chrome/browser/extensions/extension_blacklist_browsertest.cc
+++ /dev/null
@@ -1,265 +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 "base/run_loop.h"
-#include "chrome/browser/extensions/blacklist.h"
-#include "chrome/browser/extensions/extension_browsertest.h"
-#include "chrome/browser/extensions/extension_notification_observer.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_constants.h"
-
-namespace extensions {
-
-namespace {
-
-// Stores the paths to CRX files of extensions, and the extension's ID.
-// Use arbitrary extensions; we're just testing blacklisting behavior.
-class CrxInfo {
- public:
- CrxInfo(const std::string& path, const std::string& id)
- : path_(path), id_(id) {}
-
- const std::string& path() { return path_; }
- const std::string& id() { return id_; }
-
- private:
- const std::string path_;
- const std::string id_;
-};
-
-} // namespace
-
-class ExtensionBlacklistBrowserTest : public ExtensionBrowserTest {
- public:
- ExtensionBlacklistBrowserTest()
- : info_a_("install/install.crx", "ogdbpbegnmindpdjfafpmpicikegejdj"),
- info_b_("autoupdate/v1.crx", "ogjcoiohnmldgjemafoockdghcjciccf"),
- info_c_("hosted_app.crx", "kbmnembihfiondgfjekmnmcbddelicoi"),
- // Just disable the safe browsing altogether.
- // TODO(kalman): a different approach will be needed when the blacklist
- // comes entirely from safe browsing.
- scoped_blacklist_database_manager_(
- scoped_refptr<SafeBrowsingDatabaseManager>(NULL)) {}
-
- virtual ~ExtensionBlacklistBrowserTest() {}
-
- protected:
- // Returns whether |extension| is strictly safe: in one of ExtensionService's
- // non-blacklisted extension sets, and not in its blacklisted extensions.
- testing::AssertionResult IsSafe(const Extension* extension) {
- std::string id = extension->id();
- int include_mask = ExtensionService::INCLUDE_EVERYTHING &
- ~ExtensionService::INCLUDE_BLACKLISTED;
- if (!extension_service()->GetExtensionById(id, include_mask))
- return testing::AssertionFailure() << id << " is safe";
- return IsInValidState(extension);
- }
-
- // Returns whether |extension| is strictly blacklisted: in ExtensionService's
- // blacklist, and not in any of its other extension sets.
- testing::AssertionResult IsBlacklisted(const Extension* extension) {
- std::string id = extension->id();
- if (!extension_service()->blacklisted_extensions()->Contains(id))
- return testing::AssertionFailure() << id << " is not blacklisted";
- return IsInValidState(extension);
- }
-
- std::set<std::string> GetTestExtensionIDs() {
- std::set<std::string> extension_ids;
- extension_ids.insert(info_a_.id());
- extension_ids.insert(info_b_.id());
- extension_ids.insert(info_c_.id());
- return extension_ids;
- }
-
- Blacklist* blacklist() {
- return ExtensionSystem::Get(profile())->blacklist();
- }
-
- CrxInfo info_a_;
- CrxInfo info_b_;
- CrxInfo info_c_;
-
- private:
- // Returns whether |extension| is either installed or blacklisted, but
- // neither both nor neither.
- testing::AssertionResult IsInValidState(const Extension* extension) {
- std::string id = extension->id();
- bool is_blacklisted =
- extension_service()->blacklisted_extensions()->Contains(id);
- int safe_mask = ExtensionService::INCLUDE_EVERYTHING &
- ~ExtensionService::INCLUDE_BLACKLISTED;
- bool is_safe = extension_service()->GetExtensionById(id, safe_mask) != NULL;
- if (is_blacklisted && is_safe) {
- return testing::AssertionFailure() <<
- id << " is both safe and in blacklisted_extensions";
- }
- if (!is_blacklisted && !is_safe) {
- return testing::AssertionFailure() <<
- id << " is neither safe nor in blacklisted_extensions";
- }
- return testing::AssertionSuccess();
- }
-
- Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_database_manager_;
-};
-
-// Stage 1: blacklisting when there weren't any extensions installed when the
-// browser started.
-IN_PROC_BROWSER_TEST_F(ExtensionBlacklistBrowserTest, PRE_Blacklist) {
- ExtensionNotificationObserver notifications(
- content::NotificationService::AllSources(), GetTestExtensionIDs());
-
- scoped_refptr<const Extension> extension_a =
- InstallExtension(test_data_dir_.AppendASCII(info_a_.path()), 1);
- scoped_refptr<const Extension> extension_b =
- InstallExtension(test_data_dir_.AppendASCII(info_b_.path()), 1);
- scoped_refptr<const Extension> extension_c =
- InstallExtension(test_data_dir_.AppendASCII(info_c_.path()), 1);
-
- EXPECT_TRUE(notifications.CheckNotifications(
- chrome::NOTIFICATION_EXTENSION_INSTALLED,
- chrome::NOTIFICATION_EXTENSION_LOADED,
- chrome::NOTIFICATION_EXTENSION_INSTALLED,
- chrome::NOTIFICATION_EXTENSION_LOADED,
- chrome::NOTIFICATION_EXTENSION_INSTALLED,
- chrome::NOTIFICATION_EXTENSION_LOADED));
-
- ASSERT_TRUE(extension_a.get());
- ASSERT_TRUE(extension_b.get());
- ASSERT_EQ(info_a_.id(), extension_a->id());
- ASSERT_EQ(info_b_.id(), extension_b->id());
- ASSERT_EQ(info_c_.id(), extension_c->id());
-
- std::vector<std::string> empty_vector;
- std::vector<std::string> vector_a(1, info_a_.id());
- std::vector<std::string> vector_b(1, info_b_.id());
- std::vector<std::string> vector_c(1, info_c_.id());
- std::vector<std::string> vector_ab(1, info_a_.id());
- vector_ab.push_back(info_b_.id());
- std::vector<std::string> vector_bc(1, info_b_.id());
- vector_bc.push_back(info_c_.id());
- std::vector<std::string> vector_abc(1, info_a_.id());
- vector_abc.push_back(info_b_.id());
- vector_abc.push_back(info_c_.id());
-
- EXPECT_TRUE(IsSafe(extension_a.get()));
- EXPECT_TRUE(IsSafe(extension_b.get()));
- EXPECT_TRUE(IsSafe(extension_c.get()));
-
- // Blacklist a and b.
- blacklist()->SetFromUpdater(vector_ab, "1");
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsSafe(extension_c.get()));
- EXPECT_TRUE(notifications.CheckNotifications(
- chrome::NOTIFICATION_EXTENSION_UNLOADED,
- chrome::NOTIFICATION_EXTENSION_UNLOADED));
-
- // Un-blacklist a.
- blacklist()->SetFromUpdater(vector_b, "2");
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(IsSafe(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsSafe(extension_c.get()));
- EXPECT_TRUE(
- notifications.CheckNotifications(chrome::NOTIFICATION_EXTENSION_LOADED));
-
- // Blacklist a then switch with c.
- blacklist()->SetFromUpdater(vector_ab, "3");
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsSafe(extension_c.get()));
- EXPECT_TRUE(notifications.CheckNotifications(
- chrome::NOTIFICATION_EXTENSION_UNLOADED));
-
- blacklist()->SetFromUpdater(vector_bc, "4");
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(IsSafe(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsBlacklisted(extension_c.get()));
- EXPECT_TRUE(notifications.CheckNotifications(
- chrome::NOTIFICATION_EXTENSION_LOADED,
- chrome::NOTIFICATION_EXTENSION_UNLOADED));
-
- // Add a to blacklist.
- blacklist()->SetFromUpdater(vector_abc, "5");
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsBlacklisted(extension_c.get()));
- EXPECT_TRUE(notifications.CheckNotifications(
- chrome::NOTIFICATION_EXTENSION_UNLOADED));
-
- // Clear blacklist.
- blacklist()->SetFromUpdater(empty_vector, "6");
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(IsSafe(extension_a.get()));
- EXPECT_TRUE(IsSafe(extension_b.get()));
- EXPECT_TRUE(IsSafe(extension_c.get()));
- EXPECT_TRUE(
- notifications.CheckNotifications(chrome::NOTIFICATION_EXTENSION_LOADED,
- chrome::NOTIFICATION_EXTENSION_LOADED,
- chrome::NOTIFICATION_EXTENSION_LOADED));
-
- // Add a and b back again for the next test.
- blacklist()->SetFromUpdater(vector_ab, "7");
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsSafe(extension_c.get()));
- EXPECT_TRUE(notifications.CheckNotifications(
- chrome::NOTIFICATION_EXTENSION_UNLOADED,
- chrome::NOTIFICATION_EXTENSION_UNLOADED));
-}
-
-// Stage 2: blacklisting with extensions A and B having been installed,
-// with A actually in the blacklist.
-IN_PROC_BROWSER_TEST_F(ExtensionBlacklistBrowserTest, Blacklist) {
- ExtensionNotificationObserver notifications(
- content::Source<Profile>(profile()), GetTestExtensionIDs());
-
- scoped_refptr<const Extension> extension_a =
- extension_service()->blacklisted_extensions()->GetByID(info_a_.id());
- ASSERT_TRUE(extension_a.get());
-
- scoped_refptr<const Extension> extension_b =
- extension_service()->blacklisted_extensions()->GetByID(info_b_.id());
- ASSERT_TRUE(extension_b.get());
-
- scoped_refptr<const Extension> extension_c =
- extension_service()->extensions()->GetByID(info_c_.id());
- ASSERT_TRUE(extension_c.get());
-
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsBlacklisted(extension_b.get()));
- EXPECT_TRUE(IsSafe(extension_c.get()));
-
- // Make sure that we can still blacklist c and unblacklist b.
- std::vector<std::string> vector_ac(1, extension_a->id());
- vector_ac.push_back(extension_c->id());
- blacklist()->SetFromUpdater(vector_ac, "8");
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(IsBlacklisted(extension_a.get()));
- EXPECT_TRUE(IsSafe(extension_b.get()));
- EXPECT_TRUE(IsBlacklisted(extension_c.get()));
- EXPECT_TRUE(notifications.CheckNotifications(
- chrome::NOTIFICATION_EXTENSION_LOADED,
- chrome::NOTIFICATION_EXTENSION_UNLOADED));
-}
-
-} // namespace extensions
diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
index 42956ca..4ee676a 100644
--- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
+++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
@@ -124,7 +124,7 @@
message_center::MessageCenter::Get();
ASSERT_GT(message_center->NotificationCount(), index);
message_center::NotificationList::Notifications::reverse_iterator it =
- message_center->GetNotifications().rbegin();
+ message_center->GetVisibleNotifications().rbegin();
for (size_t i=0; i < index; ++i)
it++;
std::string id = (*it)->id();
@@ -143,7 +143,7 @@
message_center::MessageCenter::Get();
ASSERT_GT(message_center->NotificationCount(), index);
message_center::NotificationList::Notifications::reverse_iterator it =
- message_center->GetNotifications().rbegin();
+ message_center->GetVisibleNotifications().rbegin();
for (size_t i=0; i < index; i++) { it++; }
ASSERT_TRUE(g_browser_process->notification_ui_manager()->
CancelById((*it)->id()));
diff --git a/chrome/browser/extensions/extension_disabled_ui_browsertest.cc b/chrome/browser/extensions/extension_disabled_ui_browsertest.cc
index c6481b5..8f20cfb 100644
--- a/chrome/browser/extensions/extension_disabled_ui_browsertest.cc
+++ b/chrome/browser/extensions/extension_disabled_ui_browsertest.cc
@@ -205,7 +205,6 @@
scoped_temp_dir_.path().AppendASCII("permissions2.crx"));
extensions::ExtensionUpdater::CheckParams params;
- params.check_blacklist = false;
service_->updater()->set_default_check_params(params);
// Sync is replacing an older version, so it pends.
diff --git a/chrome/browser/extensions/extension_function_histogram_value.h b/chrome/browser/extensions/extension_function_histogram_value.h
index 96594cb..4a3b395 100644
--- a/chrome/browser/extensions/extension_function_histogram_value.h
+++ b/chrome/browser/extensions/extension_function_histogram_value.h
@@ -633,6 +633,14 @@
IMAGEWRITER_LISTREMOVABLESTORAGEDEVICES,
WALLPAPER_SETWALLPAPER,
VIRTUALKEYBOARDPRIVATE_HIDEKEYBOARD,
+ AUTOTESTPRIVATE_LOCKSCREEN,
+ WEBRTCLOGGINGPRIVATE_SETMETADATA,
+ WEBRTCLOGGINGPRIVATE_START,
+ WEBRTCLOGGINGPRIVATE_SETUPLOADONRENDERCLOSE,
+ WEBRTCLOGGINGPRIVATE_STOP,
+ WEBRTCLOGGINGPRIVATE_UPLOAD,
+ WEBRTCLOGGINGPRIVATE_DISCARD,
+ WEBVIEW_OVERRIDEUSERAGENT,
ENUM_BOUNDARY // Last entry: Add new entries above.
};
diff --git a/chrome/browser/extensions/extension_icon_image.cc b/chrome/browser/extensions/extension_icon_image.cc
index fbd1ee4..7b0b248 100644
--- a/chrome/browser/extensions/extension_icon_image.cc
+++ b/chrome/browser/extensions/extension_icon_image.cc
@@ -86,8 +86,7 @@
private:
// gfx::ImageSkiaSource overrides:
- virtual gfx::ImageSkiaRep GetImageForScale(
- ui::ScaleFactor scale_factor) OVERRIDE;
+ virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE;
// Used to load images, possibly asynchronously. NULLed out when the IconImage
// is destroyed.
@@ -112,16 +111,17 @@
host_ = NULL;
}
-gfx::ImageSkiaRep IconImage::Source::GetImageForScale(
- ui::ScaleFactor scale_factor) {
+gfx::ImageSkiaRep IconImage::Source::GetImageForScale(float scale) {
gfx::ImageSkiaRep representation;
- if (host_)
- representation = host_->LoadImageForScaleFactor(scale_factor);
+ if (host_) {
+ representation =
+ host_->LoadImageForScaleFactor(ui::GetSupportedScaleFactor(scale));
+ }
if (!representation.is_null())
return representation;
- return blank_image_.GetRepresentation(scale_factor);
+ return blank_image_.GetRepresentation(scale);
}
////////////////////////////////////////////////////////////////////////////////
@@ -163,7 +163,7 @@
if (!extension_)
return gfx::ImageSkiaRep();
- const float scale = ui::GetScaleFactorScale(scale_factor);
+ const float scale = ui::GetImageScale(scale_factor);
const int resource_size_in_pixel =
static_cast<int>(resource_size_in_dip_ * scale);
@@ -184,7 +184,7 @@
// If there is no resource found, return default icon.
if (resource.empty())
- return default_icon_.GetRepresentation(scale_factor);
+ return default_icon_.GetRepresentation(scale);
std::vector<ImageLoader::ImageRepresentation> info_list;
info_list.push_back(ImageLoader::ImageRepresentation(
@@ -198,13 +198,12 @@
loader->LoadImagesAsync(extension_, info_list,
base::Bind(&IconImage::OnImageLoaded,
weak_ptr_factory_.GetWeakPtr(),
- scale_factor));
+ scale));
return gfx::ImageSkiaRep();
}
-void IconImage::OnImageLoaded(ui::ScaleFactor scale_factor,
- const gfx::Image& image_in) {
+void IconImage::OnImageLoaded(float scale, const gfx::Image& image_in) {
const gfx::ImageSkia* image =
image_in.IsEmpty() ? &default_icon_ : image_in.ToImageSkia();
@@ -212,12 +211,12 @@
if (image->isNull())
return;
- gfx::ImageSkiaRep rep = image->GetRepresentation(scale_factor);
+ gfx::ImageSkiaRep rep = image->GetRepresentation(scale);
DCHECK(!rep.is_null());
- DCHECK_EQ(scale_factor, rep.scale_factor());
+ DCHECK_EQ(scale, rep.scale());
// Remove old representation if there is one.
- image_skia_.RemoveRepresentation(rep.scale_factor());
+ image_skia_.RemoveRepresentation(scale);
image_skia_.AddRepresentation(rep);
if (observer_)
diff --git a/chrome/browser/extensions/extension_icon_image.h b/chrome/browser/extensions/extension_icon_image.h
index d1ddd57..94cdae5 100644
--- a/chrome/browser/extensions/extension_icon_image.h
+++ b/chrome/browser/extensions/extension_icon_image.h
@@ -13,6 +13,7 @@
#include "chrome/common/extensions/extension_icon_set.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "ui/base/layout.h"
#include "ui/gfx/image/image_skia.h"
class Profile;
@@ -81,7 +82,7 @@
// observer's |OnExtensionIconImageLoaded| will be called.
gfx::ImageSkiaRep LoadImageForScaleFactor(ui::ScaleFactor scale_factor);
- void OnImageLoaded(ui::ScaleFactor scale_factor, const gfx::Image& image);
+ void OnImageLoaded(float scale_factor, const gfx::Image& image);
// content::NotificationObserver overrides:
virtual void Observe(int type,
diff --git a/chrome/browser/extensions/extension_icon_image_unittest.cc b/chrome/browser/extensions/extension_icon_image_unittest.cc
index 0d9b9a7..fd35ee9 100644
--- a/chrome/browser/extensions/extension_icon_image_unittest.cc
+++ b/chrome/browser/extensions/extension_icon_image_unittest.cc
@@ -31,7 +31,7 @@
SkBitmap CreateBlankBitmapForScale(int size_dip, ui::ScaleFactor scale_factor) {
SkBitmap bitmap;
- const float scale = ui::GetScaleFactorScale(scale_factor);
+ const float scale = ui::GetImageScale(scale_factor);
bitmap.setConfig(SkBitmap::kARGB_8888_Config,
static_cast<int>(size_dip * scale),
static_cast<int>(size_dip * scale));
@@ -59,9 +59,8 @@
}
virtual ~MockImageSkiaSource() {}
- virtual gfx::ImageSkiaRep GetImageForScale(
- ui::ScaleFactor scale_factor) OVERRIDE {
- return image_.GetRepresentation(scale_factor);
+ virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ return image_.GetRepresentation(scale);
}
private:
@@ -210,6 +209,10 @@
} // namespace
TEST_F(ExtensionIconImageTest, Basic) {
+ std::vector<ui::ScaleFactor> supported_factors;
+ supported_factors.push_back(ui::SCALE_FACTOR_100P);
+ supported_factors.push_back(ui::SCALE_FACTOR_200P);
+ ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors);
scoped_ptr<Profile> profile(new TestingProfile());
scoped_refptr<Extension> extension(CreateExtension(
"extension_icon_image", Manifest::INVALID_LOCATION));
@@ -240,8 +243,7 @@
ASSERT_EQ(0u, image_reps.size());
// Gets representation for a scale factor.
- gfx::ImageSkiaRep representation =
- image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
// Before the image representation is loaded, image should contain blank
// image representation.
@@ -253,14 +255,14 @@
EXPECT_EQ(1, ImageLoadedCount());
ASSERT_EQ(1u, image.image_skia().image_reps().size());
- representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ representation = image.image_skia().GetRepresentation(1.0f);
// We should get the right representation now.
EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
EXPECT_EQ(16, representation.pixel_width());
// Gets representation for an additional scale factor.
- representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
+ representation = image.image_skia().GetRepresentation(2.0f);
EXPECT_TRUE(gfx::BitmapsAreEqual(
representation.sk_bitmap(),
@@ -270,7 +272,7 @@
EXPECT_EQ(1, ImageLoadedCount());
ASSERT_EQ(2u, image.image_skia().image_reps().size());
- representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
+ representation = image.image_skia().GetRepresentation(2.0f);
// Image should have been resized.
EXPECT_EQ(32, representation.pixel_width());
@@ -281,6 +283,10 @@
// There is no resource with either exact or bigger size, but there is a smaller
// resource.
TEST_F(ExtensionIconImageTest, FallbackToSmallerWhenNoBigger) {
+ std::vector<ui::ScaleFactor> supported_factors;
+ supported_factors.push_back(ui::SCALE_FACTOR_100P);
+ supported_factors.push_back(ui::SCALE_FACTOR_200P);
+ ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors);
scoped_ptr<Profile> profile(new TestingProfile());
scoped_refptr<Extension> extension(CreateExtension(
"extension_icon_image", Manifest::INVALID_LOCATION));
@@ -300,18 +306,17 @@
default_icon,
this);
- gfx::ImageSkiaRep representation =
- image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
+ gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(2.0f);
WaitForImageLoad();
EXPECT_EQ(1, ImageLoadedCount());
ASSERT_EQ(1u, image.image_skia().image_reps().size());
- representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
+ representation = image.image_skia().GetRepresentation(2.0f);
// We should have loaded the biggest smaller resource resized to the actual
// size.
- EXPECT_EQ(ui::SCALE_FACTOR_200P, representation.scale_factor());
+ EXPECT_EQ(2.0f, representation.scale());
EXPECT_EQ(64, representation.pixel_width());
EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
EnsureBitmapSize(bitmap_48, 64)));
@@ -340,17 +345,16 @@
default_icon,
this);
- gfx::ImageSkiaRep representation =
- image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
WaitForImageLoad();
EXPECT_EQ(1, ImageLoadedCount());
ASSERT_EQ(1u, image.image_skia().image_reps().size());
- representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ representation = image.image_skia().GetRepresentation(1.0f);
// We should have loaded smaller (resized) resource.
- EXPECT_EQ(ui::SCALE_FACTOR_100P, representation.scale_factor());
+ EXPECT_EQ(1.0f, representation.scale());
EXPECT_EQ(17, representation.pixel_width());
EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
EnsureBitmapSize(bitmap_16, 17)));
@@ -375,23 +379,22 @@
default_icon,
this);
- gfx::ImageSkiaRep representation =
- image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
EXPECT_TRUE(gfx::BitmapsAreEqual(
representation.sk_bitmap(),
EnsureBitmapSize(
- default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
+ default_icon.GetRepresentation(1.0f).sk_bitmap(),
kRequestedSize)));
EXPECT_EQ(0, ImageLoadedCount());
// We should have a default icon representation.
ASSERT_EQ(1u, image.image_skia().image_reps().size());
- representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ representation = image.image_skia().GetRepresentation(1.0f);
EXPECT_TRUE(gfx::BitmapsAreEqual(
representation.sk_bitmap(),
EnsureBitmapSize(
- default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
+ default_icon.GetRepresentation(1.0f).sk_bitmap(),
kRequestedSize)));
}
@@ -417,8 +420,7 @@
default_icon,
this);
- gfx::ImageSkiaRep representation =
- image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
EXPECT_TRUE(gfx::BitmapsAreEqual(
representation.sk_bitmap(),
CreateBlankBitmapForScale(kInvalidIconSize, ui::SCALE_FACTOR_100P)));
@@ -428,11 +430,11 @@
// We should have default icon representation now.
ASSERT_EQ(1u, image.image_skia().image_reps().size());
- representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ representation = image.image_skia().GetRepresentation(1.0f);
EXPECT_TRUE(gfx::BitmapsAreEqual(
representation.sk_bitmap(),
EnsureBitmapSize(
- default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
+ default_icon.GetRepresentation(1.0f).sk_bitmap(),
kInvalidIconSize)));
}
@@ -458,17 +460,16 @@
lazy_default_icon,
this);
- ASSERT_FALSE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
+ ASSERT_FALSE(lazy_default_icon.HasRepresentation(1.0f));
- gfx::ImageSkiaRep representation =
- image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
// The resouce set is empty, so we should get the result right away.
- EXPECT_TRUE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
+ EXPECT_TRUE(lazy_default_icon.HasRepresentation(1.0f));
EXPECT_TRUE(gfx::BitmapsAreEqual(
representation.sk_bitmap(),
EnsureBitmapSize(
- default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
+ default_icon.GetRepresentation(1.0f).sk_bitmap(),
kRequestedSize)));
// We should have a default icon representation.
@@ -498,23 +499,22 @@
lazy_default_icon,
this);
- ASSERT_FALSE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
+ ASSERT_FALSE(lazy_default_icon.HasRepresentation(1.0f));
- gfx::ImageSkiaRep representation =
- image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
WaitForImageLoad();
EXPECT_EQ(1, ImageLoadedCount());
// We should have default icon representation now.
ASSERT_EQ(1u, image.image_skia().image_reps().size());
- EXPECT_TRUE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
+ EXPECT_TRUE(lazy_default_icon.HasRepresentation(1.0f));
- representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ representation = image.image_skia().GetRepresentation(1.0f);
EXPECT_TRUE(gfx::BitmapsAreEqual(
representation.sk_bitmap(),
EnsureBitmapSize(
- default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
+ default_icon.GetRepresentation(1.0f).sk_bitmap(),
kInvalidIconSize)));
}
@@ -545,7 +545,7 @@
// Load an image representation.
gfx::ImageSkiaRep representation =
- image->image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
+ image->image_skia().GetRepresentation(1.0f);
WaitForImageLoad();
EXPECT_EQ(1, ImageLoadedCount());
@@ -557,14 +557,14 @@
extension = NULL;
// Image skia should still be able to get previously loaded representation.
- representation = image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
+ representation = image_skia.GetRepresentation(1.0f);
- EXPECT_EQ(ui::SCALE_FACTOR_100P, representation.scale_factor());
+ EXPECT_EQ(1.0f, representation.scale());
EXPECT_EQ(16, representation.pixel_width());
EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
// When requesting another representation, we should get blank image.
- representation = image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
+ representation = image_skia.GetRepresentation(2.0f);
EXPECT_TRUE(gfx::BitmapsAreEqual(
representation.sk_bitmap(),
diff --git a/chrome/browser/extensions/extension_icon_manager.cc b/chrome/browser/extensions/extension_icon_manager.cc
index 66f42db..475f4cb 100644
--- a/chrome/browser/extensions/extension_icon_manager.cc
+++ b/chrome/browser/extensions/extension_icon_manager.cc
@@ -32,7 +32,7 @@
scoped_ptr<gfx::Canvas> result(
new gfx::Canvas(gfx::Size(source.width() + padding.width(),
source.height() + padding.height()),
- ui::SCALE_FACTOR_100P,
+ 1.0f,
false));
result->DrawImageInt(
gfx::ImageSkia::CreateFrom1xBitmap(source),
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc
index c45fefa..e4a08aa 100644
--- a/chrome/browser/extensions/extension_install_prompt.cc
+++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -122,9 +122,7 @@
// Returns pixel size under maximal scale factor for the icon whose device
// independent size is |size_in_dip|
int GetSizeForMaxScaleFactor(int size_in_dip) {
- float max_scale_factor_scale =
- ui::GetScaleFactorScale(ui::GetMaxScaleFactor());
- return static_cast<int>(size_in_dip * max_scale_factor_scale);
+ return static_cast<int>(size_in_dip * gfx::ImageSkia::GetMaxSupportedScale());
}
// Returns bitmap for the default icon with size equal to the default icon's
@@ -133,7 +131,8 @@
const gfx::ImageSkia& image = is_app ?
extensions::IconsInfo::GetDefaultAppIcon() :
extensions::IconsInfo::GetDefaultExtensionIcon();
- return image.GetRepresentation(ui::GetMaxScaleFactor()).sk_bitmap();
+ return image.GetRepresentation(
+ gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
}
// If auto confirm is enabled then posts a task to proceed with or cancel the
@@ -347,9 +346,19 @@
}
string16 ExtensionInstallPrompt::Prompt::GetRetainedFilesHeading() const {
- return l10n_util::GetStringFUTF16(
- IDS_EXTENSION_PROMPT_RETAINED_FILES,
- base::IntToString16(GetRetainedFileCount()));
+ const int kRetainedFilesMessageIDs[6] = {
+ IDS_EXTENSION_PROMPT_RETAINED_FILES_DEFAULT,
+ IDS_EXTENSION_PROMPT_RETAINED_FILE_SINGULAR,
+ IDS_EXTENSION_PROMPT_RETAINED_FILES_ZERO,
+ IDS_EXTENSION_PROMPT_RETAINED_FILES_TWO,
+ IDS_EXTENSION_PROMPT_RETAINED_FILES_FEW,
+ IDS_EXTENSION_PROMPT_RETAINED_FILES_MANY,
+ };
+ std::vector<int> message_ids;
+ for (size_t i = 0; i < arraysize(kRetainedFilesMessageIDs); i++) {
+ message_ids.push_back(kRetainedFilesMessageIDs[i]);
+ }
+ return l10n_util::GetPluralStringFUTF16(message_ids, GetRetainedFileCount());
}
bool ExtensionInstallPrompt::Prompt::ShouldShowPermissions() const {
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index cf70ec6..6222ec5 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -376,8 +376,9 @@
EXPECT_FALSE(AreAnyNonWebApisDefined());
}
+// See http://crbug.com/297866
IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
- BackgroundPageClosesOnMessageReceipt) {
+ DISABLED_BackgroundPageClosesOnMessageReceipt) {
InitializeTestServer();
// Install the web connectable extension.
diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc
index 1f8c9fb..1de7f35 100644
--- a/chrome/browser/extensions/extension_process_manager.cc
+++ b/chrome/browser/extensions/extension_process_manager.cc
@@ -66,6 +66,14 @@
return render_view_host->GetSiteInstance()->GetSiteURL().host();
}
+void OnRenderViewHostUnregistered(Profile* profile,
+ RenderViewHost* render_view_host) {
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED,
+ content::Source<Profile>(profile),
+ content::Details<RenderViewHost>(render_view_host));
+}
+
// Incognito profiles use this process manager. It is mostly a shim that decides
// whether to fall back on the original profile's ExtensionProcessManager based
// on whether a given extension uses "split" or "spanning" incognito behavior.
@@ -360,11 +368,7 @@
if (view == all_extension_views_.end())
return;
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED,
- content::Source<Profile>(GetProfile()),
- content::Details<RenderViewHost>(render_view_host));
-
+ OnRenderViewHostUnregistered(GetProfile(), render_view_host);
extensions::ViewType view_type = view->second;
all_extension_views_.erase(view);
@@ -607,7 +611,7 @@
break;
}
}
- background_page_data_.erase(extension->id());
+ UnregisterExtension(extension->id());
break;
}
@@ -773,6 +777,27 @@
}
}
+void ExtensionProcessManager::UnregisterExtension(
+ const std::string& extension_id) {
+ // The lazy_keepalive_count may be greater than zero at this point because
+ // RenderViewHosts are still alive. During extension reloading, they will
+ // decrement the lazy_keepalive_count to negative for the new extension
+ // instance when they are destroyed. Since we are erasing the background page
+ // data for the unloaded extension, unregister the RenderViewHosts too.
+ Profile* profile = GetProfile();
+ for (ExtensionRenderViews::iterator it = all_extension_views_.begin();
+ it != all_extension_views_.end(); ) {
+ if (GetExtensionID(it->first) == extension_id) {
+ OnRenderViewHostUnregistered(profile, it->first);
+ all_extension_views_.erase(it++);
+ } else {
+ ++it;
+ }
+ }
+
+ background_page_data_.erase(extension_id);
+}
+
void ExtensionProcessManager::ClearBackgroundPageData(
const std::string& extension_id) {
background_page_data_.erase(extension_id);
diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h
index b234b3c..64d4d26 100644
--- a/chrome/browser/extensions/extension_process_manager.h
+++ b/chrome/browser/extensions/extension_process_manager.h
@@ -199,6 +199,10 @@
// extension. Does nothing if this is not an extension renderer.
void RegisterRenderViewHost(content::RenderViewHost* render_view_host);
+ // Unregister RenderViewHosts and clear background page data for an extension
+ // which has been unloaded.
+ void UnregisterExtension(const std::string& extension_id);
+
// Clears background page data for this extension.
void ClearBackgroundPageData(const std::string& extension_id);
diff --git a/chrome/browser/extensions/extension_protocols.cc b/chrome/browser/extensions/extension_protocols.cc
index 25ef06b..eb247ab 100644
--- a/chrome/browser/extensions/extension_protocols.cc
+++ b/chrome/browser/extensions/extension_protocols.cc
@@ -16,6 +16,7 @@
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/sha1.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"
@@ -42,6 +43,7 @@
#include "grit/component_extension_resources_map.h"
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
+#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/url_request/url_request_error_job.h"
@@ -135,6 +137,11 @@
const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
*data = rb.GetRawDataResource(resource_id_).as_string();
+ // Add the Content-Length header now that we know the resource length.
+ response_info_.headers->AddHeader(base::StringPrintf(
+ "%s: %s", net::HttpRequestHeaders::kContentLength,
+ base::UintToString(data->size()).c_str()));
+
std::string* read_mime_type = new std::string;
bool* read_result = new bool;
bool posted = content::BrowserThread::PostBlockingPoolTaskAndReply(
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc
index 2f57a63..1008266 100644
--- a/chrome/browser/extensions/extension_protocols_unittest.cc
+++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -6,6 +6,7 @@
#include "base/file_util.h"
#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_info_map.h"
@@ -201,6 +202,16 @@
}
}
+void CheckForContentLengthHeader(net::URLRequest* request) {
+ std::string content_length;
+ request->GetResponseHeaderByName(net::HttpRequestHeaders::kContentLength,
+ &content_length);
+ EXPECT_FALSE(content_length.empty());
+ int length_value = 0;
+ EXPECT_TRUE(base::StringToInt(content_length, &length_value));
+ EXPECT_GT(length_value, 0);
+}
+
// Tests getting a resource for a component extension works correctly, both when
// the extension is enabled and when it is disabled.
TEST_F(ExtensionProtocolTest, ComponentResourceRequest) {
@@ -217,6 +228,7 @@
resource_context_.GetRequestContext());
StartRequest(&request, ResourceType::MEDIA);
EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
+ CheckForContentLengthHeader(&request);
}
// And then test it with the extension disabled.
@@ -228,6 +240,7 @@
resource_context_.GetRequestContext());
StartRequest(&request, ResourceType::MEDIA);
EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
+ CheckForContentLengthHeader(&request);
}
}
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 500e5b8..96e8fbd 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -62,6 +62,7 @@
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/sync/sync_prefs.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"
@@ -199,19 +200,6 @@
// ExtensionService.
-const char ExtensionService::kLocalAppSettingsDirectoryName[] =
- "Local App Settings";
-const char ExtensionService::kLocalExtensionSettingsDirectoryName[] =
- "Local Extension Settings";
-const char ExtensionService::kSyncAppSettingsDirectoryName[] =
- "Sync App Settings";
-const char ExtensionService::kSyncExtensionSettingsDirectoryName[] =
- "Sync Extension Settings";
-const char ExtensionService::kManagedSettingsDirectoryName[] =
- "Managed Extension Settings";
-const char ExtensionService::kStateStoreName[] = "Extension State";
-const char ExtensionService::kRulesStoreName[] = "Extension Rules";
-
void ExtensionService::CheckExternalUninstall(const std::string& id) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -370,7 +358,17 @@
installs_delayed_for_gc_(false),
is_first_run_(false),
app_sync_bundle_(this),
- extension_sync_bundle_(this) {
+ extension_sync_bundle_(this),
+ pending_app_enables_(
+ make_scoped_ptr(new browser_sync::SyncPrefs(
+ extension_prefs_->pref_service())),
+ &app_sync_bundle_,
+ syncer::APPS),
+ pending_extension_enables_(
+ make_scoped_ptr(new browser_sync::SyncPrefs(
+ extension_prefs_->pref_service())),
+ &extension_sync_bundle_,
+ syncer::EXTENSIONS) {
#if defined(OS_CHROMEOS)
disable_garbage_collection_ = false;
#endif
@@ -404,7 +402,7 @@
// Set up the ExtensionUpdater
if (autoupdate_enabled) {
- int update_frequency = kDefaultUpdateFrequencySeconds;
+ int update_frequency = extensions::kDefaultUpdateFrequencySeconds;
if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) {
base::StringToInt(command_line->GetSwitchValueASCII(
switches::kExtensionsUpdateFrequency),
@@ -414,7 +412,6 @@
extension_prefs,
profile->GetPrefs(),
profile,
- blacklist,
update_frequency));
}
@@ -983,6 +980,13 @@
content::Source<Profile>(profile_),
content::Details<const Extension>(extension));
+ // Syncing may not have started yet, so handle pending enables.
+ if (extensions::sync_helper::IsSyncableApp(extension))
+ pending_app_enables_.OnExtensionEnabled(extension->id());
+
+ if (extensions::sync_helper::IsSyncableExtension(extension))
+ pending_extension_enables_.OnExtensionEnabled(extension->id());
+
SyncExtensionChangeIfNeeded(*extension);
}
@@ -1026,6 +1030,13 @@
terminated_extensions_.Remove(extension->id());
}
+ // Syncing may not have started yet, so handle pending enables.
+ if (extensions::sync_helper::IsSyncableApp(extension))
+ pending_app_enables_.OnExtensionDisabled(extension->id());
+
+ if (extensions::sync_helper::IsSyncableExtension(extension))
+ pending_extension_enables_.OnExtensionDisabled(extension->id());
+
SyncExtensionChangeIfNeeded(*extension);
}
@@ -1297,12 +1308,14 @@
extension_sync_bundle_.SetupSync(sync_processor.release(),
sync_error_factory.release(),
initial_sync_data);
+ pending_extension_enables_.OnSyncStarted(this);
break;
case syncer::APPS:
app_sync_bundle_.SetupSync(sync_processor.release(),
sync_error_factory.release(),
initial_sync_data);
+ pending_app_enables_.OnSyncStarted(this);
break;
default:
@@ -1488,6 +1501,11 @@
return false;
}
+bool ExtensionService::IsPendingEnable(const std::string& extension_id) const {
+ return pending_app_enables_.Contains(extension_id) ||
+ pending_extension_enables_.Contains(extension_id);
+}
+
bool ExtensionService::ProcessExtensionSyncDataHelper(
const extensions::ExtensionSyncData& extension_sync_data,
syncer::ModelType type) {
@@ -1524,7 +1542,7 @@
// is called for it.
if (extension_sync_data.enabled())
EnableExtension(id);
- else
+ else if (!IsPendingEnable(id))
DisableExtension(id, Extension::DISABLE_UNKNOWN_FROM_SYNC);
// We need to cache some version information here because setting the
@@ -3095,32 +3113,29 @@
void ExtensionService::OnBlacklistUpdated() {
blacklist_->GetBlacklistedIDs(
GenerateInstalledExtensionsSet()->GetIDs(),
- base::Bind(&ExtensionService::ManageBlacklist,
- AsWeakPtr(),
- blacklisted_extensions_.GetIDs()));
+ base::Bind(&ExtensionService::ManageBlacklist, AsWeakPtr()));
}
-void ExtensionService::ManageBlacklist(
- const std::set<std::string>& old_blacklisted_ids,
- const std::set<std::string>& new_blacklisted_ids) {
+void ExtensionService::ManageBlacklist(const std::set<std::string>& updated) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ std::set<std::string> before = blacklisted_extensions_.GetIDs();
std::set<std::string> no_longer_blacklisted =
- base::STLSetDifference<std::set<std::string> >(old_blacklisted_ids,
- new_blacklisted_ids);
+ base::STLSetDifference<std::set<std::string> >(before, updated);
std::set<std::string> not_yet_blacklisted =
- base::STLSetDifference<std::set<std::string> >(new_blacklisted_ids,
- old_blacklisted_ids);
+ base::STLSetDifference<std::set<std::string> >(updated, before);
for (std::set<std::string>::iterator it = no_longer_blacklisted.begin();
it != no_longer_blacklisted.end(); ++it) {
scoped_refptr<const Extension> extension =
blacklisted_extensions_.GetByID(*it);
- DCHECK(extension.get()) << "Extension " << *it << " no longer blacklisted, "
- << "but it was never blacklisted.";
- if (!extension.get())
+ if (!extension.get()) {
+ NOTREACHED() << "Extension " << *it << " no longer blacklisted, "
+ << "but it was never blacklisted.";
continue;
+ }
blacklisted_extensions_.Remove(*it);
+ extension_prefs_->SetExtensionBlacklisted(extension->id(), false);
AddExtension(extension.get());
UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.UnblacklistInstalled",
extension->location(),
@@ -3130,11 +3145,13 @@
for (std::set<std::string>::iterator it = not_yet_blacklisted.begin();
it != not_yet_blacklisted.end(); ++it) {
scoped_refptr<const Extension> extension = GetInstalledExtension(*it);
- DCHECK(extension.get()) << "Extension " << *it << " needs to be "
- << "blacklisted, but it's not installed.";
- if (!extension.get())
+ if (!extension.get()) {
+ NOTREACHED() << "Extension " << *it << " needs to be "
+ << "blacklisted, but it's not installed.";
continue;
+ }
blacklisted_extensions_.Insert(extension);
+ extension_prefs_->SetExtensionBlacklisted(extension->id(), true);
UnloadExtension(*it, extension_misc::UNLOAD_REASON_BLACKLIST);
UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlacklistInstalled",
extension->location(), Manifest::NUM_LOCATIONS);
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 33114b2..92e0119 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -29,6 +29,7 @@
#include "chrome/browser/extensions/external_provider_interface.h"
#include "chrome/browser/extensions/management_policy.h"
#include "chrome/browser/extensions/menu_manager.h"
+#include "chrome/browser/extensions/pending_enables.h"
#include "chrome/browser/extensions/pending_extension_manager.h"
#include "chrome/browser/extensions/process_map.h"
#include "chrome/browser/extensions/update_observer.h"
@@ -137,37 +138,6 @@
public content::NotificationObserver,
public extensions::Blacklist::Observer {
public:
- // If auto-updates are turned on, default to running every 5 hours.
- static const int kDefaultUpdateFrequencySeconds = 60 * 60 * 5;
-
- // The name of the directory inside the profile where per-app local settings
- // are stored.
- static const char kLocalAppSettingsDirectoryName[];
-
- // The name of the directory inside the profile where per-extension local
- // settings are stored.
- static const char kLocalExtensionSettingsDirectoryName[];
-
- // The name of the directory inside the profile where per-app synced settings
- // are stored.
- static const char kSyncAppSettingsDirectoryName[];
-
- // The name of the directory inside the profile where per-extension synced
- // settings are stored.
- static const char kSyncExtensionSettingsDirectoryName[];
-
- // The name of the directory inside the profile where per-extension persistent
- // managed settings are stored.
- static const char kManagedSettingsDirectoryName[];
-
- // The name of the database inside the profile where chrome-internal
- // extension state resides.
- static const char kStateStoreName[];
-
- // The name of the database inside the profile where declarative extension
- // rules are stored.
- static const char kRulesStoreName[];
-
// Returns the Extension of hosted or packaged apps, NULL otherwise.
const extensions::Extension* GetInstalledApp(const GURL& url) const;
@@ -255,7 +225,7 @@
// Getter and setter for the flag that specifies whether the extension is
// being reloaded.
- bool IsBeingReloaded(const std::string& extension_name) const;
+ bool IsBeingReloaded(const std::string& extension_id) const;
void SetBeingReloaded(const std::string& extension_id, bool value);
// Getter and setter for the flag that specifies if the extension has used
@@ -726,6 +696,9 @@
void OnExtensionInstallPrefChanged();
+ // Whether the given extension has been enabled before sync has started.
+ bool IsPendingEnable(const std::string& extension_id) const;
+
// Handles setting the extension specific values in |extension_sync_data| to
// the current system.
// Returns false if the changes were not completely applied and need to be
@@ -799,8 +772,7 @@
// Manages the blacklisted extensions, intended as callback from
// Blacklist::GetBlacklistedIDs.
- void ManageBlacklist(const std::set<std::string>& old_blacklisted_ids,
- const std::set<std::string>& new_blacklisted_ids);
+ void ManageBlacklist(const std::set<std::string>& blacklisted_ids);
// Controls if installs are delayed. See comment for
// |installs_delayed_for_gc_|.
@@ -935,6 +907,10 @@
// avoid showing a "new install" notice for an extension reinstall.
std::set<std::string> extensions_being_reloaded_;
+ // Set of extensions/apps that have been enabled before sync has started.
+ extensions::PendingEnables pending_app_enables_;
+ extensions::PendingEnables pending_extension_enables_;
+
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 d405a5e..aca590f 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -31,6 +31,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/app_sync_data.h"
+#include "chrome/browser/extensions/blacklist.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/default_apps.h"
@@ -48,6 +49,7 @@
#include "chrome/browser/extensions/external_pref_loader.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/extensions/external_provider_interface.h"
+#include "chrome/browser/extensions/fake_safe_browsing_database_manager.h"
#include "chrome/browser/extensions/install_observer.h"
#include "chrome/browser/extensions/install_tracker.h"
#include "chrome/browser/extensions/install_tracker_factory.h"
@@ -64,6 +66,8 @@
#include "chrome/browser/prefs/pref_service_mock_builder.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
@@ -104,6 +108,7 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "sync/api/string_ordinal.h"
+#include "sync/api/sync_data.h"
#include "sync/api/sync_error_factory.h"
#include "sync/api/sync_error_factory_mock.h"
#include "sync/api/syncable_service.h"
@@ -124,6 +129,11 @@
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#endif
+// The blacklist tests rely on safe browsing.
+#if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
+#define ENABLE_BLACKLIST_TESTS
+#endif
+
using base::DictionaryValue;
using base::ListValue;
using base::Value;
@@ -134,12 +144,14 @@
using content::PluginService;
using extensions::APIPermission;
using extensions::APIPermissionSet;
+using extensions::Blacklist;
using extensions::CrxInstaller;
using extensions::Extension;
using extensions::ExtensionCreator;
using extensions::ExtensionPrefs;
using extensions::ExtensionResource;
using extensions::ExtensionSystem;
+using extensions::FakeSafeBrowsingDatabaseManager;
using extensions::FeatureSwitch;
using extensions::Manifest;
using extensions::PermissionSet;
@@ -151,19 +163,19 @@
namespace {
// Extension ids used during testing.
-const char* const all_zero = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-const char* const zero_n_one = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
-const char* const good0 = "behllobkkfkfnphdnhnkndlbkcpglgmj";
-const char* const good1 = "hpiknbiabeeppbpihjehijgoemciehgk";
-const char* const good2 = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
-const char* const good_crx = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
-const char* const hosted_app = "kbmnembihfiondgfjekmnmcbddelicoi";
-const char* const page_action = "obcimlgaoabeegjmmpldobjndiealpln";
-const char* const theme_crx = "iamefpfkojoapidjnbafmgkgncegbkad";
-const char* const theme2_crx = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
-const char* const permissions_crx = "eagpmdpfmaekmmcejjbmjoecnejeiiin";
-const char* const unpacked = "cbcdidchbppangcjoddlpdjlenngjldk";
-const char* const updates_from_webstore = "akjooamlhcgeopfifcmlggaebeocgokj";
+const char all_zero[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
+const char good1[] = "hpiknbiabeeppbpihjehijgoemciehgk";
+const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
+const char good2048[] = "nmgjhmhbleinmjpbdhgajfjkbijcmgbh";
+const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
+const char hosted_app[] = "kbmnembihfiondgfjekmnmcbddelicoi";
+const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
+const char theme_crx[] = "iamefpfkojoapidjnbafmgkgncegbkad";
+const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
+const char permissions_crx[] = "eagpmdpfmaekmmcejjbmjoecnejeiiin";
+const char unpacked[] = "cbcdidchbppangcjoddlpdjlenngjldk";
+const char updates_from_webstore[] = "akjooamlhcgeopfifcmlggaebeocgokj";
struct ExtensionsOrder {
bool operator()(const scoped_refptr<const Extension>& a,
@@ -534,6 +546,16 @@
InitializeExtensionService(params);
}
+void ExtensionServiceTestBase::InitializeGoodInstalledExtensionService() {
+ base::FilePath source_install_dir = data_dir_
+ .AppendASCII("good")
+ .AppendASCII("Extensions");
+ base::FilePath pref_path = source_install_dir
+ .DirName()
+ .AppendASCII("Preferences");
+ InitializeInstalledExtensionService(pref_path, source_install_dir);
+}
+
void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
InitializeExtensionServiceHelper(false, true);
}
@@ -657,6 +679,22 @@
}
protected:
+ // Paths to some of the fake extensions.
+ base::FilePath good0_path() {
+ return data_dir_.AppendASCII("good").AppendASCII("Extensions")
+ .AppendASCII(good0).AppendASCII("1.0.0.0");
+ }
+
+ base::FilePath good1_path() {
+ return data_dir_.AppendASCII("good").AppendASCII("Extensions")
+ .AppendASCII(good1).AppendASCII("2");
+ }
+
+ base::FilePath good2_path() {
+ return data_dir_.AppendASCII("good").AppendASCII("Extensions")
+ .AppendASCII(good2).AppendASCII("1.0");
+ }
+
void TestExternalProvider(MockExtensionProvider* provider,
Manifest::Location location);
@@ -996,10 +1034,11 @@
EXPECT_EQ(count, GetPrefKeyCount());
}
- void ValidateBooleanPref(const std::string& extension_id,
- const std::string& pref_path,
- bool expected_val) {
- std::string msg = " while checking: ";
+ testing::AssertionResult ValidateBooleanPref(
+ const std::string& extension_id,
+ const std::string& pref_path,
+ bool expected_val) {
+ std::string msg = "while checking: ";
msg += extension_id;
msg += " ";
msg += pref_path;
@@ -1009,13 +1048,26 @@
PrefService* prefs = profile_->GetPrefs();
const DictionaryValue* dict =
prefs->GetDictionary("extensions.settings");
- ASSERT_TRUE(dict != NULL) << msg;
+ if (!dict) {
+ return testing::AssertionFailure()
+ << "extension.settings does not exist " << msg;
+ }
+
const DictionaryValue* pref = NULL;
- ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
- EXPECT_TRUE(pref != NULL) << msg;
+ if (!dict->GetDictionary(extension_id, &pref)) {
+ return testing::AssertionFailure()
+ << "extension pref does not exist " << msg;
+ }
+
bool val;
- ASSERT_TRUE(pref->GetBoolean(pref_path, &val)) << msg;
- EXPECT_EQ(expected_val, val) << msg;
+ if (!pref->GetBoolean(pref_path, &val)) {
+ return testing::AssertionFailure()
+ << pref_path << " pref not found " << msg;
+ }
+
+ return expected_val == val
+ ? testing::AssertionSuccess()
+ : testing::AssertionFailure() << "Value is incorrect " << msg;
}
bool IsPrefExist(const std::string& extension_id,
@@ -1215,16 +1267,7 @@
// Test loading good extensions from the profile directory.
TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectorySuccess) {
InitPluginService();
-
- // Initialize the test dir with a good Preferences/extensions.
- base::FilePath source_install_dir = data_dir_
- .AppendASCII("good")
- .AppendASCII("Extensions");
- base::FilePath pref_path = source_install_dir
- .DirName()
- .AppendASCII("Preferences");
- InitializeInstalledExtensionService(pref_path, source_install_dir);
-
+ InitializeGoodInstalledExtensionService();
service_->Init();
uint32 expected_num_extensions = 3u;
@@ -1367,15 +1410,7 @@
// Test loading bad extensions from the profile directory.
TEST_F(ExtensionServiceTest, CleanupOnStartup) {
InitPluginService();
-
- base::FilePath source_install_dir = data_dir_
- .AppendASCII("good")
- .AppendASCII("Extensions");
- base::FilePath pref_path = source_install_dir
- .DirName()
- .AppendASCII("Preferences");
-
- InitializeInstalledExtensionService(pref_path, source_install_dir);
+ InitializeGoodInstalledExtensionService();
// Simulate that one of them got partially deleted by clearing its pref.
{
@@ -1597,6 +1632,13 @@
InstallCRX(path, INSTALL_NEW);
ValidatePrefKeyCount(++pref_count);
+ // A test for an extension with a 2048-bit public key.
+ path = data_dir_.AppendASCII("good2048.crx");
+ InstallCRX(path, INSTALL_NEW);
+ ValidatePrefKeyCount(++pref_count);
+ ValidateIntegerPref(good2048, "state", Extension::ENABLED);
+ ValidateIntegerPref(good2048, "location", Manifest::INTERNAL);
+
// TODO(erikkay): add more tests for many of the failure cases.
// TODO(erikkay): add tests for upgrade cases.
}
@@ -1702,12 +1744,12 @@
const Extension* extension = service_->GetExtensionById(good_crx, false);
ASSERT_TRUE(extension);
ASSERT_TRUE(extension->from_bookmark());
- ValidateBooleanPref(good_crx, kPrefFromBookmark, true);
+ ASSERT_TRUE(ValidateBooleanPref(good_crx, kPrefFromBookmark, true));
// Upgrade to version 2.0, the flag should be preserved.
path = data_dir_.AppendASCII("good2.crx");
UpdateExtension(good_crx, path, ENABLED);
- ValidateBooleanPref(good_crx, kPrefFromBookmark, true);
+ ASSERT_TRUE(ValidateBooleanPref(good_crx, kPrefFromBookmark, true));
extension = service_->GetExtensionById(good_crx, false);
ASSERT_TRUE(extension);
ASSERT_TRUE(extension->from_bookmark());
@@ -2007,14 +2049,8 @@
InitializeEmptyExtensionService();
- base::FilePath path = data_dir_
- .AppendASCII("good")
- .AppendASCII("Extensions")
- .AppendASCII(good1)
- .AppendASCII("2");
-
- ASSERT_TRUE(base::PathExists(path));
- const Extension* extension = PackAndInstallCRX(path, INSTALL_NEW);
+ ASSERT_TRUE(base::PathExists(good1_path()));
+ const Extension* extension = PackAndInstallCRX(good1_path(), INSTALL_NEW);
EXPECT_EQ(0u, GetErrors().size());
EXPECT_EQ(1u, service_->extensions()->size());
ExtensionPrefs* prefs = service_->extension_prefs();
@@ -2736,14 +2772,14 @@
std::string id = extension->id();
ValidatePrefKeyCount(1);
- ValidateBooleanPref(good_crx, "from_webstore", false);
+ ASSERT_TRUE(ValidateBooleanPref(good_crx, "from_webstore", false));
ASSERT_FALSE(extension->from_webstore());
// Test install from web store.
InstallCRXFromWebStore(path, INSTALL_UPDATED); // From web store.
ValidatePrefKeyCount(1);
- ValidateBooleanPref(good_crx, "from_webstore", true);
+ ASSERT_TRUE(ValidateBooleanPref(good_crx, "from_webstore", true));
// Reload so extension gets reinitialized with new value.
service_->ReloadExtensions();
@@ -2754,7 +2790,7 @@
path = data_dir_.AppendASCII("good2.crx");
UpdateExtension(good_crx, path, ENABLED);
ValidatePrefKeyCount(1);
- ValidateBooleanPref(good_crx, "from_webstore", true);
+ ASSERT_TRUE(ValidateBooleanPref(good_crx, "from_webstore", true));
}
// Test upgrading a signed extension.
@@ -2967,16 +3003,8 @@
#if !defined(OS_CHROMEOS)
// LOAD extensions with plugins require approval.
TEST_F(ExtensionServiceTest, LoadExtensionsWithPlugins) {
- base::FilePath extension_with_plugin_path = data_dir_
- .AppendASCII("good")
- .AppendASCII("Extensions")
- .AppendASCII(good1)
- .AppendASCII("2");
- base::FilePath extension_no_plugin_path = data_dir_
- .AppendASCII("good")
- .AppendASCII("Extensions")
- .AppendASCII(good2)
- .AppendASCII("1.0");
+ base::FilePath extension_with_plugin_path = good1_path();
+ base::FilePath extension_no_plugin_path = good2_path();
InitPluginService();
InitializeEmptyExtensionService();
@@ -3271,97 +3299,101 @@
EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
}
-// Test pref settings for blacklist and unblacklist extensions.
+#if defined(ENABLE_BLACKLIST_TESTS)
+// Tests blacklisting then unblacklisting extensions after the service has been
+// initialized.
TEST_F(ExtensionServiceTest, SetUnsetBlacklistInPrefs) {
- InitializeEmptyExtensionService();
- std::vector<std::string> blacklist;
- blacklist.push_back(good0);
- blacklist.push_back("invalid_id"); // an invalid id
- blacklist.push_back(good1);
- ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
- "v1");
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
+ new FakeSafeBrowsingDatabaseManager(true));
+ Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
- // Make sure pref is updated
- base::RunLoop().RunUntilIdle();
+ // A profile with 3 extensions installed: good0, good1, and good2.
+ InitializeGoodInstalledExtensionService();
+ service_->Init();
- // blacklist is set for good0,1,2
- ValidateBooleanPref(good0, "blacklist", true);
- ValidateBooleanPref(good1, "blacklist", true);
- // invalid_id should not be inserted to pref.
- EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist"));
+ const ExtensionSet* extensions = service_->extensions();
+ const ExtensionSet* blacklisted_extensions =
+ service_->blacklisted_extensions();
- // remove good1, add good2
- blacklist.pop_back();
- blacklist.push_back(good2);
- ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
- "v2");
+ EXPECT_TRUE( extensions->Contains(good0) &&
+ !blacklisted_extensions->Contains(good0));
+ EXPECT_TRUE( extensions->Contains(good1) &&
+ !blacklisted_extensions->Contains(good1));
+ EXPECT_TRUE( extensions->Contains(good2) &&
+ !blacklisted_extensions->Contains(good2));
- // only good0 and good1 should be set
- ValidateBooleanPref(good0, "blacklist", true);
+ EXPECT_FALSE(IsPrefExist(good0, "blacklist"));
EXPECT_FALSE(IsPrefExist(good1, "blacklist"));
- ValidateBooleanPref(good2, "blacklist", true);
+ EXPECT_FALSE(IsPrefExist(good2, "blacklist"));
+ EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist"));
+
+ // Blacklist good0 and good1 (and an invalid extension ID).
+ blacklist_db->SetUnsafe(good0, good1, "invalid_id").NotifyUpdate();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(!extensions->Contains(good0) &&
+ blacklisted_extensions->Contains(good0));
+ EXPECT_TRUE(!extensions->Contains(good1) &&
+ blacklisted_extensions->Contains(good1));
+ EXPECT_TRUE( extensions->Contains(good2) &&
+ !blacklisted_extensions->Contains(good2));
+
+ EXPECT_TRUE(ValidateBooleanPref(good0, "blacklist", true));
+ EXPECT_TRUE(ValidateBooleanPref(good1, "blacklist", true));
+ EXPECT_FALSE(IsPrefExist(good2, "blacklist"));
+ EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist"));
+
+ // Un-blacklist good1 and blacklist good2.
+ blacklist_db->SetUnsafe(good0, good2, "invalid_id").NotifyUpdate();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(!extensions->Contains(good0) &&
+ blacklisted_extensions->Contains(good0));
+ EXPECT_TRUE( extensions->Contains(good1) &&
+ !blacklisted_extensions->Contains(good1));
+ EXPECT_TRUE(!extensions->Contains(good2) &&
+ blacklisted_extensions->Contains(good2));
+
+ EXPECT_TRUE(ValidateBooleanPref(good0, "blacklist", true));
+ EXPECT_FALSE(IsPrefExist(good1, "blacklist"));
+ EXPECT_TRUE(ValidateBooleanPref(good2, "blacklist", true));
EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist"));
}
+#endif // defined(ENABLE_BLACKLIST_TESTS)
-// Unload installed extension from blacklist.
-TEST_F(ExtensionServiceTest, UnloadBlacklistedExtension) {
- InitializeEmptyExtensionService();
-
- base::FilePath path = data_dir_.AppendASCII("good.crx");
-
- const Extension* good = InstallCRX(path, INSTALL_NEW);
- EXPECT_EQ(good_crx, good->id());
- UpdateExtension(good_crx, path, FAILED_SILENTLY);
-
- std::vector<std::string> blacklist;
- blacklist.push_back(good_crx);
- ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
- "v1");
-
- // Make sure pref is updated
- base::RunLoop().RunUntilIdle();
-
- // Now, the good_crx is blacklisted.
- ValidateBooleanPref(good_crx, "blacklist", true);
- EXPECT_EQ(0u, service_->extensions()->size());
-
- // Remove good_crx from blacklist
- blacklist.pop_back();
- ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
- "v2");
-
- // Make sure pref is updated
- base::RunLoop().RunUntilIdle();
- // blacklist value should not be set for good_crx
- EXPECT_FALSE(IsPrefExist(good_crx, "blacklist"));
-}
-
-// Unload installed extension from blacklist.
+#if defined(ENABLE_BLACKLIST_TESTS)
+// Tests trying to install a blacklisted extension.
TEST_F(ExtensionServiceTest, BlacklistedExtensionWillNotInstall) {
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
+ new FakeSafeBrowsingDatabaseManager(true));
+ Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
+
InitializeEmptyExtensionService();
+ service_->Init();
- // Fake the blacklisting of good_crx by pretending that we get an update
- // which includes it.
- extensions::Blacklist* blacklist =
- ExtensionSystem::Get(profile_.get())->blacklist();
- blacklist->SetFromUpdater(std::vector<std::string>(1, good_crx), "v1");
+ // After blacklisting good_crx, we cannot install it.
+ blacklist_db->SetUnsafe(good_crx).NotifyUpdate();
+ base::RunLoop().RunUntilIdle();
- // Now good_crx is blacklisted.
- ValidateBooleanPref(good_crx, "blacklist", true);
-
- // We cannot install good_crx.
base::FilePath path = data_dir_.AppendASCII("good.crx");
// HACK: specify WAS_INSTALLED_BY_DEFAULT so that test machinery doesn't
// decide to install this silently. Somebody should fix these tests, all
// 6,000 lines of them. Hah!
InstallCRX(path, INSTALL_FAILED, Extension::WAS_INSTALLED_BY_DEFAULT);
EXPECT_EQ(0u, service_->extensions()->size());
- ValidateBooleanPref(good_crx, "blacklist", true);
}
+#endif // defined(ENABLE_BLACKLIST_TESTS)
+#if defined(ENABLE_BLACKLIST_TESTS)
// Unload blacklisted extension on policy change.
TEST_F(ExtensionServiceTest, UnloadBlacklistedExtensionPolicy) {
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
+ new FakeSafeBrowsingDatabaseManager(true));
+ Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
+
+ // A profile with no extensions installed.
InitializeEmptyExtensionService();
+
base::FilePath path = data_dir_.AppendASCII("good.crx");
const Extension* good = InstallCRX(path, INSTALL_NEW);
@@ -3374,57 +3406,77 @@
whitelist.Append(new base::StringValue(good_crx));
prefs->Set(prefs::kExtensionInstallAllowList, whitelist);
- std::vector<std::string> blacklist;
- blacklist.push_back(good_crx);
- ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
- "v1");
-
- // Make sure pref is updated
+ blacklist_db->SetUnsafe(good_crx).NotifyUpdate();
base::RunLoop().RunUntilIdle();
// The good_crx is blacklisted and the whitelist doesn't negate it.
- ValidateBooleanPref(good_crx, "blacklist", true);
+ ASSERT_TRUE(ValidateBooleanPref(good_crx, "blacklist", true));
EXPECT_EQ(0u, service_->extensions()->size());
}
+#endif // defined(ENABLE_BLACKLIST_TESTS)
-// Test loading extensions from the profile directory, except
-// blacklisted ones.
+#if defined(ENABLE_BLACKLIST_TESTS)
+// Tests that a blacklisted extension is eventually unloaded on startup, if it
+// wasn't already.
TEST_F(ExtensionServiceTest, WillNotLoadBlacklistedExtensionsFromDirectory) {
- // Initialize the test dir with a good Preferences/extensions.
- base::FilePath source_install_dir = data_dir_
- .AppendASCII("good")
- .AppendASCII("Extensions");
- base::FilePath pref_path = source_install_dir
- .DirName()
- .AppendASCII("Preferences");
- InitializeInstalledExtensionService(pref_path, source_install_dir);
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
+ new FakeSafeBrowsingDatabaseManager(true));
+ Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
- // Blacklist good1.
- std::vector<std::string> blacklist;
- blacklist.push_back(good1);
- ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist,
- "v1");
+ // A profile with 3 extensions installed: good0, good1, and good2.
+ InitializeGoodInstalledExtensionService();
- // Make sure pref is updated
- base::RunLoop().RunUntilIdle();
-
- ValidateBooleanPref(good1, "blacklist", true);
+ // Blacklist good1 before the service initializes.
+ blacklist_db->SetUnsafe(good1);
// Load extensions.
service_->Init();
+ ASSERT_EQ(3u, loaded_.size()); // hasn't had time to blacklist yet
- std::vector<string16> errors = GetErrors();
- for (std::vector<string16>::iterator err = errors.begin();
- err != errors.end(); ++err) {
- LOG(ERROR) << *err;
- }
- ASSERT_EQ(2u, loaded_.size());
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(1u, service_->blacklisted_extensions()->size());
+ ASSERT_EQ(2u, service_->extensions()->size());
- EXPECT_TRUE(service_->GetInstalledExtension(good1));
- int include_mask = ExtensionService::INCLUDE_EVERYTHING &
- ~ExtensionService::INCLUDE_BLACKLISTED;
- EXPECT_FALSE(service_->GetExtensionById(good1, include_mask));
+ ASSERT_TRUE(service_->extensions()->Contains(good0));
+ ASSERT_TRUE(service_->blacklisted_extensions()->Contains(good1));
+ ASSERT_TRUE(service_->extensions()->Contains(good2));
}
+#endif // defined(ENABLE_BLACKLIST_TESTS)
+
+#if defined(ENABLE_BLACKLIST_TESTS)
+// Tests extensions blacklisted in prefs on startup; one still blacklisted by
+// safe browsing, the other not. The not-blacklisted one should recover.
+TEST_F(ExtensionServiceTest, BlacklistedInPrefsFromStartup) {
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
+ new FakeSafeBrowsingDatabaseManager(true));
+ Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
+
+ InitializeGoodInstalledExtensionService();
+ service_->extension_prefs()->SetExtensionBlacklisted(good0, true);
+ service_->extension_prefs()->SetExtensionBlacklisted(good1, true);
+
+ blacklist_db->SetUnsafe(good1);
+
+ service_->Init();
+
+ ASSERT_EQ(2u, service_->blacklisted_extensions()->size());
+ ASSERT_EQ(1u, service_->extensions()->size());
+
+ ASSERT_TRUE(service_->blacklisted_extensions()->Contains(good0));
+ ASSERT_TRUE(service_->blacklisted_extensions()->Contains(good1));
+ ASSERT_TRUE(service_->extensions()->Contains(good2));
+
+ // Give time for the blacklist to update.
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_EQ(1u, service_->blacklisted_extensions()->size());
+ ASSERT_EQ(2u, service_->extensions()->size());
+
+ ASSERT_TRUE(service_->extensions()->Contains(good0));
+ ASSERT_TRUE(service_->blacklisted_extensions()->Contains(good1));
+ ASSERT_TRUE(service_->extensions()->Contains(good2));
+}
+#endif // defined(ENABLE_BLACKLIST_TESTS)
// Will not install extension blacklisted by policy.
TEST_F(ExtensionServiceTest, BlacklistedByPolicyWillNotInstall) {
@@ -5122,15 +5174,10 @@
&triggered_type)); // Safe due to WeakPtrFactory scope.
// Install a component extension.
- base::FilePath path = data_dir_
- .AppendASCII("good")
- .AppendASCII("Extensions")
- .AppendASCII(good0)
- .AppendASCII("1.0.0.0");
std::string manifest;
ASSERT_TRUE(base::ReadFileToString(
- path.Append(extensions::kManifestFilename), &manifest));
- service_->component_loader()->Add(manifest, path);
+ good0_path().Append(extensions::kManifestFilename), &manifest));
+ service_->component_loader()->Add(manifest, good0_path());
ASSERT_FALSE(service_->is_ready());
service_->Init();
ASSERT_TRUE(service_->is_ready());
@@ -5141,14 +5188,7 @@
}
TEST_F(ExtensionServiceTest, DeferredSyncStartupPreInstalledNormal) {
- // Initialize the test dir with a good Preferences/extensions.
- base::FilePath source_install_dir = data_dir_
- .AppendASCII("good")
- .AppendASCII("Extensions");
- base::FilePath pref_path = source_install_dir
- .DirName()
- .AppendASCII("Preferences");
- InitializeInstalledExtensionService(pref_path, source_install_dir);
+ InitializeGoodInstalledExtensionService();
bool flare_was_called = false;
syncer::ModelType triggered_type(syncer::UNSPECIFIED);
@@ -5161,6 +5201,7 @@
ASSERT_FALSE(service_->is_ready());
service_->Init();
+ ASSERT_EQ(3u, loaded_.size());
ASSERT_TRUE(service_->is_ready());
// Extensions added before service is_ready() don't trigger sync startup.
@@ -5203,6 +5244,89 @@
ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
}
+TEST_F(ExtensionServiceTest, DisableExtensionFromSync) {
+ // Start the extensions service with one external extension already installed.
+ base::FilePath source_install_dir = data_dir_
+ .AppendASCII("good")
+ .AppendASCII("Extensions");
+ base::FilePath pref_path = source_install_dir
+ .DirName()
+ .AppendASCII("Preferences");
+
+ InitializeInstalledExtensionService(pref_path, source_install_dir);
+
+ // The user has enabled sync.
+ ProfileSyncService* sync_service =
+ ProfileSyncServiceFactory::GetForProfile(profile_.get());
+ sync_service->SetSyncSetupCompleted();
+
+ service_->Init();
+ ASSERT_TRUE(service_->is_ready());
+
+ ASSERT_EQ(3u, loaded_.size());
+
+ // We start enabled.
+ const Extension* extension = service_->GetExtensionById(good0, true);
+ ASSERT_TRUE(extension);
+ ASSERT_TRUE(service_->IsExtensionEnabled(good0));
+ extensions::ExtensionSyncData disable_good_crx(*extension, false, false);
+
+ // Then sync data arrives telling us to disable |good0|.
+ syncer::SyncDataList sync_data;
+ sync_data.push_back(disable_good_crx.GetSyncData());
+ service_->MergeDataAndStartSyncing(
+ syncer::EXTENSIONS, sync_data,
+ scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
+ scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+ ASSERT_FALSE(service_->IsExtensionEnabled(good0));
+}
+
+TEST_F(ExtensionServiceTest, DontDisableExtensionWithPendingEnableFromSync) {
+ // Start the extensions service with one external extension already installed.
+ base::FilePath source_install_dir = data_dir_
+ .AppendASCII("good")
+ .AppendASCII("Extensions");
+ base::FilePath pref_path = source_install_dir
+ .DirName()
+ .AppendASCII("Preferences");
+
+ InitializeInstalledExtensionService(pref_path, source_install_dir);
+
+ // The user has enabled sync.
+ ProfileSyncService* sync_service =
+ ProfileSyncServiceFactory::GetForProfile(profile_.get());
+ sync_service->SetSyncSetupCompleted();
+
+ service_->Init();
+ ASSERT_TRUE(service_->is_ready());
+ ASSERT_EQ(3u, loaded_.size());
+
+ const Extension* extension = service_->GetExtensionById(good0, true);
+ ASSERT_TRUE(service_->IsExtensionEnabled(good0));
+
+ // Disable extension before first sync data arrives.
+ service_->DisableExtension(good0, Extension::DISABLE_USER_ACTION);
+ ASSERT_FALSE(service_->IsExtensionEnabled(good0));
+
+ // Enable extension - this is now the most recent state.
+ service_->EnableExtension(good0);
+ ASSERT_TRUE(service_->IsExtensionEnabled(good0));
+
+ // Now sync data comes in that says to disable good0. This should be
+ // ignored.
+ extensions::ExtensionSyncData disable_good_crx(*extension, false, false);
+ syncer::SyncDataList sync_data;
+ sync_data.push_back(disable_good_crx.GetSyncData());
+ service_->MergeDataAndStartSyncing(
+ syncer::EXTENSIONS, sync_data,
+ scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
+ scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+
+ // The extension was enabled locally before the sync data arrived, so it
+ // should still be enabled now.
+ ASSERT_TRUE(service_->IsExtensionEnabled(good0));
+}
+
TEST_F(ExtensionServiceTest, GetSyncData) {
InitializeEmptyExtensionService();
InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
@@ -6271,7 +6395,13 @@
}
// Test that installing multiple external extensions works.
-TEST_F(ExtensionServiceTest, ExternalInstallMultiple) {
+// Flaky on windows; http://crbug.com/295757 .
+#if defined(OS_WIN)
+#define MAYBE_ExternalInstallMultiple DISABLED_ExternalInstallMultiple
+#else
+#define MAYBE_ExternalInstallMultiple ExternalInstallMultiple
+#endif
+TEST_F(ExtensionServiceTest, MAYBE_ExternalInstallMultiple) {
FeatureSwitch::ScopedOverride prompt(
FeatureSwitch::prompt_for_external_extensions(), true);
diff --git a/chrome/browser/extensions/extension_service_unittest.h b/chrome/browser/extensions/extension_service_unittest.h
index 4239714..05b71a0 100644
--- a/chrome/browser/extensions/extension_service_unittest.h
+++ b/chrome/browser/extensions/extension_service_unittest.h
@@ -49,6 +49,8 @@
const base::FilePath& prefs_file,
const base::FilePath& source_install_dir);
+ void InitializeGoodInstalledExtensionService();
+
void InitializeEmptyExtensionService();
void InitializeExtensionProcessManager();
diff --git a/chrome/browser/extensions/extension_sync_bundle.cc b/chrome/browser/extensions/extension_sync_bundle.cc
index 893b69c..8369c86 100644
--- a/chrome/browser/extensions/extension_sync_bundle.cc
+++ b/chrome/browser/extensions/extension_sync_bundle.cc
@@ -81,17 +81,6 @@
return result;
}
-void ExtensionSyncBundle::SyncChangeIfNeeded(const Extension& extension) {
- ExtensionSyncData extension_sync_data =
- extension_service_->GetExtensionSyncData(extension);
-
- syncer::SyncChangeList sync_change_list(1, extension_sync_data.GetSyncChange(
- HasExtensionId(extension.id()) ?
- syncer::SyncChange::ACTION_UPDATE : syncer::SyncChange::ACTION_ADD));
- sync_processor_->ProcessSyncChanges(FROM_HERE, sync_change_list);
- MarkPendingExtensionSynced(extension.id());
-}
-
void ExtensionSyncBundle::ProcessSyncChange(
ExtensionSyncData extension_sync_data) {
if (extension_sync_data.uninstalled())
@@ -126,6 +115,17 @@
return sync_processor_ != NULL;
}
+void ExtensionSyncBundle::SyncChangeIfNeeded(const Extension& extension) {
+ ExtensionSyncData extension_sync_data =
+ extension_service_->GetExtensionSyncData(extension);
+
+ syncer::SyncChangeList sync_change_list(1, extension_sync_data.GetSyncChange(
+ HasExtensionId(extension.id()) ?
+ syncer::SyncChange::ACTION_UPDATE : syncer::SyncChange::ACTION_ADD));
+ sync_processor_->ProcessSyncChanges(FROM_HERE, sync_change_list);
+ MarkPendingExtensionSynced(extension.id());
+}
+
std::vector<ExtensionSyncData> ExtensionSyncBundle::GetPendingData() const {
std::vector<ExtensionSyncData> pending_extensions;
for (std::map<std::string, ExtensionSyncData>::const_iterator
diff --git a/chrome/browser/extensions/extension_sync_bundle.h b/chrome/browser/extensions/extension_sync_bundle.h
index d9fdb4b..dab36a2 100644
--- a/chrome/browser/extensions/extension_sync_bundle.h
+++ b/chrome/browser/extensions/extension_sync_bundle.h
@@ -13,6 +13,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/extension_sync_data.h"
+#include "chrome/browser/extensions/sync_bundle.h"
#include "sync/api/syncable_service.h"
class ExtensionService;
@@ -28,10 +29,10 @@
class Extension;
// Bundle of extension specific sync stuff.
-class ExtensionSyncBundle {
+class ExtensionSyncBundle : public SyncBundle {
public:
explicit ExtensionSyncBundle(ExtensionService* extension_service);
- ~ExtensionSyncBundle();
+ virtual ~ExtensionSyncBundle();
// Setup this bundle to be sync extension data.
void SetupSync(syncer::SyncChangeProcessor* sync_processor,
@@ -58,9 +59,6 @@
// Process the given sync change and apply it.
void ProcessSyncChange(ExtensionSyncData extension_sync_data);
- // Sync a newly-installed extension or change an existing one.
- void SyncChangeIfNeeded(const Extension& extension);
-
// Process the list of sync changes.
void ProcessSyncChangeList(syncer::SyncChangeList sync_change_list);
@@ -80,8 +78,12 @@
const ExtensionSet& extensions,
std::vector<extensions::ExtensionSyncData>* sync_data_list) const;
+ // Overrides for SyncBundle.
// Returns true if SetupSync has been called, false otherwise.
- bool IsSyncing() const;
+ virtual bool IsSyncing() const OVERRIDE;
+
+ // Sync a newly-installed extension or change an existing one.
+ virtual void SyncChangeIfNeeded(const Extension& extension) OVERRIDE;
private:
// Add a synced extension.
diff --git a/chrome/browser/extensions/extension_sync_data_unittest.cc b/chrome/browser/extensions/extension_sync_data_unittest.cc
index 637137d..46b3549 100644
--- a/chrome/browser/extensions/extension_sync_data_unittest.cc
+++ b/chrome/browser/extensions/extension_sync_data_unittest.cc
@@ -14,24 +14,11 @@
namespace {
-#if defined(OS_WIN)
-const base::FilePath::CharType kExtensionFilePath[] =
- FILE_PATH_LITERAL("c:\\foo");
-#elif defined(OS_POSIX)
-const base::FilePath::CharType kExtensionFilePath[] = FILE_PATH_LITERAL("/foo");
-#endif
-
const char kValidId[] = "abcdefghijklmnopabcdefghijklmnop";
-const char kValidVersion[] = "0.0.0.0";
-const char kVersion1[] = "1.0.0.1";
-const char kVersion2[] = "1.0.1.0";
-const char kVersion3[] = "1.1.0.0";
-const char kValidUpdateUrl1[] =
- "http://clients2.google.com/service/update2/crx";
-const char kValidUpdateUrl2[] =
+const char kVersion[] = "1.0.0.1";
+const char kValidUpdateUrl[] =
"https://clients2.google.com/service/update2/crx";
const char kName[] = "MyExtension";
-const char kName2[] = "MyExtension2";
class ExtensionSyncDataTest : public testing::Test {
};
@@ -40,10 +27,10 @@
sync_pb::EntitySpecifics entity;
sync_pb::ExtensionSpecifics* extension_specifics = entity.mutable_extension();
extension_specifics->set_id(kValidId);
- extension_specifics->set_update_url(kValidUpdateUrl2);
+ extension_specifics->set_update_url(kValidUpdateUrl);
extension_specifics->set_enabled(false);
extension_specifics->set_incognito_enabled(true);
- extension_specifics->set_version(kVersion1);
+ extension_specifics->set_version(kVersion);
extension_specifics->set_name(kName);
syncer::SyncData sync_data =
syncer::SyncData::CreateLocalData("sync_tag", "non_unique_title", entity);
@@ -65,10 +52,10 @@
sync_pb::EntitySpecifics entity;
sync_pb::ExtensionSpecifics* input_extension = entity.mutable_extension();
input_extension->set_id(kValidId);
- input_extension->set_update_url(kValidUpdateUrl2);
+ input_extension->set_update_url(kValidUpdateUrl);
input_extension->set_enabled(true);
input_extension->set_incognito_enabled(false);
- input_extension->set_version(kVersion1);
+ input_extension->set_version(kVersion);
input_extension->set_name(kName);
syncer::SyncData sync_data =
syncer::SyncData::CreateLocalData("sync_tag", "non_unique_title", entity);
diff --git a/chrome/browser/extensions/extension_system.cc b/chrome/browser/extensions/extension_system.cc
index 9a6474c..ef79b60 100644
--- a/chrome/browser/extensions/extension_system.cc
+++ b/chrome/browser/extensions/extension_system.cc
@@ -95,12 +95,12 @@
// requests.
state_store_.reset(new StateStore(
profile_,
- profile_->GetPath().AppendASCII(ExtensionService::kStateStoreName),
+ profile_->GetPath().AppendASCII(extensions::kStateStoreName),
true));
rules_store_.reset(new StateStore(
profile_,
- profile_->GetPath().AppendASCII(ExtensionService::kRulesStoreName),
+ profile_->GetPath().AppendASCII(extensions::kRulesStoreName),
false));
blacklist_.reset(new Blacklist(ExtensionPrefs::Get(profile_)));
diff --git a/chrome/browser/extensions/extension_uninstall_dialog.cc b/chrome/browser/extensions/extension_uninstall_dialog.cc
index 0eb8dcf..fb6bc92 100644
--- a/chrome/browser/extensions/extension_uninstall_dialog.cc
+++ b/chrome/browser/extensions/extension_uninstall_dialog.cc
@@ -21,14 +21,14 @@
#include "grit/theme_resources.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
namespace {
// Returns pixel size under maximal scale factor for the icon whose device
// independent size is |size_in_dip|
int GetSizeForMaxScaleFactor(int size_in_dip) {
- ui::ScaleFactor max_scale_factor = ui::GetMaxScaleFactor();
- float max_scale_factor_scale = ui::GetScaleFactorScale(max_scale_factor);
+ float max_scale_factor_scale = gfx::ImageSkia::GetMaxSupportedScale();
return static_cast<int>(size_in_dip * max_scale_factor_scale);
}
@@ -39,7 +39,8 @@
const gfx::ImageSkia& image = is_app ?
extensions::IconsInfo::GetDefaultAppIcon() :
extensions::IconsInfo::GetDefaultExtensionIcon();
- return image.GetRepresentation(ui::GetMaxScaleFactor()).sk_bitmap();
+ return image.GetRepresentation(
+ gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
}
} // namespace
diff --git a/chrome/browser/extensions/extension_warning_badge_service_unittest.cc b/chrome/browser/extensions/extension_warning_badge_service_unittest.cc
index 273c016..2eb9174 100644
--- a/chrome/browser/extensions/extension_warning_badge_service_unittest.cc
+++ b/chrome/browser/extensions/extension_warning_badge_service_unittest.cc
@@ -56,10 +56,6 @@
const char* ext1_id = "extension1";
const char* ext2_id = "extension2";
-const ExtensionWarning::WarningType warning_1 =
- ExtensionWarning::kNetworkDelay;
-const ExtensionWarning::WarningType warning_2 =
- ExtensionWarning::kNetworkConflict;
} // namespace
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc
index 40a4deb..631ba56 100644
--- a/chrome/browser/extensions/extension_web_ui.cc
+++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -404,7 +404,7 @@
FaviconUtil::GetFaviconScaleFactors();
std::vector<extensions::ImageLoader::ImageRepresentation> info_list;
for (size_t i = 0; i < scale_factors.size(); ++i) {
- float scale = ui::GetScaleFactorScale(scale_factors[i]);
+ float scale = ui::GetImageScale(scale_factors[i]);
int pixel_size = static_cast<int>(gfx::kFaviconSize * scale);
extensions::ExtensionResource icon_resource =
extensions::IconsInfo::GetIconResource(extension,
diff --git a/chrome/browser/extensions/external_pref_loader.h b/chrome/browser/extensions/external_pref_loader.h
index c06dd35..231fbe3 100644
--- a/chrome/browser/extensions/external_pref_loader.h
+++ b/chrome/browser/extensions/external_pref_loader.h
@@ -45,6 +45,12 @@
return (options_ & option) != 0;
}
+ // The resource id of the base path with the information about the json
+ // file containing which extensions to load.
+ const int base_path_id_;
+
+ const Options options_;
+
private:
friend class base::RefCountedThreadSafe<ExternalLoader>;
@@ -66,12 +72,6 @@
// Must be called from the File thread.
void ReadStandaloneExtensionPrefFiles(DictionaryValue * prefs);
- // The resource id of the base path with the information about the json
- // file containing which extensions to load.
- int base_path_id_;
-
- Options options_;
-
// The path (coresponding to |base_path_id_| containing the json files
// describing which extensions to load.
base::FilePath base_path_;
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc
index 9f78b2b..9b86130 100644
--- a/chrome/browser/extensions/external_provider_impl.cc
+++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -371,7 +371,6 @@
bool is_chromeos_demo_session = false;
int bundled_extension_creation_flags = Extension::NO_FLAGS;
#if defined(OS_CHROMEOS)
- typedef chromeos::ExternalPrefCacheLoader PrefLoader;
chromeos::UserManager* user_manager = chromeos::UserManager::Get();
is_chromeos_demo_session =
user_manager && user_manager->IsLoggedInAsDemoUser() &&
@@ -379,22 +378,17 @@
policy::DEVICE_MODE_RETAIL_KIOSK;
bundled_extension_creation_flags = Extension::FROM_WEBSTORE |
Extension::WAS_INSTALLED_BY_DEFAULT;
-#else
- typedef ExternalPrefLoader PrefLoader;
#endif
-#if defined(OS_LINUX)
- if (!is_chromeos_demo_session) {
- int external_apps_path_id = profile->IsManaged() ?
- chrome::DIR_MANAGED_USERS_DEFAULT_APPS :
- chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS;
-
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ if (!profile->IsManaged()) {
provider_list->push_back(
linked_ptr<ExternalProviderInterface>(
new ExternalProviderImpl(
service,
- new PrefLoader(external_apps_path_id,
- ExternalPrefLoader::NONE),
+ new ExternalPrefLoader(
+ chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS,
+ ExternalPrefLoader::NONE),
profile,
Manifest::EXTERNAL_PREF,
Manifest::EXTERNAL_PREF_DOWNLOAD,
@@ -403,6 +397,21 @@
#endif
#if defined(OS_CHROMEOS)
+ if (!is_chromeos_demo_session) {
+ int external_apps_path_id = profile->IsManaged() ?
+ chrome::DIR_MANAGED_USERS_DEFAULT_APPS :
+ chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS;
+ provider_list->push_back(
+ linked_ptr<ExternalProviderInterface>(
+ new ExternalProviderImpl(
+ service,
+ new chromeos::ExternalPrefCacheLoader(external_apps_path_id),
+ profile,
+ Manifest::EXTERNAL_PREF,
+ Manifest::EXTERNAL_PREF_DOWNLOAD,
+ bundled_extension_creation_flags)));
+ }
+
policy::AppPackUpdater* app_pack_updater =
g_browser_process->browser_policy_connector()->GetAppPackUpdater();
if (is_chromeos_demo_session && app_pack_updater &&
diff --git a/chrome/browser/extensions/fake_safe_browsing_database_manager.cc b/chrome/browser/extensions/fake_safe_browsing_database_manager.cc
index 6abb86e..a8f213d 100644
--- a/chrome/browser/extensions/fake_safe_browsing_database_manager.cc
+++ b/chrome/browser/extensions/fake_safe_browsing_database_manager.cc
@@ -11,20 +11,57 @@
#include "base/bind_helpers.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/safe_browsing/safe_browsing_util.h"
namespace extensions {
-FakeSafeBrowsingDatabaseManager::FakeSafeBrowsingDatabaseManager()
+FakeSafeBrowsingDatabaseManager::FakeSafeBrowsingDatabaseManager(bool enabled)
: SafeBrowsingDatabaseManager(
make_scoped_refptr(SafeBrowsingService::CreateSafeBrowsingService())),
- enabled_(false) {
+ enabled_(enabled) {
}
FakeSafeBrowsingDatabaseManager::~FakeSafeBrowsingDatabaseManager() {
}
+FakeSafeBrowsingDatabaseManager& FakeSafeBrowsingDatabaseManager::Enable() {
+ enabled_ = true;
+ return *this;
+}
+
+FakeSafeBrowsingDatabaseManager&
+FakeSafeBrowsingDatabaseManager::ClearUnsafe() {
+ unsafe_ids_.clear();
+ return *this;
+}
+
+FakeSafeBrowsingDatabaseManager& FakeSafeBrowsingDatabaseManager::SetUnsafe(
+ const std::string& a) {
+ ClearUnsafe();
+ unsafe_ids_.insert(a);
+ return *this;
+}
+
+FakeSafeBrowsingDatabaseManager& FakeSafeBrowsingDatabaseManager::SetUnsafe(
+ const std::string& a, const std::string& b) {
+ SetUnsafe(a);
+ unsafe_ids_.insert(b);
+ return *this;
+}
+
+FakeSafeBrowsingDatabaseManager& FakeSafeBrowsingDatabaseManager::SetUnsafe(
+ const std::string& a, const std::string& b, const std::string& c) {
+ SetUnsafe(a, b);
+ unsafe_ids_.insert(c);
+ return *this;
+}
+
+void FakeSafeBrowsingDatabaseManager::NotifyUpdate() {
+ SafeBrowsingDatabaseManager::NotifyDatabaseUpdateFinished(true);
+}
+
bool FakeSafeBrowsingDatabaseManager::CheckExtensionIDs(
const std::set<std::string>& extension_ids,
Client* client) {
diff --git a/chrome/browser/extensions/fake_safe_browsing_database_manager.h b/chrome/browser/extensions/fake_safe_browsing_database_manager.h
index 2a91b73..d6b8e37 100644
--- a/chrome/browser/extensions/fake_safe_browsing_database_manager.h
+++ b/chrome/browser/extensions/fake_safe_browsing_database_manager.h
@@ -18,7 +18,7 @@
// call set_enabled to enable it.
class FakeSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager {
public:
- FakeSafeBrowsingDatabaseManager();
+ explicit FakeSafeBrowsingDatabaseManager(bool enabled);
// Returns true if synchronously safe, false if not in which case the unsafe
// IDs taken from |unsafe_ids_| are passed to to |client| on the current
@@ -26,11 +26,18 @@
virtual bool CheckExtensionIDs(const std::set<std::string>& extension_ids,
Client* client) OVERRIDE;
- void set_enabled(bool enabled) { enabled_ = enabled; }
+ // Return |this| to chain together SetUnsafe(...).NotifyUpdate() conveniently.
+ FakeSafeBrowsingDatabaseManager& Enable();
+ FakeSafeBrowsingDatabaseManager& ClearUnsafe();
+ FakeSafeBrowsingDatabaseManager& SetUnsafe(const std::string& a);
+ FakeSafeBrowsingDatabaseManager& SetUnsafe(const std::string& a,
+ const std::string& b);
+ FakeSafeBrowsingDatabaseManager& SetUnsafe(const std::string& a,
+ const std::string& b,
+ const std::string& c);
- void set_unsafe_ids(const std::set<std::string>& unsafe_ids) {
- unsafe_ids_ = unsafe_ids;
- }
+ // Send the update notification.
+ void NotifyUpdate();
private:
virtual ~FakeSafeBrowsingDatabaseManager();
diff --git a/chrome/browser/extensions/image_loader.cc b/chrome/browser/extensions/image_loader.cc
index 2e2702e..2c8f77c 100644
--- a/chrome/browser/extensions/image_loader.cc
+++ b/chrome/browser/extensions/image_loader.cc
@@ -334,7 +334,8 @@
const ImageRepresentation& image_rep = it->image_representation;
image_skia.AddRepresentation(gfx::ImageSkiaRep(
- bitmap, image_rep.scale_factor));
+ bitmap,
+ ui::GetImageScale(image_rep.scale_factor)));
}
gfx::Image image;
diff --git a/chrome/browser/extensions/pending_enables.cc b/chrome/browser/extensions/pending_enables.cc
new file mode 100644
index 0000000..f7af99d
--- /dev/null
+++ b/chrome/browser/extensions/pending_enables.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/extensions/pending_enables.h"
+
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/sync_bundle.h"
+#include "chrome/browser/sync/sync_prefs.h"
+
+namespace extensions {
+
+PendingEnables::PendingEnables(scoped_ptr<browser_sync::SyncPrefs> sync_prefs,
+ SyncBundle* sync_bundle,
+ syncer::ModelType enable_type)
+ : sync_prefs_(sync_prefs.Pass()),
+ sync_bundle_(sync_bundle),
+ enable_type_(enable_type),
+ is_sync_enabled_for_test_(false) {
+}
+
+PendingEnables::~PendingEnables() {
+}
+
+void PendingEnables::OnExtensionEnabled(const std::string& extension_id) {
+ if (IsWaitingForSync())
+ ids_.insert(extension_id);
+}
+
+void PendingEnables::OnExtensionDisabled(const std::string& extension_id) {
+ if (IsWaitingForSync())
+ ids_.erase(extension_id);
+}
+
+void PendingEnables::OnSyncStarted(ExtensionService* service) {
+ for (std::set<std::string>::const_iterator it = ids_.begin();
+ it != ids_.end(); ++it) {
+ const Extension* extension = service->GetExtensionById(*it, true);
+ if (extension)
+ sync_bundle_->SyncChangeIfNeeded(*extension);
+ }
+ ids_.clear();
+}
+
+bool PendingEnables::Contains(const std::string& extension_id) const {
+ return ids_.find(extension_id) != ids_.end();
+}
+
+bool PendingEnables::IsSyncEnabled() {
+ if (is_sync_enabled_for_test_)
+ return true;
+ return sync_prefs_ &&
+ sync_prefs_->HasSyncSetupCompleted() &&
+ sync_prefs_->GetPreferredDataTypes(syncer::ModelTypeSet(enable_type_))
+ .Has(enable_type_);
+}
+
+bool PendingEnables::IsWaitingForSync() {
+ return IsSyncEnabled() && !sync_bundle_->IsSyncing();
+}
+
+} // namespace extensions
+
diff --git a/chrome/browser/extensions/pending_enables.h b/chrome/browser/extensions/pending_enables.h
new file mode 100644
index 0000000..2c3d590
--- /dev/null
+++ b/chrome/browser/extensions/pending_enables.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_EXTENSIONS_PENDING_ENABLES_H_
+#define CHROME_BROWSER_EXTENSIONS_PENDING_ENABLES_H_
+
+#include <set>
+
+// Included for syncer::ModelType, which is in
+// sync/internal_api/public/base/model_type.h but that is disallowed by
+// chrome/browser/DEPS.
+#include "sync/api/syncable_service.h"
+
+class ExtensionService;
+class ProfileSyncService;
+
+namespace browser_sync {
+class SyncPrefs;
+}
+
+namespace extensions {
+
+class SyncBundle;
+
+// A pending enable is when an app or extension is enabled locally before sync
+// has started. We track these to prevent sync data arriving and clobbering
+// local state, and also to ensure that these early enables get synced to the
+// server when sync does start.
+class PendingEnables {
+ public:
+ PendingEnables(scoped_ptr<browser_sync::SyncPrefs> sync_prefs,
+ SyncBundle* sync_bundle,
+ syncer::ModelType enable_type);
+ ~PendingEnables();
+
+ // Called when an extension is enabled / disabled locally.
+ // These will check the sync state and figure out whether the change
+ // needs to be remembered for syncing when syncing starts.
+ void OnExtensionEnabled(const std::string& extension_id);
+ void OnExtensionDisabled(const std::string& extension_id);
+
+ // Called when |sync_bundle_| is ready to accept sync changes.
+ // Uses |service| to look up extensions from extension ids.
+ void OnSyncStarted(ExtensionService* service);
+
+ // Whether |extension_id| has a pending enable.
+ bool Contains(const std::string& extension_id) const;
+
+ private:
+ bool IsSyncEnabled();
+ bool IsWaitingForSync();
+
+ scoped_ptr<browser_sync::SyncPrefs> sync_prefs_;
+ SyncBundle* sync_bundle_;
+ syncer::ModelType enable_type_;
+ std::set<std::string> ids_;
+
+ bool is_sync_enabled_for_test_;
+
+ DISALLOW_COPY_AND_ASSIGN(PendingEnables);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_PENDING_ENABLES_H_
diff --git a/chrome/browser/extensions/sync_bundle.h b/chrome/browser/extensions/sync_bundle.h
new file mode 100644
index 0000000..e37465c
--- /dev/null
+++ b/chrome/browser/extensions/sync_bundle.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_EXTENSIONS_SYNC_BUNDLE_H_
+#define CHROME_BROWSER_EXTENSIONS_SYNC_BUNDLE_H_
+
+namespace extensions {
+
+class Extension;
+
+// Common interface between AppSyncBundle and ExtensionSyncBundle.
+class SyncBundle {
+ public:
+ virtual ~SyncBundle() {}
+
+ // Has this bundle started syncing yet?
+ virtual bool IsSyncing() const = 0;
+
+ // Syncs changes to |extension|.
+ virtual void SyncChangeIfNeeded(const Extension& extension) = 0;
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_SYNC_BUNDLE_H_
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc
index 780b3e6..b81f480 100644
--- a/chrome/browser/extensions/tab_helper.cc
+++ b/chrome/browser/extensions/tab_helper.cc
@@ -61,12 +61,6 @@
DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::TabHelper);
-namespace {
-
-const char kPermissionError[] = "permission_error";
-
-} // namespace
-
namespace extensions {
TabHelper::ScriptExecutionObserver::ScriptExecutionObserver(
@@ -119,7 +113,10 @@
// If more classes need to listen to global content script activity, then
// a separate routing class with an observer interface should be written.
profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
+
+#if defined(ENABLE_EXTENSIONS)
AddScriptExecutionObserver(ActivityLog::GetInstance(profile_));
+#endif
registrar_.Add(this,
content::NOTIFICATION_LOAD_STOP,
@@ -132,7 +129,9 @@
}
TabHelper::~TabHelper() {
+#if defined(ENABLE_EXTENSIONS)
RemoveScriptExecutionObserver(ActivityLog::GetInstance(profile_));
+#endif
}
void TabHelper::CreateApplicationShortcuts() {
diff --git a/chrome/browser/extensions/updater/extension_downloader.cc b/chrome/browser/extensions/updater/extension_downloader.cc
index 0c114f7..a76e3c7 100644
--- a/chrome/browser/extensions/updater/extension_downloader.cc
+++ b/chrome/browser/extensions/updater/extension_downloader.cc
@@ -719,23 +719,13 @@
(response_code == 200 || url.SchemeIsFile())) {
RETRY_HISTOGRAM("CrxFetchSuccess",
extensions_queue_.active_request_failure_count(), url);
- if (id == kBlacklistAppID) {
- std::string data;
- source->GetResponseAsString(&data);
- // TODO(asargent): try to get rid of this special case for the blacklist
- // to simplify the delegate's interface.
- delegate_->OnBlacklistDownloadFinished(
- data, extensions_queue_.active_request()->package_hash,
- extensions_queue_.active_request()->version, ping, request_ids);
- } else {
- base::FilePath crx_path;
- // Take ownership of the file at |crx_path|.
- CHECK(source->GetResponseAsFilePath(true, &crx_path));
- RecordCRXWriteHistogram(true, crx_path);
- delegate_->OnExtensionDownloadFinished(
- id, crx_path, url, extensions_queue_.active_request()->version,
- ping, request_ids);
- }
+ base::FilePath crx_path;
+ // Take ownership of the file at |crx_path|.
+ CHECK(source->GetResponseAsFilePath(true, &crx_path));
+ RecordCRXWriteHistogram(true, crx_path);
+ delegate_->OnExtensionDownloadFinished(
+ id, crx_path, url, extensions_queue_.active_request()->version,
+ ping, request_ids);
} else {
VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec()
<< "' response code:" << response_code;
diff --git a/chrome/browser/extensions/updater/extension_downloader_delegate.h b/chrome/browser/extensions/updater/extension_downloader_delegate.h
index 99f5d6e..acc239b 100644
--- a/chrome/browser/extensions/updater/extension_downloader_delegate.h
+++ b/chrome/browser/extensions/updater/extension_downloader_delegate.h
@@ -89,15 +89,6 @@
const PingResult& ping_result,
const std::set<int>& request_ids) = 0;
- // Same as OnExtensionDownloadFinished() but only for the kBlacklistAppID
- // extension, which passes different data to the delegate.
- virtual void OnBlacklistDownloadFinished(
- const std::string& data,
- const std::string& package_hash,
- const std::string& version,
- const PingResult& ping_result,
- const std::set<int>& request_ids) = 0;
-
// The remaining methods are used by the ExtensionDownloader to retrieve
// information about extensions from the delegate.
diff --git a/chrome/browser/extensions/updater/extension_updater.cc b/chrome/browser/extensions/updater/extension_updater.cc
index 6b9cece..8a8e215 100644
--- a/chrome/browser/extensions/updater/extension_updater.cc
+++ b/chrome/browser/extensions/updater/extension_updater.cc
@@ -18,7 +18,6 @@
#include "base/strings/string_split.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/module/module.h"
-#include "chrome/browser/extensions/blacklist.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/pending_extension_manager.h"
@@ -32,6 +31,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "crypto/sha2.h"
+#include "extensions/common/constants.h"
#include "extensions/common/manifest.h"
using base::RandDouble;
@@ -39,7 +39,6 @@
using base::Time;
using base::TimeDelta;
using content::BrowserThread;
-using prefs::kExtensionBlacklistUpdateVersion;
using prefs::kLastExtensionsUpdateCheck;
using prefs::kNextExtensionsUpdateCheck;
@@ -93,7 +92,7 @@
namespace extensions {
ExtensionUpdater::CheckParams::CheckParams()
- : check_blacklist(true), install_immediately(false) {}
+ : install_immediately(false) {}
ExtensionUpdater::CheckParams::~CheckParams() {}
@@ -131,13 +130,12 @@
ExtensionPrefs* extension_prefs,
PrefService* prefs,
Profile* profile,
- Blacklist* blacklist,
int frequency_seconds)
: alive_(false),
weak_ptr_factory_(this),
service_(service), frequency_seconds_(frequency_seconds),
will_check_soon_(false), extension_prefs_(extension_prefs),
- prefs_(prefs), profile_(profile), blacklist_(blacklist),
+ prefs_(prefs), profile_(profile),
next_request_id_(0),
crx_install_is_running_(false) {
DCHECK_GE(frequency_seconds_, 5);
@@ -252,7 +250,7 @@
// If the user has overridden the update frequency, don't bother reporting
// this.
- if (frequency_seconds_ == ExtensionService::kDefaultUpdateFrequencySeconds) {
+ if (frequency_seconds_ == extensions::kDefaultUpdateFrequencySeconds) {
Time last = Time::FromInternalValue(prefs_->GetInt64(
kLastExtensionsUpdateCheck));
if (last.ToInternalValue() != 0) {
@@ -374,17 +372,6 @@
}
}
- // Start a fetch of the blacklist if needed.
- if (params.check_blacklist) {
- ManifestFetchData::PingData ping_data;
- ping_data.rollcall_days =
- CalculatePingDays(extension_prefs_->BlacklistLastPingDay());
- request.in_progress_ids_.push_back(ExtensionDownloader::kBlacklistAppID);
- downloader_->StartBlacklistUpdate(
- prefs_->GetString(kExtensionBlacklistUpdateVersion), ping_data,
- request_id);
- }
-
// StartAllPending() might call OnExtensionDownloadFailed/Finished before
// it returns, which would cause NotifyIfFinished to incorrectly try to
// send out a notification. So check before we call StartAllPending if any
@@ -435,7 +422,6 @@
CheckParams params;
params.ids.push_back(extension_id);
- params.check_blacklist = false;
params.callback = base::Bind(&ExtensionUpdater::ExtensionCheckFinished,
weak_ptr_factory_.GetWeakPtr(),
extension_id, callback);
@@ -498,38 +484,6 @@
MaybeInstallCRXFile();
}
-void ExtensionUpdater::OnBlacklistDownloadFinished(
- const std::string& data,
- const std::string& package_hash,
- const std::string& version,
- const PingResult& ping,
- const std::set<int>& request_ids) {
- DCHECK(alive_);
- UpdatePingData(ExtensionDownloader::kBlacklistAppID, ping);
- for (std::set<int>::const_iterator it = request_ids.begin();
- it != request_ids.end(); ++it) {
- InProgressCheck& request = requests_in_progress_[*it];
- request.in_progress_ids_.remove(ExtensionDownloader::kBlacklistAppID);
- NotifyIfFinished(*it);
- }
-
- // Verify sha256 hash value.
- char sha256_hash_value[crypto::kSHA256Length];
- crypto::SHA256HashString(data, sha256_hash_value, crypto::kSHA256Length);
- std::string hash_in_hex = base::HexEncode(sha256_hash_value,
- crypto::kSHA256Length);
-
- if (package_hash != hash_in_hex) {
- NOTREACHED() << "Fetched blacklist checksum is not as expected. "
- << "Expected: " << package_hash << " Actual: " << hash_in_hex;
- return;
- }
- std::vector<std::string> blacklist;
- base::SplitString(data, '\n', &blacklist);
-
- blacklist_->SetFromUpdater(blacklist, version);
-}
-
bool ExtensionUpdater::GetPingDataForExtension(
const std::string& id,
ManifestFetchData::PingData* ping_data) {
@@ -556,10 +510,6 @@
bool ExtensionUpdater::GetExtensionExistingVersion(const std::string& id,
std::string* version) {
DCHECK(alive_);
- if (id == ExtensionDownloader::kBlacklistAppID) {
- *version = prefs_->GetString(kExtensionBlacklistUpdateVersion);
- return true;
- }
const Extension* extension = service_->GetExtensionById(id, true);
if (!extension)
return false;
@@ -574,13 +524,8 @@
void ExtensionUpdater::UpdatePingData(const std::string& id,
const PingResult& ping_result) {
DCHECK(alive_);
- if (ping_result.did_ping) {
- if (id == ExtensionDownloader::kBlacklistAppID) {
- extension_prefs_->SetBlacklistLastPingDay(ping_result.day_start);
- } else if (service_->GetExtensionById(id, true) != NULL) {
- extension_prefs_->SetLastPingDay(id, ping_result.day_start);
- }
- }
+ if (ping_result.did_ping)
+ extension_prefs_->SetLastPingDay(id, ping_result.day_start);
if (extension_prefs_->GetActiveBit(id)) {
extension_prefs_->SetActiveBit(id, false);
extension_prefs_->SetLastActivePingDay(id, ping_result.day_start);
diff --git a/chrome/browser/extensions/updater/extension_updater.h b/chrome/browser/extensions/updater/extension_updater.h
index 3a40f7e..b178aec 100644
--- a/chrome/browser/extensions/updater/extension_updater.h
+++ b/chrome/browser/extensions/updater/extension_updater.h
@@ -32,7 +32,6 @@
namespace extensions {
-class Blacklist;
class ExtensionDownloader;
class ExtensionPrefs;
class ExtensionUpdaterTest;
@@ -53,8 +52,7 @@
typedef base::Closure FinishedCallback;
struct CheckParams {
- // Creates a default CheckParams instance that checks for all extensions and
- // the extension blacklist.
+ // Creates a default CheckParams instance that checks for all extensions.
CheckParams();
~CheckParams();
@@ -62,9 +60,6 @@
// all extensions will be included in the update check.
std::list<std::string> ids;
- // If true, the extension blacklist will also be updated.
- bool check_blacklist;
-
// Normally extension updates get installed only when the extension is idle.
// Setting this to true causes any updates that are found to be installed
// right away.
@@ -82,7 +77,6 @@
ExtensionPrefs* extension_prefs,
PrefService* prefs,
Profile* profile,
- Blacklist* blacklist,
int frequency_seconds);
virtual ~ExtensionUpdater();
@@ -187,13 +181,6 @@
const PingResult& ping,
const std::set<int>& request_id) OVERRIDE;
- virtual void OnBlacklistDownloadFinished(
- const std::string& data,
- const std::string& package_hash,
- const std::string& version,
- const PingResult& ping,
- const std::set<int>& request_id) OVERRIDE;
-
virtual bool GetPingDataForExtension(
const std::string& id,
ManifestFetchData::PingData* ping_data) OVERRIDE;
@@ -242,7 +229,6 @@
ExtensionPrefs* extension_prefs_;
PrefService* prefs_;
Profile* profile_;
- Blacklist* blacklist_;
std::map<int, InProgressCheck> requests_in_progress_;
int next_request_id_;
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc
index 7fc96f4..cc5d412 100644
--- a/chrome/browser/extensions/updater/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -24,12 +24,10 @@
#include "base/threading/thread.h"
#include "base/version.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/blacklist.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/extensions/extension_sync_data.h"
#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/test_blacklist.h"
#include "chrome/browser/extensions/test_extension_prefs.h"
#include "chrome/browser/extensions/test_extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
@@ -134,11 +132,6 @@
const std::string&,
const PingResult&,
const std::set<int>&));
- MOCK_METHOD5(OnBlacklistDownloadFinished, void(const std::string&,
- const std::string&,
- const std::string&,
- const PingResult&,
- const std::set<int>&));
MOCK_METHOD2(GetPingDataForExtension,
bool(const std::string&, ManifestFetchData::PingData*));
MOCK_METHOD1(GetUpdateUrlData, std::string(const std::string&));
@@ -236,9 +229,7 @@
class MockService : public TestExtensionService {
public:
explicit MockService(TestExtensionPrefs* prefs)
- : prefs_(prefs),
- pending_extension_manager_(*this),
- blacklist_(prefs_->prefs()) {
+ : prefs_(prefs), pending_extension_manager_(*this) {
}
virtual ~MockService() {}
@@ -259,8 +250,6 @@
PrefService* pref_service() { return prefs_->pref_service(); }
- Blacklist* blacklist() { return &blacklist_; }
-
// Creates test extensions and inserts them into list. The name and
// version are all based on their index. If |update_url| is non-null, it
// will be used as the update_url for each extension.
@@ -288,7 +277,6 @@
TestExtensionPrefs* const prefs_;
PendingExtensionManager pending_extension_manager_;
TestingProfile profile_;
- Blacklist blacklist_;
private:
DISALLOW_COPY_AND_ASSIGN(MockService);
@@ -575,13 +563,8 @@
net::TestURLFetcherFactory factory;
ExtensionUpdater updater(
&service, service.extension_prefs(), service.pref_service(),
- service.profile(), service.blacklist(), 60*60*24);
+ service.profile(), 60*60*24);
updater.Start();
- // Disable blacklist checks (tested elsewhere) so that we only see the
- // update HTTP request.
- ExtensionUpdater::CheckParams check_params;
- check_params.check_blacklist = false;
- updater.set_default_check_params(check_params);
// Tell the update that it's time to do update checks.
EXPECT_EQ(0u, observer.StartedCount());
@@ -613,45 +596,6 @@
EXPECT_EQ("", params["uc"]);
}
- void TestBlacklistUpdateCheckRequests() {
- // Setup and start the updater.
- ServiceForManifestTests service(prefs_.get());
- NotificationsObserver observer;
-
- net::TestURLFetcherFactory factory;
- ExtensionUpdater updater(
- &service, service.extension_prefs(), service.pref_service(),
- service.profile(), service.blacklist(), 60*60*24);
- updater.Start();
-
- // Tell the updater that it's time to do update checks.
- EXPECT_EQ(0u, observer.StartedCount());
- SimulateTimerFired(&updater);
- EXPECT_EQ(1u, observer.StartedCount());
-
- // Get the url our mock fetcher was asked to fetch.
- net::TestURLFetcher* fetcher =
- factory.GetFetcherByID(ExtensionDownloader::kManifestFetcherId);
- ASSERT_FALSE(fetcher == NULL);
- const GURL& url = fetcher->GetOriginalURL();
-
- EXPECT_FALSE(url.is_empty());
- EXPECT_TRUE(url.is_valid());
- EXPECT_TRUE(url.SchemeIs("https"));
- EXPECT_EQ("clients2.google.com", url.host());
- EXPECT_EQ("/service/update2/crx", url.path());
-
- // Validate the extension request parameters in the query. It should
- // look something like "x=id%3D<id>%26v%3D<version>%26uc".
- EXPECT_TRUE(url.has_query());
- std::map<std::string, std::string> params;
- VerifyQueryAndExtractParameters(url.query(), ¶ms);
- EXPECT_EQ("com.google.crx.blacklist", params["id"]);
- EXPECT_EQ("0", params["v"]);
- EXPECT_EQ("", params["uc"]);
- EXPECT_TRUE(ContainsKey(params, "ping"));
- }
-
void TestUpdateUrlDataEmpty() {
const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
const std::string version = "1.0";
@@ -1028,7 +972,6 @@
ExtensionUpdater updater(service.get(), service->extension_prefs(),
service->pref_service(),
service->profile(),
- service->blacklist(),
kUpdateFrequencySecs);
updater.Start();
ResetDownloader(
@@ -1098,58 +1041,6 @@
EXPECT_EQ(extension_file_path, tmpfile_path);
}
- void TestBlacklistDownloading() {
- net::TestURLFetcherFactory factory;
- net::TestURLFetcher* fetcher = NULL;
- MockService service(prefs_.get());
- TestBlacklist blacklist(service.blacklist());
- ExtensionUpdater updater(
- &service, service.extension_prefs(), service.pref_service(),
- service.profile(), blacklist.blacklist(), kUpdateFrequencySecs);
- updater.Start();
- ResetDownloader(
- &updater,
- new ExtensionDownloader(&updater, service.request_context()));
- updater.downloader_->extensions_queue_.set_backoff_policy(
- &kNoBackoffPolicy);
-
- GURL test_url("http://localhost/extension.crx");
-
- std::string id = "com.google.crx.blacklist";
-
- std::string hash =
- "CCEA231D3CD30A348DA1383ED311EAC11E82360773CB2BA4E2C3A5FF16E337CC";
-
- std::string version = "0.0.1";
- std::set<int> requests;
- requests.insert(0);
- scoped_ptr<ExtensionDownloader::ExtensionFetch> fetch(
- new ExtensionDownloader::ExtensionFetch(
- id, test_url, hash, version, requests));
- updater.downloader_->FetchUpdatedExtension(fetch.Pass());
-
- // Call back the ExtensionUpdater with a 200 response and some test data.
- std::string extension_data("aaaabbbbcccceeeeaaaabbbbcccceeee");
- EXPECT_FALSE(blacklist.IsBlacklisted(extension_data));
-
- fetcher = factory.GetFetcherByID(ExtensionDownloader::kExtensionFetcherId);
- EXPECT_TRUE(fetcher != NULL && fetcher->delegate() != NULL);
- EXPECT_TRUE(fetcher->GetLoadFlags() == kExpectedLoadFlags);
-
- fetcher->set_url(test_url);
- fetcher->set_status(net::URLRequestStatus());
- fetcher->set_response_code(200);
- fetcher->SetResponseString(extension_data);
- fetcher->delegate()->OnURLFetchComplete(fetcher);
-
- RunUntilIdle();
-
- EXPECT_TRUE(blacklist.IsBlacklisted(extension_data));
-
- EXPECT_EQ(version, service.pref_service()->
- GetString(prefs::kExtensionBlacklistUpdateVersion));
- }
-
// Two extensions are updated. If |updates_start_running| is true, the
// mock extensions service has UpdateExtension(...) return true, and
// the test is responsible for creating fake CrxInstallers. Otherwise,
@@ -1160,7 +1051,7 @@
ServiceForDownloadTests service(prefs_.get());
ExtensionUpdater updater(
&service, service.extension_prefs(), service.pref_service(),
- service.profile(), service.blacklist(), kUpdateFrequencySecs);
+ service.profile(), kUpdateFrequencySecs);
updater.Start();
ResetDownloader(
&updater,
@@ -1374,9 +1265,8 @@
ExtensionUpdater updater(
&service, service.extension_prefs(), service.pref_service(),
- service.profile(), service.blacklist(), kUpdateFrequencySecs);
+ service.profile(), kUpdateFrequencySecs);
ExtensionUpdater::CheckParams params;
- params.check_blacklist = false;
updater.Start();
updater.CheckNow(params);
@@ -1468,7 +1358,7 @@
ExtensionUpdater updater(
&service, service.extension_prefs(), service.pref_service(),
- service.profile(), service.blacklist(), kUpdateFrequencySecs);
+ service.profile(), kUpdateFrequencySecs);
updater.Start();
ResetDownloader(
&updater,
@@ -1517,10 +1407,6 @@
TestExtensionUpdateCheckRequests(true);
}
-TEST_F(ExtensionUpdaterTest, TestBlacklistUpdateCheckRequests) {
- TestBlacklistUpdateCheckRequests();
-}
-
TEST_F(ExtensionUpdaterTest, TestUpdateUrlData) {
TestUpdateUrlDataEmpty();
TestUpdateUrlDataSimple();
@@ -1561,10 +1447,6 @@
TestSingleExtensionDownloading(true, true);
}
-TEST_F(ExtensionUpdaterTest, TestBlacklistDownloading) {
- TestBlacklistDownloading();
-}
-
TEST_F(ExtensionUpdaterTest, TestMultipleExtensionDownloadingUpdatesFail) {
TestMultipleExtensionDownloading(false);
}
@@ -1593,7 +1475,7 @@
ServiceForManifestTests service(prefs_.get());
ExtensionUpdater updater(&service, service.extension_prefs(),
service.pref_service(), service.profile(),
- service.blacklist(), kUpdateFrequencySecs);
+ kUpdateFrequencySecs);
MockExtensionDownloaderDelegate delegate;
// Set the downloader directly, so that all its events end up in the mock
// |delegate|.
@@ -1616,7 +1498,6 @@
service.set_extensions(extensions);
ExtensionUpdater::CheckParams params;
- params.check_blacklist = false;
updater.Start();
updater.CheckNow(params);
}
@@ -1626,7 +1507,7 @@
ServiceForManifestTests service(prefs_.get());
ExtensionUpdater updater(&service, service.extension_prefs(),
service.pref_service(), service.profile(),
- service.blacklist(), kUpdateFrequencySecs);
+ kUpdateFrequencySecs);
MockExtensionDownloaderDelegate delegate;
// Set the downloader directly, so that all its events end up in the mock
// |delegate|.
@@ -1655,7 +1536,6 @@
service.set_extensions(enabled_extensions);
service.set_disabled_extensions(disabled_extensions);
ExtensionUpdater::CheckParams params;
- params.check_blacklist = false;
updater.Start();
updater.CheckNow(params);
}
@@ -1733,7 +1613,7 @@
net::TestURLFetcherFactory factory;
ExtensionUpdater updater(
&service, service.extension_prefs(), service.pref_service(),
- service.profile(), service.blacklist(), kUpdateFrequencySecs);
+ service.profile(), kUpdateFrequencySecs);
EXPECT_FALSE(updater.WillCheckSoon());
updater.Start();
EXPECT_FALSE(updater.WillCheckSoon());
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index 9ebf8f7..ab1d1c9 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -62,7 +62,6 @@
const char kApprovalKey[] = "extensions.webstore_installer";
const char kInvalidIdError[] = "Invalid id";
-const char kNoBrowserError[] = "No browser found";
const char kDownloadDirectoryError[] = "Could not create download directory";
const char kDownloadCanceledError[] = "Download canceled";
const char kInstallCanceledError[] = "Install canceled";
@@ -71,6 +70,7 @@
"Download was not a valid extension or user script";
const char kInlineInstallSource[] = "inline";
const char kDefaultInstallSource[] = "ondemand";
+const char kAppLauncherInstallSource[] = "applauncher";
base::FilePath* g_download_directory_for_tests = NULL;
@@ -203,7 +203,7 @@
NavigationController* controller,
const std::string& id,
scoped_ptr<Approval> approval,
- int flags)
+ InstallSource source)
: profile_(profile),
delegate_(delegate),
controller_(controller),
@@ -212,8 +212,20 @@
approval_(approval.release()) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(controller_);
- download_url_ = GetWebstoreInstallURL(id, flags & FLAG_INLINE_INSTALL ?
- kInlineInstallSource : kDefaultInstallSource);
+
+ const char* install_source = "";
+ switch (source) {
+ case INSTALL_SOURCE_INLINE:
+ install_source = kInlineInstallSource;
+ break;
+ case INSTALL_SOURCE_APP_LAUNCHER:
+ install_source = kAppLauncherInstallSource;
+ break;
+ case INSTALL_SOURCE_OTHER:
+ install_source = kDefaultInstallSource;
+ }
+
+ download_url_ = GetWebstoreInstallURL(id, install_source);
registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
diff --git a/chrome/browser/extensions/webstore_installer.h b/chrome/browser/extensions/webstore_installer.h
index cfb88f8..6297881 100644
--- a/chrome/browser/extensions/webstore_installer.h
+++ b/chrome/browser/extensions/webstore_installer.h
@@ -42,12 +42,12 @@
public base::RefCountedThreadSafe<
WebstoreInstaller, content::BrowserThread::DeleteOnUIThread> {
public:
- enum Flag {
- FLAG_NONE = 0,
-
+ enum InstallSource {
// Inline installs trigger slightly different behavior (install source
// is different, download referrers are the item's page in the gallery).
- FLAG_INLINE_INSTALL = 1 << 0
+ INSTALL_SOURCE_INLINE,
+ INSTALL_SOURCE_APP_LAUNCHER,
+ INSTALL_SOURCE_OTHER
};
enum FailureReason {
@@ -146,7 +146,7 @@
content::NavigationController* controller,
const std::string& id,
scoped_ptr<Approval> approval,
- int flags);
+ InstallSource source);
// Starts downloading and installing the extension.
void Start();
diff --git a/chrome/browser/extensions/webstore_installer_unittest.cc b/chrome/browser/extensions/webstore_installer_unittest.cc
index f81ec44..e46dad1 100644
--- a/chrome/browser/extensions/webstore_installer_unittest.cc
+++ b/chrome/browser/extensions/webstore_installer_unittest.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/extensions/webstore_installer.h"
#include "chrome/common/omaha_query_params/omaha_query_params.h"
#include "extensions/common/id_util.h"
+#include "net/base/escape.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPrintf;
@@ -22,14 +23,17 @@
TEST(WebstoreInstallerTest, PlatformParams) {
std::string id = extensions::id_util::GenerateId("some random string");
- GURL url = WebstoreInstaller::GetWebstoreInstallURL(id, "");
+ std::string source = "inline";
+ GURL url = WebstoreInstaller::GetWebstoreInstallURL(id, source);
std::string query = url.query();
EXPECT_TRUE(Contains(query,StringPrintf("os=%s", OmahaQueryParams::getOS())));
EXPECT_TRUE(Contains(query,StringPrintf("arch=%s",
OmahaQueryParams::getArch())));
EXPECT_TRUE(Contains(query,StringPrintf("nacl_arch=%s",
OmahaQueryParams::getNaclArch())));
-
+ EXPECT_TRUE(Contains(query,net::EscapeQueryParamValue(
+ StringPrintf("installsource=%s", source.c_str()),
+ true)));
}
} // namespace extensions
diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc
index d7185a1..c9a2f96 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.cc
+++ b/chrome/browser/extensions/webstore_standalone_installer.cc
@@ -27,7 +27,6 @@
const char kShowUserCountKey[] = "show_user_count";
const char kAverageRatingKey[] = "average_rating";
const char kRatingCountKey[] = "rating_count";
-const char kRedirectUrlKey[] = "redirect_url";
const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID";
const char kWebstoreRequestError[] =
@@ -44,6 +43,7 @@
: id_(webstore_item_id),
callback_(callback),
profile_(profile),
+ install_source_(WebstoreInstaller::INSTALL_SOURCE_INLINE),
show_user_count_(true),
average_rating_(0.0),
rating_count_(0) {
@@ -221,7 +221,7 @@
&(GetWebContents()->GetController()),
id_,
approval.Pass(),
- WebstoreInstaller::FLAG_INLINE_INSTALL);
+ install_source_);
installer->Start();
}
diff --git a/chrome/browser/extensions/webstore_standalone_installer.h b/chrome/browser/extensions/webstore_standalone_installer.h
index 1c62ab5..9175588 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.h
+++ b/chrome/browser/extensions/webstore_standalone_installer.h
@@ -118,6 +118,12 @@
}
double average_rating() const { return average_rating_; }
int rating_count() const { return rating_count_; }
+ void set_install_source(WebstoreInstaller::InstallSource source) {
+ install_source_ = source;
+ }
+ WebstoreInstaller::InstallSource install_source() const {
+ return install_source_;
+ }
private:
friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>;
@@ -172,6 +178,7 @@
std::string id_;
Callback callback_;
Profile* profile_;
+ WebstoreInstaller::InstallSource install_source_;
// Installation dialog and its underlying prompt.
scoped_ptr<ExtensionInstallPrompt> install_ui_;
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc
index 531f65d..1a2c619 100644
--- a/chrome/browser/extensions/window_open_apitest.cc
+++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -4,6 +4,7 @@
#include "base/command_line.h"
#include "base/memory/scoped_vector.h"
+#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_host.h"
@@ -16,6 +17,7 @@
#include "chrome/browser/ui/browser_iterator.h"
#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/test/base/test_switches.h"
@@ -26,6 +28,7 @@
#include "content/public/test/browser_test_utils.h"
#include "extensions/common/switches.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"
#if defined(USE_ASH)
@@ -134,6 +137,19 @@
EXPECT_TRUE(WaitForTabsAndPopups(browser(), num_tabs, num_popups, 0));
}
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowOpenPopupIframe) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ base::FilePath test_data_dir;
+ PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
+ embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
+ ASSERT_TRUE(LoadExtension(
+ test_data_dir_.AppendASCII("window_open").AppendASCII("popup_iframe")));
+
+ const int num_tabs = 0;
+ const int num_popups = 1;
+ EXPECT_TRUE(WaitForTabsAndPopups(browser(), num_tabs, num_popups, 0));
+}
+
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowOpenPopupLarge) {
ASSERT_TRUE(StartEmbeddedTestServer());
ASSERT_TRUE(LoadExtension(
diff --git a/chrome/browser/favicon/favicon_handler.cc b/chrome/browser/favicon/favicon_handler.cc
index 8eb1897..5e1459c 100644
--- a/chrome/browser/favicon/favicon_handler.cc
+++ b/chrome/browser/favicon/favicon_handler.cc
@@ -67,7 +67,7 @@
base_size = 0;
break;
}
- return ui::GetScaleFactorScale(ui::GetMaxScaleFactor()) * base_size;
+ return gfx::ImageSkia::GetMaxSupportedScale() * base_size;
}
bool DoUrlAndIconMatch(const FaviconURL& favicon_url,
@@ -148,7 +148,7 @@
FaviconUtil::GetFaviconScaleFactors();
for (size_t i = 0; i < scale_factors.size(); ++i) {
int edge_size_in_pixel = floor(
- desired_size_in_dip * ui::GetScaleFactorScale(scale_factors[i]));
+ desired_size_in_dip * ui::GetImageScale(scale_factors[i]));
std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(),
favicon_sizes.end(), gfx::Size(edge_size_in_pixel, edge_size_in_pixel));
if (it == favicon_sizes.end())
diff --git a/chrome/browser/favicon/favicon_handler_unittest.cc b/chrome/browser/favicon/favicon_handler_unittest.cc
index d89d45f..5671b73 100644
--- a/chrome/browser/favicon/favicon_handler_unittest.cc
+++ b/chrome/browser/favicon/favicon_handler_unittest.cc
@@ -410,7 +410,8 @@
// results on all platforms.
std::vector<ui::ScaleFactor> scale_factors;
scale_factors.push_back(ui::SCALE_FACTOR_100P);
- ui::test::SetSupportedScaleFactors(scale_factors);
+ scoped_set_supported_scale_factors_.reset(
+ new ui::test::ScopedSetSupportedScaleFactors(scale_factors));
ChromeRenderViewHostTestHarness::SetUp();
}
@@ -424,6 +425,9 @@
}
private:
+ typedef scoped_ptr<ui::test::ScopedSetSupportedScaleFactors>
+ ScopedSetSupportedScaleFactors;
+ ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_;
DISALLOW_COPY_AND_ASSIGN(FaviconHandlerTest);
};
diff --git a/chrome/browser/favicon/favicon_service.cc b/chrome/browser/favicon/favicon_service.cc
index 555cdb1..fd0f9eb 100644
--- a/chrome/browser/favicon/favicon_service.cc
+++ b/chrome/browser/favicon/favicon_service.cc
@@ -238,7 +238,7 @@
return;
gfx::ImageSkia image_skia = image.AsImageSkia();
- image_skia.EnsureRepsForSupportedScaleFactors();
+ image_skia.EnsureRepsForSupportedScales();
const std::vector<gfx::ImageSkiaRep>& image_reps = image_skia.image_reps();
std::vector<chrome::FaviconBitmapData> favicon_bitmap_data;
for (size_t i = 0; i < image_reps.size(); ++i) {
@@ -343,7 +343,7 @@
}
// If history bitmap is already desired pixel size, return early.
- float desired_scale = ui::GetScaleFactorScale(desired_scale_factor);
+ float desired_scale = ui::GetImageScale(desired_scale_factor);
int desired_edge_width_in_pixel = static_cast<int>(
desired_size_in_dip * desired_scale + 0.5f);
gfx::Size desired_size_in_pixel(desired_edge_width_in_pixel,
diff --git a/chrome/browser/favicon/favicon_util.cc b/chrome/browser/favicon/favicon_util.cc
index 4f2db61..a34ffca 100644
--- a/chrome/browser/favicon/favicon_util.cc
+++ b/chrome/browser/favicon/favicon_util.cc
@@ -43,18 +43,17 @@
best_candidate = png_data[i].bitmap_data;
}
}
- png_reps.push_back(gfx::ImagePNGRep(best_candidate,
- ui::SCALE_FACTOR_100P));
+ png_reps.push_back(gfx::ImagePNGRep(best_candidate, 1.0f));
return png_reps;
}
// Cache the scale factor for each pixel size as |scale_factors| may contain
// any of GetFaviconScaleFactors() which may include scale factors not
- // supported by the platform. (ui::GetScaleFactorFromScale() cannot be used.)
+ // supported by the platform. (ui::GetSupportedScaleFactor() cannot be used.)
std::map<int, ui::ScaleFactor> desired_pixel_sizes;
for (size_t i = 0; i < scale_factors.size(); ++i) {
int pixel_size = floor(favicon_size *
- ui::GetScaleFactorScale(scale_factors[i]));
+ ui::GetImageScale(scale_factors[i]));
desired_pixel_sizes[pixel_size] = scale_factors[i];
}
@@ -71,7 +70,9 @@
if (it == desired_pixel_sizes.end())
continue;
- png_reps.push_back(gfx::ImagePNGRep(png_data[i].bitmap_data, it->second));
+ png_reps.push_back(
+ gfx::ImagePNGRep(png_data[i].bitmap_data,
+ ui::GetImageScale(it->second)));
}
return png_reps;
@@ -137,7 +138,7 @@
// static
std::vector<ui::ScaleFactor> FaviconUtil::GetFaviconScaleFactors() {
- const float kScale1x = ui::GetScaleFactorScale(ui::SCALE_FACTOR_100P);
+ const float kScale1x = ui::GetImageScale(ui::SCALE_FACTOR_100P);
std::vector<ui::ScaleFactor> favicon_scale_factors =
ui::GetSupportedScaleFactors();
@@ -146,7 +147,7 @@
// well.
size_t insert_index = favicon_scale_factors.size();
for (size_t i = 0; i < favicon_scale_factors.size(); ++i) {
- float scale = ui::GetScaleFactorScale(favicon_scale_factors[i]);
+ float scale = ui::GetImageScale(favicon_scale_factors[i]);
if (scale == kScale1x) {
return favicon_scale_factors;
} else if (scale > kScale1x) {
@@ -201,7 +202,7 @@
std::vector<ui::ScaleFactor>::iterator it = std::find(
scale_factors_to_generate.begin(),
scale_factors_to_generate.end(),
- png_reps[i].scale_factor);
+ ui::GetSupportedScaleFactor(png_reps[i].scale));
CHECK(it != scale_factors_to_generate.end());
scale_factors_to_generate.erase(it);
}
@@ -229,7 +230,7 @@
for (size_t i = 0; i < scale_factors_to_generate.size(); ++i) {
ui::ScaleFactor scale_factor = scale_factors_to_generate[i];
int desired_size_in_pixel =
- ceil(favicon_size * ui::GetScaleFactorScale(scale_factor));
+ ceil(favicon_size * ui::GetImageScale(scale_factor));
SkBitmap bitmap = ResizeBitmapByDownsamplingIfPossible(
bitmaps, desired_size_in_pixel);
resized_image_skia.AddRepresentation(
@@ -246,7 +247,7 @@
if (gfx::PNGCodec::EncodeBGRASkBitmap(
resized_image_skia_reps[i].sk_bitmap(), false, &png_bytes->data())) {
png_reps.push_back(gfx::ImagePNGRep(png_bytes,
- resized_image_skia_reps[i].scale_factor()));
+ resized_image_skia_reps[i].scale()));
}
}
diff --git a/chrome/browser/feedback/feedback_data.cc b/chrome/browser/feedback/feedback_data.cc
index 4ab0347..658a17d 100644
--- a/chrome/browser/feedback/feedback_data.cc
+++ b/chrome/browser/feedback/feedback_data.cc
@@ -44,14 +44,7 @@
std::string key = it->first;
std::string value = it->second;
- // Screensize info is sent with every report to remember the window size
- // for when feedback was invoked. This is a hack needed to know what
- // dimensions the user screenshot is since the actual screenshot mechanism
- // in JS doesn't give us the dimensions of the screenshot taken. These
- // values shouldn't be sent with the report.
- if (key == FeedbackData::kScreensizeHeightKey ||
- key == FeedbackData::kScreensizeWidthKey ||
- FeedbackData::BelowCompressionThreshold(value))
+ if (FeedbackData::BelowCompressionThreshold(value))
continue;
TrimString(key, "\n ", &key);
@@ -83,11 +76,6 @@
} // namespace
// static
-const char FeedbackData::kScreensizeHeightKey[] = "ScreensizeHeight";
-// static
-const char FeedbackData::kScreensizeWidthKey[] = "ScreensizeWidth";
-
-// static
bool FeedbackData::BelowCompressionThreshold(const std::string& content) {
if (content.length() > kFeedbackMaxLength)
return false;
@@ -98,6 +86,7 @@
}
FeedbackData::FeedbackData() : profile_(NULL),
+ trace_id_(0),
feedback_page_data_complete_(false),
syslogs_compression_complete_(false),
report_sent_(false) {
@@ -115,6 +104,16 @@
scoped_ptr<FeedbackData::SystemLogsMap> sys_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (trace_id_ != 0) {
+ TracingManager* manager = TracingManager::Get();
+ if (!manager ||
+ !manager->GetTraceData(
+ trace_id_,
+ base::Bind(&FeedbackData::OnGetTraceData, this))) {
+ trace_id_ = 0;
+ }
+ }
+
sys_info_ = sys_info.Pass();
if (sys_info_.get()) {
std::string* compressed_logs_ptr = new std::string;
@@ -130,6 +129,19 @@
}
}
+void FeedbackData::OnGetTraceData(
+ scoped_refptr<base::RefCountedString> trace_data) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ scoped_ptr<std::string> data(new std::string(trace_data->data()));
+
+ set_attached_filename(kTraceFilename);
+ set_attached_filedata(data.Pass());
+ trace_id_ = 0;
+
+ SendReport();
+}
+
void FeedbackData::OnCompressLogsComplete(
scoped_ptr<std::string> compressed_logs) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -142,6 +154,7 @@
bool FeedbackData::IsDataComplete() {
return (syslogs_compression_complete_ || !sys_info_.get()) &&
+ !trace_id_ &&
feedback_page_data_complete_;
}
diff --git a/chrome/browser/feedback/feedback_data.h b/chrome/browser/feedback/feedback_data.h
index fb17a80..f88b007 100644
--- a/chrome/browser/feedback/feedback_data.h
+++ b/chrome/browser/feedback/feedback_data.h
@@ -15,6 +15,7 @@
namespace base {
class FilePath;
+class RefCountedString;
}
class Profile;
@@ -22,9 +23,6 @@
public:
typedef std::map<std::string, std::string> SystemLogsMap;
- static const char kScreensizeHeightKey[];
- static const char kScreensizeWidthKey[];
-
// Determine if the given feedback value is small enough to not need to
// be compressed.
static bool BelowCompressionThreshold(const std::string& content);
@@ -57,9 +55,10 @@
const std::string& user_email() const { return user_email_; }
std::string* image() const { return image_.get(); }
const std::string attached_filename() const { return attached_filename_; }
- const GURL attached_file_url() const { return attached_file_url_; }
+ const std::string attached_file_uuid() const { return attached_file_uuid_; }
std::string* attached_filedata() const { return attached_filedata_.get(); }
- const GURL screenshot_url() const { return screenshot_url_; }
+ const std::string screenshot_uuid() const { return screenshot_uuid_; }
+ int trace_id() const { return trace_id_; }
SystemLogsMap* sys_info() const { return sys_info_.get(); }
std::string* compressed_logs() const { return compressed_logs_.get(); }
@@ -82,14 +81,21 @@
void set_attached_filedata(scoped_ptr<std::string> attached_filedata) {
attached_filedata_ = attached_filedata.Pass();
}
- void set_attached_file_url(const GURL& url) { attached_file_url_ = url; }
- void set_screenshot_url(const GURL& url) { screenshot_url_ = url; }
+ void set_attached_file_uuid(const std::string& uuid) {
+ attached_file_uuid_ = uuid;
+ }
+ void set_screenshot_uuid(const std::string& uuid) {
+ screenshot_uuid_ = uuid;
+ }
+ void set_trace_id(int trace_id) { trace_id_ = trace_id; }
private:
friend class base::RefCountedThreadSafe<FeedbackData>;
virtual ~FeedbackData();
+ void OnGetTraceData(scoped_refptr<base::RefCountedString> trace_data);
+
Profile* profile_;
std::string category_tag_;
@@ -100,8 +106,10 @@
std::string attached_filename_;
scoped_ptr<std::string> attached_filedata_;
- GURL attached_file_url_;
- GURL screenshot_url_;
+ std::string attached_file_uuid_;
+ std::string screenshot_uuid_;
+
+ int trace_id_;
scoped_ptr<SystemLogsMap> sys_info_;
scoped_ptr<std::string> compressed_logs_;
diff --git a/chrome/browser/feedback/feedback_util.cc b/chrome/browser/feedback/feedback_util.cc
index 29e928e..4f272a5 100644
--- a/chrome/browser/feedback/feedback_util.cc
+++ b/chrome/browser/feedback/feedback_util.cc
@@ -23,6 +23,7 @@
#include "chrome/browser/feedback/feedback_data.h"
#include "chrome/browser/metrics/variations/variations_http_header_provider.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/safe_browsing/safe_browsing_util.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
@@ -61,25 +62,6 @@
void DispatchFeedback(Profile* profile, std::string* post_body, int64 delay);
-// Check the key/value pair to see if it is one of the screensize, keys. If so,
-// populate the screensize structure with the key.
-bool IsScreensizeInfo(const std::string key,
- const std::string value,
- gfx::Rect* screen_size) {
- if (key == FeedbackData::kScreensizeHeightKey) {
- int height = 0;
- base::StringToInt(value, &height);
- screen_size->SetRect(0, 0, screen_size->width(), height);
- return true;
- } else if (key == FeedbackData::kScreensizeWidthKey) {
- int width = 0;
- base::StringToInt(value, &width);
- screen_size->SetRect(0, 0, width, screen_size->height());
- return true;
- }
- return false;
-}
-
GURL GetTargetTabUrl(int session_id, int index) {
Browser* browser = chrome::FindBrowserWithID(session_id);
// Sanity checks.
@@ -96,18 +78,6 @@
return GURL();
}
-gfx::Rect GetScreenSize(Browser* browser) {
-#if defined(OS_CHROMEOS)
- // For ChromeOS, don't use the browser window but the root window
- // instead to grab the screenshot. We want everything on the screen, not
- // just the current browser.
- gfx::NativeWindow native_window = ash::Shell::GetPrimaryRootWindow();
- return gfx::Rect(native_window->bounds());
-#else
- return gfx::Rect(browser->window()->GetBounds().size());
-#endif
-}
-
// URL to post bug reports to.
const char kFeedbackPostUrl[] =
"https://www.google.com/tools/feedback/chrome/__submit";
@@ -127,8 +97,11 @@
const char kArbitraryMimeType[] = "application/octet-stream";
const char kLogsAttachmentName[] = "system_logs.zip";
+#if defined(OS_CHROMEOS)
const int kChromeOSProductId = 208;
+#else
const int kChromeBrowserProductId = 237;
+#endif
// Simple net::URLFetcherDelegate to clean up URLFetcher on completion.
class PostCleanup : public net::URLFetcherDelegate {
@@ -254,25 +227,32 @@
const char kAppLauncherCategoryTag[] = "AppLauncher";
void ShowFeedbackPage(Browser* browser,
- const std::string& description_template,
- const std::string& category_tag) {
- DCHECK(browser);
+ const std::string& description_template,
+ const std::string& category_tag) {
+ GURL page_url;
+ if (browser) {
+ page_url = GetTargetTabUrl(browser->session_id().id(),
+ browser->tab_strip_model()->active_index());
+ }
- // Get the current browser's screensize and send it with the feedback request
- // event - this browser may have changed or even been closed by the time that
- // feedback is sent.
- gfx::Rect screen_size = GetScreenSize(browser);
- GURL page_url = GetTargetTabUrl(
- browser->session_id().id(), browser->tab_strip_model()->active_index());
+ Profile* profile = NULL;
+ if (browser) {
+ profile = browser->profile();
+ } else {
+ profile = ProfileManager::GetLastUsedProfileAllowedByPolicy();
+ }
+ if (!profile) {
+ LOG(ERROR) << "Cannot invoke feedback: No profile found!";
+ return;
+ }
extensions::FeedbackPrivateAPI* api =
extensions::FeedbackPrivateAPI::GetFactoryInstance()->GetForProfile(
- browser->profile());
+ profile);
api->RequestFeedback(description_template,
category_tag,
- page_url,
- screen_size);
+ page_url);
}
} // namespace chrome
@@ -307,10 +287,8 @@
if (data->sys_info()) {
for (FeedbackData::SystemLogsMap::const_iterator i =
data->sys_info()->begin(); i != data->sys_info()->end(); ++i) {
- if (!IsScreensizeInfo(i->first, i->second, &screen_size)) {
- if (FeedbackData::BelowCompressionThreshold(i->second))
- AddFeedbackData(&feedback_data, i->first, i->second);
- }
+ if (FeedbackData::BelowCompressionThreshold(i->second))
+ AddFeedbackData(&feedback_data, i->first, i->second);
}
if (data->compressed_logs() && data->compressed_logs()->size()) {
@@ -342,10 +320,11 @@
userfeedback::PostedScreenshot screenshot;
screenshot.set_mime_type(kPngMimeType);
- // Set the dimensions of the screenshot
+ // Set that we 'have' dimensions of the screenshot. These dimensions are
+ // ignored by the server but are a 'required' field in the protobuf.
userfeedback::Dimensions dimensions;
- dimensions.set_width(static_cast<float>(screen_size.width()));
- dimensions.set_height(static_cast<float>(screen_size.height()));
+ dimensions.set_width(0.0);
+ dimensions.set_height(0.0);
*(screenshot.mutable_dimensions()) = dimensions;
screenshot.set_binary_content(*data->image());
diff --git a/chrome/browser/fullscreen_gtk.cc b/chrome/browser/fullscreen_gtk.cc
index 2835132..9399408 100644
--- a/chrome/browser/fullscreen_gtk.cc
+++ b/chrome/browser/fullscreen_gtk.cc
@@ -26,7 +26,7 @@
// to old school enumeration of all X windows.
XID root, parent, *children;
unsigned int num_children;
- int status = XQueryTree(ui::GetXDisplay(), window, &root, &parent,
+ int status = XQueryTree(gfx::GetXDisplay(), window, &root, &parent,
&children, &num_children);
if (status) {
for (long i = static_cast<long>(num_children) - 1; i >= 0; i--)
diff --git a/chrome/browser/geolocation/OWNERS b/chrome/browser/geolocation/OWNERS
index c2252ab..0ac17d2 100644
--- a/chrome/browser/geolocation/OWNERS
+++ b/chrome/browser/geolocation/OWNERS
@@ -1,6 +1,8 @@
-# Reviews:
-# Not yet owner - mvanouwerkerk@chromium.org
+# Reviewers:
bulach@chromium.org
+mvanouwerkerk@chromium.org
+
+# Additional reviewing: timvolodine@chromium.org
# Just owners:
joth@chromium.org
diff --git a/chrome/browser/google_apis/auth_service.cc b/chrome/browser/google_apis/auth_service.cc
index 2534062..463e283 100644
--- a/chrome/browser/google_apis/auth_service.cc
+++ b/chrome/browser/google_apis/auth_service.cc
@@ -30,6 +30,7 @@
class AuthRequest : public OAuth2TokenService::Consumer {
public:
AuthRequest(OAuth2TokenService* oauth2_token_service,
+ const std::string& account_id,
net::URLRequestContextGetter* url_request_context_getter,
const AuthStatusCallback& callback,
const std::vector<std::string>& scopes);
@@ -52,6 +53,7 @@
AuthRequest::AuthRequest(
OAuth2TokenService* oauth2_token_service,
+ const std::string& account_id,
net::URLRequestContextGetter* url_request_context_getter,
const AuthStatusCallback& callback,
const std::vector<std::string>& scopes)
@@ -59,6 +61,7 @@
DCHECK(!callback_.is_null());
request_ = oauth2_token_service->
StartRequestWithContext(
+ account_id,
url_request_context_getter,
OAuth2TokenService::ScopeSet(scopes.begin(), scopes.end()),
this);
@@ -117,9 +120,11 @@
AuthService::AuthService(
OAuth2TokenService* oauth2_token_service,
+ const std::string& account_id,
net::URLRequestContextGetter* url_request_context_getter,
const std::vector<std::string>& scopes)
: oauth2_token_service_(oauth2_token_service),
+ account_id_(account_id),
url_request_context_getter_(url_request_context_getter),
scopes_(scopes),
weak_ptr_factory_(this) {
@@ -127,7 +132,8 @@
// Get OAuth2 refresh token (if we have any) and register for its updates.
oauth2_token_service_->AddObserver(this);
- has_refresh_token_ = oauth2_token_service_->RefreshTokenIsAvailable();
+ has_refresh_token_ = oauth2_token_service_->RefreshTokenIsAvailable(
+ account_id_);
}
AuthService::~AuthService() {
@@ -146,6 +152,7 @@
} else if (HasRefreshToken()) {
// We have refresh token, let's get an access token.
new AuthRequest(oauth2_token_service_,
+ account_id_,
url_request_context_getter_,
base::Bind(&AuthService::OnAuthCompleted,
weak_ptr_factory_.GetWeakPtr(),
diff --git a/chrome/browser/google_apis/auth_service.h b/chrome/browser/google_apis/auth_service.h
index 302ce88..0923ad2 100644
--- a/chrome/browser/google_apis/auth_service.h
+++ b/chrome/browser/google_apis/auth_service.h
@@ -34,6 +34,7 @@
//
// |scopes| specifies OAuth2 scopes.
AuthService(OAuth2TokenService* oauth2_token_service,
+ const std::string& account_id,
net::URLRequestContextGetter* url_request_context_getter,
const std::vector<std::string>& scopes);
virtual ~AuthService();
@@ -63,6 +64,7 @@
const std::string& access_token);
OAuth2TokenService* oauth2_token_service_;
+ std::string account_id_;
net::URLRequestContextGetter* url_request_context_getter_; // Not owned.
bool has_refresh_token_;
std::string access_token_;
diff --git a/chrome/browser/google_apis/drive_api_requests.cc b/chrome/browser/google_apis/drive_api_requests.cc
index 61ee92d..fc21c1a 100644
--- a/chrome/browser/google_apis/drive_api_requests.cc
+++ b/chrome/browser/google_apis/drive_api_requests.cc
@@ -14,12 +14,12 @@
#include "chrome/browser/google_apis/request_sender.h"
#include "chrome/browser/google_apis/request_util.h"
#include "chrome/browser/google_apis/time_util.h"
+#include "net/base/url_util.h"
namespace google_apis {
namespace {
const char kContentTypeApplicationJson[] = "application/json";
-const char kDirectoryMimeType[] = "application/vnd.google-apps.folder";
const char kParentLinkKind[] = "drive#fileLink";
// Parses the JSON value to a resource typed |T| and runs |callback| on the UI
@@ -116,21 +116,39 @@
namespace drive {
+//============================ DriveApiDataRequest ===========================
+
+DriveApiDataRequest::DriveApiDataRequest(RequestSender* sender,
+ const GetDataCallback& callback)
+ : GetDataRequest(sender, callback) {
+}
+
+DriveApiDataRequest::~DriveApiDataRequest() {
+}
+
+GURL DriveApiDataRequest::GetURL() const {
+ GURL url = GetURLInternal();
+ if (!fields_.empty())
+ url = net::AppendOrReplaceQueryParameter(url, "fields", fields_);
+ return url;
+}
+
//=============================== FilesGetRequest =============================
FilesGetRequest::FilesGetRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const FileResourceCallback& callback)
- : GetDataRequest(sender,
- base::Bind(&ParseJsonAndRun<FileResource>, callback)),
+ : DriveApiDataRequest(
+ sender,
+ base::Bind(&ParseJsonAndRun<FileResource>, callback)),
url_generator_(url_generator) {
DCHECK(!callback.is_null());
}
FilesGetRequest::~FilesGetRequest() {}
-GURL FilesGetRequest::GetURL() const {
+GURL FilesGetRequest::GetURLInternal() const {
return url_generator_.GetFilesGetUrl(file_id_);
}
@@ -140,8 +158,9 @@
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const FileResourceCallback& callback)
- : GetDataRequest(sender,
- base::Bind(&ParseJsonAndRun<FileResource>, callback)),
+ : DriveApiDataRequest(
+ sender,
+ base::Bind(&ParseJsonAndRun<FileResource>, callback)),
url_generator_(url_generator) {
DCHECK(!callback.is_null());
}
@@ -152,10 +171,6 @@
return net::URLFetcher::POST;
}
-GURL FilesInsertRequest::GetURL() const {
- return url_generator_.GetFilesInsertUrl();
-}
-
bool FilesInsertRequest::GetContentData(std::string* upload_content_type,
std::string* upload_content) {
*upload_content_type = kContentTypeApplicationJson;
@@ -184,14 +199,19 @@
return true;
}
+GURL FilesInsertRequest::GetURLInternal() const {
+ return url_generator_.GetFilesInsertUrl();
+}
+
//============================== FilesPatchRequest ============================
FilesPatchRequest::FilesPatchRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const FileResourceCallback& callback)
- : GetDataRequest(sender,
- base::Bind(&ParseJsonAndRun<FileResource>, callback)),
+ : DriveApiDataRequest(
+ sender,
+ base::Bind(&ParseJsonAndRun<FileResource>, callback)),
url_generator_(url_generator),
set_modified_date_(false),
update_viewed_date_(true) {
@@ -210,7 +230,7 @@
return headers;
}
-GURL FilesPatchRequest::GetURL() const {
+GURL FilesPatchRequest::GetURLInternal() const {
return url_generator_.GetFilesPatchUrl(
file_id_, set_modified_date_, update_viewed_date_);
}
@@ -259,8 +279,9 @@
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const FileResourceCallback& callback)
- : GetDataRequest(sender,
- base::Bind(&ParseJsonAndRun<FileResource>, callback)),
+ : DriveApiDataRequest(
+ sender,
+ base::Bind(&ParseJsonAndRun<FileResource>, callback)),
url_generator_(url_generator) {
DCHECK(!callback.is_null());
}
@@ -272,7 +293,7 @@
return net::URLFetcher::POST;
}
-GURL FilesCopyRequest::GetURL() const {
+GURL FilesCopyRequest::GetURLInternal() const {
return url_generator_.GetFilesCopyUrl(file_id_);
}
@@ -285,6 +306,9 @@
base::DictionaryValue root;
+ if (!modified_date_.is_null())
+ root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
+
if (!parents_.empty()) {
base::ListValue* parents_value = new base::ListValue;
for (size_t i = 0; i < parents_.size(); ++i) {
@@ -310,7 +334,7 @@
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const FileListCallback& callback)
- : GetDataRequest(
+ : DriveApiDataRequest(
sender,
base::Bind(&ParseJsonOnBlockingPoolAndRun<FileList>,
make_scoped_refptr(sender->blocking_task_runner()),
@@ -322,7 +346,7 @@
FilesListRequest::~FilesListRequest() {}
-GURL FilesListRequest::GetURL() const {
+GURL FilesListRequest::GetURLInternal() const {
return url_generator_.GetFilesListUrl(max_results_, page_token_, q_);
}
@@ -331,7 +355,7 @@
FilesListNextPageRequest::FilesListNextPageRequest(
RequestSender* sender,
const FileListCallback& callback)
- : GetDataRequest(
+ : DriveApiDataRequest(
sender,
base::Bind(&ParseJsonOnBlockingPoolAndRun<FileList>,
make_scoped_refptr(sender->blocking_task_runner()),
@@ -342,7 +366,7 @@
FilesListNextPageRequest::~FilesListNextPageRequest() {
}
-GURL FilesListNextPageRequest::GetURL() const {
+GURL FilesListNextPageRequest::GetURLInternal() const {
return next_link_;
}
@@ -352,8 +376,9 @@
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const FileResourceCallback& callback)
- : GetDataRequest(sender,
- base::Bind(&ParseJsonAndRun<FileResource>, callback)),
+ : DriveApiDataRequest(
+ sender,
+ base::Bind(&ParseJsonAndRun<FileResource>, callback)),
url_generator_(url_generator) {
DCHECK(!callback.is_null());
}
@@ -364,7 +389,7 @@
return net::URLFetcher::POST;
}
-GURL FilesTrashRequest::GetURL() const {
+GURL FilesTrashRequest::GetURLInternal() const {
return url_generator_.GetFilesTrashUrl(file_id_);
}
@@ -374,15 +399,16 @@
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const AboutResourceCallback& callback)
- : GetDataRequest(sender,
- base::Bind(&ParseJsonAndRun<AboutResource>, callback)),
+ : DriveApiDataRequest(
+ sender,
+ base::Bind(&ParseJsonAndRun<AboutResource>, callback)),
url_generator_(url_generator) {
DCHECK(!callback.is_null());
}
AboutGetRequest::~AboutGetRequest() {}
-GURL AboutGetRequest::GetURL() const {
+GURL AboutGetRequest::GetURLInternal() const {
return url_generator_.GetAboutGetUrl();
}
@@ -392,7 +418,7 @@
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const ChangeListCallback& callback)
- : GetDataRequest(
+ : DriveApiDataRequest(
sender,
base::Bind(&ParseJsonOnBlockingPoolAndRun<ChangeList>,
make_scoped_refptr(sender->blocking_task_runner()),
@@ -406,7 +432,7 @@
ChangesListRequest::~ChangesListRequest() {}
-GURL ChangesListRequest::GetURL() const {
+GURL ChangesListRequest::GetURLInternal() const {
return url_generator_.GetChangesListUrl(
include_deleted_, max_results_, page_token_, start_change_id_);
}
@@ -416,7 +442,7 @@
ChangesListNextPageRequest::ChangesListNextPageRequest(
RequestSender* sender,
const ChangeListCallback& callback)
- : GetDataRequest(
+ : DriveApiDataRequest(
sender,
base::Bind(&ParseJsonOnBlockingPoolAndRun<ChangeList>,
make_scoped_refptr(sender->blocking_task_runner()),
@@ -427,7 +453,7 @@
ChangesListNextPageRequest::~ChangesListNextPageRequest() {
}
-GURL ChangesListNextPageRequest::GetURL() const {
+GURL ChangesListNextPageRequest::GetURLInternal() const {
return next_link_;
}
@@ -437,15 +463,16 @@
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const AppListCallback& callback)
- : GetDataRequest(sender,
- base::Bind(&ParseJsonAndRun<AppList>, callback)),
+ : DriveApiDataRequest(
+ sender,
+ base::Bind(&ParseJsonAndRun<AppList>, callback)),
url_generator_(url_generator) {
DCHECK(!callback.is_null());
}
AppsListRequest::~AppsListRequest() {}
-GURL AppsListRequest::GetURL() const {
+GURL AppsListRequest::GetURLInternal() const {
return url_generator_.GetAppsListUrl();
}
diff --git a/chrome/browser/google_apis/drive_api_requests.h b/chrome/browser/google_apis/drive_api_requests.h
index 3afb5a7..ae75915 100644
--- a/chrome/browser/google_apis/drive_api_requests.h
+++ b/chrome/browser/google_apis/drive_api_requests.h
@@ -36,12 +36,41 @@
namespace drive {
+//============================ DriveApiDataRequest ===========================
+
+// This is base class of the Drive API related requests. All Drive API requests
+// support partial request (to improve the performance). The function can be
+// shared among the Drive API requests.
+// See also https://developers.google.com/drive/performance
+class DriveApiDataRequest : public GetDataRequest {
+ public:
+ DriveApiDataRequest(RequestSender* sender, const GetDataCallback& callback);
+ virtual ~DriveApiDataRequest();
+
+ // Optional parameter.
+ const std::string& fields() const { return fields_; }
+ void set_fields(const std::string& fields) { fields_ = fields; }
+
+ protected:
+ // Overridden from GetDataRequest.
+ virtual GURL GetURL() const OVERRIDE;
+
+ // Derived classes should override GetURLInternal instead of GetURL()
+ // directly.
+ virtual GURL GetURLInternal() const = 0;
+
+ private:
+ std::string fields_;
+
+ DISALLOW_COPY_AND_ASSIGN(DriveApiDataRequest);
+};
+
//=============================== FilesGetRequest =============================
// This class performs the request for fetching a file.
// This request is mapped to
// https://developers.google.com/drive/v2/reference/files/get
-class FilesGetRequest : public GetDataRequest {
+class FilesGetRequest : public DriveApiDataRequest {
public:
FilesGetRequest(RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
@@ -53,8 +82,8 @@
void set_file_id(const std::string& file_id) { file_id_ = file_id; }
protected:
- // Overridden from GetDataRequest.
- virtual GURL GetURL() const OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
private:
const DriveApiUrlGenerator url_generator_;
@@ -70,7 +99,7 @@
// https://developers.google.com/drive/v2/reference/files/insert
// See also https://developers.google.com/drive/manage-uploads and
// https://developers.google.com/drive/folder
-class FilesInsertRequest : public GetDataRequest {
+class FilesInsertRequest : public DriveApiDataRequest {
public:
FilesInsertRequest(RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
@@ -92,10 +121,12 @@
protected:
// Overridden from GetDataRequest.
virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE;
- virtual GURL GetURL() const OVERRIDE;
virtual bool GetContentData(std::string* upload_content_type,
std::string* upload_content) OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
+
private:
const DriveApiUrlGenerator url_generator_;
@@ -111,7 +142,7 @@
// This class performs the request for patching file metadata.
// This request is mapped to
// https://developers.google.com/drive/v2/reference/files/patch
-class FilesPatchRequest : public GetDataRequest {
+class FilesPatchRequest : public DriveApiDataRequest {
public:
FilesPatchRequest(RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
@@ -156,13 +187,15 @@
void add_parent(const std::string& parent) { parents_.push_back(parent); }
protected:
- // UrlFetchRequestBase overrides.
+ // Overridden from URLFetchRequestBase.
virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE;
virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE;
- virtual GURL GetURL() const OVERRIDE;
virtual bool GetContentData(std::string* upload_content_type,
std::string* upload_content) OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
+
private:
const DriveApiUrlGenerator url_generator_;
@@ -183,7 +216,7 @@
// This class performs the request for copying a resource.
// This request is mapped to
// https://developers.google.com/drive/v2/reference/files/copy
-class FilesCopyRequest : public GetDataRequest {
+class FilesCopyRequest : public DriveApiDataRequest {
public:
// Upon completion, |callback| will be called. |callback| must not be null.
FilesCopyRequest(RequestSender* sender,
@@ -199,19 +232,28 @@
const std::vector<std::string>& parents() const { return parents_; }
void add_parent(const std::string& parent) { parents_.push_back(parent); }
+ const base::Time& modified_date() const { return modified_date_; }
+ void set_modified_date(const base::Time& modified_date) {
+ modified_date_ = modified_date;
+ }
+
const std::string& title() const { return title_; }
void set_title(const std::string& title) { title_ = title; }
protected:
+ // Overridden from URLFetchRequestBase.
virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE;
- virtual GURL GetURL() const OVERRIDE;
virtual bool GetContentData(std::string* upload_content_type,
std::string* upload_content) OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
+
private:
const DriveApiUrlGenerator url_generator_;
std::string file_id_;
+ base::Time modified_date_;
std::vector<std::string> parents_;
std::string title_;
@@ -226,7 +268,7 @@
// or by FilesListRequest with setting page token.
// This request is mapped to
// https://developers.google.com/drive/v2/reference/files/list
-class FilesListRequest : public GetDataRequest {
+class FilesListRequest : public DriveApiDataRequest {
public:
FilesListRequest(RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
@@ -246,8 +288,8 @@
void set_q(const std::string& q) { q_ = q; }
protected:
- // Overridden from GetDataRequest.
- virtual GURL GetURL() const OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
private:
const DriveApiUrlGenerator url_generator_;
@@ -264,7 +306,7 @@
// 1) Set pageToken and all params used for the initial request.
// 2) Use URL in the nextLink field in the previous response.
// This class implements 2)'s request.
-class FilesListNextPageRequest : public GetDataRequest {
+class FilesListNextPageRequest : public DriveApiDataRequest {
public:
FilesListNextPageRequest(RequestSender* sender,
const FileListCallback& callback);
@@ -274,8 +316,8 @@
void set_next_link(const GURL& next_link) { next_link_ = next_link; }
protected:
- // Overridden from GetDataRequest.
- virtual GURL GetURL() const OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
private:
GURL next_link_;
@@ -288,7 +330,7 @@
// This class performs the request for trashing a resource.
// This request is mapped to
// https://developers.google.com/drive/v2/reference/files/trash
-class FilesTrashRequest : public GetDataRequest {
+class FilesTrashRequest : public DriveApiDataRequest {
public:
FilesTrashRequest(RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
@@ -300,9 +342,11 @@
void set_file_id(const std::string& file_id) { file_id_ = file_id; }
protected:
- // UrlFetchRequestBase overrides.
+ // Overridden from UrlFetchRequestBase.
virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE;
- virtual GURL GetURL() const OVERRIDE;
+
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
private:
const DriveApiUrlGenerator url_generator_;
@@ -316,7 +360,7 @@
// This class performs the request for fetching About data.
// This request is mapped to
// https://developers.google.com/drive/v2/reference/about/get
-class AboutGetRequest : public GetDataRequest {
+class AboutGetRequest : public DriveApiDataRequest {
public:
AboutGetRequest(RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
@@ -324,8 +368,8 @@
virtual ~AboutGetRequest();
protected:
- // Overridden from GetDataRequest.
- virtual GURL GetURL() const OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
private:
const DriveApiUrlGenerator url_generator_;
@@ -341,7 +385,7 @@
// or by ChangesListRequest with setting page token.
// This request is mapped to
// https://developers.google.com/drive/v2/reference/changes/list
-class ChangesListRequest : public GetDataRequest {
+class ChangesListRequest : public DriveApiDataRequest {
public:
ChangesListRequest(RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
@@ -368,8 +412,8 @@
}
protected:
- // Overridden from GetDataRequest.
- virtual GURL GetURL() const OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
private:
const DriveApiUrlGenerator url_generator_;
@@ -387,7 +431,7 @@
// 1) Set pageToken and all params used for the initial request.
// 2) Use URL in the nextLink field in the previous response.
// This class implements 2)'s request.
-class ChangesListNextPageRequest : public GetDataRequest {
+class ChangesListNextPageRequest : public DriveApiDataRequest {
public:
ChangesListNextPageRequest(RequestSender* sender,
const ChangeListCallback& callback);
@@ -397,8 +441,8 @@
void set_next_link(const GURL& next_link) { next_link_ = next_link; }
protected:
- // Overridden from GetDataRequest.
- virtual GURL GetURL() const OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
private:
GURL next_link_;
@@ -411,7 +455,7 @@
// This class performs the request for fetching AppList.
// This request is mapped to
// https://developers.google.com/drive/v2/reference/apps/list
-class AppsListRequest : public GetDataRequest {
+class AppsListRequest : public DriveApiDataRequest {
public:
AppsListRequest(RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
@@ -419,8 +463,8 @@
virtual ~AppsListRequest();
protected:
- // Overridden from GetDataRequest.
- virtual GURL GetURL() const OVERRIDE;
+ // Overridden from DriveApiDataRequest.
+ virtual GURL GetURLInternal() const OVERRIDE;
private:
const DriveApiUrlGenerator url_generator_;
diff --git a/chrome/browser/google_apis/drive_api_requests_unittest.cc b/chrome/browser/google_apis/drive_api_requests_unittest.cc
index 331994d..30c0a2a 100644
--- a/chrome/browser/google_apis/drive_api_requests_unittest.cc
+++ b/chrome/browser/google_apis/drive_api_requests_unittest.cc
@@ -345,6 +345,48 @@
int64 content_length_;
};
+TEST_F(DriveApiRequestsTest, DriveApiDataRequest_Fields) {
+ // Make sure that "fields" query param is supported by using its subclass,
+ // AboutGetRequest.
+
+ // Set an expected data file containing valid result.
+ expected_data_file_path_ = test_util::GetTestFilePath(
+ "drive/about.json");
+
+ GDataErrorCode error = GDATA_OTHER_ERROR;
+ scoped_ptr<AboutResource> about_resource;
+
+ {
+ base::RunLoop run_loop;
+ drive::AboutGetRequest* request = new drive::AboutGetRequest(
+ request_sender_.get(),
+ *url_generator_,
+ test_util::CreateQuitCallback(
+ &run_loop,
+ test_util::CreateCopyResultCallback(&error, &about_resource)));
+ request->set_fields(
+ "kind,quotaBytesTotal,quotaBytesUsed,largestChangeId,rootFolderId");
+ request_sender_->StartRequestWithRetry(request);
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(HTTP_SUCCESS, error);
+ EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
+ EXPECT_EQ("/drive/v2/about?"
+ "fields=kind%2CquotaBytesTotal%2CquotaBytesUsed%2C"
+ "largestChangeId%2CrootFolderId",
+ http_request_.relative_url);
+
+ scoped_ptr<AboutResource> expected(
+ AboutResource::CreateFrom(
+ *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());
+ EXPECT_EQ(expected->quota_bytes_used(), about_resource->quota_bytes_used());
+ EXPECT_EQ(expected->root_folder_id(), about_resource->root_folder_id());
+}
+
TEST_F(DriveApiRequestsTest, FilesInsertRequest) {
// Set an expected data file containing the directory's entry data.
expected_data_file_path_ =
@@ -583,6 +625,8 @@
}
TEST_F(DriveApiRequestsTest, FilesCopyRequest) {
+ const base::Time::Exploded kModifiedDate = {2012, 7, 0, 19, 15, 59, 13, 123};
+
// Set an expected data file containing the dummy file entry data.
// It'd be returned if we copy a file.
expected_data_file_path_ =
@@ -601,6 +645,7 @@
&run_loop,
test_util::CreateCopyResultCallback(&error, &file_resource)));
request->set_file_id("resource_id");
+ request->set_modified_date(base::Time::FromUTCExploded(kModifiedDate));
request->add_parent("parent_resource_id");
request->set_title("new title");
request_sender_->StartRequestWithRetry(request);
@@ -614,7 +659,8 @@
EXPECT_TRUE(http_request_.has_content);
EXPECT_EQ(
- "{\"parents\":[{\"id\":\"parent_resource_id\"}],\"title\":\"new title\"}",
+ "{\"modifiedDate\":\"2012-07-19T15:59:13.123Z\","
+ "\"parents\":[{\"id\":\"parent_resource_id\"}],\"title\":\"new title\"}",
http_request_.content);
EXPECT_TRUE(file_resource);
}
diff --git a/chrome/browser/google_apis/gdata_wapi_parser.cc b/chrome/browser/google_apis/gdata_wapi_parser.cc
index 2ee0bb5..8e291f5 100644
--- a/chrome/browser/google_apis/gdata_wapi_parser.cc
+++ b/chrome/browser/google_apis/gdata_wapi_parser.cc
@@ -27,42 +27,10 @@
namespace {
// Term values for kSchemeKind category:
-const char kSchemeKind[] = "http://schemas.google.com/g/2005#kind";
const char kTermPrefix[] = "http://schemas.google.com/docs/2007#";
-const char kFileTerm[] = "file";
-const char kFolderTerm[] = "folder";
-const char kItemTerm[] = "item";
-const char kPdfTerm[] = "pdf";
-const char kDocumentTerm[] = "document";
-const char kSpreadSheetTerm[] = "spreadsheet";
-const char kPresentationTerm[] = "presentation";
-
-const char kSchemeLabels[] = "http://schemas.google.com/g/2005/labels";
// Node names.
-const char kAuthorNode[] = "author";
-const char kCategoryNode[] = "category";
-const char kContentNode[] = "content";
-const char kEditedNode[] = "edited";
-const char kEmailNode[] = "email";
const char kEntryNode[] = "entry";
-const char kFeedLinkNode[] = "feedLink";
-const char kFilenameNode[] = "filename";
-const char kIDNode[] = "id";
-const char kLastModifiedByNode[] = "lastModifiedBy";
-const char kLastViewedNode[] = "lastViewed";
-const char kLinkNode[] = "link";
-const char kMd5ChecksumNode[] = "md5Checksum";
-const char kModifiedByMeDateNode[] = "modifiedByMeDate";
-const char kNameNode[] = "name";
-const char kPublishedNode[] = "published";
-const char kQuotaBytesUsedNode[] = "quotaBytesUsed";
-const char kResourceIdNode[] = "resourceId";
-const char kSizeNode[] = "size";
-const char kSuggestedFilenameNode[] = "suggestedFilename";
-const char kTitleNode[] = "title";
-const char kUpdatedNode[] = "updated";
-const char kWritersCanInviteNode[] = "writersCanInvite";
// Field names.
const char kAuthorField[] = "author";
@@ -120,20 +88,6 @@
const char kTypeField[] = "type";
const char kUpdatedField[] = "updated.$t";
-// Attribute names.
-// Attributes are not namespace-blind as node names in XmlReader.
-const char kETagAttr[] = "gd:etag";
-const char kEmailAttr[] = "email";
-const char kHrefAttr[] = "href";
-const char kLabelAttr[] = "label";
-const char kNameAttr[] = "name";
-const char kRelAttr[] = "rel";
-const char kSchemeAttr[] = "scheme";
-const char kSrcAttr[] = "src";
-const char kTermAttr[] = "term";
-const char kTypeAttr[] = "type";
-const char kValueAttr[] = "value";
-
// Link Prefixes
const char kOpenWithPrefix[] = "http://schemas.google.com/docs/2007#open-with-";
const size_t kOpenWithPrefixSize = arraysize(kOpenWithPrefix) - 1;
diff --git a/chrome/browser/guestview/webview/webview_constants.cc b/chrome/browser/guestview/webview/webview_constants.cc
index 7c6ca93..880a6e5 100644
--- a/chrome/browser/guestview/webview/webview_constants.cc
+++ b/chrome/browser/guestview/webview/webview_constants.cc
@@ -52,4 +52,7 @@
const char kInternalEntryCount[] = "entryCount";
const char kInternalProcessId[] = "processId";
+// Initialization parameters.
+const char kParameterUserAgentOverride[] = "userAgentOverride";
+
} // namespace webview
diff --git a/chrome/browser/guestview/webview/webview_constants.h b/chrome/browser/guestview/webview/webview_constants.h
index 12ca843..e27eaf4 100644
--- a/chrome/browser/guestview/webview/webview_constants.h
+++ b/chrome/browser/guestview/webview/webview_constants.h
@@ -55,6 +55,9 @@
extern const char kInternalEntryCount[];
extern const char kInternalProcessId[];
+// Initialization parameters.
+extern const char kParameterUserAgentOverride[];
+
} // 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
index e0ee6a0..2c8e825 100644
--- a/chrome/browser/guestview/webview/webview_guest.cc
+++ b/chrome/browser/guestview/webview/webview_guest.cc
@@ -94,7 +94,8 @@
WebContentsObserver(guest_web_contents),
script_executor_(new extensions::ScriptExecutor(guest_web_contents,
&script_observers_)),
- next_permission_request_id_(0) {
+ next_permission_request_id_(0),
+ is_overriding_user_agent_(false) {
notification_registrar_.Add(
this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::Source<WebContents>(guest_web_contents));
@@ -118,6 +119,14 @@
void WebViewGuest::Attach(WebContents* embedder_web_contents,
const std::string& extension_id,
const base::DictionaryValue& args) {
+ std::string user_agent_override;
+ if (args.GetString(webview::kParameterUserAgentOverride,
+ &user_agent_override)) {
+ SetUserAgentOverride(user_agent_override);
+ } else {
+ SetUserAgentOverride("");
+ }
+
GuestView::Attach(
embedder_web_contents, extension_id, args);
@@ -230,6 +239,10 @@
#endif
}
+bool WebViewGuest::IsOverridingUserAgent() const {
+ return is_overriding_user_agent_;
+}
+
void WebViewGuest::LoadProgressed(double progress) {
scoped_ptr<DictionaryValue> args(new DictionaryValue());
args->SetString(guestview::kUrl, web_contents()->GetURL().spec());
@@ -347,6 +360,12 @@
return true;
}
+void WebViewGuest::SetUserAgentOverride(
+ const std::string& user_agent_override) {
+ is_overriding_user_agent_ = !user_agent_override.empty();
+ guest_web_contents()->SetUserAgentOverride(user_agent_override);
+}
+
void WebViewGuest::Stop() {
guest_web_contents()->Stop();
}
diff --git a/chrome/browser/guestview/webview/webview_guest.h b/chrome/browser/guestview/webview/webview_guest.h
index 5a82c0d..9fac5f9 100644
--- a/chrome/browser/guestview/webview/webview_guest.h
+++ b/chrome/browser/guestview/webview/webview_guest.h
@@ -50,6 +50,7 @@
virtual bool HandleKeyboardEvent(
const content::NativeWebKeyboardEvent& event) OVERRIDE;
virtual bool IsDragAndDropEnabled() OVERRIDE;
+ virtual bool IsOverridingUserAgent() const OVERRIDE;
virtual void LoadAbort(bool is_top_level,
const GURL& url,
const std::string& error_type) OVERRIDE;
@@ -81,6 +82,10 @@
bool should_allow,
const std::string& user_input);
+ // Overrides the user agent for this guest.
+ // This affects subsequent guest navigations.
+ void SetUserAgentOverride(const std::string& user_agent_override);
+
// Stop loading the guest.
void Stop();
@@ -155,6 +160,9 @@
typedef std::map<int, PermissionResponseCallback> RequestMap;
RequestMap pending_permission_requests_;
+ // True if the user agent is overridden.
+ bool is_overriding_user_agent_;
+
DISALLOW_COPY_AND_ASSIGN(WebViewGuest);
};
diff --git a/chrome/browser/history/android/android_provider_backend_unittest.cc b/chrome/browser/history/android/android_provider_backend_unittest.cc
index 9dbd798..1331d01 100644
--- a/chrome/browser/history/android/android_provider_backend_unittest.cc
+++ b/chrome/browser/history/android/android_provider_backend_unittest.cc
@@ -266,8 +266,7 @@
ASSERT_TRUE(base::PathExists(thumbnail_db_name_));
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
// Set url1 as bookmark.
AddBookmark(url1);
scoped_ptr<AndroidProviderBackend> backend(
@@ -416,8 +415,7 @@
ASSERT_TRUE(base::PathExists(thumbnail_db_name_));
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
// Set url1 as bookmark.
AddBookmark(url1);
@@ -506,8 +504,7 @@
row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -615,8 +612,7 @@
row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
@@ -713,8 +709,7 @@
TEST_F(AndroidProviderBackendTest, IsValidHistoryAndBookmarkRow) {
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -804,8 +799,7 @@
row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -984,8 +978,7 @@
row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1065,8 +1058,7 @@
row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1127,8 +1119,7 @@
row1.set_title(UTF8ToUTF16("cnn"));
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1193,8 +1184,7 @@
TEST_F(AndroidProviderBackendTest, UpdateSearchTermTable) {
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1272,8 +1262,7 @@
TEST_F(AndroidProviderBackendTest, QuerySearchTerms) {
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1306,8 +1295,7 @@
TEST_F(AndroidProviderBackendTest, UpdateSearchTerms) {
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1411,8 +1399,7 @@
TEST_F(AndroidProviderBackendTest, DeleteSearchTerms) {
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1518,8 +1505,7 @@
TEST_F(AndroidProviderBackendTest, InsertSearchTerm) {
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1573,8 +1559,7 @@
row2.set_favicon(base::RefCountedBytes::TakeVector(&data));
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1626,8 +1611,7 @@
TEST_F(AndroidProviderBackendTest, TestMultipleNestingTransaction) {
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1677,8 +1661,7 @@
// This is to verify the last visit time and created time are same when visit
// count is 0.
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1715,8 +1698,7 @@
// returned when folder is 0 and the non bookmark rows returned when folder
// is 1.
ASSERT_EQ(sql::INIT_OK, history_db_.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, NULL,
- &history_db_));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db_.Init(thumbnail_db_name_, &history_db_));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db_,
&thumbnail_db_, bookmark_model_, &delegate_));
@@ -1967,8 +1949,7 @@
HistoryDatabase history_db;
ThumbnailDatabase thumbnail_db;
ASSERT_EQ(sql::INIT_OK, history_db.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_, NULL,
- &history_db));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_, &history_db));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db,
@@ -2039,8 +2020,7 @@
HistoryDatabase history_db;
ThumbnailDatabase thumbnail_db;
ASSERT_EQ(sql::INIT_OK, history_db.Init(history_db_name_));
- ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_, NULL,
- &history_db));
+ ASSERT_EQ(sql::INIT_OK, thumbnail_db.Init(thumbnail_db_name_, &history_db));
scoped_ptr<AndroidProviderBackend> backend(
new AndroidProviderBackend(android_cache_db_name_, &history_db,
&thumbnail_db, bookmark_model_, &delegate_));
diff --git a/chrome/browser/history/expire_history_backend.cc b/chrome/browser/history/expire_history_backend.cc
index aa7ede3..10460d4 100644
--- a/chrome/browser/history/expire_history_backend.cc
+++ b/chrome/browser/history/expire_history_backend.cc
@@ -136,14 +136,6 @@
// iteration, so we want to wait longer before checking to avoid wasting CPU.
const int kExpirationEmptyDelayMin = 5;
-// The number of minutes that we wait for before scheduling a task to
-// delete old history index files.
-const int kIndexExpirationDelayMin = 2;
-
-// The number of the most recent months for which we do not want to delete
-// the history index files.
-const int kStoreHistoryIndexesForMonths = 3;
-
} // namespace
struct ExpireHistoryBackend::DeleteDependencies {
diff --git a/chrome/browser/history/expire_history_backend_unittest.cc b/chrome/browser/history/expire_history_backend_unittest.cc
index fd91b96..350f473 100644
--- a/chrome/browser/history/expire_history_backend_unittest.cc
+++ b/chrome/browser/history/expire_history_backend_unittest.cc
@@ -138,7 +138,7 @@
base::FilePath thumb_name = path().Append(kThumbnailFile);
thumb_db_.reset(new ThumbnailDatabase);
- if (thumb_db_->Init(thumb_name, NULL, main_db_.get()) != sql::INIT_OK)
+ if (thumb_db_->Init(thumb_name, main_db_.get()) != sql::INIT_OK)
thumb_db_.reset();
expirer_.SetDatabases(main_db_.get(), archived_db_.get(), thumb_db_.get());
diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc
index 3913d1d..2fa226d 100644
--- a/chrome/browser/history/history_backend.cc
+++ b/chrome/browser/history/history_backend.cc
@@ -32,6 +32,7 @@
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/history_publisher.h"
#include "chrome/browser/history/in_memory_history_backend.h"
+#include "chrome/browser/history/page_collector.h"
#include "chrome/browser/history/page_usage_data.h"
#include "chrome/browser/history/select_favicon_frames.h"
#include "chrome/browser/history/top_sites.h"
@@ -79,29 +80,25 @@
// This value needs to be greater or equal to
// MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct
// dependency between MostVisitedModel and the history backend.
-static const int kSegmentDataRetention = 90;
+const int kSegmentDataRetention = 90;
// How long we'll wait to do a commit, so that things are batched together.
-static const int kCommitIntervalSeconds = 10;
+const int kCommitIntervalSeconds = 10;
// The amount of time before we re-fetch the favicon.
-static const int kFaviconRefetchDays = 7;
-
-// GetSessionTabs returns all open tabs, or tabs closed kSessionCloseTimeWindow
-// seconds ago.
-static const int kSessionCloseTimeWindowSecs = 10;
+const int kFaviconRefetchDays = 7;
// The maximum number of items we'll allow in the redirect list before
// deleting some.
-static const int kMaxRedirectCount = 32;
+const int kMaxRedirectCount = 32;
// The number of days old a history entry can be before it is considered "old"
// and is archived.
-static const int kArchiveDaysThreshold = 90;
+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;
+const size_t kPageVisitStatsMaxTopSites = 50;
#endif
// Converts from PageUsageData to MostVisitedURL. |redirects| is a
@@ -550,6 +547,9 @@
last_ids.second);
}
+ if (page_collector_)
+ page_collector_->AddPageURL(request.url, request.time);
+
ScheduleCommit();
}
@@ -611,6 +611,9 @@
// Create the history publisher which needs to be passed on to the thumbnail
// database for publishing history.
+ // TODO(shess): HistoryPublisher is being deprecated. I am still
+ // trying to track down who depends on it, meanwhile talk to me
+ // before removing interactions with it. http://crbug.com/294306
history_publisher_.reset(new HistoryPublisher());
if (!history_publisher_->Init()) {
// The init may fail when there are no indexers wanting our history.
@@ -618,6 +621,12 @@
history_publisher_.reset();
}
+ // Collects page data for history_publisher_.
+ if (history_publisher_.get()) {
+ page_collector_.reset(new PageCollector());
+ page_collector_->Init(history_publisher_.get());
+ }
+
// Thumbnail database.
// TODO(shess): "thumbnail database" these days only stores
// favicons. Thumbnails are stored in "top sites". Consider
@@ -625,7 +634,6 @@
// sort.
thumbnail_db_.reset(new ThumbnailDatabase());
if (thumbnail_db_->Init(thumbnail_name,
- history_publisher_.get(),
db_.get()) != sql::INIT_OK) {
// Unlike the main database, we don't error out when the database is too
// new because this error is much less severe. Generally, this shouldn't
@@ -665,8 +673,7 @@
// *sigh*, this can all be cleaned up when that migration code is removed.
// The main DB initialization should intuitively be first (not that it
// actually matters) and the expirer should be set last.
- expirer_.SetDatabases(db_.get(), archived_db_.get(),
- thumbnail_db_.get());
+ expirer_.SetDatabases(db_.get(), archived_db_.get(), thumbnail_db_.get());
// Open the long-running transaction.
db_->BeginTransaction();
@@ -853,6 +860,12 @@
}
}
+ // TODO(shess): I'm not sure this case needs to exist anymore.
+ if (page_collector_) {
+ page_collector_->AddPageData(i->url(), i->last_visit(),
+ i->title(), string16());
+ }
+
// Sync code manages the visits itself.
if (visit_source != SOURCE_SYNCED) {
// Make up a visit to correspond to the last visit to the page.
@@ -890,11 +903,13 @@
return time < expirer_.GetCurrentArchiveTime();
}
-void HistoryBackend::SetPageTitle(const GURL& url,
- const string16& title) {
+void HistoryBackend::SetPageTitle(const GURL& url, const string16& title) {
if (!db_)
return;
+ if (page_collector_)
+ page_collector_->AddPageTitle(url, title);
+
// Search for recent redirects which should get the same title. We make a
// dummy list containing the exact URL visited if there are no redirects so
// the processing below can be the same.
@@ -1665,6 +1680,12 @@
num_databases_deleted);
}
+void HistoryBackend::SetPageContents(const GURL& url,
+ const string16& contents) {
+ if (page_collector_)
+ page_collector_->AddPageContents(url, contents);
+}
+
void HistoryBackend::GetFavicons(
const std::vector<GURL>& icon_urls,
int icon_types,
diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h
index de64e5c..f3bbf4d 100644
--- a/chrome/browser/history/history_backend.h
+++ b/chrome/browser/history/history_backend.h
@@ -38,6 +38,7 @@
class CommitLaterTask;
class HistoryPublisher;
+class PageCollector;
class VisitFilter;
struct DownloadRow;
@@ -158,6 +159,11 @@
const GURL& url,
base::Time end_ts);
+
+ // Indexing ------------------------------------------------------------------
+
+ void SetPageContents(const GURL& url, const string16& contents);
+
// Querying ------------------------------------------------------------------
// ScheduleAutocomplete() never frees |provider| (which is globally live).
@@ -833,6 +839,9 @@
// Stores old history in a larger, slower database.
scoped_ptr<ArchivedDatabase> archived_db_;
+ // Helper to collect page data for vending to history_publisher_.
+ scoped_ptr<PageCollector> page_collector_;
+
// Manages expiration between the various databases.
ExpireHistoryBackend expirer_;
diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc
index a666cf1..04af2b4 100644
--- a/chrome/browser/history/history_backend_unittest.cc
+++ b/chrome/browser/history/history_backend_unittest.cc
@@ -7,7 +7,6 @@
#include <algorithm>
#include <set>
#include <vector>
-#include <fstream>
#include "base/basictypes.h"
#include "base/bind.h"
@@ -2745,15 +2744,6 @@
service->DeleteURL(url);
}
-// Simple function to create a new dummy file.
-void CreateDummyFile(const base::FilePath& filename) {
- std::wofstream file;
- file.open(filename.value().c_str());
- ASSERT_TRUE(file.is_open());
- file << L"Dummy";
- file.close();
-}
-
// Test DeleteFTSIndexDatabases deletes expected files.
TEST_F(HistoryBackendTest, DeleteFTSIndexDatabases) {
ASSERT_TRUE(backend_.get());
@@ -2766,10 +2756,12 @@
base::FilePath db2_actual(history_path.AppendASCII("Underlying DB"));
// Setup dummy index database files.
- CreateDummyFile(db1);
- CreateDummyFile(db1_journal);
- CreateDummyFile(db1_wal);
- CreateDummyFile(db2_actual);
+ const char* data = "Dummy";
+ const size_t data_len = 5;
+ ASSERT_TRUE(file_util::WriteFile(db1, data, data_len));
+ ASSERT_TRUE(file_util::WriteFile(db1_journal, data, data_len));
+ ASSERT_TRUE(file_util::WriteFile(db1_wal, data, data_len));
+ ASSERT_TRUE(file_util::WriteFile(db2_actual, data, data_len));
#if defined(OS_POSIX)
EXPECT_TRUE(file_util::CreateSymbolicLink(db2_actual, db2_symlink));
#endif
diff --git a/chrome/browser/history/history_publisher.cc b/chrome/browser/history/history_publisher.cc
index 1c42deb..e439982 100644
--- a/chrome/browser/history/history_publisher.cc
+++ b/chrome/browser/history/history_publisher.cc
@@ -8,23 +8,6 @@
namespace history {
-const char* const HistoryPublisher::kThumbnailImageFormat = "image/jpeg";
-
-void HistoryPublisher::PublishPageThumbnail(
- const std::vector<unsigned char>& thumbnail, const GURL& url,
- const base::Time& time) const {
- PageData page_data = {
- time,
- url,
- NULL,
- NULL,
- kThumbnailImageFormat,
- &thumbnail,
- };
-
- PublishDataToIndexers(page_data);
-}
-
void HistoryPublisher::PublishPageContent(const base::Time& time,
const GURL& url,
const string16& title,
@@ -34,8 +17,6 @@
url,
contents.c_str(),
title.c_str(),
- NULL,
- NULL,
};
PublishDataToIndexers(page_data);
diff --git a/chrome/browser/history/history_publisher.h b/chrome/browser/history/history_publisher.h
index 2f16655..60e41b0 100644
--- a/chrome/browser/history/history_publisher.h
+++ b/chrome/browser/history/history_publisher.h
@@ -16,6 +16,10 @@
#include "history_indexer.h"
#endif
+// TODO(shess): HistoryPublisher is being deprecated. I am still
+// trying to track down who depends on it, meanwhile talk to me
+// before removing interactions with it.
+
class GURL;
namespace base {
@@ -34,8 +38,6 @@
// there are none registered. On false, no other function should be called.
bool Init();
- void PublishPageThumbnail(const std::vector<unsigned char>& thumbnail,
- const GURL& url, const base::Time& time) const;
void PublishPageContent(const base::Time& time, const GURL& url,
const string16& title,
const string16& contents) const;
@@ -46,8 +48,6 @@
const GURL& url;
const char16* html;
const char16* title;
- const char* thumbnail_format;
- const std::vector<unsigned char>* thumbnail;
};
void PublishDataToIndexers(const PageData& page_data) const;
diff --git a/chrome/browser/history/history_publisher_win.cc b/chrome/browser/history/history_publisher_win.cc
index e6178b5..e14ff08 100644
--- a/chrome/browser/history/history_publisher_win.cc
+++ b/chrome/browser/history/history_publisher_win.cc
@@ -93,22 +93,18 @@
const {
double var_time = TimeToUTCVariantTime(page_data.time);
- CComSafeArray<unsigned char> thumbnail_arr;
- if (page_data.thumbnail) {
- for (size_t i = 0; i < page_data.thumbnail->size(); ++i)
- thumbnail_arr.Add((*page_data.thumbnail)[i]);
- }
-
// Send data to registered indexers.
base::win::ScopedVariant time(var_time, VT_DATE);
base::win::ScopedBstr url(ASCIIToWide(page_data.url.spec()).c_str());
base::win::ScopedBstr html(page_data.html);
base::win::ScopedBstr title(page_data.title);
- // Don't send a NULL string through ASCIIToWide.
- base::win::ScopedBstr format(page_data.thumbnail_format ?
- ASCIIToWide(page_data.thumbnail_format).c_str() :
- NULL);
+
+ // No clients send thumbnail data anymore, these are needed only to
+ // retain the interface.
+ base::win::ScopedBstr format(NULL);
+ CComSafeArray<unsigned char> thumbnail_arr;
base::win::ScopedVariant psa(thumbnail_arr.m_psa);
+
for (size_t i = 0; i < indexers_.size(); ++i) {
indexers_[i]->SendPageData(time, url, html, title, format, psa);
}
diff --git a/chrome/browser/history/history_service.cc b/chrome/browser/history/history_service.cc
index dc28c42..aee38c8 100644
--- a/chrome/browser/history/history_service.cc
+++ b/chrome/browser/history/history_service.cc
@@ -584,6 +584,16 @@
&HistoryBackend::AddPagesWithDetails, info, visit_source);
}
+void HistoryService::SetPageContents(const GURL& url,
+ const string16& contents) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!CanAddURL(url))
+ return;
+
+ ScheduleAndForget(PRIORITY_LOW, &HistoryBackend::SetPageContents,
+ url, contents);
+}
+
CancelableTaskTracker::TaskId HistoryService::GetFavicons(
const std::vector<GURL>& icon_urls,
int icon_types,
diff --git a/chrome/browser/history/history_service.h b/chrome/browser/history/history_service.h
index f8d383b..6891f38 100644
--- a/chrome/browser/history/history_service.h
+++ b/chrome/browser/history/history_service.h
@@ -236,6 +236,13 @@
const GURL& url,
base::Time end_ts);
+ // Indexing ------------------------------------------------------------------
+
+ // Notifies history of the body text of the given recently-visited URL.
+ // If the URL was not visited "recently enough," the history system may
+ // discard it.
+ void SetPageContents(const GURL& url, const string16& contents);
+
// Querying ------------------------------------------------------------------
// Returns the information about the requested URL. If the URL is found,
diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/history/history_tab_helper.cc
index adbd892..4fc97c6 100644
--- a/chrome/browser/history/history_tab_helper.cc
+++ b/chrome/browser/history/history_tab_helper.cc
@@ -84,6 +84,16 @@
return add_page_args;
}
+bool HistoryTabHelper::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(HistoryTabHelper, message)
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PageContents, OnPageContents)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
void HistoryTabHelper::DidNavigateMainFrame(
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) {
@@ -155,6 +165,25 @@
}
}
+void HistoryTabHelper::OnPageContents(const GURL& url,
+ const string16& contents) {
+ // Don't index any https pages. People generally don't want their bank
+ // accounts, etc. indexed on their computer, especially since some of these
+ // things are not marked cachable.
+ // TODO(brettw) we may want to consider more elaborate heuristics such as
+ // the cachability of the page. We may also want to consider subframes (this
+ // test will still index subframes if the subframe is SSL).
+ // TODO(zelidrag) bug chromium-os:2808 - figure out if we want to reenable
+ // content indexing for chromeos in some future releases.
+#if !defined(OS_CHROMEOS)
+ if (!url.SchemeIsSecure()) {
+ HistoryService* hs = GetHistoryService();
+ if (hs)
+ hs->SetPageContents(url, contents);
+ }
+#endif
+}
+
HistoryService* HistoryTabHelper::GetHistoryService() {
Profile* profile =
Profile::FromBrowserContext(web_contents()->GetBrowserContext());
diff --git a/chrome/browser/history/history_tab_helper.h b/chrome/browser/history/history_tab_helper.h
index 2f613fa..65b03c3 100644
--- a/chrome/browser/history/history_tab_helper.h
+++ b/chrome/browser/history/history_tab_helper.h
@@ -46,6 +46,7 @@
friend class content::WebContentsUserData<HistoryTabHelper>;
// content::WebContentsObserver implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void DidNavigateMainFrame(
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) OVERRIDE;
@@ -59,9 +60,7 @@
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
- void OnPageContents(const GURL& url,
- int32 page_id,
- const string16& contents);
+ void OnPageContents(const GURL& url, const string16& contents);
// Helper function to return the history service. May return NULL.
HistoryService* GetHistoryService();
diff --git a/chrome/browser/history/in_memory_url_index_types.cc b/chrome/browser/history/in_memory_url_index_types.cc
index 1006b50..9307d5b 100644
--- a/chrome/browser/history/in_memory_url_index_types.cc
+++ b/chrome/browser/history/in_memory_url_index_types.cc
@@ -18,17 +18,6 @@
namespace history {
-// The maximum score any candidate result can achieve.
-const int kMaxTotalScore = 1425;
-
-// Score ranges used to get a 'base' score for each of the scoring factors
-// (such as recency of last visit, times visited, times the URL was typed,
-// and the quality of the string match). There is a matching value range for
-// each of these scores for each factor. Note that the top score is greater
-// than |kMaxTotalScore|. The score for each candidate will be capped in the
-// final calculation.
-const int kScoreRank[] = { 1450, 1200, 900, 400 };
-
// Matches within URL and Title Strings ----------------------------------------
string16 CleanUpUrlForMatching(const GURL& gurl,
diff --git a/chrome/browser/history/page_collector.cc b/chrome/browser/history/page_collector.cc
new file mode 100644
index 0000000..da07ad1
--- /dev/null
+++ b/chrome/browser/history/page_collector.cc
@@ -0,0 +1,157 @@
+// 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/history/page_collector.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/history/history_publisher.h"
+#include "url/gurl.h"
+
+namespace {
+
+// Page info older than this will be published even if we haven't
+// gotten a title and/or body.
+const int kExpirationSeconds = 20;
+
+} // namespace
+
+namespace history {
+
+// PageCollector::PageInfo -----------------------------------------------
+
+PageCollector::PageInfo::PageInfo(base::Time visit_time)
+ : visit_time_(visit_time),
+ added_time_(base::TimeTicks::Now()) {
+}
+
+PageCollector::PageInfo::~PageInfo() {}
+
+// NOTE(shess): Per the comment on has_title() and has_body(), this
+// code maps empty strings to single space to differentiate set title
+// and body from empty. This approach is held over from the original
+// TextDatabaseManager version.
+void PageCollector::PageInfo::set_title(const string16& ttl) {
+ if (ttl.empty())
+ title_ = ASCIIToUTF16(" ");
+ else
+ title_ = ttl;
+}
+
+void PageCollector::PageInfo::set_body(const string16& bdy) {
+ if (bdy.empty())
+ body_ = ASCIIToUTF16(" ");
+ else
+ body_ = bdy;
+}
+
+bool PageCollector::PageInfo::Expired(base::TimeTicks now) const {
+ return now - added_time_ > base::TimeDelta::FromSeconds(kExpirationSeconds);
+}
+
+PageCollector::PageCollector()
+ : recent_changes_(RecentChangeList::NO_AUTO_EVICT),
+ weak_factory_(this) {
+}
+
+PageCollector::~PageCollector() {
+}
+
+void PageCollector::Init(const HistoryPublisher* history_publisher) {
+ history_publisher_ = history_publisher;
+}
+
+void PageCollector::AddPageURL(const GURL& url, base::Time time) {
+ // Don't collect data which cannot be published.
+ if (!history_publisher_)
+ return;
+
+ // Just save this info for later (evicting any previous data). We
+ // will delete it when it expires or when all the data is complete.
+ recent_changes_.Put(url, PageInfo(time));
+
+ // Schedule flush if not already scheduled.
+ if (!weak_factory_.HasWeakPtrs())
+ ScheduleFlushCollected();
+}
+
+void PageCollector::AddPageTitle(const GURL& url, const string16& title) {
+ if (!history_publisher_)
+ return;
+
+ // If the title comes in after the page has aged out, drop it.
+ // Older code would manufacture information from the database.
+ RecentChangeList::iterator found = recent_changes_.Peek(url);
+ if (found == recent_changes_.end())
+ return;
+
+ // Publish the info if complete.
+ if (found->second.has_body()) {
+ history_publisher_->PublishPageContent(
+ found->second.visit_time(), url, title, found->second.body());
+ recent_changes_.Erase(found);
+ } else {
+ found->second.set_title(title);
+ }
+}
+
+void PageCollector::AddPageContents(const GURL& url,
+ const string16& body) {
+ if (!history_publisher_)
+ return;
+
+ // If the body comes in after the page has aged out, drop it.
+ // Older code would manufacture information from the database.
+ RecentChangeList::iterator found = recent_changes_.Peek(url);
+ if (found == recent_changes_.end())
+ return;
+
+ // Publish the info if complete.
+ if (found->second.has_title()) {
+ history_publisher_->PublishPageContent(
+ found->second.visit_time(), url, found->second.title(), body);
+ recent_changes_.Erase(found);
+ } else {
+ found->second.set_body(body);
+ }
+}
+
+void PageCollector::AddPageData(const GURL& url,
+ base::Time visit_time,
+ const string16& title,
+ const string16& body) {
+ if (!history_publisher_)
+ return;
+
+ // Publish the item.
+ history_publisher_->PublishPageContent(visit_time, url, title, body);
+}
+
+void PageCollector::ScheduleFlushCollected() {
+ weak_factory_.InvalidateWeakPtrs();
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&PageCollector::FlushCollected,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(kExpirationSeconds));
+}
+
+void PageCollector::FlushCollected() {
+ base::TimeTicks now = base::TimeTicks::Now();
+
+ // Iterate from oldest to newest publishing items which expire while
+ // waiting for title or body.
+ RecentChangeList::reverse_iterator iter = recent_changes_.rbegin();
+ while (iter != recent_changes_.rend() && iter->second.Expired(now)) {
+ AddPageData(iter->first, iter->second.visit_time(),
+ iter->second.title(), iter->second.body());
+ iter = recent_changes_.Erase(iter);
+ }
+
+ if (!recent_changes_.empty())
+ ScheduleFlushCollected();
+}
+
+} // namespace history
diff --git a/chrome/browser/history/page_collector.h b/chrome/browser/history/page_collector.h
new file mode 100644
index 0000000..c044a3b
--- /dev/null
+++ b/chrome/browser/history/page_collector.h
@@ -0,0 +1,123 @@
+// 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_HISTORY_PAGE_COLLECTOR_H_
+#define CHROME_BROWSER_HISTORY_PAGE_COLLECTOR_H_
+
+#include "base/basictypes.h"
+#include "base/containers/mru_cache.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+
+class GURL;
+
+namespace history {
+
+class HistoryPublisher;
+
+// Collect page data and publish to HistoryPublisher.
+class PageCollector {
+ public:
+ // You must call Init() to complete initialization.
+ PageCollector();
+ ~PageCollector();
+
+ // Must call before using other functions.
+ void Init(const HistoryPublisher* history_publisher);
+
+ // Sets specific information for the given page to be published.
+ // In normal operation, URLs will be added as the user visits them, the titles
+ // and bodies will come in some time after that. These changes will be
+ // automatically coalesced and added to the database some time in the future
+ // using AddPageData().
+ //
+ // AddPageURL must be called for a given URL before either the title
+ // or body set. The visit time should be the time corresponding to
+ // that visit in the history database.
+ void AddPageURL(const GURL& url, base::Time visit_time);
+ void AddPageTitle(const GURL& url, const string16& title);
+ void AddPageContents(const GURL& url, const string16& body);
+
+ void AddPageData(const GURL& url,
+ base::Time visit_time,
+ const string16& title,
+ const string16& body);
+
+ private:
+ // Stores "recent stuff" that has happened with the page, since the page
+ // visit, title, and body all come in at different times.
+ class PageInfo {
+ public:
+ explicit PageInfo(base::Time visit_time);
+ ~PageInfo();
+
+ // Getters.
+ base::Time visit_time() const { return visit_time_; }
+ const string16& title() const { return title_; }
+ const string16& body() const { return body_; }
+
+ // Setters, we can only update the title and body.
+ void set_title(const string16& ttl);
+ void set_body(const string16& bdy);
+
+ // Returns true if both the title or body of the entry has been set. Since
+ // both the title and body setters will "fix" empty strings to be a space,
+ // these indicate if the setter was ever called.
+ bool has_title() const { return !title_.empty(); }
+ bool has_body() const { return !body_.empty(); }
+
+ // Returns true if this entry was added too long ago and we should give up
+ // waiting for more data. The current time is passed in as an argument so we
+ // can check many without re-querying the timer.
+ bool Expired(base::TimeTicks now) const;
+
+ private:
+ // Time of the visit of the URL. This will be the value stored in the URL
+ // and visit tables for the entry.
+ base::Time visit_time_;
+
+ // When this page entry was created. We have a cap on the maximum time that
+ // an entry will be in the queue before being flushed to the database.
+ base::TimeTicks added_time_;
+
+ // Will be the string " " when they are set to distinguish set and unset.
+ string16 title_;
+ string16 body_;
+ };
+
+ // Collected data is published when both the title and body are
+ // present. https data is never passed to AddPageContents(), so
+ // periodically collected data is published without the contents.
+ // Pages which take a long time to load will not have their bodies
+ // published.
+ void ScheduleFlushCollected();
+ void FlushCollected();
+
+ // Lists recent additions that we have not yet filled out with the title and
+ // body. Sorted by time, we will flush them when they are complete or have
+ // been in the queue too long without modification.
+ //
+ // We kind of abuse the MRUCache because we never move things around in it
+ // using Get. Instead, we keep them in the order they were inserted, since
+ // this is the metric we use to measure age. The MRUCache gives us an ordered
+ // list with fast lookup by URL.
+ typedef base::MRUCache<GURL, PageInfo> RecentChangeList;
+ RecentChangeList recent_changes_;
+
+ // Generates tasks for our periodic checking of expired "recent changes".
+ base::WeakPtrFactory<PageCollector> weak_factory_;
+
+ // This object is created and managed by the history backend. We maintain an
+ // opaque pointer to the object for our use.
+ // This can be NULL if there are no indexers registered to receive indexing
+ // data from us.
+ const HistoryPublisher* history_publisher_;
+
+ DISALLOW_COPY_AND_ASSIGN(PageCollector);
+};
+
+} // namespace history
+
+#endif // CHROME_BROWSER_HISTORY_PAGE_COLLECTOR_H_
diff --git a/chrome/browser/history/select_favicon_frames.cc b/chrome/browser/history/select_favicon_frames.cc
index 09bf8ff..43a1fa4 100644
--- a/chrome/browser/history/select_favicon_frames.cc
+++ b/chrome/browser/history/select_favicon_frames.cc
@@ -58,7 +58,7 @@
ResizeMethod* resize_method) {
DCHECK_NE(desired_size_in_dip, 0);
- float scale = ui::GetScaleFactorScale(scale_factor);
+ float scale = ui::GetImageScale(scale_factor);
int desired_size_in_pixel =
static_cast<int>(desired_size_in_dip * scale + 0.5f);
@@ -179,7 +179,7 @@
int desired_size_in_dip,
ui::ScaleFactor scale_factor,
ResizeMethod resize_method) {
- float scale = ui::GetScaleFactorScale(scale_factor);
+ float scale = ui::GetImageScale(scale_factor);
int desired_size_in_pixel = static_cast<int>(
desired_size_in_dip * scale + 0.5f);
@@ -216,7 +216,8 @@
SkBitmap resized_bitmap = GetResizedBitmap(bitmaps[result.index],
desired_size, result.scale_factor, result.resize_method);
multi_image.AddRepresentation(
- gfx::ImageSkiaRep(resized_bitmap, result.scale_factor));
+ gfx::ImageSkiaRep(resized_bitmap,
+ ui::GetImageScale(result.scale_factor)));
}
return multi_image;
}
diff --git a/chrome/browser/history/select_favicon_frames_unittest.cc b/chrome/browser/history/select_favicon_frames_unittest.cc
index f79e773..6936ece 100644
--- a/chrome/browser/history/select_favicon_frames_unittest.cc
+++ b/chrome/browser/history/select_favicon_frames_unittest.cc
@@ -43,7 +43,8 @@
SkColor GetColor(const gfx::ImageSkia& image, ui::ScaleFactor factor,
int x = -1, int y = -1) {
- const SkBitmap& bitmap = image.GetRepresentation(factor).sk_bitmap();
+ const SkBitmap& bitmap =
+ image.GetRepresentation(ui::GetImageScale(factor)).sk_bitmap();
if (x == -1)
x = bitmap.width() / 2;
if (y == -1)
@@ -71,7 +72,7 @@
gfx::ImageSkia image = SelectFaviconFrames(bitmaps,
SizesFromBitmaps(bitmaps), Scale1x(), 0, NULL);
EXPECT_EQ(1u, image.image_reps().size());
- ASSERT_TRUE(image.HasRepresentation(ui::SCALE_FACTOR_100P));
+ ASSERT_TRUE(image.HasRepresentation(1.0f));
EXPECT_EQ(48, image.width());
EXPECT_EQ(48, image.height());
@@ -87,7 +88,7 @@
gfx::ImageSkia image = SelectFaviconFrames(bitmaps,
SizesFromBitmaps(bitmaps), Scale1x(), 16, NULL);
EXPECT_EQ(1u, image.image_reps().size());
- ASSERT_TRUE(image.HasRepresentation(ui::SCALE_FACTOR_100P));
+ ASSERT_TRUE(image.HasRepresentation(1.0f));
EXPECT_EQ(16, image.width());
EXPECT_EQ(16, image.height());
EXPECT_EQ(SK_ColorGREEN, GetColor1x(image));
@@ -102,7 +103,7 @@
gfx::ImageSkia image = SelectFaviconFrames(bitmaps,
SizesFromBitmaps(bitmaps), Scale1x(), 16, NULL);
EXPECT_EQ(1u, image.image_reps().size());
- ASSERT_TRUE(image.HasRepresentation(ui::SCALE_FACTOR_100P));
+ ASSERT_TRUE(image.HasRepresentation(1.0f));
EXPECT_EQ(16, image.width());
EXPECT_EQ(16, image.height());
EXPECT_EQ(SK_ColorGREEN, GetColor1x(image));
@@ -118,7 +119,7 @@
gfx::ImageSkia image = SelectFaviconFrames(bitmaps,
SizesFromBitmaps(bitmaps), Scale1x(), 16, NULL);
EXPECT_EQ(1u, image.image_reps().size());
- ASSERT_TRUE(image.HasRepresentation(ui::SCALE_FACTOR_100P));
+ ASSERT_TRUE(image.HasRepresentation(1.0f));
EXPECT_EQ(16, image.width());
EXPECT_EQ(16, image.height());
EXPECT_EQ(SK_ColorGREEN, GetColor1x(image));
@@ -131,8 +132,8 @@
gfx::ImageSkia image = SelectFaviconFrames(bitmaps,
SizesFromBitmaps(bitmaps), Scale1x2x(), 16, NULL);
EXPECT_EQ(2u, image.image_reps().size());
- ASSERT_TRUE(image.HasRepresentation(ui::SCALE_FACTOR_100P));
- ASSERT_TRUE(image.HasRepresentation(ui::SCALE_FACTOR_200P));
+ ASSERT_TRUE(image.HasRepresentation(1.0f));
+ ASSERT_TRUE(image.HasRepresentation(2.0f));
EXPECT_EQ(16, image.width());
EXPECT_EQ(16, image.height());
EXPECT_EQ(SK_ColorGREEN, GetColor1x(image));
@@ -147,8 +148,8 @@
gfx::ImageSkia image = SelectFaviconFrames(bitmaps,
SizesFromBitmaps(bitmaps), Scale1x2x(), 16, NULL);
EXPECT_EQ(2u, image.image_reps().size());
- ASSERT_TRUE(image.HasRepresentation(ui::SCALE_FACTOR_100P));
- ASSERT_TRUE(image.HasRepresentation(ui::SCALE_FACTOR_200P));
+ ASSERT_TRUE(image.HasRepresentation(1.0f));
+ ASSERT_TRUE(image.HasRepresentation(2.0f));
EXPECT_EQ(16, image.width());
EXPECT_EQ(16, image.height());
EXPECT_EQ(SK_ColorGREEN, GetColor1x(image));
diff --git a/chrome/browser/history/text_database_unittest.cc b/chrome/browser/history/text_database_unittest.cc
deleted file mode 100644
index 25b7d79..0000000
--- a/chrome/browser/history/text_database_unittest.cc
+++ /dev/null
@@ -1,306 +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 <string>
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/history/text_database.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-using base::Time;
-
-namespace history {
-
-namespace {
-
-// Note that all pages have "COUNTTAG" which allows us to count the number of
-// pages in the database withoujt adding any extra functions to the DB object.
-const char kURL1[] = "http://www.google.com/";
-const int kTime1 = 1000;
-const char kTitle1[] = "Google";
-const char kBody1[] =
- "COUNTTAG Web Images Maps News Shopping Gmail more My Account | "
- "Sign out Advanced Search Preferences Language Tools Advertising Programs "
- "- Business Solutions - About Google, 2008 Google";
-
-const char kURL2[] = "http://images.google.com/";
-const int kTime2 = 2000;
-const char kTitle2[] = "Google Image Search";
-const char kBody2[] =
- "COUNTTAG Web Images Maps News Shopping Gmail more My Account | "
- "Sign out Advanced Image Search Preferences The most comprehensive image "
- "search on the web. Want to help improve Google Image Search? Try Google "
- "Image Labeler. Advertising Programs - Business Solutions - About Google "
- "2008 Google";
-
-const char kURL3[] = "http://slashdot.org/";
-const int kTime3 = 3000;
-const char kTitle3[] = "Slashdot: News for nerds, stuff that matters";
-const char kBody3[] =
- "COUNTTAG Slashdot Log In Create Account Subscribe Firehose Why "
- "Log In? Why Subscribe? Nickname Password Public Terminal Sections "
- "Main Apple AskSlashdot Backslash Books Developers Games Hardware "
- "Interviews IT Linux Mobile Politics Science YRO";
-
-// Returns the number of rows currently in the database.
-int RowCount(TextDatabase* db) {
- QueryOptions options;
- options.begin_time = Time::FromInternalValue(0);
- // Leave end_time at now.
-
- std::vector<TextDatabase::Match> results;
- TextDatabase::URLSet unique_urls;
- db->GetTextMatches("COUNTTAG", options, &results, &unique_urls);
- return static_cast<int>(results.size());
-}
-
-// Adds each of the test pages to the database.
-void AddAllTestData(TextDatabase* db) {
- EXPECT_TRUE(db->AddPageData(
- Time::FromInternalValue(kTime1), kURL1, kTitle1, kBody1));
- EXPECT_TRUE(db->AddPageData(
- Time::FromInternalValue(kTime2), kURL2, kTitle2, kBody2));
- EXPECT_TRUE(db->AddPageData(
- Time::FromInternalValue(kTime3), kURL3, kTitle3, kBody3));
- EXPECT_EQ(3, RowCount(db));
-}
-
-bool ResultsHaveURL(const std::vector<TextDatabase::Match>& results,
- const char* url) {
- GURL gurl(url);
- for (size_t i = 0; i < results.size(); i++) {
- if (results[i].url == gurl)
- return true;
- }
- return false;
-}
-
-} // namespace
-
-class TextDatabaseTest : public PlatformTest {
- public:
- TextDatabaseTest() {}
-
- protected:
- virtual void SetUp() {
- PlatformTest::SetUp();
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- }
-
- // Create databases with this function, which will ensure that the files are
- // deleted on shutdown. Only open one database for each file. Returns NULL on
- // failure.
- //
- // Set |delete_file| to delete any existing file. If we are trying to create
- // the file for the first time, we don't want a previous test left in a
- // weird state to have left a file that would affect us.
- TextDatabase* CreateDB(TextDatabase::DBIdent id,
- bool allow_create,
- bool delete_file) {
- TextDatabase* db = new TextDatabase(temp_dir_.path(), id, allow_create);
-
- if (delete_file)
- sql::Connection::Delete(db->file_name());
-
- if (!db->Init()) {
- delete db;
- return NULL;
- }
- return db;
- }
-
- // Directory containing the databases.
- base::ScopedTempDir temp_dir_;
-
- // Name of the main database file.
- base::FilePath file_name_;
-};
-
-TEST_F(TextDatabaseTest, AttachDetach) {
- // First database with one page.
- const int kIdee1 = 200801;
- scoped_ptr<TextDatabase> db1(CreateDB(kIdee1, true, true));
- ASSERT_TRUE(!!db1.get());
- EXPECT_TRUE(db1->AddPageData(
- Time::FromInternalValue(kTime1), kURL1, kTitle1, kBody1));
-
- // Second database with one page.
- const int kIdee2 = 200802;
- scoped_ptr<TextDatabase> db2(CreateDB(kIdee2, true, true));
- ASSERT_TRUE(!!db2.get());
- EXPECT_TRUE(db2->AddPageData(
- Time::FromInternalValue(kTime2), kURL2, kTitle2, kBody2));
-
- // Detach, then reattach database one. The file should exist, so we force
- // opening an existing file.
- db1.reset();
- db1.reset(CreateDB(kIdee1, false, false));
- ASSERT_TRUE(!!db1.get());
-
- // We should not be able to attach this random database for which no file
- // exists.
- const int kIdeeNoExisto = 999999999;
- scoped_ptr<TextDatabase> db3(CreateDB(kIdeeNoExisto, false, true));
- EXPECT_FALSE(!!db3.get());
-}
-
-TEST_F(TextDatabaseTest, AddRemove) {
- // Create a database and add some pages to it.
- const int kIdee1 = 200801;
- scoped_ptr<TextDatabase> db(CreateDB(kIdee1, true, true));
- ASSERT_TRUE(!!db.get());
- URLID id1 = db->AddPageData(
- Time::FromInternalValue(kTime1), kURL1, kTitle1, kBody1);
- EXPECT_NE(0, id1);
- URLID id2 = db->AddPageData(
- Time::FromInternalValue(kTime2), kURL2, kTitle2, kBody2);
- EXPECT_NE(0, id2);
- URLID id3 = db->AddPageData(
- Time::FromInternalValue(kTime3), kURL3, kTitle3, kBody3);
- EXPECT_NE(0, id3);
- EXPECT_EQ(3, RowCount(db.get()));
-
- // Make sure we can delete some of the data.
- db->DeletePageData(Time::FromInternalValue(kTime1), kURL1);
- EXPECT_EQ(2, RowCount(db.get()));
-
- // Close and reopen.
- db.reset(new TextDatabase(temp_dir_.path(), kIdee1, false));
- EXPECT_TRUE(db->Init());
-
- // Verify that the deleted ID is gone and try to delete another one.
- EXPECT_EQ(2, RowCount(db.get()));
- db->DeletePageData(Time::FromInternalValue(kTime2), kURL2);
- EXPECT_EQ(1, RowCount(db.get()));
-}
-
-TEST_F(TextDatabaseTest, Query) {
- // Make a database with some pages.
- const int kIdee1 = 200801;
- scoped_ptr<TextDatabase> db(CreateDB(kIdee1, true, true));
- EXPECT_TRUE(!!db.get());
- AddAllTestData(db.get());
-
- // Get all the results.
- QueryOptions options;
- options.begin_time = Time::FromInternalValue(0);
-
- std::vector<TextDatabase::Match> results;
- TextDatabase::URLSet unique_urls;
- db->GetTextMatches("COUNTTAG", options, &results, &unique_urls);
- EXPECT_TRUE(unique_urls.empty()) << "Didn't ask for unique URLs";
-
- // All 3 sites should be returned in order.
- ASSERT_EQ(3U, results.size());
- EXPECT_EQ(GURL(kURL1), results[2].url);
- EXPECT_EQ(GURL(kURL2), results[1].url);
- EXPECT_EQ(GURL(kURL3), results[0].url);
-
- // Verify the info on those results.
- EXPECT_TRUE(Time::FromInternalValue(kTime1) == results[2].time);
- EXPECT_TRUE(Time::FromInternalValue(kTime2) == results[1].time);
- EXPECT_TRUE(Time::FromInternalValue(kTime3) == results[0].time);
-
- EXPECT_EQ(std::string(kTitle1), UTF16ToUTF8(results[2].title));
- EXPECT_EQ(std::string(kTitle2), UTF16ToUTF8(results[1].title));
- EXPECT_EQ(std::string(kTitle3), UTF16ToUTF8(results[0].title));
-
- // Should have no matches in the title.
- EXPECT_EQ(0U, results[0].title_match_positions.size());
- EXPECT_EQ(0U, results[1].title_match_positions.size());
- EXPECT_EQ(0U, results[2].title_match_positions.size());
-
- // We don't want to be dependent on the exact snippet algorithm, but we know
- // since we searched for "COUNTTAG" which occurs at the beginning of each
- // document, that each snippet should start with that.
- EXPECT_TRUE(StartsWithASCII(UTF16ToUTF8(results[0].snippet.text()),
- "COUNTTAG", false));
- EXPECT_TRUE(StartsWithASCII(UTF16ToUTF8(results[1].snippet.text()),
- "COUNTTAG", false));
- EXPECT_TRUE(StartsWithASCII(UTF16ToUTF8(results[2].snippet.text()),
- "COUNTTAG", false));
-}
-
-TEST_F(TextDatabaseTest, TimeRange) {
- // Make a database with some pages.
- const int kIdee1 = 200801;
- scoped_ptr<TextDatabase> db(CreateDB(kIdee1, true, true));
- ASSERT_TRUE(!!db.get());
- AddAllTestData(db.get());
-
- // Beginning should be inclusive, and the ending exclusive.
- // Get all the results.
- QueryOptions options;
- options.begin_time = Time::FromInternalValue(kTime1);
- options.end_time = Time::FromInternalValue(kTime3);
-
- std::vector<TextDatabase::Match> results;
- TextDatabase::URLSet unique_urls;
- bool has_more_results = db->GetTextMatches(
- "COUNTTAG", options, &results, &unique_urls);
- EXPECT_TRUE(unique_urls.empty()) << "Didn't ask for unique URLs";
-
- // The first and second should have been returned.
- EXPECT_EQ(2U, results.size());
- EXPECT_TRUE(ResultsHaveURL(results, kURL1));
- EXPECT_TRUE(ResultsHaveURL(results, kURL2));
- EXPECT_FALSE(ResultsHaveURL(results, kURL3));
- EXPECT_EQ(kTime1, results.back().time.ToInternalValue());
- EXPECT_FALSE(has_more_results);
-
- // Do a query where there isn't a result on the begin boundary.
- options.begin_time = Time::FromInternalValue((kTime2 - kTime1) / 2 + kTime1);
- options.end_time = Time::FromInternalValue(kTime3 + 1);
- results.clear(); // GetTextMatches does *not* clear the results.
- has_more_results = db->GetTextMatches(
- "COUNTTAG", options, &results, &unique_urls);
- EXPECT_TRUE(unique_urls.empty()) << "Didn't ask for unique URLs";
- EXPECT_FALSE(has_more_results);
-
- // Should have two results, the second and third.
- EXPECT_EQ(2U, results.size());
- EXPECT_FALSE(ResultsHaveURL(results, kURL1));
- EXPECT_TRUE(ResultsHaveURL(results, kURL2));
- EXPECT_TRUE(ResultsHaveURL(results, kURL3));
-
- // Try a range that has no results.
- options.begin_time = Time::FromInternalValue(kTime3 + 1);
- options.end_time = Time::FromInternalValue(kTime3 * 100);
- results.clear();
- has_more_results = db->GetTextMatches(
- "COUNTTAG", options, &results, &unique_urls);
- EXPECT_FALSE(has_more_results);
-}
-
-// Make sure that max_count works.
-TEST_F(TextDatabaseTest, MaxCount) {
- // Make a database with some pages.
- const int kIdee1 = 200801;
- scoped_ptr<TextDatabase> db(CreateDB(kIdee1, true, true));
- ASSERT_TRUE(!!db.get());
- AddAllTestData(db.get());
-
- // Set up the query to return all the results with "Google" (should be 2), but
- // with a maximum of 1.
- QueryOptions options;
- options.begin_time = Time::FromInternalValue(kTime1);
- options.end_time = Time::FromInternalValue(kTime3 + 1);
- options.max_count = 1;
-
- std::vector<TextDatabase::Match> results;
- TextDatabase::URLSet unique_urls;
- db->GetTextMatches("google", options, &results, &unique_urls);
- EXPECT_TRUE(unique_urls.empty()) << "Didn't ask for unique URLs";
-
- // There should be one result, the most recent one.
- EXPECT_EQ(1U, results.size());
- EXPECT_TRUE(ResultsHaveURL(results, kURL2));
- EXPECT_EQ(kTime2, results.back().time.ToInternalValue());
-}
-
-} // namespace history
diff --git a/chrome/browser/history/thumbnail_database.cc b/chrome/browser/history/thumbnail_database.cc
index 3014338..4ba08a5 100644
--- a/chrome/browser/history/thumbnail_database.cc
+++ b/chrome/browser/history/thumbnail_database.cc
@@ -17,10 +17,10 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
-#include "chrome/browser/history/history_publisher.h"
#include "chrome/browser/history/url_database.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/dump_without_crashing.h"
+#include "sql/recovery.h"
#include "sql/statement.h"
#include "sql/transaction.h"
#include "third_party/sqlite/sqlite3.h"
@@ -205,66 +205,411 @@
// TODO(shess): If this proves out, perhaps lift the code out to
// chrome/browser/diagnostics/sqlite_diagnostics.{h,cc}.
-void DatabaseErrorCallback(sql::Connection* db,
- size_t startup_kb,
- int error,
- sql::Statement* stmt) {
- // TODO(shess): Assert that this is running on a safe thread.
- // AFAICT, should be the history thread, but at this level I can't
- // see how to reach that.
+void GenerateDiagnostics(sql::Connection* db,
+ size_t startup_kb,
+ int extended_error) {
+ int error = (extended_error & 0xFF);
// Infrequently report information about the error up to the crash
// server.
static const uint64 kReportsPerMillion = 50000;
+ // Since some/most errors will not resolve themselves, only report
+ // once per Chrome run.
+ static bool reported = false;
+ if (reported)
+ return;
+
+ uint64 rand = base::RandGenerator(1000000);
+ if (error == SQLITE_CORRUPT) {
+ // Once the database is known to be corrupt, it will generate a
+ // stream of errors until someone fixes it, so give one chance.
+ // Set first in case of errors in generating the report.
+ reported = true;
+
+ // Corrupt cases currently dominate, report them very infrequently.
+ static const uint64 kCorruptReportsPerMillion = 10000;
+ if (rand < kCorruptReportsPerMillion)
+ ReportCorrupt(db, startup_kb);
+ } else if (error == SQLITE_READONLY) {
+ // SQLITE_READONLY appears similar to SQLITE_CORRUPT - once it
+ // is seen, it is almost guaranteed to be seen again.
+ reported = true;
+
+ if (rand < kReportsPerMillion)
+ ReportError(db, extended_error);
+ } else {
+ // Only set the flag when making a report. This should allow
+ // later (potentially different) errors in a stream of errors to
+ // be reported.
+ //
+ // TODO(shess): Would it be worthwile to audit for which cases
+ // want once-only handling? Sqlite.Error.Thumbnail shows
+ // CORRUPT and READONLY as almost 95% of all reports on these
+ // channels, so probably easier to just harvest from the field.
+ if (rand < kReportsPerMillion) {
+ reported = true;
+ ReportError(db, extended_error);
+ }
+ }
+}
+
+bool InitTables(sql::Connection* db) {
+ const char kIconMappingSql[] =
+ "CREATE TABLE IF NOT EXISTS icon_mapping"
+ "("
+ "id INTEGER PRIMARY KEY,"
+ "page_url LONGVARCHAR NOT NULL,"
+ "icon_id INTEGER"
+ ")";
+ if (!db->Execute(kIconMappingSql))
+ return false;
+
+ const char kFaviconsSql[] =
+ "CREATE TABLE IF NOT EXISTS favicons"
+ "("
+ "id INTEGER PRIMARY KEY,"
+ "url LONGVARCHAR NOT NULL,"
+ // Set the default icon_type as FAVICON to be consistent with
+ // table upgrade in UpgradeToVersion4().
+ "icon_type INTEGER DEFAULT 1"
+ ")";
+ if (!db->Execute(kFaviconsSql))
+ return false;
+
+ const char kFaviconBitmapsSql[] =
+ "CREATE TABLE IF NOT EXISTS favicon_bitmaps"
+ "("
+ "id INTEGER PRIMARY KEY,"
+ "icon_id INTEGER NOT NULL,"
+ "last_updated INTEGER DEFAULT 0,"
+ "image_data BLOB,"
+ "width INTEGER DEFAULT 0,"
+ "height INTEGER DEFAULT 0"
+ ")";
+ if (!db->Execute(kFaviconBitmapsSql))
+ return false;
+
+ return true;
+}
+
+bool InitIndices(sql::Connection* db) {
+ const char kIconMappingUrlIndexSql[] =
+ "CREATE INDEX IF NOT EXISTS icon_mapping_page_url_idx"
+ " ON icon_mapping(page_url)";
+ const char kIconMappingIdIndexSql[] =
+ "CREATE INDEX IF NOT EXISTS icon_mapping_icon_id_idx"
+ " ON icon_mapping(icon_id)";
+ if (!db->Execute(kIconMappingUrlIndexSql) ||
+ !db->Execute(kIconMappingIdIndexSql)) {
+ return false;
+ }
+
+ const char kFaviconsIndexSql[] =
+ "CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)";
+ if (!db->Execute(kFaviconsIndexSql))
+ return false;
+
+ const char kFaviconBitmapsIndexSql[] =
+ "CREATE INDEX IF NOT EXISTS favicon_bitmaps_icon_id ON "
+ "favicon_bitmaps(icon_id)";
+ if (!db->Execute(kFaviconBitmapsIndexSql))
+ return false;
+
+ return true;
+}
+
+enum RecoveryEventType {
+ RECOVERY_EVENT_RECOVERED = 0,
+ RECOVERY_EVENT_FAILED_SCOPER,
+ RECOVERY_EVENT_FAILED_META_VERSION_ERROR,
+ RECOVERY_EVENT_FAILED_META_VERSION_NONE,
+ RECOVERY_EVENT_FAILED_META_WRONG_VERSION6,
+ RECOVERY_EVENT_FAILED_META_WRONG_VERSION5,
+ RECOVERY_EVENT_FAILED_META_WRONG_VERSION,
+ RECOVERY_EVENT_FAILED_RECOVER_META,
+ RECOVERY_EVENT_FAILED_META_INSERT,
+ RECOVERY_EVENT_FAILED_INIT,
+ RECOVERY_EVENT_FAILED_RECOVER_FAVICONS,
+ RECOVERY_EVENT_FAILED_FAVICONS_INSERT,
+ RECOVERY_EVENT_FAILED_RECOVER_FAVICON_BITMAPS,
+ RECOVERY_EVENT_FAILED_FAVICON_BITMAPS_INSERT,
+ RECOVERY_EVENT_FAILED_RECOVER_ICON_MAPPING,
+ RECOVERY_EVENT_FAILED_ICON_MAPPING_INSERT,
+
+ // Always keep this at the end.
+ RECOVERY_EVENT_MAX,
+};
+
+void RecordRecoveryEvent(RecoveryEventType recovery_event) {
+ UMA_HISTOGRAM_ENUMERATION("History.FaviconsRecovery",
+ recovery_event, RECOVERY_EVENT_MAX);
+}
+
+// Recover the database to the extent possible, razing it if recovery
+// is not possible.
+// TODO(shess): This is mostly just a safe proof of concept. In the
+// real world, this database is probably not worthwhile recovering, as
+// opposed to just razing it and starting over whenever corruption is
+// detected. So this database is a good test subject.
+void RecoverDatabaseOrRaze(sql::Connection* db, const base::FilePath& db_path) {
+ // TODO(shess): Reset back after?
+ db->reset_error_callback();
+
+ scoped_ptr<sql::Recovery> recovery = sql::Recovery::Begin(db, db_path);
+ if (!recovery) {
+ // TODO(shess): Unable to create recovery connection. This
+ // implies something substantial is wrong. At this point |db| has
+ // been poisoned so there is nothing really to do.
+ //
+ // Possible responses are unclear. If the failure relates to a
+ // problem somehow specific to the temporary file used to back the
+ // database, then an in-memory database could possibly be used.
+ // This could potentially allow recovering the main database, and
+ // might be simple to implement w/in Begin().
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_SCOPER);
+ return;
+ }
+
+ // Setup the meta recovery table, and check that the version number
+ // is covered by the recovery code.
+ // TODO(shess): sql::Recovery should provide a helper to handle meta.
+ {
+ const char kRecoverySql[] =
+ "CREATE VIRTUAL TABLE temp.recover_meta USING recover"
+ "("
+ "corrupt.meta,"
+ "key TEXT NOT NULL,"
+ "value TEXT" // Really? Never int?
+ ")";
+ if (!recovery->db()->Execute(kRecoverySql)) {
+ // TODO(shess): Failure to create the recover_meta table could
+ // mean that the main database is too corrupt to access, or that
+ // the meta table doesn't exist.
+ sql::Recovery::Rollback(recovery.Pass());
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_META);
+ return;
+ }
+
+ {
+ const char kRecoveryVersionSql[] =
+ "SELECT value FROM recover_meta WHERE key = 'version'";
+ sql::Statement recovery_version(
+ recovery->db()->GetUniqueStatement(kRecoveryVersionSql));
+ if (!recovery_version.Step()) {
+ if (!recovery_version.Succeeded()) {
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_VERSION_ERROR);
+ // TODO(shess): An error while processing the statement is
+ // probably not recoverable.
+ } else {
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_VERSION_NONE);
+ // TODO(shess): If a positive version lock cannot be achieved,
+ // the database could still be recovered by optimistically
+ // attempting to copy things. In the limit, the schema found
+ // could be inspected. Less clear is whether optimistic
+ // recovery really makes sense.
+ }
+ recovery_version.Clear();
+ sql::Recovery::Rollback(recovery.Pass());
+ return;
+ } else if (7 != recovery_version.ColumnInt(0)) {
+ // TODO(shess): Recovery code is generally schema-dependent.
+ // Version 6 should be easy, if the numbers warrant it.
+ // Version 5 is probably not warranted.
+ switch (recovery_version.ColumnInt(0)) {
+ case 6 :
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION6);
+ break;
+ case 5 :
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION5);
+ break;
+ default :
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION);
+ break;
+ }
+ recovery_version.Clear();
+ sql::Recovery::Rollback(recovery.Pass());
+ return;
+ }
+ }
+
+ const char kCopySql[] =
+ "INSERT OR REPLACE INTO meta SELECT key, value FROM recover_meta";
+ if (!recovery->db()->Execute(kCopySql)) {
+ // TODO(shess): Earlier the version was queried, unclear what
+ // this failure could mean.
+ sql::Recovery::Rollback(recovery.Pass());
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_INSERT);
+ return;
+ }
+ }
+
+ // Create a fresh version of the database. The recovery code uses
+ // conflict-resolution to handle duplicates, so the indices are
+ // necessary.
+ if (!InitTables(recovery->db()) || !InitIndices(recovery->db())) {
+ // TODO(shess): Unable to create the new schema in the new
+ // database. The new database should be a temporary file, so
+ // being unable to work with it is pretty unclear.
+ //
+ // What are the potential responses, even? The recovery database
+ // could be opened as in-memory. If the temp database had a
+ // filesystem problem and the temp filesystem differs from the
+ // main database, then that could fix it.
+ sql::Recovery::Rollback(recovery.Pass());
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_INIT);
+ return;
+ }
+
+ // Setup favicons table.
+ {
+ const char kRecoverySql[] =
+ "CREATE VIRTUAL TABLE temp.recover_favicons USING recover"
+ "("
+ "corrupt.favicons,"
+ "id ROWID,"
+ "url TEXT NOT NULL,"
+ "icon_type INTEGER"
+ ")";
+ if (!recovery->db()->Execute(kRecoverySql)) {
+ // TODO(shess): Failure to create the recovery table probably
+ // means unrecoverable.
+ sql::Recovery::Rollback(recovery.Pass());
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_FAVICONS);
+ return;
+ }
+
+ // TODO(shess): Check if the DEFAULT 1 will just cover the
+ // COALESCE(). Either way, the new code has a literal 1 rather
+ // than a NULL, right?
+ const char kCopySql[] =
+ "INSERT OR REPLACE INTO favicons "
+ "SELECT id, url, COALESCE(icon_type, 1) FROM recover_favicons";
+ if (!recovery->db()->Execute(kCopySql)) {
+ // TODO(shess): The recover_favicons table should mask problems
+ // with the source file, so this implies failure to write to the
+ // recovery database.
+ sql::Recovery::Rollback(recovery.Pass());
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_FAVICONS_INSERT);
+ return;
+ }
+ }
+
+ // Setup favicons_bitmaps table.
+ {
+ const char kRecoverySql[] =
+ "CREATE VIRTUAL TABLE temp.recover_favicons_bitmaps USING recover"
+ "("
+ "corrupt.favicon_bitmaps,"
+ "id ROWID,"
+ "icon_id INTEGER STRICT NOT NULL,"
+ "last_updated INTEGER,"
+ "image_data BLOB,"
+ "width INTEGER,"
+ "height INTEGER"
+ ")";
+ if (!recovery->db()->Execute(kRecoverySql)) {
+ // TODO(shess): Failure to create the recovery table probably
+ // means unrecoverable.
+ sql::Recovery::Rollback(recovery.Pass());
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_FAVICON_BITMAPS);
+ return;
+ }
+
+ const char kCopySql[] =
+ "INSERT OR REPLACE INTO favicon_bitmaps "
+ "SELECT id, icon_id, COALESCE(last_updated, 0), image_data, "
+ " COALESCE(width, 0), COALESCE(height, 0) "
+ "FROM recover_favicons_bitmaps";
+ if (!recovery->db()->Execute(kCopySql)) {
+ // TODO(shess): The recover_faviconbitmaps table should mask
+ // problems with the source file, so this implies failure to
+ // write to the recovery database.
+ sql::Recovery::Rollback(recovery.Pass());
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_FAVICON_BITMAPS_INSERT);
+ return;
+ }
+ }
+
+ // Setup icon_mapping table.
+ {
+ const char kRecoverySql[] =
+ "CREATE VIRTUAL TABLE temp.recover_icon_mapping USING recover"
+ "("
+ "corrupt.icon_mapping,"
+ "id ROWID,"
+ "page_url TEXT STRICT NOT NULL,"
+ "icon_id INTEGER STRICT"
+ ")";
+ if (!recovery->db()->Execute(kRecoverySql)) {
+ // TODO(shess): Failure to create the recovery table probably
+ // means unrecoverable.
+ sql::Recovery::Rollback(recovery.Pass());
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_ICON_MAPPING);
+ return;
+ }
+
+ const char kCopySql[] =
+ "INSERT OR REPLACE INTO icon_mapping "
+ "SELECT id, page_url, icon_id FROM recover_icon_mapping";
+ if (!recovery->db()->Execute(kCopySql)) {
+ // TODO(shess): The recover_icon_mapping table should mask
+ // problems with the source file, so this implies failure to
+ // write to the recovery database.
+ sql::Recovery::Rollback(recovery.Pass());
+ RecordRecoveryEvent(RECOVERY_EVENT_FAILED_ICON_MAPPING_INSERT);
+ return;
+ }
+ }
+
+ // TODO(shess): Is it possible/likely to have broken foreign-key
+ // issues with the tables?
+ // - icon_mapping.icon_id maps to no favicons.id
+ // - favicon_bitmaps.icon_id maps to no favicons.id
+ // - favicons.id is referenced by no icon_mapping.icon_id
+ // - favicons.id is referenced by no favicon_bitmaps.icon_id
+ // This step is possibly not worth the effort necessary to develop
+ // and sequence the statements, as it is basically a form of garbage
+ // collection.
+
+ ignore_result(sql::Recovery::Recovered(recovery.Pass()));
+ RecordRecoveryEvent(RECOVERY_EVENT_RECOVERED);
+}
+
+void DatabaseErrorCallback(sql::Connection* db,
+ const base::FilePath& db_path,
+ size_t startup_kb,
+ int extended_error,
+ sql::Statement* stmt) {
+ // TODO(shess): Assert that this is running on a safe thread.
+ // AFAICT, should be the history thread, but at this level I can't
+ // see how to reach that.
+
// TODO(shess): For now, don't report on beta or stable so as not to
// overwhelm the crash server. Once the big fish are fried,
// consider reporting at a reduced rate on the bigger channels.
chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
-
- // Since some/most errors will not resolve themselves, only report
- // once per Chrome run.
- static bool reported = false;
-
if (channel != chrome::VersionInfo::CHANNEL_STABLE &&
- channel != chrome::VersionInfo::CHANNEL_BETA &&
- !reported) {
- uint64 rand = base::RandGenerator(1000000);
- if (error == SQLITE_CORRUPT) {
- // Once the database is known to be corrupt, it will generate a
- // stream of errors until someone fixes it, so give one chance.
- // Set first in case of errors in generating the report.
- reported = true;
+ channel != chrome::VersionInfo::CHANNEL_BETA) {
+ GenerateDiagnostics(db, startup_kb, extended_error);
+ }
- // Corrupt cases currently dominate, report them very infrequently.
- static const uint64 kCorruptReportsPerMillion = 10000;
- if (rand < kCorruptReportsPerMillion)
- ReportCorrupt(db, startup_kb);
- } else if (error == SQLITE_READONLY) {
- // SQLITE_READONLY appears similar to SQLITE_CORRUPT - once it
- // is seen, it is almost guaranteed to be seen again.
- reported = true;
-
- if (rand < kReportsPerMillion)
- ReportError(db, error);
- } else {
- // Only set the flag when making a report. This should allow
- // later (potentially different) errors in a stream of errors to
- // be reported.
- //
- // TODO(shess): Would it be worthwile to audit for which cases
- // want once-only handling? Sqlite.Error.Thumbnail shows
- // CORRUPT and READONLY as almost 95% of all reports on these
- // channels, so probably easier to just harvest from the field.
- if (rand < kReportsPerMillion) {
- reported = true;
- ReportError(db, error);
- }
+ // Attempt to recover corrupt databases.
+ // TODO(shess): Remove the channel restriction once it becomes clear
+ // that the recovery code fails gracefully.
+ if (channel != chrome::VersionInfo::CHANNEL_STABLE &&
+ channel != chrome::VersionInfo::CHANNEL_BETA) {
+ int error = (extended_error & 0xFF);
+ if (error == SQLITE_CORRUPT ||
+ error == SQLITE_CANTOPEN ||
+ error == SQLITE_NOTADB) {
+ RecoverDatabaseOrRaze(db, db_path);
}
}
// The default handling is to assert on debug and to ignore on release.
- DLOG(FATAL) << db->GetErrorMessage();
+ if (!sql::Connection::ShouldIgnoreSqliteError(extended_error))
+ DLOG(FATAL) << db->GetErrorMessage();
}
} // namespace
@@ -297,8 +642,7 @@
return true;
}
-ThumbnailDatabase::ThumbnailDatabase()
- : history_publisher_(NULL) {
+ThumbnailDatabase::ThumbnailDatabase() {
}
sql::InitStatus ThumbnailDatabase::CantUpgradeToVersion(int cur_version) {
@@ -314,9 +658,7 @@
sql::InitStatus ThumbnailDatabase::Init(
const base::FilePath& db_name,
- const HistoryPublisher* history_publisher,
URLDatabase* url_db) {
- history_publisher_ = history_publisher;
sql::InitStatus status = OpenDatabase(&db_, db_name);
if (status != sql::INIT_OK)
return status;
@@ -337,12 +679,8 @@
// Create the tables.
if (!meta_table_.Init(&db_, kCurrentVersionNumber,
kCompatibleVersionNumber) ||
- !InitFaviconBitmapsTable(&db_) ||
- !InitFaviconBitmapsIndex() ||
- !InitFaviconsTable(&db_) ||
- !InitFaviconsIndex() ||
- !InitIconMappingTable(&db_) ||
- !InitIconMappingIndex()) {
+ !InitTables(&db_) ||
+ !InitIndices(&db_)) {
db_.Close();
return sql::INIT_FAILURE;
}
@@ -435,7 +773,8 @@
startup_kb = static_cast<size_t>(size_64 / 1024);
db->set_histogram_tag("Thumbnail");
- db->set_error_callback(base::Bind(&DatabaseErrorCallback, db, startup_kb));
+ db->set_error_callback(base::Bind(&DatabaseErrorCallback,
+ db, db_name, startup_kb));
// Thumbnails db now only stores favicons, so we don't need that big a page
// size or cache.
@@ -467,45 +806,6 @@
return true;
}
-bool ThumbnailDatabase::InitFaviconsTable(sql::Connection* db) {
- const char kSql[] =
- "CREATE TABLE IF NOT EXISTS favicons"
- "("
- "id INTEGER PRIMARY KEY,"
- "url LONGVARCHAR NOT NULL,"
- // Set the default icon_type as FAVICON to be consistent with
- // table upgrade in UpgradeToVersion4().
- "icon_type INTEGER DEFAULT 1"
- ")";
- return db->Execute(kSql);
-}
-
-bool ThumbnailDatabase::InitFaviconsIndex() {
- // Add an index on the url column.
- return
- db_.Execute("CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)");
-}
-
-bool ThumbnailDatabase::InitFaviconBitmapsTable(sql::Connection* db) {
- const char kSql[] =
- "CREATE TABLE IF NOT EXISTS favicon_bitmaps"
- "("
- "id INTEGER PRIMARY KEY,"
- "icon_id INTEGER NOT NULL,"
- "last_updated INTEGER DEFAULT 0,"
- "image_data BLOB,"
- "width INTEGER DEFAULT 0,"
- "height INTEGER DEFAULT 0"
- ")";
- return db->Execute(kSql);
-}
-
-bool ThumbnailDatabase::InitFaviconBitmapsIndex() {
- // Add an index on the icon_id column.
- return db_.Execute("CREATE INDEX IF NOT EXISTS favicon_bitmaps_icon_id ON "
- "favicon_bitmaps(icon_id)");
-}
-
bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() {
return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons");
}
@@ -938,72 +1238,72 @@
}
}
- {
- const char kRenameIconMappingTable[] =
- "ALTER TABLE icon_mapping RENAME TO old_icon_mapping";
- const char kCopyIconMapping[] =
- "INSERT INTO icon_mapping (page_url, icon_id) "
- "SELECT old.page_url, mapping.new_icon_id "
- "FROM old_icon_mapping AS old "
- "JOIN temp.icon_id_mapping AS mapping "
- "ON (old.icon_id = mapping.old_icon_id)";
- const char kDropOldIconMappingTable[] = "DROP TABLE old_icon_mapping";
- if (!db_.Execute(kRenameIconMappingTable) ||
- !InitIconMappingTable(&db_) ||
- !db_.Execute(kCopyIconMapping) ||
- !db_.Execute(kDropOldIconMappingTable)) {
- return false;
- }
- }
+ const char kRenameIconMappingTable[] =
+ "ALTER TABLE icon_mapping RENAME TO old_icon_mapping";
+ const char kCopyIconMapping[] =
+ "INSERT INTO icon_mapping (page_url, icon_id) "
+ "SELECT old.page_url, mapping.new_icon_id "
+ "FROM old_icon_mapping AS old "
+ "JOIN temp.icon_id_mapping AS mapping "
+ "ON (old.icon_id = mapping.old_icon_id)";
+ const char kDropOldIconMappingTable[] = "DROP TABLE old_icon_mapping";
- {
- const char kRenameFaviconsTable[] =
- "ALTER TABLE favicons RENAME TO old_favicons";
- const char kCopyFavicons[] =
- "INSERT INTO favicons (id, url, icon_type) "
- "SELECT mapping.new_icon_id, old.url, old.icon_type "
- "FROM old_favicons AS old "
- "JOIN temp.icon_id_mapping AS mapping "
- "ON (old.id = mapping.old_icon_id)";
- const char kDropOldFaviconsTable[] = "DROP TABLE old_favicons";
- if (!db_.Execute(kRenameFaviconsTable) ||
- !InitFaviconsTable(&db_) ||
- !db_.Execute(kCopyFavicons) ||
- !db_.Execute(kDropOldFaviconsTable)) {
- return false;
- }
- }
+ const char kRenameFaviconsTable[] =
+ "ALTER TABLE favicons RENAME TO old_favicons";
+ const char kCopyFavicons[] =
+ "INSERT INTO favicons (id, url, icon_type) "
+ "SELECT mapping.new_icon_id, old.url, old.icon_type "
+ "FROM old_favicons AS old "
+ "JOIN temp.icon_id_mapping AS mapping "
+ "ON (old.id = mapping.old_icon_id)";
+ const char kDropOldFaviconsTable[] = "DROP TABLE old_favicons";
- {
- const char kRenameFaviconBitmapsTable[] =
- "ALTER TABLE favicon_bitmaps RENAME TO old_favicon_bitmaps";
- const char kCopyFaviconBitmaps[] =
- "INSERT INTO favicon_bitmaps "
- " (icon_id, last_updated, image_data, width, height) "
- "SELECT mapping.new_icon_id, old.last_updated, "
- " old.image_data, old.width, old.height "
- "FROM old_favicon_bitmaps AS old "
- "JOIN temp.icon_id_mapping AS mapping "
- "ON (old.icon_id = mapping.old_icon_id)";
- const char kDropOldFaviconBitmapsTable[] =
- "DROP TABLE old_favicon_bitmaps";
- if (!db_.Execute(kRenameFaviconBitmapsTable) ||
- !InitFaviconBitmapsTable(&db_) ||
- !db_.Execute(kCopyFaviconBitmaps) ||
- !db_.Execute(kDropOldFaviconBitmapsTable)) {
- return false;
- }
- }
+ const char kRenameFaviconBitmapsTable[] =
+ "ALTER TABLE favicon_bitmaps RENAME TO old_favicon_bitmaps";
+ const char kCopyFaviconBitmaps[] =
+ "INSERT INTO favicon_bitmaps "
+ " (icon_id, last_updated, image_data, width, height) "
+ "SELECT mapping.new_icon_id, old.last_updated, "
+ " old.image_data, old.width, old.height "
+ "FROM old_favicon_bitmaps AS old "
+ "JOIN temp.icon_id_mapping AS mapping "
+ "ON (old.icon_id = mapping.old_icon_id)";
+ const char kDropOldFaviconBitmapsTable[] =
+ "DROP TABLE old_favicon_bitmaps";
- // Renaming the tables adjusts the indices to reference the new
- // name, BUT DOES NOT RENAME THE INDICES. The DROP will drop the
- // indices, now re-create them against the new tables.
- if (!InitIconMappingIndex() ||
- !InitFaviconsIndex() ||
- !InitFaviconBitmapsIndex()) {
+ // Rename existing tables to new location.
+ if (!db_.Execute(kRenameIconMappingTable) ||
+ !db_.Execute(kRenameFaviconsTable) ||
+ !db_.Execute(kRenameFaviconBitmapsTable)) {
return false;
}
+ // Initialize the replacement tables. At this point the old indices
+ // still exist (pointing to the old_* tables), so do not initialize
+ // the indices.
+ if (!InitTables(&db_))
+ return false;
+
+ // Copy all of the data over.
+ if (!db_.Execute(kCopyIconMapping) ||
+ !db_.Execute(kCopyFavicons) ||
+ !db_.Execute(kCopyFaviconBitmaps)) {
+ return false;
+ }
+
+ // Drop the old_* tables, which also drops the indices.
+ if (!db_.Execute(kDropOldIconMappingTable) ||
+ !db_.Execute(kDropOldFaviconsTable) ||
+ !db_.Execute(kDropOldFaviconBitmapsTable)) {
+ return false;
+ }
+
+ // Recreate the indices.
+ // TODO(shess): UNIQUE indices could fail due to duplication. This
+ // could happen in case of corruption.
+ if (!InitIndices(&db_))
+ return false;
+
const char kIconMappingDrop[] = "DROP TABLE temp.icon_id_mapping";
if (!db_.Execute(kIconMappingDrop))
return false;
@@ -1011,26 +1311,6 @@
return transaction.Commit();
}
-bool ThumbnailDatabase::InitIconMappingTable(sql::Connection* db) {
- const char kSql[] =
- "CREATE TABLE IF NOT EXISTS icon_mapping"
- "("
- "id INTEGER PRIMARY KEY,"
- "page_url LONGVARCHAR NOT NULL,"
- "icon_id INTEGER"
- ")";
- return db->Execute(kSql);
-}
-
-bool ThumbnailDatabase::InitIconMappingIndex() {
- // Add an index on the url column.
- return
- db_.Execute("CREATE INDEX IF NOT EXISTS icon_mapping_page_url_idx"
- " ON icon_mapping(page_url)") &&
- db_.Execute("CREATE INDEX IF NOT EXISTS icon_mapping_icon_id_idx"
- " ON icon_mapping(icon_id)");
-}
-
IconMappingID ThumbnailDatabase::AddIconMapping(const GURL& page_url,
chrome::FaviconID icon_id) {
const char kSql[] =
diff --git a/chrome/browser/history/thumbnail_database.h b/chrome/browser/history/thumbnail_database.h
index 6db3b9c..eba1551 100644
--- a/chrome/browser/history/thumbnail_database.h
+++ b/chrome/browser/history/thumbnail_database.h
@@ -15,24 +15,14 @@
#include "sql/meta_table.h"
#include "sql/statement.h"
-struct ThumbnailScore;
-class SkBitmap;
-
namespace base {
class FilePath;
class RefCountedMemory;
class Time;
}
-namespace gfx {
-class Image;
-}
-
namespace history {
-class ExpireHistoryBackend;
-class HistoryPublisher;
-
// This database interface is owned by the history backend and runs on the
// history thread. It is a totally separate component from history partially
// because we may want to move it to its own thread in the future. The
@@ -48,7 +38,6 @@
// Must be called after creation but before any other methods are called.
// When not INIT_OK, no other functions should be called.
sql::InitStatus Init(const base::FilePath& db_name,
- const HistoryPublisher* history_publisher,
URLDatabase* url_database);
// Open database on a given filename. If the file does not exist,
@@ -249,16 +238,12 @@
bool RetainDataForPageUrls(const std::vector<GURL>& urls_to_keep);
private:
- friend class ExpireHistoryBackend;
- FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest,
- GetFaviconAfterMigrationToTopSites);
FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version3);
FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version4);
FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version5);
FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version6);
FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version7);
FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, RetainDataForPageUrls);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MigrationIconMapping);
// Creates the thumbnail table, returning true if the table already exists
// or was successfully created.
@@ -286,41 +271,6 @@
// Return whether the migration succeeds.
bool MigrateIconMappingData(URLDatabase* url_db);
- // Creates the favicon table, returning true if the table already exists,
- // or was successfully created.
- // |db| is the connection to use for initializing the table.
- // A different connection is used in RenameAndDropThumbnails, when we
- // need to copy the favicons between two database files.
- bool InitFaviconsTable(sql::Connection* db);
-
- // Creates the index over the favicon table. This will be called during
- // initialization after the table is created. This is a separate function
- // because it is used by SwapFaviconTables to create an index over the
- // newly-renamed favicons table (formerly the temporary table with no index).
- bool InitFaviconsIndex();
-
- // Creates the favicon_bitmaps table, return true if the table already exists
- // or was successfully created.
- bool InitFaviconBitmapsTable(sql::Connection* db);
-
- // Creates the index over the favicon_bitmaps table. This will be called
- // during initialization after the table is created. This is a separate
- // function because it is used by CommitTemporaryTables to create an
- // index over the newly-renamed favicon_bitmaps table (formerly the temporary
- // table with no index).
- bool InitFaviconBitmapsIndex();
-
- // Creates the icon_map table, return true if the table already exists or was
- // successfully created.
- bool InitIconMappingTable(sql::Connection* db);
-
- // Creates the index over the icon_mapping table, This will be called during
- // initialization after the table is created. This is a separate function
- // because it is used by CommitTemporaryIconMappingTable to create an index
- // over the newly-renamed icon_mapping table (formerly the temporary table
- // with no index).
- bool InitIconMappingIndex();
-
// Returns true if the |favicons| database is missing a column.
bool IsFaviconDBStructureIncorrect();
@@ -329,12 +279,6 @@
sql::Connection db_;
sql::MetaTable meta_table_;
-
- // This object is created and managed by the history backend. We maintain an
- // opaque pointer to the object for our use.
- // This can be NULL if there are no indexers registered to receive indexing
- // data from us.
- const HistoryPublisher* history_publisher_;
};
} // namespace history
diff --git a/chrome/browser/history/thumbnail_database_unittest.cc b/chrome/browser/history/thumbnail_database_unittest.cc
index 6d420b0..bc1a25a 100644
--- a/chrome/browser/history/thumbnail_database_unittest.cc
+++ b/chrome/browser/history/thumbnail_database_unittest.cc
@@ -6,6 +6,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted_memory.h"
@@ -17,8 +18,10 @@
#include "chrome/test/base/testing_profile.h"
#include "sql/connection.h"
#include "sql/statement.h"
+#include "sql/test/scoped_error_ignorer.h"
#include "sql/test/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/sqlite/sqlite3.h"
#include "url/gurl.h"
namespace history {
@@ -57,6 +60,49 @@
return sql::test::CreateDatabaseFromSQL(db_path, sql_path);
}
+int GetPageSize(sql::Connection* db) {
+ sql::Statement s(db->GetUniqueStatement("PRAGMA page_size"));
+ EXPECT_TRUE(s.Step());
+ return s.ColumnInt(0);
+}
+
+// Get |name|'s root page number in the database.
+int GetRootPage(sql::Connection* db, const char* name) {
+ const char kPageSql[] = "SELECT rootpage FROM sqlite_master WHERE name = ?";
+ sql::Statement s(db->GetUniqueStatement(kPageSql));
+ s.BindString(0, name);
+ EXPECT_TRUE(s.Step());
+ return s.ColumnInt(0);
+}
+
+// Helper to read a SQLite page into a buffer. |page_no| is 1-based
+// per SQLite usage.
+bool ReadPage(const base::FilePath& path, size_t page_no,
+ char* buf, size_t page_size) {
+ file_util::ScopedFILE file(file_util::OpenFile(path, "rb"));
+ if (!file.get())
+ return false;
+ if (0 != fseek(file.get(), (page_no - 1) * page_size, SEEK_SET))
+ return false;
+ if (1u != fread(buf, page_size, 1, file.get()))
+ return false;
+ return true;
+}
+
+// Helper to write a SQLite page into a buffer. |page_no| is 1-based
+// per SQLite usage.
+bool WritePage(const base::FilePath& path, size_t page_no,
+ const char* buf, size_t page_size) {
+ file_util::ScopedFILE file(file_util::OpenFile(path, "rb+"));
+ if (!file.get())
+ return false;
+ if (0 != fseek(file.get(), (page_no - 1) * page_size, SEEK_SET))
+ return false;
+ if (1u != fwrite(buf, page_size, 1, file.get()))
+ return false;
+ return true;
+}
+
// Verify that the up-to-date database has the expected tables and
// columns. Functional tests only check whether the things which
// should be there are, but do not check if extraneous items are
@@ -166,7 +212,7 @@
}
scoped_ptr<ThumbnailDatabase> db(new ThumbnailDatabase());
- EXPECT_EQ(sql::INIT_OK, db->Init(file_name_, NULL, url_db));
+ EXPECT_EQ(sql::INIT_OK, db->Init(file_name_, url_db));
db->BeginTransaction();
return db.Pass();
@@ -186,7 +232,7 @@
TEST_F(ThumbnailDatabaseTest, AddIconMapping) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
@@ -211,7 +257,7 @@
TEST_F(ThumbnailDatabaseTest, UpdateIconMapping) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
GURL url("http://google.com");
@@ -240,7 +286,7 @@
TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
@@ -272,7 +318,7 @@
TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURL) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
@@ -301,7 +347,7 @@
TEST_F(ThumbnailDatabaseTest, RetainDataForPageUrls) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
@@ -351,7 +397,7 @@
// rows from the database.
TEST_F(ThumbnailDatabaseTest, DeleteFavicon) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
std::vector<unsigned char> data1(kBlob1, kBlob1 + sizeof(kBlob1));
@@ -375,7 +421,7 @@
TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLForReturnOrder) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
// Add a favicon
@@ -443,7 +489,7 @@
// Test result of GetIconMappingsForPageURL when an icon type is passed in.
TEST_F(ThumbnailDatabaseTest, GetIconMappingsForPageURLWithIconType) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
GURL url("http://google.com");
@@ -507,7 +553,7 @@
TEST_F(ThumbnailDatabaseTest, HasMappingFor) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
@@ -558,7 +604,7 @@
TEST_F(ThumbnailDatabaseTest, CloneIconMappings) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
@@ -623,7 +669,7 @@
TEST_F(ThumbnailDatabaseTest, IconMappingEnumerator) {
ThumbnailDatabase db;
- ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL, NULL));
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
db.BeginTransaction();
std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
@@ -792,4 +838,170 @@
kIconUrl3, kLargeSize, sizeof(kBlob2), kBlob2));
}
+TEST_F(ThumbnailDatabaseTest, Recovery) {
+ chrome::FaviconID id1, id2;
+ GURL page_url1("http://www.google.com");
+ GURL page_url2("http://news.google.com");
+ GURL favicon_url("http://www.google.com/favicon.png");
+
+ // Create an example database.
+ // TODO(shess): Merge with the load-dump code when that lands.
+ {
+ ThumbnailDatabase db;
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
+ db.BeginTransaction();
+
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
+ scoped_refptr<base::RefCountedBytes> favicon(
+ new base::RefCountedBytes(data));
+
+ id1 = db.AddFavicon(favicon_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(page_url1, id1));
+ EXPECT_LT(0, db.AddIconMapping(page_url2, id1));
+
+ id2 = db.AddFavicon(favicon_url, chrome::FAVICON);
+ EXPECT_NE(id1, id2);
+ db.AddFaviconBitmap(id2, favicon, time, kSmallSize);
+ EXPECT_LT(0, db.AddIconMapping(page_url1, id2));
+ db.CommitTransaction();
+ }
+
+ // Test that the contents make sense after clean open.
+ {
+ ThumbnailDatabase db;
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
+
+ std::vector<IconMapping> icon_mappings;
+ EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url1, &icon_mappings));
+ ASSERT_EQ(2u, icon_mappings.size());
+ EXPECT_EQ(id1, icon_mappings[0].icon_id);
+ EXPECT_EQ(id2, icon_mappings[1].icon_id);
+ }
+
+ {
+ sql::Connection raw_db;
+ EXPECT_TRUE(raw_db.Open(file_name_));
+ {
+ sql::Statement statement(
+ raw_db.GetUniqueStatement("PRAGMA integrity_check"));
+ EXPECT_TRUE(statement.Step());
+ ASSERT_EQ("ok", statement.ColumnString(0));
+ }
+
+ const char kIndexName[] = "icon_mapping_page_url_idx";
+ const int idx_root_page = GetRootPage(&raw_db, kIndexName);
+ const int page_size = GetPageSize(&raw_db);
+ scoped_ptr<char[]> buf(new char[page_size]);
+ EXPECT_TRUE(ReadPage(file_name_, idx_root_page, buf.get(), page_size));
+
+ {
+ const char kDeleteSql[] = "DELETE FROM icon_mapping WHERE page_url = ?";
+ sql::Statement statement(raw_db.GetUniqueStatement(kDeleteSql));
+ statement.BindString(0, URLDatabase::GURLToDatabaseURL(page_url2));
+ EXPECT_TRUE(statement.Run());
+ }
+ raw_db.Close();
+
+ EXPECT_TRUE(WritePage(file_name_, idx_root_page, buf.get(), page_size));
+ }
+
+ // Database should be corrupt.
+ {
+ sql::Connection raw_db;
+ EXPECT_TRUE(raw_db.Open(file_name_));
+ sql::Statement statement(
+ raw_db.GetUniqueStatement("PRAGMA integrity_check"));
+ EXPECT_TRUE(statement.Step());
+ ASSERT_NE("ok", statement.ColumnString(0));
+ }
+
+ // Open the database and access the corrupt index.
+ {
+ sql::ScopedErrorIgnorer ignore_errors;
+ ignore_errors.IgnoreError(SQLITE_CORRUPT);
+ ThumbnailDatabase db;
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
+
+ // Data for page_url2 was deleted, but the index entry remains,
+ // this will throw SQLITE_CORRUPT. The corruption handler will
+ // recover the database and poison the handle, so the outer call
+ // fails.
+ std::vector<IconMapping> icon_mappings;
+ EXPECT_FALSE(db.GetIconMappingsForPageURL(page_url2, &icon_mappings));
+ ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ }
+
+ // Check that the database is recovered at a SQLite level.
+ {
+ sql::Connection raw_db;
+ EXPECT_TRUE(raw_db.Open(file_name_));
+ sql::Statement statement(
+ raw_db.GetUniqueStatement("PRAGMA integrity_check"));
+ EXPECT_TRUE(statement.Step());
+ EXPECT_EQ("ok", statement.ColumnString(0));
+ }
+
+ // Database should also be recovered at higher levels.
+ {
+ ThumbnailDatabase db;
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
+
+ std::vector<IconMapping> icon_mappings;
+
+ EXPECT_FALSE(db.GetIconMappingsForPageURL(page_url2, &icon_mappings));
+
+ EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url1, &icon_mappings));
+ ASSERT_EQ(2u, icon_mappings.size());
+ EXPECT_EQ(id1, icon_mappings[0].icon_id);
+ EXPECT_EQ(id2, icon_mappings[1].icon_id);
+ }
+
+ // Corrupt the database again by making the actual file shorter than
+ // the header expects.
+ {
+ int64 db_size = 0;
+ EXPECT_TRUE(file_util::GetFileSize(file_name_, &db_size));
+ {
+ sql::Connection raw_db;
+ EXPECT_TRUE(raw_db.Open(file_name_));
+ EXPECT_TRUE(raw_db.Execute("CREATE TABLE t(x)"));
+ }
+ file_util::ScopedFILE file(file_util::OpenFile(file_name_, "rb+"));
+ ASSERT_TRUE(file.get() != NULL);
+ EXPECT_EQ(0, fseek(file.get(), static_cast<long>(db_size), SEEK_SET));
+ EXPECT_TRUE(file_util::TruncateFile(file.get()));
+ }
+
+ // Database is unusable at the SQLite level.
+ {
+ sql::ScopedErrorIgnorer ignore_errors;
+ ignore_errors.IgnoreError(SQLITE_CORRUPT);
+ sql::Connection raw_db;
+ EXPECT_TRUE(raw_db.Open(file_name_));
+ EXPECT_FALSE(raw_db.IsSQLValid("PRAGMA integrity_check"));
+ ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ }
+
+ // Database should be recovered during open.
+ {
+ sql::ScopedErrorIgnorer ignore_errors;
+ ignore_errors.IgnoreError(SQLITE_CORRUPT);
+ ThumbnailDatabase db;
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL));
+
+ std::vector<IconMapping> icon_mappings;
+
+ EXPECT_FALSE(db.GetIconMappingsForPageURL(page_url2, &icon_mappings));
+
+ EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url1, &icon_mappings));
+ ASSERT_EQ(2u, icon_mappings.size());
+ EXPECT_EQ(id1, icon_mappings[0].icon_id);
+ EXPECT_EQ(id2, icon_mappings[1].icon_id);
+ ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ }
+}
+
} // namespace history
diff --git a/chrome/browser/history/typed_url_syncable_service_unittest.cc b/chrome/browser/history/typed_url_syncable_service_unittest.cc
index c97a473..f5919ad 100644
--- a/chrome/browser/history/typed_url_syncable_service_unittest.cc
+++ b/chrome/browser/history/typed_url_syncable_service_unittest.cc
@@ -27,11 +27,10 @@
namespace {
// Constants used to limit size of visits processed.
-static const int kMaxTypedUrlVisits = 100;
-static const int kMaxVisitsToFetch = 1000;
+const int kMaxTypedUrlVisits = 100;
// Visits with this timestamp are treated as expired.
-static const int EXPIRED_VISIT = -1;
+const int EXPIRED_VISIT = -1;
// TestChangeProcessor --------------------------------------------------------
diff --git a/chrome/browser/history/web_history_service.cc b/chrome/browser/history/web_history_service.cc
index 3def0b6..3816713 100644
--- a/chrome/browser/history/web_history_service.cc
+++ b/chrome/browser/history/web_history_service.cc
@@ -81,7 +81,8 @@
ProfileOAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
- token_request_ = token_service->StartRequest(oauth_scopes, this);
+ token_request_ = token_service->StartRequest(
+ token_service->GetPrimaryAccountId(), oauth_scopes, this);
is_pending_ = true;
}
@@ -99,10 +100,13 @@
if (response_code_ == net::HTTP_UNAUTHORIZED && ++auth_retry_count_ <= 1) {
OAuth2TokenService::ScopeSet oauth_scopes;
oauth_scopes.insert(kHistoryOAuthScope);
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
- ->InvalidateToken(oauth_scopes, access_token_);
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
+ token_service->InvalidateToken(token_service->GetPrimaryAccountId(),
+ oauth_scopes,
+ access_token_);
- access_token_ = std::string();
+ access_token_.clear();
Start();
return;
}
diff --git a/chrome/browser/idle_linux.cc b/chrome/browser/idle_linux.cc
index 28d2037..efcbb6d 100644
--- a/chrome/browser/idle_linux.cc
+++ b/chrome/browser/idle_linux.cc
@@ -26,6 +26,8 @@
// check if the workstation is locked.
#if defined(OS_CHROMEOS)
return false;
+#elif defined(USE_OZONE)
+ return false;
#else
return ScreensaverWindowFinder::ScreensaverWindowExists();
#endif
diff --git a/chrome/browser/idle_query_x11.cc b/chrome/browser/idle_query_x11.cc
index da81e36..845ec5b 100644
--- a/chrome/browser/idle_query_x11.cc
+++ b/chrome/browser/idle_query_x11.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/idle_query_x11.h"
#include <X11/extensions/scrnsaver.h>
-#include "ui/base/x/x11_util.h"
+#include "ui/gfx/x/x11_types.h"
namespace chrome {
@@ -14,7 +14,7 @@
IdleData() {
int event_base;
int error_base;
- if (XScreenSaverQueryExtension(ui::GetXDisplay(), &event_base,
+ if (XScreenSaverQueryExtension(gfx::GetXDisplay(), &event_base,
&error_base)) {
mit_info = XScreenSaverAllocInfo();
} else {
@@ -38,8 +38,8 @@
if (!idle_data_->mit_info)
return 0;
- if (XScreenSaverQueryInfo(ui::GetXDisplay(),
- RootWindow(ui::GetXDisplay(), 0),
+ if (XScreenSaverQueryInfo(gfx::GetXDisplay(),
+ RootWindow(gfx::GetXDisplay(), 0),
idle_data_->mit_info)) {
return (idle_data_->mit_info->idle) / 1000;
} else {
diff --git a/chrome/browser/importer/OWNERS b/chrome/browser/importer/OWNERS
index 66d2678..6238904 100644
--- a/chrome/browser/importer/OWNERS
+++ b/chrome/browser/importer/OWNERS
@@ -8,5 +8,4 @@
per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
diff --git a/chrome/browser/importer/firefox_importer_browsertest.cc b/chrome/browser/importer/firefox_importer_browsertest.cc
index 83f9eba..e623e36 100644
--- a/chrome/browser/importer/firefox_importer_browsertest.cc
+++ b/chrome/browser/importer/firefox_importer_browsertest.cc
@@ -94,8 +94,6 @@
{ L"\x4E2D\x6587", "http://www.google.com/" },
};
-const int kDefaultFirefoxKeywordIndex = 8;
-
class FirefoxObserver : public ProfileWriter,
public importer::ImporterProgressObserver {
public:
diff --git a/chrome/browser/invalidation/invalidation_service_factory.cc b/chrome/browser/invalidation/invalidation_service_factory.cc
index 9daa716..32bbaf5 100644
--- a/chrome/browser/invalidation/invalidation_service_factory.cc
+++ b/chrome/browser/invalidation/invalidation_service_factory.cc
@@ -16,16 +16,12 @@
#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"
#if defined(OS_ANDROID)
#include "chrome/browser/invalidation/invalidation_controller_android.h"
#endif // defined(OS_ANDROID)
-class TokenService;
-
namespace invalidation {
// static
@@ -97,13 +93,11 @@
#else
SigninManagerBase* signin_manager =
SigninManagerFactory::GetForProfile(profile);
- TokenService* token_service = TokenServiceFactory::GetForProfile(profile);
- OAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenService* oauth2_token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
TiclInvalidationService* service = new TiclInvalidationService(
signin_manager,
- token_service,
oauth2_token_service,
profile);
service->Init();
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.cc b/chrome/browser/invalidation/ticl_invalidation_service.cc
index 2d11a0d..b80a2d8 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service.cc
+++ b/chrome/browser/invalidation/ticl_invalidation_service.cc
@@ -56,12 +56,10 @@
TiclInvalidationService::TiclInvalidationService(
SigninManagerBase* signin,
- TokenService* token_service,
- OAuth2TokenService* oauth2_token_service,
+ ProfileOAuth2TokenService* 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) {
@@ -88,12 +86,7 @@
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_TOKENS_CLEARED,
- content::Source<TokenService>(token_service_));
+ oauth2_token_service_->AddObserver(this);
}
void TiclInvalidationService::InitForTest(syncer::Invalidator* invalidator) {
@@ -171,29 +164,8 @@
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK(CalledOnValidThread());
-
- switch (type) {
- case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
- if (!IsStarted() && IsReadyToStart()) {
- StartInvalidator();
- }
- break;
- }
- case chrome::NOTIFICATION_TOKENS_CLEARED: {
- access_token_.clear();
- if (IsStarted()) {
- UpdateInvalidatorCredentials();
- }
- break;
- }
- case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: {
- Logout();
- break;
- }
- default: {
- NOTREACHED();
- }
- }
+ DCHECK_EQ(type, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT);
+ Logout();
}
void TiclInvalidationService::RequestAccessToken() {
@@ -206,10 +178,14 @@
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_);
+ const std::string& account_id = oauth2_token_service_->GetPrimaryAccountId();
+ oauth2_token_service_->InvalidateToken(account_id,
+ oauth2_scopes,
+ access_token_);
access_token_.clear();
- access_token_request_ =
- oauth2_token_service_->StartRequest(oauth2_scopes, this);
+ access_token_request_ = oauth2_token_service_->StartRequest(account_id,
+ oauth2_scopes,
+ this);
}
void TiclInvalidationService::OnGetTokenSuccess(
@@ -275,6 +251,25 @@
}
}
+void TiclInvalidationService::OnRefreshTokenAvailable(
+ const std::string& account_id) {
+ if (oauth2_token_service_->GetPrimaryAccountId() == account_id) {
+ if (!IsStarted() && IsReadyToStart()) {
+ StartInvalidator();
+ }
+ }
+}
+
+void TiclInvalidationService::OnRefreshTokenRevoked(
+ const std::string& account_id) {
+ if (oauth2_token_service_->GetPrimaryAccountId() == account_id) {
+ access_token_.clear();
+ if (IsStarted()) {
+ UpdateInvalidatorCredentials();
+ }
+ }
+}
+
void TiclInvalidationService::OnInvalidatorStateChange(
syncer::InvalidatorState state) {
if (state == syncer::INVALIDATION_CREDENTIALS_REJECTED) {
@@ -303,6 +298,7 @@
void TiclInvalidationService::Shutdown() {
DCHECK(CalledOnValidThread());
+ oauth2_token_service_->RemoveObserver(this);
if (IsStarted()) {
StopInvalidator();
}
@@ -327,7 +323,8 @@
return false;
}
- if (!oauth2_token_service_->RefreshTokenIsAvailable()) {
+ if (!oauth2_token_service_->RefreshTokenIsAvailable(
+ oauth2_token_service_->GetPrimaryAccountId())) {
DVLOG(2)
<< "Not starting TiclInvalidationServce: Waiting for refresh token.";
return false;
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.h b/chrome/browser/invalidation/ticl_invalidation_service.h
index a117e98..26c5039 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service.h
+++ b/chrome/browser/invalidation/ticl_invalidation_service.h
@@ -10,7 +10,7 @@
#include "base/timer/timer.h"
#include "chrome/browser/invalidation/invalidation_service.h"
#include "chrome/browser/invalidation/invalidator_storage.h"
-#include "chrome/browser/signin/token_service.h"
+#include "chrome/browser/signin/profile_oauth2_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"
@@ -35,11 +35,11 @@
public InvalidationService,
public content::NotificationObserver,
public OAuth2TokenService::Consumer,
+ public OAuth2TokenService::Observer,
public syncer::InvalidationHandler {
public:
TiclInvalidationService(SigninManagerBase* signin,
- TokenService* token_service,
- OAuth2TokenService* oauth2_token_service,
+ ProfileOAuth2TokenService* oauth2_token_service,
Profile* profile);
virtual ~TiclInvalidationService();
@@ -76,6 +76,10 @@
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) OVERRIDE;
+ // OAuth2TokenService::Observer implementation
+ virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
+ virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE;
+
// syncer::InvalidationHandler implementation.
virtual void OnInvalidatorStateChange(
syncer::InvalidatorState state) OVERRIDE;
@@ -102,8 +106,7 @@
Profile *const profile_;
SigninManagerBase *const signin_manager_;
- TokenService *const token_service_;
- OAuth2TokenService *const oauth2_token_service_;
+ ProfileOAuth2TokenService *const oauth2_token_service_;
scoped_ptr<syncer::InvalidatorRegistrar> invalidator_registrar_;
scoped_ptr<InvalidatorStorage> invalidator_storage_;
diff --git a/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
index 314e8a7..64379ec 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
+++ b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/invalidation/invalidation_service_factory.h"
#include "chrome/browser/invalidation/invalidation_service_test_template.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
#include "chrome/test/base/testing_profile.h"
#include "sync/notifier/fake_invalidation_handler.h"
#include "sync/notifier/fake_invalidator.h"
@@ -25,8 +26,11 @@
void CreateInvalidationService() {
fake_invalidator_ = new syncer::FakeInvalidator();
profile_.reset(new TestingProfile());
+ token_service_.reset(new FakeProfileOAuth2TokenService);
invalidation_service_.reset(
- new TiclInvalidationService(NULL, NULL, NULL, profile_.get()));
+ new TiclInvalidationService(NULL,
+ token_service_.get(),
+ profile_.get()));
invalidation_service_->InitForTest(fake_invalidator_);
}
@@ -50,6 +54,7 @@
syncer::FakeInvalidator* fake_invalidator_; // owned by the service.
scoped_ptr<TiclInvalidationService> invalidation_service_;
scoped_ptr<TestingProfile> profile_;
+ scoped_ptr<FakeProfileOAuth2TokenService> token_service_;
};
INSTANTIATE_TYPED_TEST_CASE_P(
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index d2745b3..13f71ce 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -822,9 +822,13 @@
registry->RegisterListPref(prefs::kDailyHttpOriginalContentLength);
registry->RegisterListPref(prefs::kDailyHttpReceivedContentLength);
registry->RegisterListPref(
- prefs::kDailyHttpReceivedContentLengthViaDataReductionProxy);
+ prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled);
registry->RegisterListPref(
- prefs::kDailyHttpReceivedContentLengthWithDataReductionProxyEnabled);
+ prefs::kDailyContentLengthWithDataReductionProxyEnabled);
+ registry->RegisterListPref(
+ prefs::kDailyOriginalContentLengthViaDataReductionProxy);
+ registry->RegisterListPref(
+ prefs::kDailyContentLengthViaDataReductionProxy);
registry->RegisterInt64Pref(prefs::kDailyHttpContentLengthLastUpdateDate, 0L);
#endif
registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, true);
diff --git a/chrome/browser/local_discovery/cloud_print_base_api_flow.cc b/chrome/browser/local_discovery/cloud_print_base_api_flow.cc
index 0b8371d..9a15917 100644
--- a/chrome/browser/local_discovery/cloud_print_base_api_flow.cc
+++ b/chrome/browser/local_discovery/cloud_print_base_api_flow.cc
@@ -25,10 +25,12 @@
CloudPrintBaseApiFlow::CloudPrintBaseApiFlow(
net::URLRequestContextGetter* request_context,
OAuth2TokenService* token_service,
+ const std::string& account_id,
const GURL& automated_claim_url,
Delegate* delegate)
: request_context_(request_context),
token_service_(token_service),
+ account_id_(account_id),
user_index_(kAccountIndexUseOAuth2),
url_(automated_claim_url),
delegate_(delegate) {
@@ -42,6 +44,7 @@
Delegate* delegate)
: request_context_(request_context),
token_service_(NULL),
+ account_id_(""),
user_index_(user_index),
xsrf_token_(xsrf_token),
url_(automated_claim_url),
@@ -55,6 +58,7 @@
Delegate* delegate)
: request_context_(request_context),
token_service_(NULL),
+ account_id_(""),
user_index_(user_index),
url_(automated_claim_url),
delegate_(delegate) {
@@ -67,7 +71,9 @@
if (UseOAuth2()) {
OAuth2TokenService::ScopeSet oauth_scopes;
oauth_scopes.insert(cloud_print::kCloudPrintAuth);
- oauth_request_ = token_service_->StartRequest(oauth_scopes, this);
+ oauth_request_ = token_service_->StartRequest(account_id_,
+ oauth_scopes,
+ this);
} else {
GURL cookie_url = url_;
diff --git a/chrome/browser/local_discovery/cloud_print_base_api_flow.h b/chrome/browser/local_discovery/cloud_print_base_api_flow.h
index b60ecf1..64915b2 100644
--- a/chrome/browser/local_discovery/cloud_print_base_api_flow.h
+++ b/chrome/browser/local_discovery/cloud_print_base_api_flow.h
@@ -44,6 +44,7 @@
// Create an OAuth2-based confirmation.
CloudPrintBaseApiFlow(net::URLRequestContextGetter* request_context,
OAuth2TokenService* token_service_,
+ const std::string& account_id,
const GURL& automated_claim_url,
Delegate* delegate);
@@ -89,6 +90,7 @@
scoped_ptr<OAuth2TokenService::Request> oauth_request_;
scoped_refptr<net::URLRequestContextGetter> request_context_;
OAuth2TokenService* token_service_;
+ std::string account_id_;
int user_index_;
std::string xsrf_token_;
GURL url_;
diff --git a/chrome/browser/local_discovery/cloud_print_printer_list.cc b/chrome/browser/local_discovery/cloud_print_printer_list.cc
index f97d881..1f3feea 100644
--- a/chrome/browser/local_discovery/cloud_print_printer_list.cc
+++ b/chrome/browser/local_discovery/cloud_print_printer_list.cc
@@ -18,12 +18,14 @@
net::URLRequestContextGetter* request_context,
const std::string& cloud_print_url,
OAuth2TokenService* token_service,
+ const std::string& account_id,
Delegate* delegate)
: request_context_(request_context),
url_(base::StringPrintf(kPrinterListURLFormat, cloud_print_url.c_str())),
delegate_(delegate),
api_flow_(request_context_,
token_service,
+ account_id,
url_,
this) {
}
diff --git a/chrome/browser/local_discovery/cloud_print_printer_list.h b/chrome/browser/local_discovery/cloud_print_printer_list.h
index 3b9f2f1..95b5aca 100644
--- a/chrome/browser/local_discovery/cloud_print_printer_list.h
+++ b/chrome/browser/local_discovery/cloud_print_printer_list.h
@@ -39,6 +39,7 @@
CloudPrintPrinterList(net::URLRequestContextGetter* request_context,
const std::string& cloud_print_url,
OAuth2TokenService* token_service,
+ const std::string& account_id,
Delegate* delegate);
virtual ~CloudPrintPrinterList();
diff --git a/chrome/browser/local_discovery/cloud_print_printer_list_unittest.cc b/chrome/browser/local_discovery/cloud_print_printer_list_unittest.cc
index a2219f9..3309073 100644
--- a/chrome/browser/local_discovery/cloud_print_printer_list_unittest.cc
+++ b/chrome/browser/local_discovery/cloud_print_printer_list_unittest.cc
@@ -41,7 +41,7 @@
: request_context_(request_context) {
}
protected:
- virtual std::string GetRefreshToken() OVERRIDE {
+ virtual std::string GetRefreshToken(const std::string& account_id) OVERRIDE {
return "SampleToken";
}
@@ -73,6 +73,7 @@
new CloudPrintPrinterList(request_context_.get(),
"http://SoMeUrL.com/cloudprint",
&token_service_,
+ "account_id",
&delegate_));
fallback_fetcher_factory_.reset(new net::TestURLFetcherFactory());
diff --git a/chrome/browser/local_discovery/privet_confirm_api_flow.cc b/chrome/browser/local_discovery/privet_confirm_api_flow.cc
index 4bfbeca..2f42194 100644
--- a/chrome/browser/local_discovery/privet_confirm_api_flow.cc
+++ b/chrome/browser/local_discovery/privet_confirm_api_flow.cc
@@ -12,10 +12,12 @@
PrivetConfirmApiCallFlow::PrivetConfirmApiCallFlow(
net::URLRequestContextGetter* request_context,
OAuth2TokenService* token_service,
+ const std::string& account_id,
const GURL& automated_claim_url,
const ResponseCallback& callback)
: flow_(request_context,
token_service,
+ account_id,
automated_claim_url,
this),
callback_(callback) {
diff --git a/chrome/browser/local_discovery/privet_confirm_api_flow.h b/chrome/browser/local_discovery/privet_confirm_api_flow.h
index 61a6269..9f2ace1 100644
--- a/chrome/browser/local_discovery/privet_confirm_api_flow.h
+++ b/chrome/browser/local_discovery/privet_confirm_api_flow.h
@@ -22,6 +22,7 @@
// Create an OAuth2-based confirmation
PrivetConfirmApiCallFlow(net::URLRequestContextGetter* request_context,
OAuth2TokenService* token_service_,
+ const std::string& account_id,
const GURL& automated_claim_url,
const ResponseCallback& callback);
diff --git a/chrome/browser/local_discovery/privet_confirm_api_flow_unittest.cc b/chrome/browser/local_discovery/privet_confirm_api_flow_unittest.cc
index b8d7b6c..97c2f04 100644
--- a/chrome/browser/local_discovery/privet_confirm_api_flow_unittest.cc
+++ b/chrome/browser/local_discovery/privet_confirm_api_flow_unittest.cc
@@ -5,6 +5,7 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/local_discovery/privet_confirm_api_flow.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
#include "content/public/test/test_browser_thread.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/base/host_port_pair.h"
@@ -33,13 +34,15 @@
" \"success\""
"]";
+const char kAccountId[] = "account_id";
+
class TestOAuth2TokenService : public OAuth2TokenService {
public:
explicit TestOAuth2TokenService(net::URLRequestContextGetter* request_context)
: request_context_(request_context) {
}
protected:
- virtual std::string GetRefreshToken() OVERRIDE {
+ virtual std::string GetRefreshToken(const std::string& account_id) OVERRIDE {
return "SampleToken";
}
@@ -68,7 +71,8 @@
&loop_),
request_context_(new net::TestURLRequestContextGetter(
base::MessageLoopProxy::current())),
- token_service_(request_context_.get()) {
+ token_service_(request_context_.get()),
+ account_id_(kAccountId) {
ui_thread_.Stop(); // HACK: Fake being on the UI thread
}
@@ -82,11 +86,13 @@
net::TestURLFetcherFactory fetcher_factory_;
TestOAuth2TokenService token_service_;
MockableConfirmCallback callback_;
+ std::string account_id_;
};
TEST_F(PrivetConfirmApiFlowTest, SuccessOAuth2) {
PrivetConfirmApiCallFlow confirm_flow(request_context_.get(),
&token_service_,
+ account_id_,
GURL("http://SoMeUrL.com"),
callback_.callback());
CloudPrintBaseApiFlow* cloudprint_flow =
@@ -151,6 +157,7 @@
TEST_F(PrivetConfirmApiFlowTest, BadToken) {
PrivetConfirmApiCallFlow confirm_flow(request_context_.get(),
&token_service_,
+ account_id_,
GURL("http://SoMeUrL.com"),
callback_.callback());
@@ -168,6 +175,7 @@
TEST_F(PrivetConfirmApiFlowTest, ServerFailure) {
PrivetConfirmApiCallFlow confirm_flow(request_context_.get(),
&token_service_,
+ account_id_,
GURL("http://SoMeUrL.com"),
callback_.callback());
@@ -195,6 +203,7 @@
TEST_F(PrivetConfirmApiFlowTest, BadJson) {
PrivetConfirmApiCallFlow confirm_flow(request_context_.get(),
&token_service_,
+ account_id_,
GURL("http://SoMeUrL.com"),
callback_.callback());
diff --git a/chrome/browser/local_discovery/privet_notifications.cc b/chrome/browser/local_discovery/privet_notifications.cc
index 94f68a2..d3829c1 100644
--- a/chrome/browser/local_discovery/privet_notifications.cc
+++ b/chrome/browser/local_discovery/privet_notifications.cc
@@ -5,14 +5,17 @@
#include "chrome/browser/local_discovery/privet_notifications.h"
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/local_discovery/privet_device_lister_impl.h"
#include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h"
#include "chrome/browser/local_discovery/privet_traffic_detector.h"
-#include "chrome/browser/local_discovery/service_discovery_host_client.h"
+#include "chrome/browser/local_discovery/service_discovery_shared_client.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/profiles/profile.h"
@@ -21,6 +24,8 @@
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/web_contents.h"
@@ -29,21 +34,41 @@
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/message_center/message_center_util.h"
#include "ui/message_center/notifier_settings.h"
namespace local_discovery {
namespace {
+
const int kTenMinutesInSeconds = 600;
const char kPrivetInfoKeyUptime[] = "uptime";
-const char kPrivetNotificationIDPrefix[] = "privet_notification:";
+const char kPrivetNotificationID[] = "privet_notification";
const char kPrivetNotificationOriginUrl[] = "chrome://devices";
const int kStartDelaySeconds = 5;
+
+enum PrivetNotificationsEvent {
+ PRIVET_SERVICE_STARTED,
+ PRIVET_LISTER_STARTED,
+ PRIVET_DEVICE_CHANGED,
+ PRIVET_INFO_DONE,
+ PRIVET_NOTIFICATION_SHOWN,
+ PRIVET_NOTIFICATION_CANCELED,
+ PRIVET_NOTIFICATION_CLICKED,
+ PRIVET_DISABLE_NOTIFICATIONS_CLICKED,
+ PRIVET_EVENT_MAX,
+};
+
+void ReportPrivetUmaEvent(PrivetNotificationsEvent privet_event) {
+ UMA_HISTOGRAM_ENUMERATION("LocalDiscovery.PrivetNotificationsEvent",
+ privet_event, PRIVET_EVENT_MAX);
}
+} // namespace
+
PrivetNotificationsListener::PrivetNotificationsListener(
scoped_ptr<PrivetHTTPAsynchronousFactory> privet_http_factory,
- Delegate* delegate) : delegate_(delegate) {
+ Delegate* delegate) : delegate_(delegate), devices_active_(0) {
privet_http_factory_.swap(privet_http_factory);
}
@@ -54,12 +79,13 @@
bool added,
const std::string& name,
const DeviceDescription& description) {
+ ReportPrivetUmaEvent(PRIVET_DEVICE_CHANGED);
DeviceContextMap::iterator found = devices_seen_.find(name);
if (found != devices_seen_.end()) {
if (!description.id.empty() && // Device is registered
found->second->notification_may_be_active) {
found->second->notification_may_be_active = false;
- delegate_->PrivetRemoveNotification(name);
+ NotifyDeviceRemoved();
}
return; // Already saw this device.
}
@@ -68,8 +94,6 @@
device_context->notification_may_be_active = false;
device_context->registered = !description.id.empty();
- device_context->human_readable_name = description.name;
- device_context->description = description.description;
devices_seen_.insert(make_pair(name, device_context));
@@ -101,6 +125,7 @@
PrivetInfoOperation* operation,
int http_code,
const base::DictionaryValue* json_value) {
+ ReportPrivetUmaEvent(PRIVET_INFO_DONE);
std::string name = operation->GetHTTPClient()->GetName();
DeviceContextMap::iterator device_iter = devices_seen_.find(name);
DCHECK(device_iter != devices_seen_.end());
@@ -116,8 +141,8 @@
DCHECK(!device->notification_may_be_active);
device->notification_may_be_active = true;
- delegate_->PrivetNotify(name, device->human_readable_name,
- device->description);
+ devices_active_++;
+ delegate_->PrivetNotify(devices_active_ > 1, true);
}
void PrivetNotificationsListener::DeviceRemoved(const std::string& name) {
@@ -129,7 +154,7 @@
device->info_operation.reset();
device->privet_http_resolution.reset();
device->notification_may_be_active = false;
- delegate_->PrivetRemoveNotification(name);
+ NotifyDeviceRemoved();
}
void PrivetNotificationsListener::DeviceCacheFlushed() {
@@ -141,9 +166,20 @@
device->privet_http_resolution.reset();
if (device->notification_may_be_active) {
device->notification_may_be_active = false;
- delegate_->PrivetRemoveNotification(i->first);
}
}
+
+ devices_active_ = 0;
+ delegate_->PrivetRemoveNotification();
+}
+
+void PrivetNotificationsListener::NotifyDeviceRemoved() {
+ devices_active_--;
+ if (devices_active_ == 0) {
+ delegate_->PrivetRemoveNotification();
+ } else {
+ delegate_->PrivetNotify(devices_active_ > 1, true);
+ }
}
PrivetNotificationsListener::DeviceContext::DeviceContext() {
@@ -180,11 +216,37 @@
privet_notifications_listener_->DeviceCacheFlushed();
}
-void PrivetNotificationService::PrivetNotify(
- const std::string& device_name,
- const std::string& human_readable_name,
- const std::string& description) {
- if (!LocalDiscoveryUIHandler::GetHasVisible()) {
+// static
+bool PrivetNotificationService::IsEnabled() {
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ return !command_line->HasSwitch(switches::kDisableDeviceDiscovery) &&
+ !command_line->HasSwitch(
+ switches::kDisableDeviceDiscoveryNotifications) &&
+ message_center::IsRichNotificationEnabled();
+}
+
+// static
+bool PrivetNotificationService::IsForced() {
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ return command_line->HasSwitch(switches::kEnableDeviceDiscoveryNotifications);
+}
+
+void PrivetNotificationService::PrivetNotify(bool has_multiple,
+ bool added) {
+ string16 product_name = l10n_util::GetStringUTF16(
+ IDS_LOCAL_DISOCVERY_PRODUCT_NAME_PRINTER);
+
+ int title_resource = has_multiple ?
+ IDS_LOCAL_DISOCVERY_NOTIFICATION_TITLE_PRINTER_MULTIPLE :
+ IDS_LOCAL_DISOCVERY_NOTIFICATION_TITLE_PRINTER;
+
+ int body_resource = has_multiple ?
+ IDS_LOCAL_DISOCVERY_NOTIFICATION_CONTENTS_PRINTER_MULTIPLE :
+ IDS_LOCAL_DISOCVERY_NOTIFICATION_CONTENTS_PRINTER;
+
+ string16 title = l10n_util::GetStringUTF16(title_resource);
+ string16 body = l10n_util::GetStringFUTF16(body_resource, product_name);
+
Profile* profile_object = Profile::FromBrowserContext(profile_);
message_center::RichNotificationData rich_notification_data;
@@ -192,56 +254,76 @@
message_center::ButtonInfo(l10n_util::GetStringUTF16(
IDS_LOCAL_DISOCVERY_NOTIFICATION_BUTTON_PRINTER)));
+ rich_notification_data.buttons.push_back(
+ message_center::ButtonInfo(l10n_util::GetStringUTF16(
+ IDS_LOCAL_DISCOVERY_NOTIFICATIONS_DISABLE_BUTTON_LABEL)));
+
Notification notification(
message_center::NOTIFICATION_TYPE_SIMPLE,
GURL(kPrivetNotificationOriginUrl),
- l10n_util::GetStringUTF16(
- IDS_LOCAL_DISOCVERY_NOTIFICATION_TITLE_PRINTER),
- l10n_util::GetStringFUTF16(
- IDS_LOCAL_DISOCVERY_NOTIFICATION_CONTENTS_PRINTER,
- UTF8ToUTF16(human_readable_name)),
+ title,
+ body,
ui::ResourceBundle::GetSharedInstance().GetImageNamed(
IDR_LOCAL_DISCOVERY_CLOUDPRINT_ICON),
WebKit::WebTextDirectionDefault,
message_center::NotifierId(
message_center::NotifierId::SYSTEM_COMPONENT),
- l10n_util::GetStringUTF16(
- IDS_LOCAL_DISOCVERY_NOTIFICATION_DISPLAY_SOURCE_PRINTER),
- UTF8ToUTF16(kPrivetNotificationIDPrefix +
- device_name),
+ product_name,
+ UTF8ToUTF16(kPrivetNotificationID),
rich_notification_data,
- new PrivetNotificationDelegate(device_name, profile_));
+ new PrivetNotificationDelegate(profile_));
- g_browser_process->notification_ui_manager()->Add(notification,
- profile_object);
- }
+ bool updated = g_browser_process->notification_ui_manager()->Update(
+ notification, profile_object);
+ if (!updated && added && !LocalDiscoveryUIHandler::GetHasVisible()) {
+ ReportPrivetUmaEvent(PRIVET_NOTIFICATION_SHOWN);
+ g_browser_process->notification_ui_manager()->Add(notification,
+ profile_object);
+ }
}
-void PrivetNotificationService::PrivetRemoveNotification(
- const std::string& device_name) {
+void PrivetNotificationService::PrivetRemoveNotification() {
+ ReportPrivetUmaEvent(PRIVET_NOTIFICATION_CANCELED);
g_browser_process->notification_ui_manager()->CancelById(
- kPrivetNotificationIDPrefix + device_name);
+ kPrivetNotificationID);
}
void PrivetNotificationService::Start() {
- traffic_detector_v4_ =
- new PrivetTrafficDetector(
- net::ADDRESS_FAMILY_IPV4,
- base::Bind(&PrivetNotificationService::StartLister, AsWeakPtr()));
- traffic_detector_v6_ =
- new PrivetTrafficDetector(
- net::ADDRESS_FAMILY_IPV6,
- base::Bind(&PrivetNotificationService::StartLister, AsWeakPtr()));
+ enable_privet_notification_member_.Init(
+ prefs::kLocalDiscoveryNotificationsEnabled,
+ Profile::FromBrowserContext(profile_)->GetPrefs(),
+ base::Bind(&PrivetNotificationService::OnNotificationsEnabledChanged,
+ base::Unretained(this)));
+ OnNotificationsEnabledChanged();
+}
+
+void PrivetNotificationService::OnNotificationsEnabledChanged() {
+ if (IsForced()) {
+ StartLister();
+ } else if (*enable_privet_notification_member_) {
+ ReportPrivetUmaEvent(PRIVET_SERVICE_STARTED);
+ traffic_detector_ =
+ new PrivetTrafficDetector(
+ net::ADDRESS_FAMILY_IPV4,
+ base::Bind(&PrivetNotificationService::StartLister, AsWeakPtr()));
+ traffic_detector_->Start();
+ } else {
+ traffic_detector_ = NULL;
+ device_lister_.reset();
+ service_discovery_client_ = NULL;
+ privet_notifications_listener_.reset();
+ }
}
void PrivetNotificationService::StartLister() {
- traffic_detector_v4_ = NULL;
- traffic_detector_v6_ = NULL;
+ ReportPrivetUmaEvent(PRIVET_LISTER_STARTED);
+ traffic_detector_ = NULL;
DCHECK(!service_discovery_client_);
service_discovery_client_ = ServiceDiscoverySharedClient::GetInstance();
device_lister_.reset(new PrivetDeviceListerImpl(service_discovery_client_,
this));
device_lister_->Start();
+ device_lister_->DiscoverNewDevices(false);
scoped_ptr<PrivetHTTPAsynchronousFactory> http_factory(
PrivetHTTPAsynchronousFactory::CreateInstance(
@@ -252,15 +334,15 @@
}
PrivetNotificationDelegate::PrivetNotificationDelegate(
- const std::string& device_id, content::BrowserContext* profile)
- : device_id_(device_id), profile_(profile) {
+ content::BrowserContext* profile)
+ : profile_(profile) {
}
PrivetNotificationDelegate::~PrivetNotificationDelegate() {
}
std::string PrivetNotificationDelegate::id() const {
- return kPrivetNotificationIDPrefix + device_id_;
+ return kPrivetNotificationID;
}
content::RenderViewHost* PrivetNotificationDelegate::GetRenderViewHost() const {
@@ -271,7 +353,7 @@
}
void PrivetNotificationDelegate::Error() {
- LOG(ERROR) << "Error displaying privet notification " << device_id_;
+ LOG(ERROR) << "Error displaying privet notification";
}
void PrivetNotificationDelegate::Close(bool by_user) {
@@ -282,8 +364,11 @@
void PrivetNotificationDelegate::ButtonClick(int button_index) {
if (button_index == 0) {
- // TODO(noamsml): Direct-to-register URL
+ ReportPrivetUmaEvent(PRIVET_NOTIFICATION_CLICKED);
OpenTab(GURL(kPrivetNotificationOriginUrl));
+ } else if (button_index == 1) {
+ ReportPrivetUmaEvent(PRIVET_DISABLE_NOTIFICATIONS_CLICKED);
+ DisableNotifications();
}
}
@@ -304,5 +389,12 @@
browser->tab_strip_model()->AppendWebContents(contents.release(), true);
}
+void PrivetNotificationDelegate::DisableNotifications() {
+ Profile* profile_obj = Profile::FromBrowserContext(profile_);
+
+ profile_obj->GetPrefs()->SetBoolean(
+ prefs::kLocalDiscoveryNotificationsEnabled,
+ false);
+}
} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/privet_notifications.h b/chrome/browser/local_discovery/privet_notifications.h
index 27639eb..2877918 100644
--- a/chrome/browser/local_discovery/privet_notifications.h
+++ b/chrome/browser/local_discovery/privet_notifications.h
@@ -8,6 +8,7 @@
#include <map>
#include <string>
+#include "base/prefs/pref_member.h"
#include "chrome/browser/local_discovery/privet_device_lister.h"
#include "chrome/browser/local_discovery/privet_http.h"
#include "chrome/browser/notifications/notification_delegate.h"
@@ -36,12 +37,10 @@
virtual ~Delegate() {}
// Notify user of the existence of device |device_name|.
- virtual void PrivetNotify(const std::string& device_name,
- const std::string& human_readable_name,
- const std::string& description) = 0;
+ virtual void PrivetNotify(bool multiple, bool added) = 0;
// Remove the noitification for |device_name| if it still exists.
- virtual void PrivetRemoveNotification(const std::string& device_name) = 0;
+ virtual void PrivetRemoveNotification() = 0;
};
PrivetNotificationsListener(
@@ -71,8 +70,6 @@
bool notification_may_be_active;
bool registered;
- std::string human_readable_name;
- std::string description;
scoped_ptr<PrivetInfoOperation> info_operation;
scoped_ptr<PrivetHTTPResolution> privet_http_resolution;
scoped_ptr<PrivetHTTPClient> privet_http;
@@ -82,10 +79,13 @@
void CreateInfoOperation(scoped_ptr<PrivetHTTPClient> http_client);
+ void NotifyDeviceRemoved();
+
Delegate* delegate_;
scoped_ptr<PrivetDeviceLister> device_lister_;
scoped_ptr<PrivetHTTPAsynchronousFactory> privet_http_factory_;
DeviceContextMap devices_seen_;
+ int devices_active_;
};
class PrivetNotificationService
@@ -103,30 +103,30 @@
virtual void DeviceRemoved(const std::string& name) OVERRIDE;
// PrivetNotificationListener::Delegate implementation:
- virtual void PrivetNotify(const std::string& device_name,
- const std::string& human_readable_name,
- const std::string& description) OVERRIDE;
+ virtual void PrivetNotify(bool has_multiple, bool added) OVERRIDE;
- virtual void PrivetRemoveNotification(
- const std::string& device_name) OVERRIDE;
+ virtual void PrivetRemoveNotification() OVERRIDE;
virtual void DeviceCacheFlushed() OVERRIDE;
+ static bool IsEnabled();
+ static bool IsForced();
+
private:
void Start();
+ void OnNotificationsEnabledChanged();
void StartLister();
content::BrowserContext* profile_;
scoped_ptr<PrivetDeviceLister> device_lister_;
scoped_refptr<ServiceDiscoverySharedClient> service_discovery_client_;
- scoped_refptr<PrivetTrafficDetector> traffic_detector_v4_;
- scoped_refptr<PrivetTrafficDetector> traffic_detector_v6_;
+ scoped_refptr<PrivetTrafficDetector> traffic_detector_;
scoped_ptr<PrivetNotificationsListener> privet_notifications_listener_;
+ BooleanPrefMember enable_privet_notification_member_;
};
class PrivetNotificationDelegate : public NotificationDelegate {
public:
- explicit PrivetNotificationDelegate(const std::string& device_id,
- content::BrowserContext* profile);
+ explicit PrivetNotificationDelegate(content::BrowserContext* profile);
// NotificationDelegate implementation.
virtual std::string id() const OVERRIDE;
@@ -139,10 +139,10 @@
private:
void OpenTab(const GURL& url);
+ void DisableNotifications();
virtual ~PrivetNotificationDelegate();
- std::string device_id_;
content::BrowserContext* profile_;
};
diff --git a/chrome/browser/local_discovery/privet_notifications_factory.cc b/chrome/browser/local_discovery/privet_notifications_factory.cc
index f37edcd..7c3bdf4 100644
--- a/chrome/browser/local_discovery/privet_notifications_factory.cc
+++ b/chrome/browser/local_discovery/privet_notifications_factory.cc
@@ -4,10 +4,8 @@
#include "chrome/browser/local_discovery/privet_notifications_factory.h"
-#include "base/command_line.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/local_discovery/privet_notifications.h"
-#include "chrome/common/chrome_switches.h"
#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
namespace local_discovery {
@@ -34,11 +32,7 @@
bool
PrivetNotificationServiceFactory::ServiceIsCreatedWithBrowserContext() const {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- using switches::kDisableDeviceDiscovery;
- using switches::kDisableDeviceDiscoveryNotifications;
- return !command_line->HasSwitch(kDisableDeviceDiscovery) &&
- !command_line->HasSwitch(kDisableDeviceDiscoveryNotifications);
+ return PrivetNotificationService::IsEnabled();
}
bool PrivetNotificationServiceFactory::ServiceIsNULLWhileTesting() const {
diff --git a/chrome/browser/local_discovery/privet_notifications_unittest.cc b/chrome/browser/local_discovery/privet_notifications_unittest.cc
index 2c89289..01ecbd2 100644
--- a/chrome/browser/local_discovery/privet_notifications_unittest.cc
+++ b/chrome/browser/local_discovery/privet_notifications_unittest.cc
@@ -25,10 +25,8 @@
class MockPrivetNotificationsListenerDeleagate
: public PrivetNotificationsListener::Delegate {
public:
- MOCK_METHOD3(PrivetNotify, void(const std::string& device_name,
- const std::string& human_readable_name,
- const std::string& description));
- MOCK_METHOD1(PrivetRemoveNotification, void(const std::string& device_name));
+ MOCK_METHOD2(PrivetNotify, void(bool multiple, bool added));
+ MOCK_METHOD0(PrivetRemoveNotification, void());
};
class MockPrivetInfoOperation : public PrivetInfoOperation {
@@ -178,9 +176,8 @@
ExpectInfoOperation();
EXPECT_CALL(mock_delegate_, PrivetNotify(
- kExampleDeviceName,
- kExampleDeviceHumanName,
- kExampleDeviceDescription));
+ false,
+ true));
notification_listener_->DeviceChanged(
true,
@@ -194,8 +191,7 @@
info_operation_->delegate()->OnPrivetInfoDone(info_operation_,
200, &value);
- EXPECT_CALL(mock_delegate_, PrivetRemoveNotification(
- kExampleDeviceName));
+ EXPECT_CALL(mock_delegate_, PrivetRemoveNotification());
notification_listener_->DeviceRemoved(
kExampleDeviceName);
@@ -217,9 +213,8 @@
ExpectInfoOperation();
EXPECT_CALL(mock_delegate_, PrivetNotify(
- kExampleDeviceName,
- kExampleDeviceHumanName,
- kExampleDeviceDescription));
+ false,
+ true));
notification_listener_->DeviceChanged(
true,
@@ -233,8 +228,7 @@
info_operation_->delegate()->OnPrivetInfoDone(info_operation_,
200, &value);
- EXPECT_CALL(mock_delegate_, PrivetRemoveNotification(
- kExampleDeviceName));
+ EXPECT_CALL(mock_delegate_, PrivetRemoveNotification());
description_.id = kExampleDeviceID;
diff --git a/chrome/browser/local_discovery/privet_traffic_detector.cc b/chrome/browser/local_discovery/privet_traffic_detector.cc
index 6d92cb5..5bca644 100644
--- a/chrome/browser/local_discovery/privet_traffic_detector.cc
+++ b/chrome/browser/local_discovery/privet_traffic_detector.cc
@@ -4,8 +4,8 @@
#include "chrome/browser/local_discovery/privet_traffic_detector.h"
+#include "base/metrics/histogram.h"
#include "base/sys_byteorder.h"
-#include "chrome/browser/local_discovery/privet_constants.h"
#include "net/base/dns_util.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
@@ -16,9 +16,37 @@
#include "net/udp/udp_server_socket.h"
namespace {
-const char kPrivetDefaultDev2iceType[] = "\x07_privet\x04_tcp\x05local";
+
+const int kMaxRestartAttempts = 10;
+const char kPrivetDeviceTypeDnsString[] = "\x07_privet\x04_tcp\x05local";
+
+void GetNetworkListOnFileThread(
+ const base::Callback<void(const net::NetworkInterfaceList&)> callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ net::NetworkInterfaceList networks;
+ if (!GetNetworkList(&networks))
+ return;
+
+ net::NetworkInterfaceList ip4_networks;
+ for (size_t i = 0; i < networks.size(); ++i) {
+ net::AddressFamily address_family =
+ net::GetAddressFamily(networks[i].address);
+ if (address_family == net::ADDRESS_FAMILY_IPV4)
+ ip4_networks.push_back(networks[i]);
+ }
+
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(callback, ip4_networks));
}
+bool IsIpPrefixEqual(const net::IPAddressNumber& ip1,
+ const net::IPAddressNumber& ip2) {
+ return !ip1.empty() && ip1.size() == ip2.size() &&
+ std::equal(ip1.begin(), ip1.end() - 1, ip2.begin());
+}
+
+} // namespace
+
namespace local_discovery {
PrivetTrafficDetector::PrivetTrafficDetector(
@@ -27,12 +55,18 @@
: on_traffic_detected_(on_traffic_detected),
callback_runner_(base::MessageLoop::current()->message_loop_proxy()),
address_family_(address_family),
- recv_addr_(new net::IPEndPoint),
io_buffer_(
- new net::IOBufferWithSize(net::dns_protocol::kMaxMulticastSize)) {
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&PrivetTrafficDetector::Start,
- this));
+ new net::IOBufferWithSize(net::dns_protocol::kMaxMulticastSize)),
+ restart_attempts_(kMaxRestartAttempts),
+ weak_ptr_factory_(this) {
+}
+
+void PrivetTrafficDetector::Start() {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&PrivetTrafficDetector::StartOnIOThread,
+ weak_ptr_factory_.GetWeakPtr()));
}
PrivetTrafficDetector::~PrivetTrafficDetector() {
@@ -40,7 +74,7 @@
net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
}
-void PrivetTrafficDetector::Start() {
+void PrivetTrafficDetector::StartOnIOThread() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
ScheduleRestart();
@@ -49,6 +83,7 @@
void PrivetTrafficDetector::OnNetworkChanged(
net::NetworkChangeNotifier::ConnectionType type) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ restart_attempts_ = kMaxRestartAttempts;
if (type != net::NetworkChangeNotifier::CONNECTION_NONE)
ScheduleRestart();
}
@@ -56,22 +91,34 @@
void PrivetTrafficDetector::ScheduleRestart() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
socket_.reset();
- restart_callback_.Reset(
- base::Bind(&PrivetTrafficDetector::Restart, base::Unretained(this)));
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- restart_callback_.callback(),
- base::TimeDelta::FromSeconds(1));
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ content::BrowserThread::PostDelayedTask(
+ content::BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&GetNetworkListOnFileThread,
+ base::Bind(&PrivetTrafficDetector::Restart,
+ weak_ptr_factory_.GetWeakPtr())),
+ base::TimeDelta::FromSeconds(3));
}
-void PrivetTrafficDetector::Restart() {
+void PrivetTrafficDetector::Restart(const net::NetworkInterfaceList& networks) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ networks_ = networks;
if (Bind() < net::OK || DoLoop(0) < net::OK) {
- ScheduleRestart();
+ if ((restart_attempts_--) > 0)
+ ScheduleRestart();
+ } else {
+ // Reset on success.
+ restart_attempts_ = kMaxRestartAttempts;
}
}
int PrivetTrafficDetector::Bind() {
+ if (!start_time_.is_null()) {
+ base::TimeDelta time_delta = base::Time::Now() - start_time_;
+ UMA_HISTOGRAM_LONG_TIMES("LocaDiscovery.DetectorRestartTime", time_delta);
+ }
+ start_time_ = base::Time::Now();
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
socket_.reset(new net::UDPServerSocket(NULL, net::NetLog::Source()));
net::IPEndPoint multicast_addr = net::GetMDnsIPEndPoint(address_family_);
@@ -85,33 +132,50 @@
return socket_->JoinGroup(multicast_addr.address());
}
+bool PrivetTrafficDetector::IsSourceAcceptable() const {
+ for (size_t i = 0; i < networks_.size(); ++i) {
+ if (IsIpPrefixEqual(recv_addr_.address(), networks_[i].address))
+ return true;
+ }
+ return false;
+}
+
+bool PrivetTrafficDetector::IsPrivetPacket(int rv) const {
+ if (rv <= static_cast<int>(sizeof(net::dns_protocol::Header)) ||
+ !IsSourceAcceptable()) {
+ return false;
+ }
+
+ const char* buffer_begin = io_buffer_->data();
+ const char* buffer_end = buffer_begin + rv;
+ const net::dns_protocol::Header* header =
+ reinterpret_cast<const net::dns_protocol::Header*>(buffer_begin);
+ // Check if response packet.
+ if (!(header->flags & base::HostToNet16(net::dns_protocol::kFlagResponse)))
+ return false;
+ const char* substring_begin = kPrivetDeviceTypeDnsString;
+ const char* substring_end = substring_begin +
+ arraysize(kPrivetDeviceTypeDnsString);
+ // Check for expected substring, any Privet device must include this.
+ return std::search(buffer_begin, buffer_end, substring_begin,
+ substring_end) != buffer_end;
+}
+
int PrivetTrafficDetector::DoLoop(int rv) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
do {
- if (rv > static_cast<int>(sizeof(net::dns_protocol::Header))) {
- const char* buffer_begin = io_buffer_->data();
- const char* buffer_end = buffer_begin + rv;
- const net::dns_protocol::Header* header =
- reinterpret_cast<const net::dns_protocol::Header*>(buffer_begin);
- // Check if it's response packet.
- if (header->flags & base::HostToNet16(net::dns_protocol::kFlagResponse)) {
- const char* substring_begin = kPrivetDefaultDev2iceType;
- const char* substring_end = substring_begin +
- arraysize(kPrivetDefaultDev2iceType);
- // Check for expected substring, any Privet device must include this.
- if (std::search(buffer_begin, buffer_end,
- substring_begin, substring_end) != buffer_end) {
- socket_.reset();
- callback_runner_->PostTask(FROM_HERE, on_traffic_detected_);
- return net::OK;
- }
- }
+ if (IsPrivetPacket(rv)) {
+ socket_.reset();
+ callback_runner_->PostTask(FROM_HERE, on_traffic_detected_);
+ base::TimeDelta time_delta = base::Time::Now() - start_time_;
+ UMA_HISTOGRAM_LONG_TIMES("LocaDiscovery.DetectorTriggerTime", time_delta);
+ return net::OK;
}
rv = socket_->RecvFrom(
io_buffer_,
io_buffer_->size(),
- recv_addr_.get(),
+ &recv_addr_,
base::Bind(base::IgnoreResult(&PrivetTrafficDetector::DoLoop),
base::Unretained(this)));
} while (rv > 0);
diff --git a/chrome/browser/local_discovery/privet_traffic_detector.h b/chrome/browser/local_discovery/privet_traffic_detector.h
index 85a7d4e..1cbf3fb 100644
--- a/chrome/browser/local_discovery/privet_traffic_detector.h
+++ b/chrome/browser/local_discovery/privet_traffic_detector.h
@@ -9,12 +9,12 @@
#include "base/cancelable_callback.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/address_family.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/network_change_notifier.h"
namespace net {
class DatagramServerSocket;
class IOBufferWithSize;
-class IPEndPoint;
}
namespace local_discovery {
@@ -31,6 +31,8 @@
PrivetTrafficDetector(net::AddressFamily address_family,
const base::Closure& on_traffic_detected);
+ void Start();
+
private:
friend struct content::BrowserThread::DeleteOnThread<
content::BrowserThread::IO>;
@@ -41,19 +43,25 @@
virtual void OnNetworkChanged(
net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
- void Start();
+ void StartOnIOThread();
void ScheduleRestart();
- void Restart();
+ void Restart(const net::NetworkInterfaceList& networks);
int Bind();
+ bool IsSourceAcceptable() const;
+ bool IsPrivetPacket(int rv) const;
int DoLoop(int rv);
base::Closure on_traffic_detected_;
scoped_refptr<base::TaskRunner> callback_runner_;
+ net::NetworkInterfaceList networks_;
net::AddressFamily address_family_;
- scoped_ptr<net::IPEndPoint> recv_addr_;
+ net::IPEndPoint recv_addr_;
scoped_ptr<net::DatagramServerSocket> socket_;
scoped_refptr<net::IOBufferWithSize> io_buffer_;
- base::CancelableClosure restart_callback_;
+ base::Time start_time_;
+ int restart_attempts_;
+
+ base::WeakPtrFactory<PrivetTrafficDetector> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PrivetTrafficDetector);
};
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac.h b/chrome/browser/local_discovery/service_discovery_client_mac.h
new file mode 100644
index 0000000..55841ba
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_mac.h
@@ -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.
+
+#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_H_
+#define CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_H_
+
+#include <string>
+
+#include "base/mac/scoped_nsobject.h"
+#include "chrome/browser/local_discovery/service_discovery_shared_client.h"
+
+namespace local_discovery {
+
+// Implementation of ServiceDiscoveryClient that uses the Bonjour SDK.
+// https://developer.apple.com/library/mac/documentation/Networking/Conceptual/
+// NSNetServiceProgGuide/Articles/BrowsingForServices.html
+class ServiceDiscoveryClientMac : public ServiceDiscoverySharedClient {
+ public:
+ ServiceDiscoveryClientMac();
+
+ private:
+ virtual ~ServiceDiscoveryClientMac();
+
+ // ServiceDiscoveryClient implementation.
+ virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher(
+ const std::string& service_type,
+ const ServiceWatcher::UpdatedCallback& callback) OVERRIDE;
+ virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
+ const std::string& service_name,
+ const ServiceResolver::ResolveCompleteCallback& callback) OVERRIDE;
+ virtual scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver(
+ const std::string& domain,
+ net::AddressFamily address_family,
+ const LocalDomainResolver::IPAddressCallback& callback) OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceDiscoveryClientMac);
+};
+
+class ServiceWatcherImplMac : public ServiceWatcher {
+ public:
+ ServiceWatcherImplMac(const std::string& service_type,
+ const ServiceWatcher::UpdatedCallback& callback);
+
+ void OnServicesUpdate(ServiceWatcher::UpdateType update,
+ const std::string& service);
+
+ private:
+ virtual ~ServiceWatcherImplMac();
+
+ virtual void Start() OVERRIDE;
+ virtual void DiscoverNewServices(bool force_update) OVERRIDE;
+ virtual std::string GetServiceType() const OVERRIDE;
+
+ std::string service_type_;
+
+ ServiceWatcher::UpdatedCallback callback_;
+ bool started_;
+ base::scoped_nsobject<id> delegate_;
+ base::scoped_nsobject<NSNetServiceBrowser> browser_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWatcherImplMac);
+};
+
+class ServiceResolverImplMac : public ServiceResolver {
+ public:
+ ServiceResolverImplMac(
+ const std::string& service_name,
+ const ServiceResolver::ResolveCompleteCallback& callback);
+
+ void OnResolveUpdate(RequestStatus);
+
+ // Testing methods.
+ void SetServiceForTesting(
+ base::scoped_nsobject<NSNetService> service);
+
+ private:
+ virtual ~ServiceResolverImplMac();
+
+ virtual void StartResolving() OVERRIDE;
+ virtual std::string GetName() const OVERRIDE;
+
+ const std::string service_name_;
+ ServiceResolver::ResolveCompleteCallback callback_;
+ bool has_resolved_;
+ base::scoped_nsobject<id> delegate_;
+ base::scoped_nsobject<NSNetService> service_;
+ ServiceDescription service_description_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceResolverImplMac);
+};
+
+} // namespace local_discovery
+
+#endif // CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_H_
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac.mm b/chrome/browser/local_discovery/service_discovery_client_mac.mm
new file mode 100644
index 0000000..bca3ade
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_mac.mm
@@ -0,0 +1,312 @@
+// Copyright 2013 The Chromium 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_mac.h"
+
+#import <Foundation/Foundation.h>
+#import <arpa/inet.h>
+#import <net/if_dl.h>
+
+#include "base/memory/singleton.h"
+
+using local_discovery::ServiceWatcherImplMac;
+using local_discovery::ServiceResolverImplMac;
+
+@interface NetServiceBrowserDelegate
+ : NSObject<NSNetServiceBrowserDelegate, NSNetServiceDelegate> {
+ @private
+ ServiceWatcherImplMac* serviceWatcherImpl_; // weak.
+ base::scoped_nsobject<NSMutableArray> services_;
+}
+
+- (id)initWithServiceWatcher:(ServiceWatcherImplMac*)serviceWatcherImpl;
+
+@end
+
+@interface NetServiceDelegate : NSObject <NSNetServiceDelegate> {
+ @private
+ ServiceResolverImplMac* serviceResolverImpl_;
+}
+
+-(id) initWithServiceResolver:(ServiceResolverImplMac*)serviceResolverImpl;
+
+@end
+
+namespace local_discovery {
+
+namespace {
+
+const NSTimeInterval kResolveTimeout = 10.0;
+
+// Extracts the instance name, name type and domain from a full service name or
+// the service type and domain from a service type. Returns true if successful.
+// TODO(justinlin): This current only handles service names with format
+// <name>._<protocol2>._<protocol1>.<domain>. Service names with
+// subtypes will not parse correctly:
+// <name>._<type>._<sub>._<protocol2>._<protocol1>.<domain>.
+bool ExtractServiceInfo(const std::string& service,
+ bool is_service_name,
+ std::string* instance,
+ std::string* type,
+ std::string* domain) {
+ if (service.empty())
+ return false;
+
+ const size_t last_period = service.find_last_of('.');
+ if (last_period == std::string::npos || service.length() <= last_period)
+ return false;
+
+ if (!is_service_name) {
+ *instance = std::string();
+ *type = service.substr(0, last_period) + ".";
+ } else {
+ // Find third last period that delimits type and instance name.
+ size_t type_period = last_period;
+ for (int i = 0; i < 2; ++i) {
+ type_period = service.find_last_of('.', type_period - 1);
+ if (type_period == std::string::npos)
+ return false;
+ }
+
+ *instance = service.substr(0, type_period);
+ *type = service.substr(type_period + 1, last_period - type_period);
+ }
+ *domain = service.substr(last_period + 1) + ".";
+
+ return !domain->empty() &&
+ !type->empty() &&
+ (!is_service_name || !instance->empty());
+}
+
+void ParseTxtRecord(NSData* record, std::vector<std::string>* output) {
+ if (record == nil || [record length] <= 1)
+ return;
+
+ const uint8* record_bytes = reinterpret_cast<const uint8*>([record bytes]);
+ const uint8* const record_end = record_bytes + [record length];
+ // TODO(justinlin): More strict bounds checking.
+ while (record_bytes < record_end) {
+ uint8 size = *record_bytes++;
+ if (size <= 0)
+ continue;
+
+ if (record_bytes + size <= record_end) {
+ output->push_back(
+ [[[NSString alloc] initWithBytes:record_bytes
+ length:size
+ encoding:NSUTF8StringEncoding] UTF8String]);
+ }
+ record_bytes += size;
+ }
+}
+
+} // namespace
+
+ServiceDiscoveryClientMac::ServiceDiscoveryClientMac() {}
+ServiceDiscoveryClientMac::~ServiceDiscoveryClientMac() {}
+
+scoped_ptr<ServiceWatcher> ServiceDiscoveryClientMac::CreateServiceWatcher(
+ const std::string& service_type,
+ const ServiceWatcher::UpdatedCallback& callback) {
+ return scoped_ptr<ServiceWatcher>(new ServiceWatcherImplMac(service_type,
+ callback));
+}
+
+scoped_ptr<ServiceResolver> ServiceDiscoveryClientMac::CreateServiceResolver(
+ const std::string& service_name,
+ const ServiceResolver::ResolveCompleteCallback& callback) {
+ return scoped_ptr<ServiceResolver>(new ServiceResolverImplMac(service_name,
+ callback));
+}
+
+scoped_ptr<LocalDomainResolver>
+ServiceDiscoveryClientMac::CreateLocalDomainResolver(
+ const std::string& domain,
+ net::AddressFamily address_family,
+ const LocalDomainResolver::IPAddressCallback& callback) {
+ NOTIMPLEMENTED(); // TODO(justinlin): Implement.
+ return scoped_ptr<LocalDomainResolver>();
+}
+
+ServiceWatcherImplMac::ServiceWatcherImplMac(
+ const std::string& service_type,
+ const ServiceWatcher::UpdatedCallback& callback)
+ : service_type_(service_type), callback_(callback), started_(false) {}
+
+ServiceWatcherImplMac::~ServiceWatcherImplMac() {}
+
+void ServiceWatcherImplMac::Start() {
+ DCHECK(!started_);
+ delegate_.reset([[NetServiceBrowserDelegate alloc]
+ initWithServiceWatcher:this]);
+ browser_.reset([[NSNetServiceBrowser alloc] init]);
+ [browser_ setDelegate:delegate_];
+ started_ = true;
+}
+
+// TODO(justinlin): Implement flushing DNS cache to respect parameter.
+void ServiceWatcherImplMac::DiscoverNewServices(bool force_update) {
+ DCHECK(started_);
+
+ std::string instance;
+ std::string type;
+ std::string domain;
+
+ if (!ExtractServiceInfo(service_type_, false, &instance, &type, &domain))
+ return;
+
+ DCHECK(instance.empty());
+ DVLOG(1) << "Listening for service type '" << type
+ << "' on domain '" << domain << "'";
+
+ [browser_ searchForServicesOfType:[NSString stringWithUTF8String:type.c_str()]
+ inDomain:[NSString stringWithUTF8String:domain.c_str()]];
+}
+
+std::string ServiceWatcherImplMac::GetServiceType() const {
+ return service_type_;
+}
+
+void ServiceWatcherImplMac::OnServicesUpdate(ServiceWatcher::UpdateType update,
+ const std::string& service) {
+ callback_.Run(update, service + "." + service_type_);
+}
+
+ServiceResolverImplMac::ServiceResolverImplMac(
+ const std::string& service_name,
+ const ServiceResolver::ResolveCompleteCallback& callback)
+ : service_name_(service_name), callback_(callback), has_resolved_(false) {
+ std::string instance;
+ std::string type;
+ std::string domain;
+
+ if (ExtractServiceInfo(service_name, true, &instance, &type, &domain)) {
+ delegate_.reset([[NetServiceDelegate alloc] initWithServiceResolver:this]);
+ service_.reset(
+ [[NSNetService alloc]
+ initWithDomain:[[NSString alloc] initWithUTF8String:domain.c_str()]
+ type:[[NSString alloc] initWithUTF8String:type.c_str()]
+ name:[[NSString alloc] initWithUTF8String:instance.c_str()]]);
+ [service_ setDelegate:delegate_];
+ }
+}
+
+ServiceResolverImplMac::~ServiceResolverImplMac() {}
+
+void ServiceResolverImplMac::StartResolving() {
+ if (!service_.get())
+ return;
+
+ DVLOG(1) << "Resolving service " << service_name_;
+ [service_ resolveWithTimeout:kResolveTimeout];
+}
+
+std::string ServiceResolverImplMac::GetName() const {
+ return service_name_;
+}
+
+void ServiceResolverImplMac::OnResolveUpdate(RequestStatus status) {
+ if (status == STATUS_SUCCESS) {
+ service_description_.service_name = service_name_;
+
+ for (NSData* address in [service_ addresses]) {
+ const void* bytes = [address bytes];
+ // TODO(justinlin): Handle IPv6 addresses?
+ if (static_cast<const sockaddr*>(bytes)->sa_family == AF_INET) {
+ const sockaddr_in* sock = static_cast<const sockaddr_in*>(bytes);
+ char addr[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &sock->sin_addr, addr, INET_ADDRSTRLEN);
+ service_description_.address =
+ net::HostPortPair(addr, ntohs(sock->sin_port));
+ net::ParseIPLiteralToNumber(addr, &service_description_.ip_address);
+ break;
+ }
+ }
+
+ ParseTxtRecord([service_ TXTRecordData], &service_description_.metadata);
+
+ // TODO(justinlin): Implement last_seen.
+ service_description_.last_seen = base::Time::Now();
+ callback_.Run(status, service_description_);
+ } else {
+ callback_.Run(status, ServiceDescription());
+ }
+ has_resolved_ = true;
+}
+
+void ServiceResolverImplMac::SetServiceForTesting(
+ base::scoped_nsobject<NSNetService> service) {
+ service_ = service;
+}
+
+} // namespace local_discovery
+
+@implementation NetServiceBrowserDelegate
+
+- (id)initWithServiceWatcher:(ServiceWatcherImplMac*)serviceWatcherImpl {
+ if ((self = [super init])) {
+ serviceWatcherImpl_ = serviceWatcherImpl;
+ services_.reset([[NSMutableArray alloc] initWithCapacity:1]);
+ }
+ return self;
+}
+
+- (void)netServiceBrowser:(NSNetServiceBrowser *)netServiceBrowser
+ didFindService:(NSNetService *)netService
+ moreComing:(BOOL)moreServicesComing {
+ // Start monitoring this service for updates.
+ [netService setDelegate:self];
+ [netService startMonitoring];
+ [services_ addObject:netService];
+
+ serviceWatcherImpl_->OnServicesUpdate(
+ local_discovery::ServiceWatcher::UPDATE_ADDED,
+ [[netService name] UTF8String]);
+}
+
+- (void)netServiceBrowser:(NSNetServiceBrowser *)netServiceBrowser
+ didRemoveService:(NSNetService *)netService
+ moreComing:(BOOL)moreServicesComing {
+ serviceWatcherImpl_->OnServicesUpdate(
+ local_discovery::ServiceWatcher::UPDATE_REMOVED,
+ [[netService name] UTF8String]);
+
+ NSUInteger index = [services_ indexOfObject:netService];
+ if (index != NSNotFound) {
+ // Stop monitoring this service for updates.
+ [[services_ objectAtIndex:index] stopMonitoring];
+ [services_ removeObjectAtIndex:index];
+ }
+}
+
+- (void)netService:(NSNetService *)sender
+ didUpdateTXTRecordData:(NSData *)data {
+ serviceWatcherImpl_->OnServicesUpdate(
+ local_discovery::ServiceWatcher::UPDATE_CHANGED,
+ [[sender name] UTF8String]);
+}
+
+@end
+
+@implementation NetServiceDelegate
+
+-(id) initWithServiceResolver:(ServiceResolverImplMac*)serviceResolverImpl {
+ if ((self = [super init])) {
+ serviceResolverImpl_ = serviceResolverImpl;
+ }
+ return self;
+}
+
+- (void)netServiceDidResolveAddress:(NSNetService *)sender {
+ serviceResolverImpl_->OnResolveUpdate(
+ local_discovery::ServiceResolver::STATUS_SUCCESS);
+}
+
+- (void)netService:(NSNetService *)sender
+ didNotResolve:(NSDictionary *)errorDict {
+ serviceResolverImpl_->OnResolveUpdate(
+ local_discovery::ServiceResolver::STATUS_REQUEST_TIMEOUT);
+}
+
+@end
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac_factory.h b/chrome/browser/local_discovery/service_discovery_client_mac_factory.h
new file mode 100644
index 0000000..68c77f7
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_mac_factory.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_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_FACTORY_H_
+#define CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_FACTORY_H_
+
+#include "chrome/browser/local_discovery/service_discovery_shared_client.h"
+
+namespace local_discovery {
+
+class ServiceDiscoveryClientMacFactory {
+ public:
+ static scoped_refptr<ServiceDiscoverySharedClient> CreateInstance();
+
+ private:
+ ServiceDiscoveryClientMacFactory() {}
+ virtual ~ServiceDiscoveryClientMacFactory() {}
+};
+
+} // namespace local_discovery
+
+#endif // CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_FACTORY_H_
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac_factory.mm b/chrome/browser/local_discovery/service_discovery_client_mac_factory.mm
new file mode 100644
index 0000000..331969e
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_mac_factory.mm
@@ -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/browser/local_discovery/service_discovery_client_mac_factory.h"
+
+#include "chrome/browser/local_discovery/service_discovery_client_mac.h"
+
+namespace local_discovery {
+
+// static
+scoped_refptr<ServiceDiscoverySharedClient>
+ServiceDiscoveryClientMacFactory::CreateInstance() {
+ return new ServiceDiscoveryClientMac();
+}
+
+} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm b/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm
new file mode 100644
index 0000000..b09b5d8
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm
@@ -0,0 +1,126 @@
+// Copyright 2013 The Chromium 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 <Cocoa/Cocoa.h>
+
+#include "base/bind.h"
+#include "base/mac/scoped_nsobject.h"
+#include "chrome/common/local_discovery/service_discovery_client.h"
+#include "chrome/browser/local_discovery/service_discovery_client_mac.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "testing/gtest_mac.h"
+
+@interface TestNSNetService : NSNetService {
+ @private
+ NSData* data_;
+}
+- (id) initWithData:(NSData *)data;
+@end
+
+@implementation TestNSNetService
+
+-(id) initWithData:(NSData *)data {
+ if ((self = [super init])) {
+ data_ = data;
+ }
+ return self;
+}
+
+- (NSArray *)addresses {
+ return [NSMutableArray array];
+}
+
+- (NSData *)TXTRecordData {
+ return data_;
+}
+
+@end
+
+namespace local_discovery {
+
+class ServiceDiscoveryClientMacTest : public CocoaTest {
+ public:
+ ServiceDiscoveryClientMacTest() : num_updates_(0), num_resolves_(0) {
+ client_mac_ = new ServiceDiscoveryClientMac();
+ client_ = client_mac_;
+ }
+
+ void OnServiceUpdated(
+ ServiceWatcher::UpdateType update,
+ const std::string& service_name) {
+ last_update_ = update;
+ last_service_name_ = service_name;
+ num_updates_++;
+ }
+
+
+ void OnResolveComplete(
+ ServiceResolver::RequestStatus status,
+ const ServiceDescription& service_description) {
+ last_status_ = status;
+ last_service_description_ = service_description;
+ num_resolves_++;
+ }
+
+ protected:
+ scoped_refptr<ServiceDiscoveryClientMac> client_mac_;
+ ServiceDiscoveryClient* client_; // weak
+
+ ServiceWatcher::UpdateType last_update_;
+ std::string last_service_name_;
+ int num_updates_;
+ ServiceResolver::RequestStatus last_status_;
+ ServiceDescription last_service_description_;
+ int num_resolves_;
+};
+
+TEST_F(ServiceDiscoveryClientMacTest, ServiceWatcher) {
+ const std::string test_service_type = "_testing._tcp.local";
+ const std::string test_service_name = "Test.123";
+
+ scoped_ptr<ServiceWatcher> watcher = client_->CreateServiceWatcher(
+ test_service_type,
+ base::Bind(&ServiceDiscoveryClientMacTest::OnServiceUpdated,
+ base::Unretained(this)));
+ watcher->Start();
+
+ // Weak pointer to implementation class.
+ ServiceWatcherImplMac* watcher_impl =
+ static_cast<ServiceWatcherImplMac*>(watcher.get());
+ // Simulate service update events.
+ watcher_impl->OnServicesUpdate(
+ ServiceWatcher::UPDATE_ADDED, test_service_name);
+ watcher_impl->OnServicesUpdate(
+ ServiceWatcher::UPDATE_CHANGED, test_service_name);
+ watcher_impl->OnServicesUpdate(
+ ServiceWatcher::UPDATE_REMOVED, test_service_name);
+ EXPECT_EQ(last_service_name_, test_service_name + "." + test_service_type);
+ EXPECT_EQ(num_updates_, 3);
+}
+
+TEST_F(ServiceDiscoveryClientMacTest, ServiceResolver) {
+ const std::string test_service_name = "Test.123._testing._tcp.local";
+ scoped_ptr<ServiceResolver> resolver = client_->CreateServiceResolver(
+ test_service_name,
+ base::Bind(&ServiceDiscoveryClientMacTest::OnResolveComplete,
+ base::Unretained(this)));
+ resolver->StartResolving();
+
+ const uint8 record_bytes[] = { 2, 'a', 'b', 3, 'd', '=', 'e' };
+ base::scoped_nsobject<NSNetService> test_service(
+ [[TestNSNetService alloc] initWithData:
+ [[NSData alloc] initWithBytes:record_bytes
+ length:arraysize(record_bytes)]]);
+
+ // Weak pointer to implementation class.
+ ServiceResolverImplMac* resolver_impl =
+ static_cast<ServiceResolverImplMac*>(resolver.get());
+ resolver_impl->SetServiceForTesting(test_service);
+ resolver_impl->OnResolveUpdate(ServiceResolver::STATUS_SUCCESS);
+
+ EXPECT_EQ(num_resolves_, 1);
+ EXPECT_EQ(last_service_description_.metadata.size(), 2u);
+}
+
+} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/service_discovery_client_mdns.cc b/chrome/browser/local_discovery/service_discovery_client_mdns.cc
new file mode 100644
index 0000000..bb81b55
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_mdns.cc
@@ -0,0 +1,93 @@
+// Copyright 2013 The Chromium 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_mdns.h"
+
+#include "chrome/browser/local_discovery/service_discovery_host_client.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace local_discovery {
+
+using content::BrowserThread;
+
+namespace {
+const int kMaxRestartAttempts = 10;
+const int kRestartDelayOnNetworkChangeSeconds = 3;
+}
+
+scoped_ptr<ServiceWatcher> ServiceDiscoveryClientMdns::CreateServiceWatcher(
+ const std::string& service_type,
+ const ServiceWatcher::UpdatedCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ return host_client_->CreateServiceWatcher(service_type, callback);
+}
+
+scoped_ptr<ServiceResolver> ServiceDiscoveryClientMdns::CreateServiceResolver(
+ const std::string& service_name,
+ const ServiceResolver::ResolveCompleteCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ return host_client_->CreateServiceResolver(service_name, callback);
+}
+
+scoped_ptr<LocalDomainResolver>
+ServiceDiscoveryClientMdns::CreateLocalDomainResolver(
+ const std::string& domain,
+ net::AddressFamily address_family,
+ const LocalDomainResolver::IPAddressCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ return host_client_->CreateLocalDomainResolver(domain, address_family,
+ callback);
+}
+
+ServiceDiscoveryClientMdns::ServiceDiscoveryClientMdns()
+ : restart_attempts_(kMaxRestartAttempts),
+ weak_ptr_factory_(this) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
+ StartNewClient();
+}
+
+ServiceDiscoveryClientMdns::~ServiceDiscoveryClientMdns() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
+ host_client_->Shutdown();
+}
+
+void ServiceDiscoveryClientMdns::OnNetworkChanged(
+ net::NetworkChangeNotifier::ConnectionType type) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Only network changes resets kMaxRestartAttempts.
+ restart_attempts_ = kMaxRestartAttempts;
+ ScheduleStartNewClient();
+}
+
+void ServiceDiscoveryClientMdns::ScheduleStartNewClient() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ host_client_->Shutdown();
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ServiceDiscoveryClientMdns::StartNewClient,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(kRestartDelayOnNetworkChangeSeconds));
+}
+
+void ServiceDiscoveryClientMdns::StartNewClient() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ scoped_refptr<ServiceDiscoveryHostClient> old_client = host_client_;
+ if ((restart_attempts_--) > 0) {
+ host_client_ = new ServiceDiscoveryHostClient();
+ host_client_->Start(
+ base::Bind(&ServiceDiscoveryClientMdns::ScheduleStartNewClient,
+ weak_ptr_factory_.GetWeakPtr()));
+ } else {
+ host_client_ = NULL;
+ }
+ // Run when host_client_ is created. Callbacks created by InvalidateWatchers
+ // may create new watchers.
+ if (old_client)
+ old_client->InvalidateWatchers();
+}
+
+} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/service_discovery_client_mdns.h b/chrome/browser/local_discovery/service_discovery_client_mdns.h
new file mode 100644
index 0000000..308cbf3
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_client_mdns.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_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MDNS_H_
+#define CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MDNS_H_
+
+#include <string>
+
+#include "base/cancelable_callback.h"
+#include "chrome/browser/local_discovery/service_discovery_shared_client.h"
+#include "chrome/common/local_discovery/service_discovery_client.h"
+#include "net/base/network_change_notifier.h"
+
+namespace local_discovery {
+
+class ServiceDiscoveryHostClient;
+
+class ServiceDiscoveryClientMdns
+ : public ServiceDiscoverySharedClient,
+ public net::NetworkChangeNotifier::NetworkChangeObserver {
+ public:
+ ServiceDiscoveryClientMdns();
+
+ // ServiceDiscoveryClient implementation.
+ virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher(
+ const std::string& service_type,
+ const ServiceWatcher::UpdatedCallback& callback) OVERRIDE;
+ virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
+ const std::string& service_name,
+ const ServiceResolver::ResolveCompleteCallback& callback) OVERRIDE;
+ virtual scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver(
+ const std::string& domain,
+ net::AddressFamily address_family,
+ const LocalDomainResolver::IPAddressCallback& callback) OVERRIDE;
+
+ // net::NetworkChangeNotifier::NetworkChangeObserver implementation.
+ virtual void OnNetworkChanged(
+ net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
+
+ private:
+ friend class base::RefCounted<ServiceDiscoveryClientMdns>;
+
+ virtual ~ServiceDiscoveryClientMdns();
+ void ScheduleStartNewClient();
+ void StartNewClient();
+
+ scoped_refptr<ServiceDiscoveryHostClient> host_client_;
+ int restart_attempts_;
+ base::WeakPtrFactory<ServiceDiscoveryClientMdns> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceDiscoveryClientMdns);
+};
+
+} // namespace local_discovery
+
+#endif // CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MDNS_H_
diff --git a/chrome/browser/local_discovery/service_discovery_host_client.cc b/chrome/browser/local_discovery/service_discovery_host_client.cc
index 02e5001..9d3d971 100644
--- a/chrome/browser/local_discovery/service_discovery_host_client.cc
+++ b/chrome/browser/local_discovery/service_discovery_host_client.cc
@@ -4,20 +4,16 @@
#include "chrome/browser/local_discovery/service_discovery_host_client.h"
-#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
-#endif // OS_POSIX
-
#include "chrome/common/local_discovery/local_discovery_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/utility_process_host.h"
#include "net/socket/socket_descriptor.h"
-namespace local_discovery {
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#endif // OS_POSIX
-namespace {
-ServiceDiscoverySharedClient* g_service_discovery_client = NULL;
-} // namespace
+namespace local_discovery {
using content::BrowserThread;
using content::UtilityProcessHost;
@@ -144,9 +140,6 @@
}
ServiceDiscoveryHostClient::~ServiceDiscoveryHostClient() {
- // The ServiceDiscoveryHostClient may be destroyed from the IO thread or the
- // owning thread.
- DetachFromThread();
DCHECK(service_watcher_callbacks_.empty());
DCHECK(service_resolver_callbacks_.empty());
DCHECK(domain_resolver_callbacks_.empty());
@@ -155,7 +148,7 @@
scoped_ptr<ServiceWatcher> ServiceDiscoveryHostClient::CreateServiceWatcher(
const std::string& service_type,
const ServiceWatcher::UpdatedCallback& callback) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return scoped_ptr<ServiceWatcher>(
new ServiceWatcherProxy(this, service_type, callback));
}
@@ -163,7 +156,7 @@
scoped_ptr<ServiceResolver> ServiceDiscoveryHostClient::CreateServiceResolver(
const std::string& service_name,
const ServiceResolver::ResolveCompleteCallback& callback) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return scoped_ptr<ServiceResolver>(
new ServiceResolverProxy(this, service_name, callback));
}
@@ -173,14 +166,14 @@
const std::string& domain,
net::AddressFamily address_family,
const LocalDomainResolver::IPAddressCallback& callback) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return scoped_ptr<LocalDomainResolver>(new LocalDomainResolverProxy(
this, domain, address_family, callback));
}
uint64 ServiceDiscoveryHostClient::RegisterWatcherCallback(
const ServiceWatcher::UpdatedCallback& callback) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!ContainsKey(service_watcher_callbacks_, current_id_ + 1));
service_watcher_callbacks_[++current_id_] = callback;
return current_id_;
@@ -188,7 +181,7 @@
uint64 ServiceDiscoveryHostClient::RegisterResolverCallback(
const ServiceResolver::ResolveCompleteCallback& callback) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!ContainsKey(service_resolver_callbacks_, current_id_ + 1));
service_resolver_callbacks_[++current_id_] = callback;
return current_id_;
@@ -196,37 +189,39 @@
uint64 ServiceDiscoveryHostClient::RegisterLocalDomainResolverCallback(
const LocalDomainResolver::IPAddressCallback& callback) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!ContainsKey(domain_resolver_callbacks_, current_id_ + 1));
domain_resolver_callbacks_[++current_id_] = callback;
return current_id_;
}
void ServiceDiscoveryHostClient::UnregisterWatcherCallback(uint64 id) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
service_watcher_callbacks_.erase(id);
}
void ServiceDiscoveryHostClient::UnregisterResolverCallback(uint64 id) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
service_resolver_callbacks_.erase(id);
}
void ServiceDiscoveryHostClient::UnregisterLocalDomainResolverCallback(
uint64 id) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
domain_resolver_callbacks_.erase(id);
}
-void ServiceDiscoveryHostClient::Start() {
- DCHECK(CalledOnValidThread());
+void ServiceDiscoveryHostClient::Start(
+ const base::Closure& error_callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ error_callback_ = error_callback;
io_runner_->PostTask(
FROM_HERE,
base::Bind(&ServiceDiscoveryHostClient::StartOnIOThread, this));
}
void ServiceDiscoveryHostClient::Shutdown() {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
io_runner_->PostTask(
FROM_HERE,
base::Bind(&ServiceDiscoveryHostClient::ShutdownOnIOThread, this));
@@ -265,10 +260,11 @@
utility_host_->Send(new LocalDiscoveryMsg_ShutdownLocalDiscovery);
utility_host_->EndBatchMode();
}
+ error_callback_ = base::Closure();
}
void ServiceDiscoveryHostClient::Send(IPC::Message* msg) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
io_runner_->PostTask(
FROM_HERE,
base::Bind(&ServiceDiscoveryHostClient::SendOnIOThread, this, msg));
@@ -280,10 +276,16 @@
utility_host_->Send(msg);
}
+void ServiceDiscoveryHostClient::OnProcessCrashed(int exit_code) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ OnError();
+}
+
bool ServiceDiscoveryHostClient::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ServiceDiscoveryHostClient, message)
+ IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_Error, OnError)
IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_WatcherCallback,
OnWatcherCallback)
IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_ResolverCallback,
@@ -309,6 +311,12 @@
}
}
+void ServiceDiscoveryHostClient::OnError() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!error_callback_.is_null())
+ callback_runner_->PostTask(FROM_HERE, error_callback_);
+}
+
void ServiceDiscoveryHostClient::OnWatcherCallback(
uint64 id,
ServiceWatcher::UpdateType update,
@@ -347,7 +355,7 @@
uint64 id,
ServiceWatcher::UpdateType update,
const std::string& service_name) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
WatcherCallbacks::iterator it = service_watcher_callbacks_.find(id);
if (it != service_watcher_callbacks_.end() && !it->second.is_null())
it->second.Run(update, service_name);
@@ -357,7 +365,7 @@
uint64 id,
ServiceResolver::RequestStatus status,
const ServiceDescription& description) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ResolverCallbacks::iterator it = service_resolver_callbacks_.find(id);
if (it != service_resolver_callbacks_.end() && !it->second.is_null())
it->second.Run(status, description);
@@ -368,84 +376,10 @@
bool success,
const net::IPAddressNumber& ip_address_ipv4,
const net::IPAddressNumber& ip_address_ipv6) {
- DCHECK(CalledOnValidThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DomainResolverCallbacks::iterator it = domain_resolver_callbacks_.find(id);
if (it != domain_resolver_callbacks_.end() && !it->second.is_null())
it->second.Run(success, ip_address_ipv4, ip_address_ipv6);
}
-scoped_ptr<ServiceWatcher> ServiceDiscoverySharedClient::CreateServiceWatcher(
- const std::string& service_type,
- const ServiceWatcher::UpdatedCallback& callback) {
- DCHECK(CalledOnValidThread());
- return host_client_->CreateServiceWatcher(service_type, callback);
-}
-
-scoped_ptr<ServiceResolver> ServiceDiscoverySharedClient::CreateServiceResolver(
- const std::string& service_name,
- const ServiceResolver::ResolveCompleteCallback& callback) {
- DCHECK(CalledOnValidThread());
- return host_client_->CreateServiceResolver(service_name, callback);
-}
-
-scoped_ptr<LocalDomainResolver>
-ServiceDiscoverySharedClient::CreateLocalDomainResolver(
- const std::string& domain,
- net::AddressFamily address_family,
- const LocalDomainResolver::IPAddressCallback& callback) {
- DCHECK(CalledOnValidThread());
- return host_client_->CreateLocalDomainResolver(domain, address_family,
- callback);
-}
-
-ServiceDiscoverySharedClient::ServiceDiscoverySharedClient() {
- net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
- DCHECK(!g_service_discovery_client);
- g_service_discovery_client = this;
- host_client_ = new ServiceDiscoveryHostClient();
- host_client_->Start();
-}
-
-ServiceDiscoverySharedClient::~ServiceDiscoverySharedClient() {
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
- DCHECK_EQ(g_service_discovery_client, this);
- g_service_discovery_client = NULL;
- host_client_->Shutdown();
-}
-
-
-
-void ServiceDiscoverySharedClient::OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) {
- DCHECK(CalledOnValidThread());
- host_client_->Shutdown();
- network_change_callback_.Reset(
- base::Bind(&ServiceDiscoverySharedClient::StartNewClient,
- base::Unretained(this))); // Unretained to avoid ref cycle.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- network_change_callback_.callback(),
- base::TimeDelta::FromSeconds(3));
-}
-
-void ServiceDiscoverySharedClient::StartNewClient() {
- DCHECK(CalledOnValidThread());
- scoped_refptr<ServiceDiscoveryHostClient> old_client = host_client_;
- host_client_ = new ServiceDiscoveryHostClient();
- host_client_->Start();
- // Run when host_client_ is created. Callbacks created by InvalidateWatchers
- // may create new watchers.
- old_client->InvalidateWatchers();
-}
-
-scoped_refptr<ServiceDiscoverySharedClient>
- ServiceDiscoverySharedClient::GetInstance() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (g_service_discovery_client)
- return g_service_discovery_client;
-
- return new ServiceDiscoverySharedClient();
-}
-
} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/service_discovery_host_client.h b/chrome/browser/local_discovery/service_discovery_host_client.h
index 663a7c1..7b335b1 100644
--- a/chrome/browser/local_discovery/service_discovery_host_client.h
+++ b/chrome/browser/local_discovery/service_discovery_host_client.h
@@ -8,12 +8,8 @@
#include <map>
#include <string>
-#include "base/cancelable_callback.h"
-#include "base/memory/singleton.h"
-#include "base/threading/non_thread_safe.h"
#include "chrome/common/local_discovery/service_discovery_client.h"
#include "content/public/browser/utility_process_host_client.h"
-#include "net/base/network_change_notifier.h"
namespace base {
class TaskRunner;
@@ -28,14 +24,13 @@
// Implementation of ServiceDiscoveryClient that delegates all functionality to
// utility process.
class ServiceDiscoveryHostClient
- : public base::NonThreadSafe,
- public ServiceDiscoveryClient,
+ : public ServiceDiscoveryClient,
public content::UtilityProcessHostClient {
public:
ServiceDiscoveryHostClient();
// Starts utility process with ServiceDiscoveryClient.
- void Start();
+ void Start(const base::Closure& error_callback);
// Shutdowns utility process.
void Shutdown();
@@ -53,6 +48,7 @@
const LocalDomainResolver::IPAddressCallback& callback) OVERRIDE;
// UtilityProcessHostClient implementation.
+ virtual void OnProcessCrashed(int exit_code) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
protected:
@@ -62,7 +58,7 @@
class ServiceWatcherProxy;
class ServiceResolverProxy;
class LocalDomainResolverProxy;
- friend class ServiceDiscoverySharedClient;
+ friend class ServiceDiscoveryClientMdns;
typedef std::map<uint64, ServiceWatcher::UpdatedCallback> WatcherCallbacks;
typedef std::map<uint64, ServiceResolver::ResolveCompleteCallback>
@@ -90,6 +86,7 @@
void UnregisterLocalDomainResolverCallback(uint64 id);
// IPC Message handlers.
+ void OnError();
void OnWatcherCallback(uint64 id,
ServiceWatcher::UpdateType update,
const std::string& service_name);
@@ -121,6 +118,7 @@
// Incrementing counter to assign ID to watchers and resolvers.
uint64 current_id_;
+ base::Closure error_callback_;
WatcherCallbacks service_watcher_callbacks_;
ResolverCallbacks service_resolver_callbacks_;
DomainResolverCallbacks domain_resolver_callbacks_;
@@ -130,44 +128,6 @@
DISALLOW_COPY_AND_ASSIGN(ServiceDiscoveryHostClient);
};
-class ServiceDiscoverySharedClient
- : public base::RefCounted<ServiceDiscoverySharedClient>,
- public base::NonThreadSafe,
- public ServiceDiscoveryClient,
- public net::NetworkChangeNotifier::NetworkChangeObserver {
- public:
- static scoped_refptr<ServiceDiscoverySharedClient> GetInstance();
-
- // ServiceDiscoveryClient implementation.
- virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher(
- const std::string& service_type,
- const ServiceWatcher::UpdatedCallback& callback) OVERRIDE;
- virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
- const std::string& service_name,
- const ServiceResolver::ResolveCompleteCallback& callback) OVERRIDE;
- virtual scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver(
- const std::string& domain,
- net::AddressFamily address_family,
- const LocalDomainResolver::IPAddressCallback& callback) OVERRIDE;
-
- // net::NetworkChangeNotifier::NetworkChangeObserver implementation.
- virtual void OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
-
- private:
- friend class base::RefCounted<ServiceDiscoverySharedClient>;
- ServiceDiscoverySharedClient();
- virtual ~ServiceDiscoverySharedClient();
-
- void StartNewClient();
-
- base::CancelableClosure network_change_callback_;
-
- scoped_refptr<ServiceDiscoveryHostClient> host_client_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceDiscoverySharedClient);
-};
-
} // namespace local_discovery
#endif // CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_HOST_CLIENT_H_
diff --git a/chrome/browser/local_discovery/service_discovery_shared_client.cc b/chrome/browser/local_discovery/service_discovery_shared_client.cc
new file mode 100644
index 0000000..d5fc9e0
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_shared_client.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/local_discovery/service_discovery_shared_client.h"
+
+#include "content/public/browser/browser_thread.h"
+
+#if defined(OS_MACOSX)
+#include "chrome/browser/local_discovery/service_discovery_client_mac_factory.h"
+#endif
+
+#if defined(ENABLE_MDNS)
+#include "chrome/browser/local_discovery/service_discovery_client_mdns.h"
+#endif // ENABLE_MDNS
+
+namespace local_discovery {
+
+using content::BrowserThread;
+
+namespace {
+ServiceDiscoverySharedClient* g_service_discovery_client = NULL;
+} // namespace
+
+ServiceDiscoverySharedClient::ServiceDiscoverySharedClient() {
+ DCHECK(!g_service_discovery_client);
+ g_service_discovery_client = this;
+}
+
+ServiceDiscoverySharedClient::~ServiceDiscoverySharedClient() {
+ DCHECK_EQ(g_service_discovery_client, this);
+ g_service_discovery_client = NULL;
+}
+
+#if defined(ENABLE_MDNS) || defined(OS_MACOSX)
+
+scoped_refptr<ServiceDiscoverySharedClient>
+ ServiceDiscoverySharedClient::GetInstance() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (g_service_discovery_client)
+ return g_service_discovery_client;
+
+#if defined(OS_MACOSX)
+ return ServiceDiscoveryClientMacFactory::CreateInstance();
+#else
+ return new ServiceDiscoveryClientMdns();
+#endif
+}
+
+#else
+
+scoped_refptr<ServiceDiscoverySharedClient>
+ ServiceDiscoverySharedClient::GetInstance() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+#endif // ENABLE_MDNS
+
+} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/service_discovery_shared_client.h b/chrome/browser/local_discovery/service_discovery_shared_client.h
new file mode 100644
index 0000000..700e620
--- /dev/null
+++ b/chrome/browser/local_discovery/service_discovery_shared_client.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_LOCAL_DISCOVERY_SERVICE_DISCOVERY_SHARED_CLIENT_H_
+#define CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_SHARED_CLIENT_H_
+
+#include "chrome/common/local_discovery/service_discovery_client.h"
+
+namespace local_discovery {
+
+class ServiceDiscoverySharedClient
+ : public base::RefCounted<ServiceDiscoverySharedClient>,
+ public ServiceDiscoveryClient {
+ public:
+ static scoped_refptr<ServiceDiscoverySharedClient> GetInstance();
+
+ protected:
+ ServiceDiscoverySharedClient();
+ virtual ~ServiceDiscoverySharedClient();
+
+ private:
+ friend class base::RefCounted<ServiceDiscoverySharedClient>;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceDiscoverySharedClient);
+};
+
+} // namespace local_discovery
+
+#endif // CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_SHARED_CLIENT_H_
diff --git a/chrome/browser/managed_mode/managed_mode_site_list.cc b/chrome/browser/managed_mode/managed_mode_site_list.cc
index d516c73..41d6c84 100644
--- a/chrome/browser/managed_mode/managed_mode_site_list.cc
+++ b/chrome/browser/managed_mode/managed_mode_site_list.cc
@@ -18,7 +18,6 @@
const char kCategoriesKey[] = "categories";
const char kHostnameHashesKey[] = "hostname_hashes";
-const char kIdKey[] = "id";
const char kNameKey[] = "name";
const char kSitesKey[] = "sites";
const char kSitelistFormatVersionKey[] = "version";
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 1d9e410..aade313 100644
--- a/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.cc
+++ b/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.cc
@@ -52,7 +52,8 @@
public GaiaOAuthClient::Delegate {
public:
ManagedUserRefreshTokenFetcherImpl(OAuth2TokenService* oauth2_token_service,
- URLRequestContextGetter* context);
+ const std::string& account_id,
+ URLRequestContextGetter* context);
virtual ~ManagedUserRefreshTokenFetcherImpl();
// ManagedUserRefreshTokenFetcher implementation:
@@ -89,6 +90,7 @@
void DispatchGoogleServiceAuthError(const GoogleServiceAuthError& error,
const std::string& token);
OAuth2TokenService* oauth2_token_service_;
+ std::string account_id_;
URLRequestContextGetter* context_;
std::string device_name_;
@@ -104,8 +106,10 @@
ManagedUserRefreshTokenFetcherImpl::ManagedUserRefreshTokenFetcherImpl(
OAuth2TokenService* oauth2_token_service,
+ const std::string& account_id,
URLRequestContextGetter* context)
: oauth2_token_service_(oauth2_token_service),
+ account_id_(account_id),
context_(context),
access_token_expired_(false) {}
@@ -125,7 +129,8 @@
void ManagedUserRefreshTokenFetcherImpl::StartFetching() {
OAuth2TokenService::ScopeSet scopes;
scopes.insert(GaiaUrls::GetInstance()->oauth1_login_scope());
- access_token_request_ = oauth2_token_service_->StartRequest(scopes, this);
+ access_token_request_ = oauth2_token_service_->StartRequest(
+ account_id_, scopes, this);
}
void ManagedUserRefreshTokenFetcherImpl::OnGetTokenSuccess(
@@ -180,7 +185,8 @@
int response_code = source->GetResponseCode();
if (response_code == net::HTTP_UNAUTHORIZED && !access_token_expired_) {
access_token_expired_ = true;
- oauth2_token_service_->InvalidateToken(OAuth2TokenService::ScopeSet(),
+ oauth2_token_service_->InvalidateToken(account_id_,
+ OAuth2TokenService::ScopeSet(),
access_token_);
StartFetching();
return;
@@ -265,9 +271,11 @@
// static
scoped_ptr<ManagedUserRefreshTokenFetcher>
ManagedUserRefreshTokenFetcher::Create(OAuth2TokenService* oauth2_token_service,
+ const std::string& account_id,
URLRequestContextGetter* context) {
scoped_ptr<ManagedUserRefreshTokenFetcher> fetcher(
- new ManagedUserRefreshTokenFetcherImpl(oauth2_token_service, context));
+ new ManagedUserRefreshTokenFetcherImpl(oauth2_token_service, account_id,
+ context));
return fetcher.Pass();
}
diff --git a/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.h b/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.h
index c671a72..3657f68 100644
--- a/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.h
+++ b/chrome/browser/managed_mode/managed_user_refresh_token_fetcher.h
@@ -37,6 +37,7 @@
static scoped_ptr<ManagedUserRefreshTokenFetcher> Create(
OAuth2TokenService* oauth2_token_service,
+ const std::string& account_id,
net::URLRequestContextGetter* context);
virtual ~ManagedUserRefreshTokenFetcher();
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 04c4aa9..cb4043f 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
@@ -23,8 +23,9 @@
namespace {
-const char kManagedUserId[] = "abcdef";
+const char kAccountId[] = "account_id";
const char kDeviceName[] = "Compy";
+const char kManagedUserId[] = "abcdef";
const char kAccessToken[] = "accesstoken";
const char kAuthorizationCode[] = "authorizationcode";
@@ -123,7 +124,8 @@
ManagedUserRefreshTokenFetcherTest::ManagedUserRefreshTokenFetcherTest()
: token_fetcher_(
ManagedUserRefreshTokenFetcher::Create(&oauth2_token_service_,
- profile_.GetRequestContext())),
+ kAccountId,
+ profile_.GetRequestContext())),
error_(GoogleServiceAuthError::NONE),
weak_ptr_factory_(this) {}
diff --git a/chrome/browser/managed_mode/managed_user_registration_utility.cc b/chrome/browser/managed_mode/managed_user_registration_utility.cc
index ce72772..e2b75b5 100644
--- a/chrome/browser/managed_mode/managed_user_registration_utility.cc
+++ b/chrome/browser/managed_mode/managed_user_registration_utility.cc
@@ -29,10 +29,6 @@
namespace {
-const char kAcknowledged[] = "acknowledged";
-const char kName[] = "name";
-const char kMasterKey[] = "masterKey";
-
ManagedUserRegistrationUtility* g_instance_for_tests = NULL;
// Actual implementation of ManagedUserRegistrationUtility.
@@ -135,9 +131,13 @@
g_instance_for_tests = NULL;
return make_scoped_ptr(result);
}
+
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher =
ManagedUserRefreshTokenFetcher::Create(
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
+ token_service,
+ token_service->GetPrimaryAccountId(),
profile->GetRequestContext());
ManagedUserSyncService* managed_user_sync_service =
ManagedUserSyncServiceFactory::GetForProfile(profile);
diff --git a/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc b/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc
index ded7bc6..075a7f7 100644
--- a/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc
+++ b/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc
@@ -156,8 +156,16 @@
GetUserMediaAndDeny(tab_contents);
}
+// Times out on win debug builds; http://crbug.com/295723 .
+#if defined(OS_WIN) && !defined(NDEBUG)
+#define MAYBE_DenyingMicDoesNotCauseStickyDenyForCameras \
+ DISABLED_DenyingMicDoesNotCauseStickyDenyForCameras
+#else
+#define MAYBE_DenyingMicDoesNotCauseStickyDenyForCameras \
+ DenyingMicDoesNotCauseStickyDenyForCameras
+#endif
IN_PROC_BROWSER_TEST_F(MediaStreamInfoBarTest,
- DenyingMicDoesNotCauseStickyDenyForCameras) {
+ MAYBE_DenyingMicDoesNotCauseStickyDenyForCameras) {
content::WebContents* tab_contents = LoadTestPageInTab();
// If mic blocking also blocked cameras, the second call here would hang.
@@ -185,8 +193,18 @@
kAudioOnlyCallConstraints);
}
-IN_PROC_BROWSER_TEST_F(MediaStreamInfoBarTest,
- DenyingMicStillSucceedsWithCameraForAudioVideoCalls) {
+
+// Times out on windows, http://crbug.com/295723 .
+#if defined(OS_WIN)
+#define MAYBE_DenyingMicStillSucceedsWithCameraForAudioVideoCalls \
+ DISABLED_DenyingMicStillSucceedsWithCameraForAudioVideoCalls
+#else
+#define MAYBE_DenyingMicStillSucceedsWithCameraForAudioVideoCalls \
+ DenyingMicStillSucceedsWithCameraForAudioVideoCalls
+#endif
+IN_PROC_BROWSER_TEST_F(
+ MediaStreamInfoBarTest,
+ MAYBE_DenyingMicStillSucceedsWithCameraForAudioVideoCalls) {
content::WebContents* tab_contents = LoadTestPageInTab();
// If microphone blocking also blocked a AV call, the second call here
diff --git a/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc b/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc
index 769d99f..f2dcc59 100644
--- a/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc
+++ b/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc
@@ -25,13 +25,6 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/perf/perf_test.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 kReferenceFile[] =
#if defined (OS_WIN)
FILE_PATH_LITERAL("pyauto_private/webrtc/human-voice-win.wav");
diff --git a/chrome/browser/media/desktop_media_picker_model.cc b/chrome/browser/media/desktop_media_picker_model.cc
index b77ddd7..bcab694 100644
--- a/chrome/browser/media/desktop_media_picker_model.cc
+++ b/chrome/browser/media/desktop_media_picker_model.cc
@@ -95,7 +95,8 @@
scoped_ptr<webrtc::WindowCapturer> window_capturer);
virtual ~Worker();
- void Refresh(const gfx::Size& thumbnail_size);
+ void Refresh(const gfx::Size& thumbnail_size,
+ content::DesktopMediaID::Id view_dialog_id);
private:
typedef std::map<DesktopMediaID, uint32> ImageHashesMap;
@@ -132,7 +133,8 @@
DesktopMediaPickerModelImpl::Worker::~Worker() {}
void DesktopMediaPickerModelImpl::Worker::Refresh(
- const gfx::Size& thumbnail_size) {
+ const gfx::Size& thumbnail_size,
+ content::DesktopMediaID::Id view_dialog_id) {
std::vector<SourceDescription> sources;
if (screen_capturer_) {
@@ -147,9 +149,12 @@
if (window_capturer_->GetWindowList(&windows)) {
for (webrtc::WindowCapturer::WindowList::iterator it = windows.begin();
it != windows.end(); ++it) {
- sources.push_back(SourceDescription(
- DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id),
- base::UTF8ToUTF16(it->title)));
+ // Skip the picker dialog window.
+ if (it->id != view_dialog_id) {
+ sources.push_back(SourceDescription(
+ DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id),
+ base::UTF8ToUTF16(it->title)));
+ }
}
}
}
@@ -227,6 +232,7 @@
window_capturer_(window_capturer.Pass()),
update_period_(base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)),
thumbnail_size_(100, 100),
+ view_dialog_id_(-1),
observer_(NULL),
weak_factory_(this) {
base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
@@ -248,6 +254,11 @@
thumbnail_size_ = thumbnail_size;
}
+void DesktopMediaPickerModelImpl::SetViewDialogWindowId(
+ content::DesktopMediaID::Id dialog_id) {
+ view_dialog_id_ = dialog_id;
+}
+
void DesktopMediaPickerModelImpl::StartUpdating(Observer* observer) {
DCHECK(!observer_);
DCHECK(screen_capturer_ || window_capturer_);
@@ -277,7 +288,7 @@
void DesktopMediaPickerModelImpl::Refresh() {
capture_task_runner_->PostTask(
FROM_HERE, base::Bind(&Worker::Refresh, base::Unretained(worker_.get()),
- thumbnail_size_));
+ thumbnail_size_, view_dialog_id_));
}
void DesktopMediaPickerModelImpl::OnSourcesList(
diff --git a/chrome/browser/media/desktop_media_picker_model.h b/chrome/browser/media/desktop_media_picker_model.h
index 6b936bf..839ffc7 100644
--- a/chrome/browser/media/desktop_media_picker_model.h
+++ b/chrome/browser/media/desktop_media_picker_model.h
@@ -61,6 +61,10 @@
// until they are updated.
virtual void SetThumbnailSize(const gfx::Size& thumbnail_size) = 0;
+ // Sets ID of the hosting desktop picker dialog. The window with this ID will
+ // be filtered out from the list of sources.
+ virtual void SetViewDialogWindowId(content::DesktopMediaID::Id dialog_id) = 0;
+
// Starts updating the model. The model is initially empty, so OnSourceAdded()
// notifications will be generated for each existing source as it is
// enumerated. After the initial enumeration the model will be refreshed based
@@ -82,12 +86,14 @@
scoped_ptr<webrtc::WindowCapturer> window_capturer);
virtual ~DesktopMediaPickerModelImpl();
- // DesktopMediaPickerModelInterface:
+ // DesktopMediaPickerModel interface.
virtual void SetUpdatePeriod(base::TimeDelta period) OVERRIDE;
virtual void SetThumbnailSize(const gfx::Size& thumbnail_size) OVERRIDE;
virtual void StartUpdating(Observer* observer) OVERRIDE;
virtual int source_count() const OVERRIDE;
virtual const Source& source(int index) const OVERRIDE;
+ virtual void SetViewDialogWindowId(
+ content::DesktopMediaID::Id dialog_id) OVERRIDE;
private:
class Worker;
@@ -126,6 +132,9 @@
// Size of thumbnails generated by the model.
gfx::Size thumbnail_size_;
+ // ID of the hosting dialog.
+ content::DesktopMediaID::Id view_dialog_id_;
+
// The observer passed to StartUpdating().
Observer* observer_;
diff --git a/chrome/browser/media/desktop_media_picker_model_unittest.cc b/chrome/browser/media/desktop_media_picker_model_unittest.cc
index 17b23b7..05f40e5 100644
--- a/chrome/browser/media/desktop_media_picker_model_unittest.cc
+++ b/chrome/browser/media/desktop_media_picker_model_unittest.cc
@@ -191,6 +191,46 @@
EXPECT_EQ(model_->source(1).name, UTF8ToUTF16(window.title));
}
+// Verifies that the window specified with SetViewDialogWindowId() is filtered
+// from the results.
+TEST_F(DesktopMediaPickerModelTest, Filtering) {
+ CreateWithDefaultCapturers();
+
+ webrtc::WindowCapturer::WindowList list;
+ webrtc::WindowCapturer::Window window;
+
+ window.id = 0;
+ window.title = "Test window";
+ list.push_back(window);
+
+ window.id = 1;
+ list.push_back(window);
+
+ window_capturer_->SetWindowList(list);
+
+ {
+ testing::InSequence dummy;
+ EXPECT_CALL(observer_, OnSourceAdded(0))
+ .WillOnce(CheckListSize(model_.get(), 1));
+ EXPECT_CALL(observer_, OnSourceAdded(1))
+ .WillOnce(CheckListSize(model_.get(), 2));
+ EXPECT_CALL(observer_, OnSourceThumbnailChanged(0));
+ EXPECT_CALL(observer_, OnSourceThumbnailChanged(1))
+ .WillOnce(QuitMessageLoop(&message_loop_));
+ }
+
+ model_->SetViewDialogWindowId(0);
+
+ model_->StartUpdating(&observer_);
+ message_loop_.Run();
+
+ EXPECT_EQ(model_->source(0).id.type, content::DesktopMediaID::TYPE_SCREEN);
+ EXPECT_EQ(model_->source(0).id.id, 0);
+ EXPECT_EQ(model_->source(1).id.type, content::DesktopMediaID::TYPE_WINDOW);
+ EXPECT_EQ(model_->source(1).id.id, 1);
+ EXPECT_EQ(model_->source(1).name, UTF8ToUTF16(window.title));
+}
+
TEST_F(DesktopMediaPickerModelTest, WindowsOnly) {
window_capturer_ = new FakeWindowCapturer();
model_.reset(new DesktopMediaPickerModelImpl(
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index fd4be3f..da6ef73 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -31,20 +31,22 @@
#endif // defined(ENABLE_PEPPER_CDMS)
// Available key systems.
-static const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
-static const char kExternalClearKeyKeySystem[] =
+const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
+const char kExternalClearKeyKeySystem[] =
"org.chromium.externalclearkey";
// Supported media types.
-static const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
-static const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
-static const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
-static const char kMP4AudioOnly[] = "audio/mp4; codecs=\"mp4a.40.2\"";
-static const char kMP4VideoOnly[] = "video/mp4; codecs=\"avc1.4D4041\"";
+const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
+const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
+const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
+#if defined(USE_PROPRIETARY_CODECS)
+const char kMP4AudioOnly[] = "audio/mp4; codecs=\"mp4a.40.2\"";
+const char kMP4VideoOnly[] = "video/mp4; codecs=\"avc1.4D4041\"";
+#endif // defined(USE_PROPRIETARY_CODECS)
// EME-specific test results and errors.
-static const char kEmeGkrException[] = "GENERATE_KEY_REQUEST_EXCEPTION";
-static const char kEmeKeyError[] = "KEYERROR";
+const char kEmeGkrException[] = "GENERATE_KEY_REQUEST_EXCEPTION";
+const char kEmeKeyError[] = "KEYERROR";
// The type of video src used to load media.
enum SrcType {
diff --git a/chrome/browser/media/encrypted_media_istypesupported_browsertest.cc b/chrome/browser/media/encrypted_media_istypesupported_browsertest.cc
index 0b2757c..647fdaa 100644
--- a/chrome/browser/media/encrypted_media_istypesupported_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_istypesupported_browsertest.cc
@@ -81,15 +81,16 @@
namespace chrome {
-static const char kPrefixedClearKey[] = "webkit-org.w3.clearkey";
-static const char kPrefixedClearKeyParent[] = "webkit-org.w3";
+const char kPrefixedClearKey[] = "webkit-org.w3.clearkey";
+const char kPrefixedClearKeyParent[] = "webkit-org.w3";
// TODO(ddorwin): Duplicate prefixed tests for unprefixed.
-static const char kUnprefixedClearKey[] = "org.w3.clearkey";
-static const char kUnprefixedClearKeyParent[] = "org.w3";
-static const char kExternalClearKey[] = "org.chromium.externalclearkey";
-static const char kWidevineAlpha[] = "com.widevine.alpha";
-static const char kWidevine[] = "com.widevine";
-static const char kWidevineAlphaHr[] = "com.widevine.alpha.hr";
+const char kUnprefixedClearKey[] = "org.w3.clearkey";
+const char kExternalClearKey[] = "org.chromium.externalclearkey";
+const char kWidevineAlpha[] = "com.widevine.alpha";
+const char kWidevine[] = "com.widevine";
+const char kWidevineAlphaHr[] = "com.widevine.alpha.hr";
+const char kWidevineAlphaHrNonCompositing[] =
+ "com.widevine.alpha.hrnoncompositing";
class EncryptedMediaIsTypeSupportedTest : public InProcessBrowserTest {
protected:
@@ -854,6 +855,15 @@
"video/webm", no_codecs(), kWidevineAlphaHr));
}
+IN_PROC_BROWSER_TEST_F(EncryptedMediaIsTypeSupportedWidevineTest,
+ Widevine_HR_NonCompositing_Basic) {
+ // HR non-compositing support cannot be detected in tests, so this is expected
+ // to fail everywhere.
+ EXPECT_FALSE(IsConcreteSupportedKeySystem(kWidevineAlphaHrNonCompositing));
+ EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType(
+ "video/webm", no_codecs(), kWidevineAlphaHrNonCompositing));
+}
+
#if defined(ENABLE_PEPPER_CDMS)
// Since this test fixture does not register the CDMs on the command line, the
// check for the CDMs in chrome_key_systems.cc should fail, and they should not
diff --git a/chrome/browser/media/encrypted_media_message_filter_android.cc b/chrome/browser/media/encrypted_media_message_filter_android.cc
index 71ad564..968f9b9 100644
--- a/chrome/browser/media/encrypted_media_message_filter_android.cc
+++ b/chrome/browser/media/encrypted_media_message_filter_android.cc
@@ -69,8 +69,8 @@
}
void EncryptedMediaMessageFilterAndroid::OnGetSupportedKeySystems(
- const android::SupportedKeySystemRequest& request,
- android::SupportedKeySystemResponse* response) {
+ const SupportedKeySystemRequest& request,
+ SupportedKeySystemResponse* response) {
if (!MediaDrmBridge::IsAvailable() || !MediaCodecBridge::IsAvailable())
return;
diff --git a/chrome/browser/media/encrypted_media_message_filter_android.h b/chrome/browser/media/encrypted_media_message_filter_android.h
index 9e1d0d5..9d426ae 100644
--- a/chrome/browser/media/encrypted_media_message_filter_android.h
+++ b/chrome/browser/media/encrypted_media_message_filter_android.h
@@ -8,10 +8,8 @@
#include "base/basictypes.h"
#include "content/public/browser/browser_message_filter.h"
-namespace android {
struct SupportedKeySystemRequest;
struct SupportedKeySystemResponse;
-}
namespace chrome {
@@ -34,8 +32,8 @@
// Retrieve the supported key systems.
void OnGetSupportedKeySystems(
- const android::SupportedKeySystemRequest& request,
- android::SupportedKeySystemResponse* response);
+ const SupportedKeySystemRequest& request,
+ SupportedKeySystemResponse* response);
DISALLOW_COPY_AND_ASSIGN(EncryptedMediaMessageFilterAndroid);
};
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc
index d289aef..40f7934 100644
--- a/chrome/browser/media/media_capture_devices_dispatcher.cc
+++ b/chrome/browser/media/media_capture_devices_dispatcher.cc
@@ -200,7 +200,7 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE ||
- request.audio_type == content::MEDIA_SYSTEM_AUDIO_CAPTURE) {
+ request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE) {
ProcessDesktopCaptureAccessRequest(
web_contents, request, callback, extension);
} else if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE ||
@@ -249,12 +249,19 @@
content::MEDIA_DESKTOP_VIDEO_CAPTURE, media_id.ToString(),
std::string()));
+ bool loopback_audio_supported = false;
+#if defined(USE_CRAS) || defined(OS_WIN)
+ // Currently loopback audio capture is supported only on Windows and ChromeOS.
+ loopback_audio_supported = true;
+#endif
+
// Audio is only supported for screen capture streams.
if (media_id.type == content::DesktopMediaID::TYPE_SCREEN &&
- request.audio_type == content::MEDIA_SYSTEM_AUDIO_CAPTURE) {
+ request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE &&
+ loopback_audio_supported) {
devices.push_back(content::MediaStreamDevice(
- content::MEDIA_SYSTEM_AUDIO_CAPTURE, media_id.ToString(),
- "System Audio"));
+ content::MEDIA_LOOPBACK_AUDIO_CAPTURE,
+ media::AudioManagerBase::kLoopbackInputDeviceId, "System Audio"));
}
ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16(
@@ -291,22 +298,12 @@
return;
}
- const bool system_audio_capture_requested =
- request.audio_type == content::MEDIA_SYSTEM_AUDIO_CAPTURE;
-
+ bool loopback_audio_supported = false;
#if defined(USE_CRAS) || defined(OS_WIN)
- const bool system_audio_capture_supported = true;
-#else
- const bool system_audio_capture_supported = false;
+ // Currently loopback audio capture is supported only on Windows and ChromeOS.
+ loopback_audio_supported = true;
#endif
- // Reject request when audio capture was requested but is not supported on
- // this system.
- if (system_audio_capture_requested && !system_audio_capture_supported) {
- callback.Run(devices, ui.Pass());
- return;
- }
-
const bool component_extension =
extension && extension->location() == extensions::Manifest::COMPONENT;
@@ -348,14 +345,12 @@
if (user_approved || component_extension) {
devices.push_back(content::MediaStreamDevice(
content::MEDIA_DESKTOP_VIDEO_CAPTURE, media_id.ToString(), "Screen"));
- if (system_audio_capture_requested) {
-#if defined(USE_CRAS) || defined(OS_WIN)
+ if (request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE &&
+ loopback_audio_supported) {
// Use the special loopback device ID for system audio capture.
devices.push_back(content::MediaStreamDevice(
- content::MEDIA_SYSTEM_AUDIO_CAPTURE,
- media::AudioManagerBase::kLoopbackInputDeviceId,
- "System Audio"));
-#endif
+ content::MEDIA_LOOPBACK_AUDIO_CAPTURE,
+ media::AudioManagerBase::kLoopbackInputDeviceId, "System Audio"));
}
}
}
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc
index 04c239c..ef4860e 100644
--- a/chrome/browser/media/media_stream_devices_controller.cc
+++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -55,6 +55,16 @@
} // namespace
+MediaStreamDevicesController::MediaStreamTypeSettings::MediaStreamTypeSettings(
+ Permission permission, const std::string& requested_device_id):
+ permission(permission), requested_device_id(requested_device_id) {}
+
+MediaStreamDevicesController::MediaStreamTypeSettings::
+ MediaStreamTypeSettings(): permission(MEDIA_NONE) {}
+
+MediaStreamDevicesController::MediaStreamTypeSettings::
+ ~MediaStreamTypeSettings() {}
+
MediaStreamDevicesController::MediaStreamDevicesController(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
@@ -77,20 +87,30 @@
request.request_type == content::MEDIA_OPEN_DEVICE) {
if (GetDevicePolicy(prefs::kAudioCaptureAllowed,
prefs::kAudioCaptureAllowedUrls) == ALWAYS_DENY) {
- request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
- MEDIA_BLOCKED_BY_POLICY;
+ request_permissions_.insert(std::make_pair(
+ content::MEDIA_DEVICE_AUDIO_CAPTURE,
+ MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY,
+ request.requested_audio_device_id)));
} else {
- request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE] = MEDIA_ALLOWED;
+ request_permissions_.insert(std::make_pair(
+ content::MEDIA_DEVICE_AUDIO_CAPTURE,
+ MediaStreamTypeSettings(MEDIA_ALLOWED,
+ request.requested_audio_device_id)));
}
}
if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE ||
request.request_type == content::MEDIA_OPEN_DEVICE) {
if (GetDevicePolicy(prefs::kVideoCaptureAllowed,
prefs::kVideoCaptureAllowedUrls) == ALWAYS_DENY) {
- request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
- MEDIA_BLOCKED_BY_POLICY;
+ request_permissions_.insert(std::make_pair(
+ content::MEDIA_DEVICE_VIDEO_CAPTURE,
+ MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY,
+ request.requested_video_device_id)));
} else {
- request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE] = MEDIA_ALLOWED;
+ request_permissions_.insert(std::make_pair(
+ content::MEDIA_DEVICE_VIDEO_CAPTURE,
+ MediaStreamTypeSettings(MEDIA_ALLOWED,
+ request.requested_video_device_id)));
}
}
}
@@ -159,6 +179,23 @@
return true;
}
+ if (request_.request_type == content::MEDIA_OPEN_DEVICE) {
+ bool no_matched_audio_device =
+ (request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE &&
+ !request_.requested_audio_device_id.empty() &&
+ MediaCaptureDevicesDispatcher::GetInstance()->GetRequestedAudioDevice(
+ request_.requested_audio_device_id) == NULL);
+ bool no_matched_video_device =
+ (request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE &&
+ !request_.requested_video_device_id.empty() &&
+ MediaCaptureDevicesDispatcher::GetInstance()->GetRequestedVideoDevice(
+ request_.requested_video_device_id) == NULL);
+ if (no_matched_audio_device || no_matched_video_device) {
+ Deny(false);
+ return true;
+ }
+ }
+
// Show the infobar.
return false;
}
@@ -186,24 +223,26 @@
switch (request_.request_type) {
case content::MEDIA_OPEN_DEVICE: {
const content::MediaStreamDevice* device = NULL;
- // For open device request pick the desired device or fall back to the
- // first available of the given type.
+ // For open device request, when requested device_id is empty, pick
+ // the first available of the given type. If requested device_id is
+ // not empty, return the desired device if it's available. Otherwise,
+ // return no device.
if (audio_allowed &&
request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
- device = MediaCaptureDevicesDispatcher::GetInstance()->
- GetRequestedAudioDevice(request_.requested_audio_device_id);
- // TODO(wjia): Confirm this is the intended behavior.
- if (!device) {
+ if (!request_.requested_audio_device_id.empty()) {
+ device = MediaCaptureDevicesDispatcher::GetInstance()->
+ GetRequestedAudioDevice(request_.requested_audio_device_id);
+ } else {
device = MediaCaptureDevicesDispatcher::GetInstance()->
GetFirstAvailableAudioDevice();
}
} else if (video_allowed &&
request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
// Pepper API opens only one device at a time.
- device = MediaCaptureDevicesDispatcher::GetInstance()->
- GetRequestedVideoDevice(request_.requested_video_device_id);
- // TODO(wjia): Confirm this is the intended behavior.
- if (!device) {
+ if (!request_.requested_video_device_id.empty()) {
+ device = MediaCaptureDevicesDispatcher::GetInstance()->
+ GetRequestedVideoDevice(request_.requested_video_device_id);
+ } else {
device = MediaCaptureDevicesDispatcher::GetInstance()->
GetFirstAvailableVideoDevice();
}
@@ -396,7 +435,7 @@
request_.security_origin,
CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
- request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MEDIA_BLOCKED_BY_USER_SETTING;
} else {
++requested_devices;
@@ -409,7 +448,7 @@
request_.security_origin,
CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
- request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MEDIA_BLOCKED_BY_USER_SETTING;
} else {
++requested_devices;
@@ -494,11 +533,11 @@
return;
if (IsDeviceAudioCaptureRequestedAndAllowed()) {
- request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MEDIA_BLOCKED_BY_USER;
}
if (IsDeviceVideoCaptureRequestedAndAllowed()) {
- request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MEDIA_BLOCKED_BY_USER;
}
@@ -508,14 +547,16 @@
bool MediaStreamDevicesController::IsDeviceAudioCaptureRequestedAndAllowed()
const {
- MediaStreamTypePermissionMap::const_iterator it =
+ MediaStreamTypeSettingsMap::const_iterator it =
request_permissions_.find(content::MEDIA_DEVICE_AUDIO_CAPTURE);
- return it != request_permissions_.end() && it->second == MEDIA_ALLOWED;
+ return (it != request_permissions_.end() &&
+ it->second.permission == MEDIA_ALLOWED);
}
bool MediaStreamDevicesController::IsDeviceVideoCaptureRequestedAndAllowed()
const {
- MediaStreamTypePermissionMap::const_iterator it =
+ MediaStreamTypeSettingsMap::const_iterator it =
request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE);
- return it != request_permissions_.end() && it->second == MEDIA_ALLOWED;
+ return (it != request_permissions_.end() &&
+ it->second.permission == MEDIA_ALLOWED);
}
diff --git a/chrome/browser/media/media_stream_devices_controller.h b/chrome/browser/media/media_stream_devices_controller.h
index 3f37048..7456303 100644
--- a/chrome/browser/media/media_stream_devices_controller.h
+++ b/chrome/browser/media/media_stream_devices_controller.h
@@ -24,15 +24,26 @@
class MediaStreamDevicesController {
public:
// Permissions for media stream types.
- enum MediaStreamTypePermission {
+ enum Permission {
+ MEDIA_NONE,
MEDIA_ALLOWED,
MEDIA_BLOCKED_BY_POLICY,
MEDIA_BLOCKED_BY_USER_SETTING,
MEDIA_BLOCKED_BY_USER,
};
- typedef std::map<content::MediaStreamType, MediaStreamTypePermission>
- MediaStreamTypePermissionMap;
+ struct MediaStreamTypeSettings {
+ MediaStreamTypeSettings(Permission permission,
+ const std::string& requested_device_id);
+ MediaStreamTypeSettings();
+ ~MediaStreamTypeSettings();
+
+ Permission permission;
+ std::string requested_device_id;
+ };
+
+ typedef std::map<content::MediaStreamType, MediaStreamTypeSettings>
+ MediaStreamTypeSettingsMap;
MediaStreamDevicesController(content::WebContents* web_contents,
const content::MediaStreamRequest& request,
@@ -138,7 +149,7 @@
// resolved. Currently only used by MEDIA_DEVICE_AUDIO_CAPTURE and
// MEDIA_DEVICE_VIDEO_CAPTURE since those are the only types that require
// updates in the settings.
- MediaStreamTypePermissionMap request_permissions_;
+ MediaStreamTypeSettingsMap request_permissions_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamDevicesController);
};
diff --git a/chrome/browser/media/protected_media_identifier_infobar_delegate.cc b/chrome/browser/media/protected_media_identifier_infobar_delegate.cc
new file mode 100644
index 0000000..bde3fbf
--- /dev/null
+++ b/chrome/browser/media/protected_media_identifier_infobar_delegate.cc
@@ -0,0 +1,108 @@
+// Copyright 2013 The Chromium 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/protected_media_identifier_infobar_delegate.h"
+
+#include "chrome/browser/content_settings/permission_queue_controller.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/navigation_entry.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
+
+// static
+InfoBarDelegate* ProtectedMediaIdentifierInfoBarDelegate::Create(
+ InfoBarService* infobar_service,
+ PermissionQueueController* controller,
+ const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ const std::string& display_languages) {
+ const content::NavigationEntry* committed_entry =
+ infobar_service->web_contents()->GetController().GetLastCommittedEntry();
+ return infobar_service->AddInfoBar(
+ scoped_ptr<InfoBarDelegate>(new ProtectedMediaIdentifierInfoBarDelegate(
+ infobar_service,
+ controller,
+ id,
+ requesting_frame,
+ committed_entry ? committed_entry->GetUniqueID() : 0,
+ display_languages)));
+}
+
+
+ProtectedMediaIdentifierInfoBarDelegate::
+ ProtectedMediaIdentifierInfoBarDelegate(
+ InfoBarService* infobar_service,
+ PermissionQueueController* controller,
+ const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ int contents_unique_id,
+ const std::string& display_languages)
+ : ConfirmInfoBarDelegate(infobar_service),
+ controller_(controller),
+ id_(id),
+ requesting_frame_(requesting_frame),
+ contents_unique_id_(contents_unique_id),
+ display_languages_(display_languages) {}
+
+ProtectedMediaIdentifierInfoBarDelegate::
+ ~ProtectedMediaIdentifierInfoBarDelegate() {}
+
+bool ProtectedMediaIdentifierInfoBarDelegate::Accept() {
+ SetPermission(true, true);
+ return true;
+}
+
+void ProtectedMediaIdentifierInfoBarDelegate::SetPermission(
+ bool update_content_setting,
+ bool allowed) {
+ controller_->OnPermissionSet(id_,
+ requesting_frame_,
+ web_contents()->GetLastCommittedURL(),
+ update_content_setting,
+ allowed);
+}
+
+void ProtectedMediaIdentifierInfoBarDelegate::InfoBarDismissed() {
+ SetPermission(false, false);
+}
+
+int ProtectedMediaIdentifierInfoBarDelegate::GetIconID() const {
+ return IDR_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_ICON;
+}
+
+InfoBarDelegate::Type ProtectedMediaIdentifierInfoBarDelegate::GetInfoBarType()
+ const {
+ return PAGE_ACTION_TYPE;
+}
+
+bool ProtectedMediaIdentifierInfoBarDelegate::ShouldExpireInternal(
+ const content::LoadCommittedDetails& details) const {
+ // This implementation matches InfoBarDelegate::ShouldExpireInternal(), but
+ // uses the unique ID we set in the constructor instead of that stored in the
+ // base class.
+ return (contents_unique_id_ != details.entry->GetUniqueID()) ||
+ (content::PageTransitionStripQualifier(
+ details.entry->GetTransitionType()) ==
+ content::PAGE_TRANSITION_RELOAD);
+}
+
+string16 ProtectedMediaIdentifierInfoBarDelegate::GetMessageText() const {
+ return l10n_util::GetStringFUTF16(
+ IDS_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_QUESTION,
+ net::FormatUrl(requesting_frame_.GetOrigin(), display_languages_));
+}
+
+string16 ProtectedMediaIdentifierInfoBarDelegate::GetButtonLabel(
+ InfoBarButton button) const {
+ return l10n_util::GetStringUTF16(
+ (button == BUTTON_OK) ? IDS_PROTECTED_MEDIA_IDENTIFIER_ALLOW_BUTTON
+ : IDS_PROTECTED_MEDIA_IDENTIFIER_DENY_BUTTON);
+}
+
+bool ProtectedMediaIdentifierInfoBarDelegate::Cancel() {
+ SetPermission(true, false);
+ return true;
+}
diff --git a/chrome/browser/media/protected_media_identifier_infobar_delegate.h b/chrome/browser/media/protected_media_identifier_infobar_delegate.h
new file mode 100644
index 0000000..9510772
--- /dev/null
+++ b/chrome/browser/media/protected_media_identifier_infobar_delegate.h
@@ -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.
+
+#ifndef CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_DELEGATE_H_
+#define CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_DELEGATE_H_
+
+#include <string>
+
+#include "chrome/browser/content_settings/permission_request_id.h"
+#include "chrome/browser/infobars/confirm_infobar_delegate.h"
+#include "url/gurl.h"
+
+class PermissionQueueController;
+class InfoBarService;
+
+class ProtectedMediaIdentifierInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+ // Creates a protected media identifier infobar delegate and adds it to
+ // |infobar_service|.
+ // Returns the delegate if it was successfully added.
+ static InfoBarDelegate* Create(InfoBarService* infobar_service,
+ PermissionQueueController* controller,
+ const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ const std::string& display_languages);
+ protected:
+ ProtectedMediaIdentifierInfoBarDelegate(InfoBarService* infobar_service,
+ PermissionQueueController* controller,
+ const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ int contents_unique_id,
+ const std::string& display_languages);
+ virtual ~ProtectedMediaIdentifierInfoBarDelegate();
+
+ // Call back to the controller, to inform of the user's decision.
+ void SetPermission(bool update_content_setting, bool allowed);
+
+ private:
+ // ConfirmInfoBarDelegate:
+ virtual void InfoBarDismissed() OVERRIDE;
+ virtual int GetIconID() const OVERRIDE;
+ virtual Type GetInfoBarType() const OVERRIDE;
+ virtual bool ShouldExpireInternal(
+ const content::LoadCommittedDetails& details) const OVERRIDE;
+ virtual string16 GetMessageText() const OVERRIDE;
+ virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
+ virtual bool Accept() OVERRIDE;
+ virtual bool Cancel() OVERRIDE;
+
+ PermissionQueueController* controller_;
+ const PermissionRequestID id_;
+ GURL requesting_frame_;
+ int contents_unique_id_;
+ std::string display_languages_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProtectedMediaIdentifierInfoBarDelegate);
+};
+
+#endif // CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/media/protected_media_identifier_permission_context.cc b/chrome/browser/media/protected_media_identifier_permission_context.cc
new file mode 100644
index 0000000..6f01795
--- /dev/null
+++ b/chrome/browser/media/protected_media_identifier_permission_context.cc
@@ -0,0 +1,202 @@
+// Copyright 2013 The Chromium 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/protected_media_identifier_permission_context.h"
+
+#include <functional>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/content_settings/permission_request_id.h"
+#include "chrome/browser/content_settings/tab_specific_content_settings.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/suggest_permission_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/view_type_utils.h"
+
+using extensions::APIPermission;
+
+ProtectedMediaIdentifierPermissionContext::
+ ProtectedMediaIdentifierPermissionContext(Profile* profile)
+ : profile_(profile), shutting_down_(false) {}
+
+ProtectedMediaIdentifierPermissionContext::
+ ~ProtectedMediaIdentifierPermissionContext() {
+ // ProtectedMediaIdentifierPermissionContext may be destroyed on either
+ // the UI thread or the IO thread, but the PermissionQueueController must have
+ // been destroyed on the UI thread.
+ DCHECK(!permission_queue_controller_.get());
+}
+
+void ProtectedMediaIdentifierPermissionContext::
+ RequestProtectedMediaIdentifierPermission(
+ int render_process_id,
+ int render_view_id,
+ const GURL& requesting_frame,
+ const base::Callback<void(bool)>& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (shutting_down_)
+ return;
+
+ content::WebContents* web_contents =
+ tab_util::GetWebContentsByID(render_process_id, render_view_id);
+ const PermissionRequestID id(render_process_id, render_view_id, 0);
+
+ if (extensions::GetViewType(web_contents) !=
+ extensions::VIEW_TYPE_TAB_CONTENTS) {
+ // The tab may have gone away, or the request may not be from a tab at all.
+ LOG(WARNING)
+ << "Attempt to use protected media identifier in tabless renderer: "
+ << id.ToString()
+ << " (can't prompt user without a visible tab)";
+ NotifyPermissionSet(id, requesting_frame, callback, false);
+ return;
+ }
+
+ GURL embedder = web_contents->GetLastCommittedURL();
+ if (!requesting_frame.is_valid() || !embedder.is_valid()) {
+ LOG(WARNING)
+ << "Attempt to use protected media identifier from an invalid URL: "
+ << requesting_frame << "," << embedder
+ << " (proteced media identifier is not supported in popups)";
+ NotifyPermissionSet(id, requesting_frame, callback, false);
+ return;
+ }
+
+ DecidePermission(id, requesting_frame, embedder, callback);
+}
+
+void ProtectedMediaIdentifierPermissionContext::
+ CancelProtectedMediaIdentifierPermissionRequest(
+ int render_process_id,
+ int render_view_id,
+ const GURL& requesting_frame) {
+ CancelPendingInfoBarRequest(
+ PermissionRequestID(render_process_id, render_view_id, 0));
+}
+
+void ProtectedMediaIdentifierPermissionContext::DecidePermission(
+ const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ const GURL& embedder,
+ const base::Callback<void(bool)>& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+#if defined(OS_ANDROID)
+ // Check if the protected media identifier master switch is disabled.
+ if (!profile()->GetPrefs()->GetBoolean(
+ prefs::kProtectedMediaIdentifierEnabled)) {
+ PermissionDecided(id, requesting_frame, embedder, callback, false);
+ return;
+ }
+#endif
+
+ ContentSetting content_setting =
+ profile_->GetHostContentSettingsMap()->GetContentSetting(
+ requesting_frame,
+ embedder,
+ CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
+ std::string());
+ switch (content_setting) {
+ case CONTENT_SETTING_BLOCK:
+ PermissionDecided(id, requesting_frame, embedder, callback, false);
+ break;
+ case CONTENT_SETTING_ALLOW:
+ PermissionDecided(id, requesting_frame, embedder, callback, true);
+ break;
+ case CONTENT_SETTING_ASK:
+ QueueController()->CreateInfoBarRequest(
+ id,
+ requesting_frame,
+ embedder,
+ base::Bind(&ProtectedMediaIdentifierPermissionContext::
+ NotifyPermissionSet,
+ base::Unretained(this),
+ id,
+ requesting_frame,
+ callback));
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+void ProtectedMediaIdentifierPermissionContext::ShutdownOnUIThread() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ permission_queue_controller_.reset();
+ shutting_down_ = true;
+}
+
+void ProtectedMediaIdentifierPermissionContext::PermissionDecided(
+ const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ const GURL& embedder,
+ const base::Callback<void(bool)>& callback,
+ bool allowed) {
+ NotifyPermissionSet(id, requesting_frame, callback, allowed);
+}
+
+void ProtectedMediaIdentifierPermissionContext::NotifyPermissionSet(
+ const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ const base::Callback<void(bool)>& callback,
+ bool allowed) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ // WebContents may have gone away.
+ TabSpecificContentSettings* content_settings =
+ TabSpecificContentSettings::Get(id.render_process_id(),
+ id.render_view_id());
+ if (content_settings) {
+ content_settings->OnProtectedMediaIdentifierPermissionSet(
+ requesting_frame.GetOrigin(), allowed);
+ }
+
+ callback.Run(allowed);
+}
+
+PermissionQueueController*
+ ProtectedMediaIdentifierPermissionContext::QueueController() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(!shutting_down_);
+ if (!permission_queue_controller_)
+ permission_queue_controller_.reset(CreateQueueController());
+ return permission_queue_controller_.get();
+}
+
+PermissionQueueController*
+ ProtectedMediaIdentifierPermissionContext::CreateQueueController() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ return new PermissionQueueController(
+ profile(), CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER);
+}
+
+void
+ProtectedMediaIdentifierPermissionContext::CancelPendingInfoBarRequest(
+ const PermissionRequestID& id) {
+ if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&ProtectedMediaIdentifierPermissionContext::
+ CancelPendingInfoBarRequest,
+ this,
+ id));
+ return;
+ }
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (shutting_down_)
+ return;
+ QueueController()->CancelInfoBarRequest(id);
+}
diff --git a/chrome/browser/media/protected_media_identifier_permission_context.h b/chrome/browser/media/protected_media_identifier_permission_context.h
new file mode 100644
index 0000000..b30fc23
--- /dev/null
+++ b/chrome/browser/media/protected_media_identifier_permission_context.h
@@ -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.
+
+#ifndef CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_H_
+#define CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/content_settings/permission_queue_controller.h"
+
+class PermissionRequestID;
+class Profile;
+
+// Manages protected media identifier permissions flow, and delegates UI
+// handling via PermissionQueueController.
+class ProtectedMediaIdentifierPermissionContext
+ : public base::RefCountedThreadSafe<
+ ProtectedMediaIdentifierPermissionContext> {
+ public:
+ explicit ProtectedMediaIdentifierPermissionContext(Profile* profile);
+
+ void RequestProtectedMediaIdentifierPermission(
+ int render_process_id,
+ int render_view_id,
+ const GURL& requesting_frame,
+ const base::Callback<void(bool)>& callback);
+ void CancelProtectedMediaIdentifierPermissionRequest(
+ int render_process_id,
+ int render_view_id,
+ const GURL& requesting_frame);
+
+ // Called on the UI thread when the profile is about to be destroyed.
+ void ShutdownOnUIThread();
+
+ private:
+ friend class base::RefCountedThreadSafe<
+ ProtectedMediaIdentifierPermissionContext>;
+ ~ProtectedMediaIdentifierPermissionContext();
+
+ Profile* profile() const { return profile_; }
+
+ // Return an instance of the infobar queue controller, creating it
+ // if necessary.
+ PermissionQueueController* QueueController();
+
+ // Notifies whether or not the corresponding bridge is allowed to use
+ // protected media identifier via
+ // SetProtectedMediaIdentifierPermissionResponse(). Called on the UI thread.
+ void NotifyPermissionSet(const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ const base::Callback<void(bool)>& callback,
+ bool allowed);
+
+ // Decide whether the protected media identifier permission should be granted.
+ // Calls PermissionDecided if permission can be decided non-interactively,
+ // or NotifyPermissionSet if permission decided by presenting an
+ // infobar to the user. Called on the UI thread.
+ void DecidePermission(const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ const GURL& embedder,
+ const base::Callback<void(bool)>& callback);
+
+ // Called when permission is granted without interactively asking
+ // the user. Can be overridden to introduce additional UI flow.
+ // Should ultimately ensure that NotifyPermissionSet is called.
+ // Called on the UI thread.
+ void PermissionDecided(const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ const GURL& embedder,
+ const base::Callback<void(bool)>& callback,
+ bool allowed);
+
+ // Create an PermissionQueueController. overridden in derived classes to
+ // provide additional UI flow. Called on the UI thread.
+ PermissionQueueController* CreateQueueController();
+
+ // Removes any pending InfoBar request.
+ void CancelPendingInfoBarRequest(const PermissionRequestID& id);
+
+ // These must only be accessed from the UI thread.
+ Profile* const profile_;
+ bool shutting_down_;
+ scoped_ptr<PermissionQueueController> permission_queue_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProtectedMediaIdentifierPermissionContext);
+};
+
+#endif // CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_H_
diff --git a/chrome/browser/media/protected_media_identifier_permission_context_factory.cc b/chrome/browser/media/protected_media_identifier_permission_context_factory.cc
new file mode 100644
index 0000000..b4a2f47
--- /dev/null
+++ b/chrome/browser/media/protected_media_identifier_permission_context_factory.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 "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
+
+#include "chrome/browser/media/protected_media_identifier_permission_context.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.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"
+
+namespace {
+
+class Service : public BrowserContextKeyedService {
+ public:
+ explicit Service(Profile* profile) {
+ context_ = new ProtectedMediaIdentifierPermissionContext(profile);
+ }
+
+ ProtectedMediaIdentifierPermissionContext* context() {
+ return context_.get();
+ }
+
+ virtual void Shutdown() OVERRIDE {
+ context()->ShutdownOnUIThread();
+ }
+
+ private:
+ scoped_refptr<ProtectedMediaIdentifierPermissionContext> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(Service);
+};
+
+} // namespace
+
+// static
+ProtectedMediaIdentifierPermissionContext*
+ProtectedMediaIdentifierPermissionContextFactory::GetForProfile(
+ Profile* profile) {
+ return static_cast<Service*>(
+ GetInstance()->GetServiceForBrowserContext(profile, true))->context();
+}
+
+// static
+ProtectedMediaIdentifierPermissionContextFactory*
+ProtectedMediaIdentifierPermissionContextFactory::GetInstance() {
+ return Singleton<
+ ProtectedMediaIdentifierPermissionContextFactory>::get();
+}
+
+ProtectedMediaIdentifierPermissionContextFactory::
+ProtectedMediaIdentifierPermissionContextFactory()
+ : BrowserContextKeyedServiceFactory(
+ "ProtectedMediaIdentifierPermissionContext",
+ BrowserContextDependencyManager::GetInstance()) {
+}
+
+ProtectedMediaIdentifierPermissionContextFactory::
+~ProtectedMediaIdentifierPermissionContextFactory() {
+}
+
+BrowserContextKeyedService*
+ProtectedMediaIdentifierPermissionContextFactory::BuildServiceInstanceFor(
+ content::BrowserContext* profile) const {
+ return new Service(static_cast<Profile*>(profile));
+}
+
+void
+ProtectedMediaIdentifierPermissionContextFactory::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterBooleanPref(
+ prefs::kProtectedMediaIdentifierEnabled,
+ true,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
+content::BrowserContext*
+ProtectedMediaIdentifierPermissionContextFactory::GetBrowserContextToUse(
+ content::BrowserContext* context) const {
+ return chrome::GetBrowserContextOwnInstanceInIncognito(context);
+}
diff --git a/chrome/browser/media/protected_media_identifier_permission_context_factory.h b/chrome/browser/media/protected_media_identifier_permission_context_factory.h
new file mode 100644
index 0000000..a6f85fe
--- /dev/null
+++ b/chrome/browser/media/protected_media_identifier_permission_context_factory.h
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium 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_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_FACTORY_H_
+#define CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+
+class ProtectedMediaIdentifierPermissionContext;
+class Profile;
+
+class ProtectedMediaIdentifierPermissionContextFactory
+ : public BrowserContextKeyedServiceFactory {
+ public:
+ static ProtectedMediaIdentifierPermissionContext* GetForProfile(
+ Profile* profile);
+
+ static ProtectedMediaIdentifierPermissionContextFactory* GetInstance();
+
+ private:
+ friend struct DefaultSingletonTraits<
+ ProtectedMediaIdentifierPermissionContextFactory>;
+
+ ProtectedMediaIdentifierPermissionContextFactory();
+ virtual ~ProtectedMediaIdentifierPermissionContextFactory();
+
+ // BrowserContextKeyedBaseFactory methods:
+ virtual BrowserContextKeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* profile) const OVERRIDE;
+ virtual void RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) OVERRIDE;
+ virtual content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(
+ ProtectedMediaIdentifierPermissionContextFactory);
+};
+
+#endif // CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_FACTORY_H_
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 52cfd03..63a553c 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
@@ -164,6 +164,7 @@
scoped_ptr<FileSystemOperationContext> context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
@@ -175,6 +176,7 @@
scoped_ptr<FileSystemOperationContext> context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
NOTIMPLEMENTED();
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 bf9a7dd..82f313a 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
@@ -70,12 +70,14 @@
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) OVERRIDE;
virtual void MoveFileLocal(
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) OVERRIDE;
virtual void CopyInForeignFile(
scoped_ptr<fileapi::FileSystemOperationContext> context,
diff --git a/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc b/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
index 036d914..2c8c1b5 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
@@ -196,7 +196,7 @@
void OnTestFilesReady(bool expected_result, bool test_files_ready) {
ASSERT_TRUE(test_files_ready);
operation_runner()->Move(
- move_src_, move_dest_,
+ move_src_, move_dest_, fileapi::FileSystemOperation::OPTION_NONE,
base::Bind(&MediaFileValidatorTest::OnMoveResult,
base::Unretained(this), expected_result));
}
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 a4d6927..ae3b06f 100644
--- a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
@@ -205,6 +205,7 @@
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
@@ -213,7 +214,7 @@
FROM_HERE,
base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
weak_factory_.GetWeakPtr(), base::Passed(&context),
- src_url, dest_url, true /* copy */, callback));
+ src_url, dest_url, option, true /* copy */, callback));
DCHECK(success);
}
@@ -221,6 +222,7 @@
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
fileapi::FileSystemOperationContext* context_ptr = context.get();
@@ -228,7 +230,7 @@
FROM_HERE,
base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
weak_factory_.GetWeakPtr(), base::Passed(&context),
- src_url, dest_url, false /* copy */, callback));
+ src_url, dest_url, option, false /* copy */, callback));
DCHECK(success);
}
@@ -339,11 +341,12 @@
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
bool copy,
const StatusCallback& callback) {
DCHECK(IsOnTaskRunnerThread(context.get()));
base::PlatformFileError error =
- CopyOrMoveFileSync(context.get(), src_url, dest_url, copy);
+ CopyOrMoveFileSync(context.get(), src_url, dest_url, option, copy);
content::BrowserThread::PostTask(
content::BrowserThread::IO,
FROM_HERE,
@@ -410,6 +413,7 @@
fileapi::FileSystemOperationContext* context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
bool copy) {
DCHECK(IsOnTaskRunnerThread(context));
base::FilePath src_file_path;
@@ -437,8 +441,8 @@
if (!media_path_filter_->Match(dest_file_path))
return base::PLATFORM_FILE_ERROR_SECURITY;
- return fileapi::NativeFileUtil::CopyOrMoveFile(src_file_path, dest_file_path,
- copy);
+ return fileapi::NativeFileUtil::CopyOrMoveFile(
+ src_file_path, dest_file_path, option, copy);
}
base::PlatformFileError NativeMediaFileUtil::CopyInForeignFileSync(
@@ -454,8 +458,9 @@
GetFilteredLocalFilePath(context, dest_url, &dest_file_path);
if (error != base::PLATFORM_FILE_OK)
return error;
- return fileapi::NativeFileUtil::CopyOrMoveFile(src_file_path, dest_file_path,
- true);
+ return fileapi::NativeFileUtil::CopyOrMoveFile(
+ src_file_path, dest_file_path,
+ fileapi::FileSystemOperation::OPTION_NONE, true);
}
base::PlatformFileError NativeMediaFileUtil::GetFileInfoSync(
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 05cfc9c..a0bf8cd 100644
--- a/chrome/browser/media_galleries/fileapi/native_media_file_util.h
+++ b/chrome/browser/media_galleries/fileapi/native_media_file_util.h
@@ -63,12 +63,14 @@
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) OVERRIDE;
virtual void MoveFileLocal(
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) OVERRIDE;
virtual void CopyInForeignFile(
scoped_ptr<fileapi::FileSystemOperationContext> context,
@@ -111,6 +113,7 @@
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
bool copy,
const StatusCallback& callback);
virtual void CopyInForeignFileOnTaskRunnerThread(
@@ -139,6 +142,7 @@
fileapi::FileSystemOperationContext* context,
const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
bool copy);
virtual base::PlatformFileError CopyInForeignFileSync(
fileapi::FileSystemOperationContext* context,
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 c131af6..86c902a 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
@@ -304,6 +304,7 @@
}
operation_runner()->Copy(
url, dest_url,
+ fileapi::FileSystemOperation::OPTION_NONE,
fileapi::FileSystemOperationRunner::CopyProgressCallback(),
base::Bind(&ExpectEqHelper, test_name, expectation));
base::MessageLoop::current()->RunUntilIdle();
@@ -368,6 +369,7 @@
}
operation_runner()->Copy(
src_url, url,
+ fileapi::FileSystemOperation::OPTION_NONE,
fileapi::FileSystemOperationRunner::CopyProgressCallback(),
base::Bind(&ExpectEqHelper, test_name, expectation));
base::MessageLoop::current()->RunUntilIdle();
@@ -406,7 +408,8 @@
expectation = base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
}
operation_runner()->Move(
- url, dest_url, base::Bind(&ExpectEqHelper, test_name, expectation));
+ url, dest_url, fileapi::FileSystemOperation::OPTION_NONE,
+ base::Bind(&ExpectEqHelper, test_name, expectation));
base::MessageLoop::current()->RunUntilIdle();
}
}
@@ -470,7 +473,8 @@
}
}
operation_runner()->Move(
- src_url, url, base::Bind(&ExpectEqHelper, test_name, expectation));
+ src_url, url, fileapi::FileSystemOperation::OPTION_NONE,
+ base::Bind(&ExpectEqHelper, test_name, expectation));
base::MessageLoop::current()->RunUntilIdle();
}
}
diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc
index 25004bd..5fb2a0f 100644
--- a/chrome/browser/media_galleries/media_file_system_registry.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry.cc
@@ -21,6 +21,7 @@
#include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
#include "chrome/browser/media_galleries/media_file_system_context.h"
#include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
+#include "chrome/browser/media_galleries/media_galleries_histograms.h"
#include "chrome/browser/media_galleries/media_galleries_preferences_factory.h"
#include "chrome/browser/media_galleries/scoped_mtp_device_map_entry.h"
#include "chrome/browser/profiles/profile.h"
@@ -476,6 +477,7 @@
// Create an empty entry so the initialization code below only gets called
// once per profile.
extension_hosts_map_[profile] = ExtensionHostMap();
+ media_galleries::UsageCount(media_galleries::PROFILES_WITH_USAGE);
// TODO(gbillock): Move this stanza to MediaGalleriesPreferences init code.
StorageMonitor* monitor = StorageMonitor::GetInstance();
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 a4f6329..559a94b 100644
--- a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
@@ -248,6 +248,8 @@
const std::vector<string16>& names,
const std::vector<MediaFileSystemInfo>& expected,
const std::vector<MediaFileSystemInfo>& actual);
+ bool ContainsEntry(const MediaFileSystemInfo& info,
+ const std::vector<MediaFileSystemInfo>& container);
int GetAndClearComparisonCount();
@@ -548,6 +550,20 @@
compare_names_all_.push_back(name);
}
+bool ProfileState::ContainsEntry(
+ const MediaFileSystemInfo& info,
+ const std::vector<MediaFileSystemInfo>& container) {
+ for (size_t i = 0; i < container.size(); ++i) {
+ if (info.path.value() == container[i].path.value()) {
+ EXPECT_FALSE(container[i].fsid.empty());
+ if (!info.fsid.empty())
+ EXPECT_EQ(info.fsid, container[i].fsid);
+ return true;
+ }
+ }
+ return false;
+}
+
void ProfileState::CompareResults(
const std::string& test,
const std::vector<string16>& names,
@@ -566,11 +582,8 @@
for (size_t i = 0; i < expect.size() && i < sorted.size(); ++i) {
if (expect_names.size() > i)
- EXPECT_EQ(expect_names[i], sorted[i].name);
- EXPECT_EQ(expect[i].path.value(), sorted[i].path.value()) << test;
- EXPECT_FALSE(sorted[i].fsid.empty()) << test;
- if (!expect[i].fsid.empty())
- EXPECT_EQ(expect[i].fsid, sorted[i].fsid) << test;
+ EXPECT_EQ(expect_names[i], sorted[i].name) << test;
+ EXPECT_TRUE(ContainsEntry(expect[i], sorted)) << test;
}
}
@@ -1008,20 +1021,40 @@
one_expectation.push_back(added_info);
profile_state->AddNameForReadCompare(
+#if defined(OS_CHROMEOS)
empty_dir().BaseName().LossyDisplayName());
+#else
+ empty_dir().LossyDisplayName());
+#endif
profile_state->AddNameForAllCompare(
+#if defined(OS_CHROMEOS)
empty_dir().BaseName().LossyDisplayName());
+#else
+ empty_dir().LossyDisplayName());
+#endif
// This part of the test is conditional on default directories existing
// on the test platform. In ChromeOS, these directories do not exist.
base::FilePath path;
if (num_auto_galleries() > 0) {
ASSERT_TRUE(PathService::Get(chrome::DIR_USER_MUSIC, &path));
+#if defined(OS_CHROMEOS)
profile_state->AddNameForAllCompare(path.BaseName().LossyDisplayName());
+#else
+ profile_state->AddNameForAllCompare(path.LossyDisplayName());
+#endif
ASSERT_TRUE(PathService::Get(chrome::DIR_USER_PICTURES, &path));
+#if defined(OS_CHROMEOS)
profile_state->AddNameForAllCompare(path.BaseName().LossyDisplayName());
+#else
+ profile_state->AddNameForAllCompare(path.LossyDisplayName());
+#endif
ASSERT_TRUE(PathService::Get(chrome::DIR_USER_VIDEOS, &path));
+#if defined(OS_CHROMEOS)
profile_state->AddNameForAllCompare(path.BaseName().LossyDisplayName());
+#else
+ profile_state->AddNameForAllCompare(path.LossyDisplayName());
+#endif
profile_state->CheckGalleries("names-dir", one_expectation, auto_galleries);
} else {
diff --git a/chrome/browser/media_galleries/media_galleries_dialog_controller.cc b/chrome/browser/media_galleries/media_galleries_dialog_controller.cc
index c389f65..26fc81f 100644
--- a/chrome/browser/media_galleries/media_galleries_dialog_controller.cc
+++ b/chrome/browser/media_galleries/media_galleries_dialog_controller.cc
@@ -9,6 +9,7 @@
#include "base/strings/utf_string_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_histograms.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/storage_monitor/storage_info.h"
#include "chrome/browser/storage_monitor/storage_monitor.h"
@@ -87,7 +88,8 @@
}
string16 MediaGalleriesDialogController::GetHeader() const {
- return l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_HEADER);
+ return l10n_util::GetStringFUTF16(IDS_MEDIA_GALLERIES_DIALOG_HEADER,
+ UTF8ToUTF16(extension_->name()));
}
string16 MediaGalleriesDialogController::GetSubtext() const {
@@ -348,14 +350,22 @@
}
void MediaGalleriesDialogController::SavePermissions() {
+ media_galleries::UsageCount(media_galleries::SAVE_DIALOG);
for (KnownGalleryPermissions::const_iterator iter = known_galleries_.begin();
iter != known_galleries_.end(); ++iter) {
- preferences_->SetGalleryPermissionForExtension(
+ bool changed = preferences_->SetGalleryPermissionForExtension(
*extension_, iter->first, iter->second.allowed);
+ if (changed) {
+ if (iter->second.allowed)
+ media_galleries::UsageCount(media_galleries::DIALOG_PERMISSION_ADDED);
+ else
+ media_galleries::UsageCount(media_galleries::DIALOG_PERMISSION_REMOVED);
+ }
}
for (GalleryPermissionsVector::const_iterator iter = new_galleries_.begin();
iter != new_galleries_.end(); ++iter) {
+ media_galleries::UsageCount(media_galleries::DIALOG_GALLERY_ADDED);
// If the user added a gallery then unchecked it, forget about it.
if (!iter->allowed)
continue;
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 8590e80..9f43cef 100644
--- a/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc
@@ -24,17 +24,29 @@
gallery.device_id = StorageInfo::MakeDeviceId(
StorageInfo::FIXED_MASS_STORAGE, "/path/to/gallery");
gallery.type = MediaGalleryPrefInfo::kAutoDetected;
- EXPECT_EQ("gallery", GalleryName(gallery));
+ std::string galleryName("/path/to/gallery");
+#if defined(OS_CHROMEOS)
+ galleryName = "gallery";
+#endif
+ EXPECT_EQ(galleryName, GalleryName(gallery));
gallery.display_name = ASCIIToUTF16("override");
EXPECT_EQ("override", GalleryName(gallery));
gallery.display_name = string16();
gallery.volume_label = ASCIIToUTF16("label");
- EXPECT_EQ("gallery", GalleryName(gallery));
+ EXPECT_EQ(galleryName, GalleryName(gallery));
gallery.path = base::FilePath(FILE_PATH_LITERAL("sub/gallery2"));
- EXPECT_EQ("gallery2", GalleryName(gallery));
+ galleryName = "/path/to/gallery/sub/gallery2";
+#if defined(OS_CHROMEOS)
+ galleryName = "gallery2";
+#endif
+#if defined(OS_WIN)
+ galleryName = base::FilePath(FILE_PATH_LITERAL("/path/to/gallery"))
+ .Append(gallery.path).MaybeAsASCII();
+#endif
+ EXPECT_EQ(galleryName, GalleryName(gallery));
gallery.path = base::FilePath();
gallery.device_id = StorageInfo::MakeDeviceId(
diff --git a/chrome/browser/media_galleries/media_galleries_histograms.cc b/chrome/browser/media_galleries/media_galleries_histograms.cc
new file mode 100644
index 0000000..cf3f5c7
--- /dev/null
+++ b/chrome/browser/media_galleries/media_galleries_histograms.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/browser/media_galleries/media_galleries_histograms.h"
+
+#include "base/metrics/histogram.h"
+
+namespace media_galleries {
+
+void UsageCount(MediaGalleriesUsages usage) {
+ DCHECK_LT(usage, MEDIA_GALLERIES_NUM_USAGES);
+ UMA_HISTOGRAM_ENUMERATION("MediaGalleries.Usage", usage,
+ MEDIA_GALLERIES_NUM_USAGES);
+}
+
+} // namespace media_galleries
diff --git a/chrome/browser/media_galleries/media_galleries_histograms.h b/chrome/browser/media_galleries/media_galleries_histograms.h
new file mode 100644
index 0000000..d90cb05
--- /dev/null
+++ b/chrome/browser/media_galleries/media_galleries_histograms.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_MEDIA_GALLERIES_MEDIA_GALLERIES_HISTOGRAMS_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_HISTOGRAMS_H_
+
+namespace media_galleries {
+
+enum MediaGalleriesUsages {
+ DIALOG_GALLERY_ADDED,
+ DIALOG_PERMISSION_ADDED,
+ DIALOG_PERMISSION_REMOVED,
+ GET_MEDIA_FILE_SYSTEMS,
+ PROFILES_WITH_USAGE,
+ SHOW_DIALOG,
+ SAVE_DIALOG,
+ WEBUI_ADD_GALLERY,
+ WEBUI_FORGET_GALLERY,
+ MEDIA_GALLERIES_NUM_USAGES
+};
+
+void UsageCount(MediaGalleriesUsages usage);
+
+} // namespace media_galleries
+
+#endif // CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_HISTOGRAMS_H_
diff --git a/chrome/browser/media_galleries/media_galleries_preferences.cc b/chrome/browser/media_galleries/media_galleries_preferences.cc
index 61bd074..ac1e632 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/base_paths_posix.h"
#include "base/i18n/time_formatting.h"
#include "base/path_service.h"
#include "base/prefs/pref_service.h"
@@ -272,16 +273,27 @@
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?
+ // For fixed storage, the default name is the fully qualified directory
+ // name, or in the case of a root directory, the root directory name.
+ // Exception: ChromeOS -- the full pathname isn't visible there, so only
+ // the directory name is used.
base::FilePath path = AbsolutePath();
if (!display_name.empty())
return display_name;
- if (path == path.DirName())
- return path.LossyDisplayName();
+
+#if defined(OS_CHROMEOS)
+ // See chrome/browser/chromeos/fileapi/file_system_backend.cc
+ base::FilePath home_path;
+ if (PathService::Get(base::DIR_HOME, &home_path)) {
+ home_path = home_path.AppendASCII("Downloads");
+ base::FilePath relative;
+ if (home_path.AppendRelativePath(path, &relative))
+ return relative.LossyDisplayName();
+ }
return path.BaseName().LossyDisplayName();
+#else
+ return path.LossyDisplayName();
+#endif
}
string16 name = display_name;
@@ -794,7 +806,7 @@
return result;
}
-void MediaGalleriesPreferences::SetGalleryPermissionForExtension(
+bool MediaGalleriesPreferences::SetGalleryPermissionForExtension(
const extensions::Extension& extension,
MediaGalleryPrefId pref_id,
bool has_permission) {
@@ -803,7 +815,7 @@
MediaGalleriesPrefInfoMap::const_iterator gallery_info =
known_galleries_.find(pref_id);
if (gallery_info == known_galleries_.end())
- return;
+ return false;
bool default_permission = false;
if (gallery_info->second.type == MediaGalleryPrefInfo::kAutoDetected)
@@ -812,10 +824,10 @@
if (has_permission == default_permission) {
if (!UnsetGalleryPermissionInPrefs(extension.id(), pref_id))
// If permission wasn't set, assume nothing has changed.
- return;
+ return false;
} else {
if (!SetGalleryPermissionInPrefs(extension.id(), pref_id, has_permission))
- return;
+ return false;
}
if (has_permission)
FOR_EACH_OBSERVER(GalleryChangeObserver,
@@ -825,6 +837,7 @@
FOR_EACH_OBSERVER(GalleryChangeObserver,
gallery_change_observers_,
OnPermissionRemoved(this, extension.id(), pref_id));
+ return true;
}
void MediaGalleriesPreferences::Shutdown() {
diff --git a/chrome/browser/media_galleries/media_galleries_preferences.h b/chrome/browser/media_galleries/media_galleries_preferences.h
index a65a2be..40ab10a 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences.h
+++ b/chrome/browser/media_galleries/media_galleries_preferences.h
@@ -197,7 +197,9 @@
MediaGalleryPrefIdSet GalleriesForExtension(
const extensions::Extension& extension) const;
- void SetGalleryPermissionForExtension(const extensions::Extension& extension,
+ // Returns true if the permission changed. Returns false if there was
+ // no change.
+ bool SetGalleryPermissionForExtension(const extensions::Extension& extension,
MediaGalleryPrefId pref_id,
bool has_permission);
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 7e50792..373e088 100644
--- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -20,6 +20,7 @@
#include "content/public/browser/browser_thread.h"
#include "ui/base/touch/touch_device.h"
#include "ui/base/ui_base_switches.h"
+#include "ui/events/event_switches.h"
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
#include <gnu/libc-version.h>
diff --git a/chrome/browser/net/chrome_network_data_saving_metrics.cc b/chrome/browser/net/chrome_network_data_saving_metrics.cc
new file mode 100644
index 0000000..59fc447
--- /dev/null
+++ b/chrome/browser/net/chrome_network_data_saving_metrics.cc
@@ -0,0 +1,342 @@
+// Copyright 2013 The Chromium 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/chrome_network_data_saving_metrics.h"
+
+#include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/common/pref_names.h"
+
+#if defined(OS_ANDROID)
+namespace {
+
+// The number of days of history stored in the content lengths prefs.
+const size_t kNumDaysInHistory = 60;
+
+// Increments an int64, stored as a string, in a ListPref at the specified
+// index. The value must already exist and be a string representation of a
+// number.
+void AddInt64ToListPref(size_t index,
+ int64 length,
+ base::ListValue* list_update) {
+ int64 value = 0;
+ std::string old_string_value;
+ bool rv = list_update->GetString(index, &old_string_value);
+ DCHECK(rv);
+ if (rv) {
+ rv = base::StringToInt64(old_string_value, &value);
+ DCHECK(rv);
+ }
+ value += length;
+ list_update->Set(index, Value::CreateStringValue(base::Int64ToString(value)));
+}
+
+int64 ListPrefInt64Value(const base::ListValue& list_update, size_t index) {
+ std::string string_value;
+ if (!list_update.GetString(index, &string_value)) {
+ NOTREACHED();
+ return 0;
+ }
+
+ int64 value = 0;
+ bool rv = base::StringToInt64(string_value, &value);
+ DCHECK(rv);
+ return value;
+}
+
+// Report UMA metrics for daily data reductions.
+void RecordDailyContentLengthHistograms(
+ int64 original_length,
+ int64 received_length,
+ int64 original_length_with_data_reduction_enabled,
+ int64 received_length_with_data_reduction_enabled,
+ int64 original_length_via_data_reduction_proxy,
+ int64 received_length_via_data_reduction_proxy) {
+ // Report daily UMA only for days having received content.
+ if (original_length <= 0 || received_length <= 0)
+ return;
+
+ // Record metrics in KB.
+ UMA_HISTOGRAM_COUNTS(
+ "Net.DailyOriginalContentLength", original_length >> 10);
+ UMA_HISTOGRAM_COUNTS(
+ "Net.DailyContentLength", received_length >> 10);
+ int percent = 0;
+ // UMA percentage cannot be negative.
+ if (original_length > received_length) {
+ percent = (100 * (original_length - received_length)) / original_length;
+ }
+ UMA_HISTOGRAM_PERCENTAGE("Net.DailyContentSavingPercent", percent);
+
+ if (original_length_with_data_reduction_enabled <= 0 ||
+ received_length_with_data_reduction_enabled <= 0) {
+ return;
+ }
+
+ UMA_HISTOGRAM_COUNTS(
+ "Net.DailyOriginalContentLength_DataReductionProxyEnabled",
+ original_length_with_data_reduction_enabled >> 10);
+ UMA_HISTOGRAM_COUNTS(
+ "Net.DailyContentLength_DataReductionProxyEnabled",
+ received_length_with_data_reduction_enabled >> 10);
+
+ int percent_data_reduction_proxy_enabled = 0;
+ // UMA percentage cannot be negative.
+ if (original_length_with_data_reduction_enabled >
+ received_length_with_data_reduction_enabled) {
+ percent_data_reduction_proxy_enabled =
+ 100 * (original_length_with_data_reduction_enabled -
+ received_length_with_data_reduction_enabled) /
+ original_length_with_data_reduction_enabled;
+ }
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Net.DailyContentSavingPercent_DataReductionProxyEnabled",
+ percent_data_reduction_proxy_enabled);
+
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Net.DailyContentPercent_DataReductionProxyEnabled",
+ (100 * received_length_with_data_reduction_enabled) / received_length);
+
+ if (original_length_via_data_reduction_proxy <= 0 ||
+ received_length_via_data_reduction_proxy <= 0) {
+ return;
+ }
+
+ UMA_HISTOGRAM_COUNTS(
+ "Net.DailyOriginalContentLength_ViaDataReductionProxy",
+ original_length_via_data_reduction_proxy >> 10);
+ UMA_HISTOGRAM_COUNTS(
+ "Net.DailyContentLength_ViaDataReductionProxy",
+ received_length_via_data_reduction_proxy >> 10);
+ int percent_via_data_reduction_proxy = 0;
+ if (original_length_via_data_reduction_proxy >
+ received_length_via_data_reduction_proxy) {
+ percent_via_data_reduction_proxy =
+ 100 * (original_length_via_data_reduction_proxy -
+ received_length_via_data_reduction_proxy) /
+ original_length_via_data_reduction_proxy;
+ }
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Net.DailyContentSavingPercent_ViaDataReductionProxy",
+ percent_via_data_reduction_proxy);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Net.DailyContentPercent_ViaDataReductionProxy",
+ (100 * received_length_via_data_reduction_proxy) / received_length);
+}
+
+// Ensure list has exactly |length| elements, either by truncating at the
+// front, or appending "0"'s to the back.
+void MaintainContentLengthPrefsWindow(base::ListValue* list, size_t length) {
+ // Remove data for old days from the front.
+ while (list->GetSize() > length)
+ list->Remove(0, NULL);
+ // Newly added lists are empty. Add entries to back to fill the window,
+ // each initialized to zero.
+ while (list->GetSize() < length)
+ list->AppendString(base::Int64ToString(0));
+ DCHECK_EQ(length, list->GetSize());
+}
+
+// Update list for date change and ensure list has exactly |length| elements.
+// The last entry in each list will be for the current day after the update.
+void MaintainContentLengthPrefsForDateChange(
+ base::ListValue* original_update,
+ base::ListValue* received_update,
+ int days_since_last_update) {
+ if (days_since_last_update == -1) {
+ // The system may go backwards in time by up to a day for legitimate
+ // reasons, such as with changes to the time zone. In such cases, we
+ // keep adding to the current day.
+ // Note: we accept the fact that some reported data is shifted to
+ // the adjacent day if users travel back and forth across time zones.
+ days_since_last_update = 0;
+ } else if (days_since_last_update < -1) {
+ // Erase all entries if the system went backwards in time by more than
+ // a day.
+ original_update->Clear();
+ received_update->Clear();
+
+ days_since_last_update = kNumDaysInHistory;
+ }
+ DCHECK_GE(days_since_last_update, 0);
+
+ // Add entries for days since last update event. This will make the
+ // lists longer than kNumDaysInHistory. The additional items will be cut off
+ // from the head of the lists by |MaintainContentLengthPrefsWindow|, below.
+ for (int i = 0;
+ i < days_since_last_update && i < static_cast<int>(kNumDaysInHistory);
+ ++i) {
+ original_update->AppendString(base::Int64ToString(0));
+ received_update->AppendString(base::Int64ToString(0));
+ }
+
+ // Entries for new days may have been appended. Maintain the invariant that
+ // there should be exactly |kNumDaysInHistory| days in the histories.
+ MaintainContentLengthPrefsWindow(original_update, kNumDaysInHistory);
+ MaintainContentLengthPrefsWindow(received_update, kNumDaysInHistory);
+}
+
+// DailyDataSavingUpdate maintains a pair of data saving prefs, original_update_
+// and received_update_. pref_original is a list of |kNumDaysInHistory| elements
+// of daily total original content lengths for the past |kNumDaysInHistory|
+// days. pref_received is the corresponding list of the daily total received
+// content lengths.
+class DailyDataSavingUpdate {
+ public:
+ DailyDataSavingUpdate(
+ const char* pref_original, const char* pref_received,
+ PrefService* pref_service)
+ : pref_original_(pref_original),
+ pref_received_(pref_received),
+ original_update_(pref_service, pref_original_),
+ received_update_(pref_service, pref_received_) {
+ }
+
+ void UpdateForDataChange(int days_since_last_update) {
+ // New empty lists may have been created. Maintain the invariant that
+ // there should be exactly |kNumDaysInHistory| days in the histories.
+ MaintainContentLengthPrefsWindow(original_update_.Get(), kNumDaysInHistory);
+ MaintainContentLengthPrefsWindow(received_update_.Get(), kNumDaysInHistory);
+ if (days_since_last_update) {
+ MaintainContentLengthPrefsForDateChange(
+ original_update_.Get(), received_update_.Get(),
+ days_since_last_update);
+ }
+ }
+
+ // Update the lengths for the current day.
+ void Add(int original_content_length, int received_content_length) {
+ AddInt64ToListPref(
+ kNumDaysInHistory - 1, original_content_length, original_update_.Get());
+ AddInt64ToListPref(
+ kNumDaysInHistory - 1, received_content_length, received_update_.Get());
+ }
+
+ int64 GetOriginalListPrefValue(size_t index) {
+ return ListPrefInt64Value(*original_update_, index);
+ }
+ int64 GetReceivedListPrefValue(size_t index) {
+ return ListPrefInt64Value(*received_update_, index);
+ }
+
+ private:
+ const char* pref_original_;
+ const char* pref_received_;
+ ListPrefUpdate original_update_;
+ ListPrefUpdate received_update_;
+};
+
+} // namespace
+#endif // defined(OS_ANDROID)
+
+namespace chrome_browser_net {
+
+#if defined(OS_ANDROID)
+void UpdateContentLengthPrefsForDataReductionProxy(
+ int received_content_length, int original_content_length,
+ bool with_data_reduction_proxy_enabled, bool via_data_reduction_proxy,
+ base::Time now, PrefService* prefs) {
+ // TODO(bengr): Remove this check once the underlying cause of
+ // http://crbug.com/287821 is fixed. For now, only continue if the current
+ // year is reported as being between 1972 and 2970.
+ base::TimeDelta time_since_unix_epoch = now - base::Time::UnixEpoch();
+ const int kMinDaysSinceUnixEpoch = 365 * 2; // 2 years.
+ const int kMaxDaysSinceUnixEpoch = 365 * 1000; // 1000 years.
+ if (time_since_unix_epoch.InDays() < kMinDaysSinceUnixEpoch ||
+ time_since_unix_epoch.InDays() > kMaxDaysSinceUnixEpoch) {
+ return;
+ }
+
+ // Determine how many days it has been since the last update.
+ int64 then_internal = prefs->GetInt64(
+ prefs::kDailyHttpContentLengthLastUpdateDate);
+ // Local midnight could have been shifted due to time zone change.
+ base::Time then_midnight =
+ base::Time::FromInternalValue(then_internal).LocalMidnight();
+ base::Time midnight = now.LocalMidnight();
+ int days_since_last_update = (midnight - then_midnight).InDays();
+
+ // Each day, we calculate the total number of bytes received and the total
+ // size of all corresponding resources before any data-reducing recompression
+ // is applied. These values are used to compute the data savings realized
+ // by applying our compression techniques. Totals for the last
+ // |kNumDaysInHistory| days are maintained.
+ DailyDataSavingUpdate total(
+ prefs::kDailyHttpOriginalContentLength,
+ prefs::kDailyHttpReceivedContentLength,
+ prefs);
+ total.UpdateForDataChange(days_since_last_update);
+
+ DailyDataSavingUpdate proxy_enabled(
+ prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled,
+ prefs::kDailyContentLengthWithDataReductionProxyEnabled,
+ prefs);
+ proxy_enabled.UpdateForDataChange(days_since_last_update);
+
+ DailyDataSavingUpdate via_proxy(
+ prefs::kDailyOriginalContentLengthViaDataReductionProxy,
+ prefs::kDailyContentLengthViaDataReductionProxy,
+ prefs);
+ via_proxy.UpdateForDataChange(days_since_last_update);
+
+ total.Add(original_content_length, received_content_length);
+ if (with_data_reduction_proxy_enabled) {
+ proxy_enabled.Add(original_content_length, received_content_length);
+ // Ignore cases, if exist, when
+ // "with_data_reduction_proxy_enabled == false", and
+ // "via_data_reduction_proxy == true"
+ if (via_data_reduction_proxy) {
+ via_proxy.Add(original_content_length, received_content_length);
+ }
+ }
+
+ if (days_since_last_update) {
+ // Record the last update time in microseconds in UTC.
+ prefs->SetInt64(prefs::kDailyHttpContentLengthLastUpdateDate,
+ midnight.ToInternalValue());
+
+ // A new day. Report the previous day's data if exists. We'll lose usage
+ // data if the last time Chrome was run was more than a day ago.
+ // Here, we prefer collecting less data but the collected data is
+ // associated with an accurate date.
+ if (days_since_last_update == 1) {
+ // The previous day's data point is the second one from the tail.
+ RecordDailyContentLengthHistograms(
+ total.GetOriginalListPrefValue(kNumDaysInHistory - 2),
+ total.GetReceivedListPrefValue(kNumDaysInHistory - 2),
+ proxy_enabled.GetOriginalListPrefValue(kNumDaysInHistory - 2),
+ proxy_enabled.GetReceivedListPrefValue(kNumDaysInHistory - 2),
+ via_proxy.GetOriginalListPrefValue(kNumDaysInHistory - 2),
+ via_proxy.GetReceivedListPrefValue(kNumDaysInHistory - 2));
+ }
+ }
+}
+#endif // defined(OS_ANDROID)
+
+void UpdateContentLengthPrefs(
+ int received_content_length, int original_content_length,
+ bool with_data_reduction_proxy_enabled, bool via_data_reduction_proxy,
+ PrefService* prefs) {
+ int64 total_received = prefs->GetInt64(prefs::kHttpReceivedContentLength);
+ int64 total_original = prefs->GetInt64(prefs::kHttpOriginalContentLength);
+ total_received += received_content_length;
+ total_original += original_content_length;
+ prefs->SetInt64(prefs::kHttpReceivedContentLength, total_received);
+ prefs->SetInt64(prefs::kHttpOriginalContentLength, total_original);
+
+#if defined(OS_ANDROID)
+ UpdateContentLengthPrefsForDataReductionProxy(
+ received_content_length,
+ original_content_length,
+ with_data_reduction_proxy_enabled,
+ via_data_reduction_proxy,
+ base::Time::Now(),
+ prefs);
+#endif // defined(OS_ANDROID)
+
+}
+
+} // namespace chrome_browser_net
diff --git a/chrome/browser/net/chrome_network_data_saving_metrics.h b/chrome/browser/net/chrome_network_data_saving_metrics.h
new file mode 100644
index 0000000..5d201fe
--- /dev/null
+++ b/chrome/browser/net/chrome_network_data_saving_metrics.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_BROWSER_NET_CHROME_NETWORK_DATA_SAVING_METRICS_H_
+#define CHROME_BROWSER_NET_CHROME_NETWORK_DATA_SAVING_METRICS_H_
+
+#include "base/time/time.h"
+
+class PrefService;
+
+namespace chrome_browser_net {
+
+#if defined(OS_ANDROID)
+// This is only exposed for testing. It is normally called by
+// UpdateContentLengthPrefs.
+void UpdateContentLengthPrefsForDataReductionProxy(
+ int received_content_length, int original_content_length,
+ bool with_data_reduction_proxy_enabled, bool via_data_reduction_proxy,
+ base::Time now, PrefService* prefs);
+#endif
+
+// Records daily data savings statistics to prefs and reports data savings UMA.
+void UpdateContentLengthPrefs(
+ int received_content_length,
+ int original_content_length,
+ bool with_data_reduction_proxy_enabled,
+ bool via_data_reduction_proxy,
+ PrefService* prefs);
+
+} // namespace chrome_browser_net
+
+#endif // CHROME_BROWSER_NET_CHROME_NETWORK_DATA_SAVING_METRICS_H_
diff --git a/chrome/browser/net/chrome_network_data_saving_metrics_unittest.cc b/chrome/browser/net/chrome_network_data_saving_metrics_unittest.cc
new file mode 100644
index 0000000..1089476
--- /dev/null
+++ b/chrome/browser/net/chrome_network_data_saving_metrics_unittest.cc
@@ -0,0 +1,483 @@
+// Copyright 2013 The Chromium 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/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "base/prefs/testing_pref_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/net/chrome_network_data_saving_metrics.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/common/pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+#if defined(OS_ANDROID)
+const size_t kNumDaysInHistory = 60;
+
+int64 GetListPrefInt64Value(
+ const base::ListValue& list_update, size_t index) {
+ std::string string_value;
+ EXPECT_TRUE(list_update.GetString(index, &string_value));
+
+ int64 value = 0;
+ EXPECT_TRUE(base::StringToInt64(string_value, &value));
+ return value;
+}
+
+#endif // defined(OS_ANDROID)
+
+// Test UpdateContentLengthPrefs.
+class ChromeNetworkDataSavingMetricsTest : public testing::Test {
+ protected:
+ ChromeNetworkDataSavingMetricsTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ PrefRegistrySimple* registry = pref_service_.registry();
+ registry->RegisterInt64Pref(prefs::kHttpReceivedContentLength, 0);
+ registry->RegisterInt64Pref(prefs::kHttpOriginalContentLength, 0);
+
+#if defined(OS_ANDROID)
+ registry->RegisterListPref(prefs::kDailyHttpOriginalContentLength);
+ registry->RegisterListPref(prefs::kDailyHttpReceivedContentLength);
+ registry->RegisterListPref(
+ prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled);
+ registry->RegisterListPref(
+ prefs::kDailyContentLengthWithDataReductionProxyEnabled);
+ registry->RegisterListPref(
+ prefs::kDailyOriginalContentLengthViaDataReductionProxy);
+ registry->RegisterListPref(
+ prefs::kDailyContentLengthViaDataReductionProxy);
+ registry->RegisterInt64Pref(
+ prefs::kDailyHttpContentLengthLastUpdateDate, 0L);
+#endif // defined(OS_ANDROID)
+ }
+
+ TestingPrefServiceSimple pref_service_;
+};
+
+TEST_F(ChromeNetworkDataSavingMetricsTest, TotalLengths) {
+ const int64 kOriginalLength = 200;
+ const int64 kReceivedLength = 100;
+
+ chrome_browser_net::UpdateContentLengthPrefs(
+ kReceivedLength, kOriginalLength,
+ false, false, &pref_service_);
+ EXPECT_EQ(kReceivedLength,
+ pref_service_.GetInt64(prefs::kHttpReceivedContentLength));
+ EXPECT_EQ(kOriginalLength,
+ pref_service_.GetInt64(prefs::kHttpOriginalContentLength));
+
+ // Record the same numbers again, and total lengths should be dobuled.
+ chrome_browser_net::UpdateContentLengthPrefs(
+ kReceivedLength, kOriginalLength,
+ false, false, &pref_service_);
+ EXPECT_EQ(kReceivedLength * 2,
+ pref_service_.GetInt64(prefs::kHttpReceivedContentLength));
+ EXPECT_EQ(kOriginalLength * 2,
+ pref_service_.GetInt64(prefs::kHttpOriginalContentLength));
+}
+
+#if defined(OS_ANDROID)
+
+// The initial last update time used in test. There is no leap second a few
+// days around this time used in the test.
+// Note: No time zone is specified. Local time will be assumed by
+// base::Time::FromString below.
+const char kLastUpdateTime[] = "Wed, 18 Sep 2013 03:45:26";
+
+class ChromeNetworkDailyDataSavingMetricsTest
+ : public ChromeNetworkDataSavingMetricsTest {
+ protected:
+ ChromeNetworkDailyDataSavingMetricsTest() {
+ base::Time::FromString(kLastUpdateTime, &now_);
+ }
+
+ virtual void SetUp() OVERRIDE {
+ ChromeNetworkDataSavingMetricsTest::SetUp();
+
+ // Only create two lists in Setup to test that adding new lists is fine.
+ CreatePrefList(prefs::kDailyHttpOriginalContentLength);
+ CreatePrefList(prefs::kDailyHttpReceivedContentLength);
+ }
+
+ base::Time FakeNow() const {
+ return now_ + now_delta_;
+ }
+
+ void SetFakeTimeDeltaInHours(int hours) {
+ now_delta_ = base::TimeDelta::FromHours(hours);
+ }
+
+ void AddFakeTimeDeltaInHours(int hours) {
+ now_delta_ += base::TimeDelta::FromHours(hours);
+ }
+
+ // Create daily pref list of |kNumDaysInHistory| zero values.
+ void CreatePrefList(const char* pref) {
+ ListPrefUpdate update(&pref_service_, pref);
+ update->Clear();
+ for (size_t i = 0; i < kNumDaysInHistory; ++i) {
+ update->Insert(0, new StringValue(base::Int64ToString(0)));
+ }
+ }
+
+ // Verify the pref list values are equal to the given values.
+ // If the count of values is less than kNumDaysInHistory, zeros are assumed
+ // at the beginning.
+ void VerifyPrefList(const char* pref, const int64* values, size_t count) {
+ ASSERT_GE(kNumDaysInHistory, count);
+ ListPrefUpdate update(&pref_service_, pref);
+ ASSERT_EQ(kNumDaysInHistory, update->GetSize()) << "Pref: " << pref;
+
+ for (size_t i = 0; i < count; ++i) {
+ EXPECT_EQ(
+ values[i],
+ GetListPrefInt64Value(*update, kNumDaysInHistory - count + i))
+ << "index=" << (kNumDaysInHistory - count + i);
+ }
+ for (size_t i = 0; i < kNumDaysInHistory - count; ++i) {
+ EXPECT_EQ(0, GetListPrefInt64Value(*update, i)) << "index=" << i;
+ }
+ }
+
+ // Verify all daily pref list values.
+ void VerifyDailyContentLengthPrefLists(
+ const int64* original_values, size_t original_count,
+ const int64* received_values, size_t received_count,
+ const int64* original_with_data_reduction_proxy_enabled_values,
+ size_t original_with_data_reduction_proxy_enabled_count,
+ const int64* received_with_data_reduction_proxy_enabled_values,
+ size_t received_with_data_reduction_proxy_count,
+ const int64* original_via_data_reduction_proxy_values,
+ size_t original_via_data_reduction_proxy_count,
+ const int64* received_via_data_reduction_proxy_values,
+ size_t received_via_data_reduction_proxy_count) {
+ VerifyPrefList(prefs::kDailyHttpOriginalContentLength,
+ original_values, original_count);
+ VerifyPrefList(prefs::kDailyHttpReceivedContentLength,
+ received_values, received_count);
+ VerifyPrefList(
+ prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled,
+ original_with_data_reduction_proxy_enabled_values,
+ original_with_data_reduction_proxy_enabled_count);
+ VerifyPrefList(
+ prefs::kDailyContentLengthWithDataReductionProxyEnabled,
+ received_with_data_reduction_proxy_enabled_values,
+ received_with_data_reduction_proxy_count);
+ VerifyPrefList(
+ prefs::kDailyOriginalContentLengthViaDataReductionProxy,
+ original_via_data_reduction_proxy_values,
+ original_via_data_reduction_proxy_count);
+ VerifyPrefList(
+ prefs::kDailyContentLengthViaDataReductionProxy,
+ received_via_data_reduction_proxy_values,
+ received_via_data_reduction_proxy_count);
+ }
+
+ private:
+ base::Time now_;
+ base::TimeDelta now_delta_;
+};
+
+TEST_F(ChromeNetworkDailyDataSavingMetricsTest, OneResponse) {
+ const int64 kOriginalLength = 200;
+ const int64 kReceivedLength = 100;
+ int64 original[] = {kOriginalLength};
+ int64 received[] = {kReceivedLength};
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ VerifyDailyContentLengthPrefLists(
+ original, 1, received, 1,
+ original, 1, received, 1,
+ original, 1, received, 1);
+}
+
+TEST_F(ChromeNetworkDailyDataSavingMetricsTest, MultipleResponses) {
+ const int64 kOriginalLength = 150;
+ const int64 kReceivedLength = 100;
+ int64 original[] = {kOriginalLength};
+ int64 received[] = {kReceivedLength};
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ false, false, FakeNow(), &pref_service_);
+ VerifyDailyContentLengthPrefLists(
+ original, 1, received, 1,
+ NULL, 0, NULL, 0, NULL, 0, NULL, 0);
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, false, FakeNow(), &pref_service_);
+ original[0] += kOriginalLength;
+ received[0] += kReceivedLength;
+ int64 original_proxy_enabled[] = {kOriginalLength};
+ int64 received_proxy_enabled[] = {kReceivedLength};
+ VerifyDailyContentLengthPrefLists(
+ original, 1, received, 1,
+ original_proxy_enabled, 1, received_proxy_enabled, 1,
+ NULL, 0, NULL, 0);
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ original[0] += kOriginalLength;
+ received[0] += kReceivedLength;
+ original_proxy_enabled[0] += kOriginalLength;
+ received_proxy_enabled[0] += kReceivedLength;
+ int64 original_via_proxy[] = {kOriginalLength};
+ int64 received_via_proxy[] = {kReceivedLength};
+ VerifyDailyContentLengthPrefLists(
+ original, 1, received, 1,
+ original_proxy_enabled, 1, received_proxy_enabled, 1,
+ original_via_proxy, 1, received_via_proxy, 1);
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, false, FakeNow(), &pref_service_);
+ original[0] += kOriginalLength;
+ received[0] += kReceivedLength;
+ original_proxy_enabled[0] += kOriginalLength;
+ received_proxy_enabled[0] += kReceivedLength;
+ VerifyDailyContentLengthPrefLists(
+ original, 1, received, 1,
+ original_proxy_enabled, 1, received_proxy_enabled, 1,
+ original_via_proxy, 1, received_via_proxy, 1);
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ false, false, FakeNow(), &pref_service_);
+ original[0] += kOriginalLength;
+ received[0] += kReceivedLength;
+ VerifyDailyContentLengthPrefLists(
+ original, 1, received, 1,
+ original_proxy_enabled, 1, received_proxy_enabled, 1,
+ original_via_proxy, 1, received_via_proxy, 1);
+}
+
+TEST_F(ChromeNetworkDailyDataSavingMetricsTest, ForwardOneDay) {
+ const int64 kOriginalLength = 200;
+ const int64 kReceivedLength = 100;
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+
+ // Forward one day.
+ SetFakeTimeDeltaInHours(24);
+
+ // Proxy not enabled. Not via proxy.
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ false, false, FakeNow(), &pref_service_);
+
+ int64 original[] = {kOriginalLength, kOriginalLength};
+ int64 received[] = {kReceivedLength, kReceivedLength};
+ int64 original_with_data_reduction_proxy_enabled[] = {kOriginalLength, 0};
+ int64 received_with_data_reduction_proxy_enabled[] = {kReceivedLength, 0};
+ int64 original_via_data_reduction_proxy[] = {kOriginalLength, 0};
+ int64 received_via_data_reduction_proxy[] = {kReceivedLength, 0};
+ VerifyDailyContentLengthPrefLists(
+ original, 2,
+ received, 2,
+ original_with_data_reduction_proxy_enabled, 2,
+ received_with_data_reduction_proxy_enabled, 2,
+ original_via_data_reduction_proxy, 2,
+ received_via_data_reduction_proxy, 2);
+
+ // Proxy enabled. Not via proxy.
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, false, FakeNow(), &pref_service_);
+ original[1] += kOriginalLength;
+ received[1] += kReceivedLength;
+ original_with_data_reduction_proxy_enabled[1] += kOriginalLength;
+ received_with_data_reduction_proxy_enabled[1] += kReceivedLength;
+ VerifyDailyContentLengthPrefLists(
+ original, 2,
+ received, 2,
+ original_with_data_reduction_proxy_enabled, 2,
+ received_with_data_reduction_proxy_enabled, 2,
+ original_via_data_reduction_proxy, 2,
+ received_via_data_reduction_proxy, 2);
+
+ // Proxy enabled and via proxy.
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ original[1] += kOriginalLength;
+ received[1] += kReceivedLength;
+ original_with_data_reduction_proxy_enabled[1] += kOriginalLength;
+ received_with_data_reduction_proxy_enabled[1] += kReceivedLength;
+ original_via_data_reduction_proxy[1] += kOriginalLength;
+ received_via_data_reduction_proxy[1] += kReceivedLength;
+ VerifyDailyContentLengthPrefLists(
+ original, 2,
+ received, 2,
+ original_with_data_reduction_proxy_enabled, 2,
+ received_with_data_reduction_proxy_enabled, 2,
+ original_via_data_reduction_proxy, 2,
+ received_via_data_reduction_proxy, 2);
+}
+
+TEST_F(ChromeNetworkDailyDataSavingMetricsTest, PartialDayTimeChange) {
+ const int64 kOriginalLength = 200;
+ const int64 kReceivedLength = 100;
+ int64 original[] = {0, kOriginalLength};
+ int64 received[] = {0, kReceivedLength};
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ VerifyDailyContentLengthPrefLists(
+ original, 2, received, 2,
+ original, 2, received, 2,
+ original, 2, received, 2);
+
+ // Forward 10 hours, stay in the same day.
+ // See kLastUpdateTime: "Now" in test is 03:45am.
+ SetFakeTimeDeltaInHours(10);
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ original[1] += kOriginalLength;
+ received[1] += kReceivedLength;
+ VerifyDailyContentLengthPrefLists(
+ original, 2, received, 2,
+ original, 2, received, 2,
+ original, 2, received, 2);
+
+ // Forward 11 more hours, comes to tomorrow.
+ AddFakeTimeDeltaInHours(11);
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ int64 original2[] = {kOriginalLength * 2, kOriginalLength};
+ int64 received2[] = {kReceivedLength * 2, kReceivedLength};
+ VerifyDailyContentLengthPrefLists(
+ original2, 2, received2, 2,
+ original2, 2, received2, 2,
+ original2, 2, received2, 2);
+}
+
+TEST_F(ChromeNetworkDailyDataSavingMetricsTest, ForwardMultipleDays) {
+ const int64 kOriginalLength = 200;
+ const int64 kReceivedLength = 100;
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+
+ // Forward three days.
+ SetFakeTimeDeltaInHours(3 * 24);
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+
+ int64 original[] = {kOriginalLength, 0, 0, kOriginalLength};
+ int64 received[] = {kReceivedLength, 0, 0, kReceivedLength};
+ VerifyDailyContentLengthPrefLists(
+ original, 4, received, 4,
+ original, 4, received, 4,
+ original, 4, received, 4);
+
+ // Forward four more days.
+ AddFakeTimeDeltaInHours(4 * 24);
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ int64 original2[] = {
+ kOriginalLength, 0, 0, kOriginalLength, 0, 0, 0, kOriginalLength,
+ };
+ int64 received2[] = {
+ kReceivedLength, 0, 0, kReceivedLength, 0, 0, 0, kReceivedLength,
+ };
+ VerifyDailyContentLengthPrefLists(
+ original2, 8, received2, 8,
+ original2, 8, received2, 8,
+ original2, 8, received2, 8);
+
+ // Forward |kNumDaysInHistory| more days.
+ AddFakeTimeDeltaInHours(kNumDaysInHistory * 24);
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ int64 original3[] = {kOriginalLength};
+ int64 received3[] = {kReceivedLength};
+ VerifyDailyContentLengthPrefLists(
+ original3, 1, received3, 1,
+ original3, 1, received3, 1,
+ original3, 1, received3, 1);
+
+ // Forward |kNumDaysInHistory| + 1 more days.
+ AddFakeTimeDeltaInHours((kNumDaysInHistory + 1)* 24);
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ VerifyDailyContentLengthPrefLists(
+ original3, 1, received3, 1,
+ original3, 1, received3, 1,
+ original3, 1, received3, 1);
+}
+
+TEST_F(ChromeNetworkDailyDataSavingMetricsTest, BackwardAndForwardOneDay) {
+ const int64 kOriginalLength = 200;
+ const int64 kReceivedLength = 100;
+ int64 original[] = {kOriginalLength};
+ int64 received[] = {kReceivedLength};
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+
+ // Backward one day.
+ SetFakeTimeDeltaInHours(-24);
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ original[0] += kOriginalLength;
+ received[0] += kReceivedLength;
+ VerifyDailyContentLengthPrefLists(
+ original, 1, received, 1,
+ original, 1, received, 1,
+ original, 1, received, 1);
+
+ // Then, Forward one day
+ AddFakeTimeDeltaInHours(24);
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ int64 original2[] = {kOriginalLength * 2, kOriginalLength};
+ int64 received2[] = {kReceivedLength * 2, kReceivedLength};
+ VerifyDailyContentLengthPrefLists(
+ original2, 2, received2, 2,
+ original2, 2, received2, 2,
+ original2, 2, received2, 2);
+}
+
+TEST_F(ChromeNetworkDailyDataSavingMetricsTest, BackwardTwoDays) {
+ const int64 kOriginalLength = 200;
+ const int64 kReceivedLength = 100;
+ int64 original[] = {kOriginalLength};
+ int64 received[] = {kReceivedLength};
+
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ // Backward two days.
+ SetFakeTimeDeltaInHours(-2 * 24);
+ chrome_browser_net::UpdateContentLengthPrefsForDataReductionProxy(
+ kReceivedLength, kOriginalLength,
+ true, true, FakeNow(), &pref_service_);
+ VerifyDailyContentLengthPrefLists(
+ original, 1, received, 1,
+ original, 1, received, 1,
+ original, 1, received, 1);
+}
+#endif // defined(OS_ANDROID)
+
+} // namespace
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index 3c0ba5d..11a211f 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -29,10 +29,10 @@
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/net/chrome_network_data_saving_metrics.h"
#include "chrome/browser/net/connect_interceptor.h"
#include "chrome/browser/net/load_time_stats.h"
#include "chrome/browser/performance_monitor/performance_monitor.h"
-#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/task_manager/task_manager.h"
#include "chrome/common/pref_names.h"
@@ -214,96 +214,9 @@
}
}
-#if defined(OS_ANDROID) || defined(OS_IOS)
-// Increments an int64, stored as a string, in a ListPref at the specified
-// index. The value must already exist and be a string representation of a
-// number.
-void AddInt64ToListPref(size_t index, int64 length,
- base::ListValue* list_update) {
- int64 value = 0;
- std::string old_string_value;
- bool rv = list_update->GetString(index, &old_string_value);
- DCHECK(rv);
- if (rv) {
- rv = base::StringToInt64(old_string_value, &value);
- DCHECK(rv);
- }
- value += length;
- list_update->Set(index, Value::CreateStringValue(base::Int64ToString(value)));
-}
-
-int64 ListPrefInt64Value(const base::ListValue& list_update, size_t index) {
- std::string string_value;
- if (!list_update.GetString(index, &string_value))
- return 0;
-
- int64 value = 0;
- bool rv = base::StringToInt64(string_value, &value);
- DCHECK(rv);
- return value;
-}
-
-// Ensure list has exactly n elements.
-void MaintainContentLengthPrefsWindow(base::ListValue* list, size_t n) {
- // Remove data for old days from the front.
- while (list->GetSize() > n)
- list->Remove(0, NULL);
- // Newly added lists are empty. Add entries to back to fill the window,
- // each initialized to zero.
- while (list->GetSize() < n)
- list->AppendString(base::Int64ToString(0));
- DCHECK_EQ(n, list->GetSize());
-}
-
-void RecordDailyContentLengthHistograms(
- int64 original_length,
- int64 received_length,
- int64 length_with_data_reduction_enabled,
- int64 length_via_data_reduction_proxy) {
- // Record metrics in KB.
- UMA_HISTOGRAM_COUNTS(
- "Net.DailyHttpOriginalContentLength", original_length >> 10);
- UMA_HISTOGRAM_COUNTS(
- "Net.DailyHttpReceivedContentLength", received_length >> 10);
- UMA_HISTOGRAM_COUNTS(
- "Net.DailyHttpContentLengthWithDataReductionProxyEnabled",
- length_with_data_reduction_enabled >> 10);
- UMA_HISTOGRAM_COUNTS(
- "Net.DailyHttpContentLengthViaDataReductionProxy",
- length_via_data_reduction_proxy >> 10);
-
- if (original_length > 0 && received_length > 0) {
- int percent = (100 * (original_length - received_length)) / original_length;
- // UMA percentage cannot be negative.
- if (percent < 0)
- percent = 0;
- UMA_HISTOGRAM_PERCENTAGE("Net.DailyHttpContentSavings", percent);
- // If the data reduction proxy is enabled for some responses.
- if (length_with_data_reduction_enabled > 0) {
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyHttpContentSavings_DataReductionProxy", percent);
- }
- }
- if (received_length > 0 && length_with_data_reduction_enabled >= 0) {
- DCHECK_GE(received_length, length_with_data_reduction_enabled);
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyReceivedContentWithDataReductionProxyEnabled",
- (100 * length_with_data_reduction_enabled) / received_length);
- }
- if (received_length > 0 &&
- length_via_data_reduction_proxy >= 0) {
- DCHECK_GE(received_length, length_via_data_reduction_proxy);
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyReceivedContentViaDataReductionProxy",
- (100 * length_via_data_reduction_proxy) / received_length);
- }
-}
-
-#endif // defined(OS_ANDROID) || defined(OS_IOS)
-
void UpdateContentLengthPrefs(int received_content_length,
int original_content_length,
- bool data_reduction_proxy_was_used) {
+ bool via_data_reduction_proxy) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK_GE(received_content_length, 0);
DCHECK_GE(original_content_length, 0);
@@ -316,140 +229,19 @@
if (!prefs)
return;
- int64 total_received = prefs->GetInt64(prefs::kHttpReceivedContentLength);
- int64 total_original = prefs->GetInt64(prefs::kHttpOriginalContentLength);
- total_received += received_content_length;
- total_original += original_content_length;
- prefs->SetInt64(prefs::kHttpReceivedContentLength, total_received);
- prefs->SetInt64(prefs::kHttpOriginalContentLength, total_original);
-
-#if defined(OS_ANDROID) || defined(OS_IOS)
- // TODO(bengr): Remove this check once the underlying cause of
- // http://crbug.com/287821 is fixed. For now, only continue if the current
- // year is reported as being between 1972 and 2970.
- base::TimeDelta time_since_unix_epoch =
- base::Time::Now() - base::Time::UnixEpoch();
- const int kMinDaysSinceUnixEpoch = 365 * 2; // 2 years.
- const int kMaxDaysSinceUnixEpoch = 365 * 1000; // 1000 years.
- if (time_since_unix_epoch.InDays() < kMinDaysSinceUnixEpoch ||
- time_since_unix_epoch.InDays() > kMaxDaysSinceUnixEpoch)
- return;
-
- base::Time now = base::Time::Now().LocalMidnight();
- const size_t kNumDaysInHistory = 60;
-
- // Each day, we calculate the total number of bytes received and the total
- // size of all corresponding resources before any data-reducing recompression
- // is applied. These values are used to compute the data savings realized
- // by applying our compression techniques. Totals for the last
- // |kNumDaysInHistory| days are maintained.
- ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength);
- ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength);
- ListPrefUpdate data_reduction_enabled_update(
- prefs,
- prefs::kDailyHttpReceivedContentLengthWithDataReductionProxyEnabled);
- ListPrefUpdate via_data_reduction_update(
- prefs, prefs::kDailyHttpReceivedContentLengthViaDataReductionProxy);
-
- // New empty lists may have been created. Maintain the invariant that
- // there should be exactly |kNumDaysInHistory| days in the histories.
- MaintainContentLengthPrefsWindow(original_update.Get(), kNumDaysInHistory);
- MaintainContentLengthPrefsWindow(received_update.Get(), kNumDaysInHistory);
- MaintainContentLengthPrefsWindow(
- data_reduction_enabled_update.Get(), kNumDaysInHistory);
- MaintainContentLengthPrefsWindow(
- via_data_reduction_update.Get(), kNumDaysInHistory);
-
- // Determine how many days it has been since the last update.
- int64 then_internal = prefs->GetInt64(
- prefs::kDailyHttpContentLengthLastUpdateDate);
- base::Time then = base::Time::FromInternalValue(then_internal);
- int days_since_last_update = (now - then).InDays();
-
- if (days_since_last_update) {
- // Record the last update time.
- prefs->SetInt64(prefs::kDailyHttpContentLengthLastUpdateDate,
- now.ToInternalValue());
-
- if (days_since_last_update == -1) {
- // The system may go backwards in time by up to a day for legitimate
- // reasons, such as with changes to the time zone. In such cases the
- // history is likely still valid. Shift backwards one day and retain all
- // values.
- original_update->Remove(kNumDaysInHistory - 1, NULL);
- received_update->Remove(kNumDaysInHistory - 1, NULL);
- data_reduction_enabled_update->Remove(kNumDaysInHistory - 1, NULL);
- via_data_reduction_update->Remove(kNumDaysInHistory - 1, NULL);
- original_update->Insert(0, new StringValue(base::Int64ToString(0)));
- received_update->Insert(0, new StringValue(base::Int64ToString(0)));
- data_reduction_enabled_update->Insert(
- 0, new StringValue(base::Int64ToString(0)));
- via_data_reduction_update->Insert(
- 0, new StringValue(base::Int64ToString(0)));
- days_since_last_update = 0;
-
- } else if (days_since_last_update < -1) {
- // Erase all entries if the system went backwards in time by more than
- // a day.
- original_update->Clear();
- received_update->Clear();
- data_reduction_enabled_update->Clear();
- via_data_reduction_update->Clear();
- days_since_last_update = kNumDaysInHistory;
- }
-
- // A new day. Report the previous day's data if exists. We'll lose usage
- // data if Chrome isn't run for a day. Here, we prefer collecting less data
- // but the collected data are associated with an accurate date.
- if (days_since_last_update == 1) {
- RecordDailyContentLengthHistograms(
- ListPrefInt64Value(*original_update, original_update->GetSize() - 1),
- ListPrefInt64Value(*received_update, received_update->GetSize() - 1),
- ListPrefInt64Value(*data_reduction_enabled_update,
- data_reduction_enabled_update->GetSize() - 1),
- ListPrefInt64Value(*via_data_reduction_update,
- via_data_reduction_update->GetSize() - 1));
- }
- // Add entries for days since last update event. This will make the
- // lists longer than kNumDaysInHistory. The additional items will be cut off
- // from the head of the lists by MaintainContentLengthPrefsWindow, below.
- for (int i = 0;
- i < days_since_last_update && i < static_cast<int>(kNumDaysInHistory);
- ++i) {
- original_update->AppendString(base::Int64ToString(0));
- received_update->AppendString(base::Int64ToString(0));
- data_reduction_enabled_update->AppendString(base::Int64ToString(0));
- via_data_reduction_update->AppendString(base::Int64ToString(0));
- }
-
- // Entries for new days may have been appended. Maintain the invariant that
- // there should be exactly |kNumDaysInHistory| days in the histories.
- MaintainContentLengthPrefsWindow(original_update.Get(), kNumDaysInHistory);
- MaintainContentLengthPrefsWindow(received_update.Get(), kNumDaysInHistory);
- MaintainContentLengthPrefsWindow(
- data_reduction_enabled_update.Get(), kNumDaysInHistory);
- MaintainContentLengthPrefsWindow(
- via_data_reduction_update.Get(), kNumDaysInHistory);
- }
-
- // Update the counts for the current day.
- AddInt64ToListPref(kNumDaysInHistory - 1,
- original_content_length, original_update.Get());
- AddInt64ToListPref(kNumDaysInHistory - 1,
- received_content_length, received_update.Get());
-
- if (g_browser_process->profile_manager()->GetDefaultProfile()->
- GetPrefs()->GetBoolean(prefs::kSpdyProxyAuthEnabled)) {
- AddInt64ToListPref(kNumDaysInHistory - 1,
- received_content_length,
- data_reduction_enabled_update.Get());
- }
- if (data_reduction_proxy_was_used) {
- AddInt64ToListPref(kNumDaysInHistory - 1,
- received_content_length,
- via_data_reduction_update.Get());
- }
+#if defined(OS_ANDROID)
+ bool with_data_reduction_proxy_enabled =
+ g_browser_process->profile_manager()->GetDefaultProfile()->
+ GetPrefs()->GetBoolean(prefs::kSpdyProxyAuthEnabled);
+#else
+ bool with_data_reduction_proxy_enabled = false;
#endif
+
+ chrome_browser_net::UpdateContentLengthPrefs(
+ received_content_length,
+ original_content_length,
+ with_data_reduction_proxy_enabled,
+ via_data_reduction_proxy, prefs);
}
void StoreAccumulatedContentLength(int received_content_length,
@@ -465,7 +257,7 @@
int64 received_content_length,
int64 original_content_length,
const base::TimeDelta& freshness_lifetime) {
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
// Add the current resource to these histograms only when a valid
// X-Original-Content-Length header is present.
if (original_content_length >= 0) {
@@ -503,7 +295,7 @@
return;
UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable24Hours",
received_content_length);
-#endif
+#endif // defined(OS_ANDROID)
}
} // namespace
@@ -721,7 +513,7 @@
int64 original_content_length =
request->response_info().headers->GetInt64HeaderValue(
"x-original-content-length");
- bool data_reduction_proxy_was_used =
+ bool via_data_reduction_proxy =
request->response_info().headers->HasHeaderValue(
"via", "1.1 Chrome Compression Proxy");
@@ -735,7 +527,7 @@
request->response_info().response_time);
AccumulateContentLength(received_content_length,
adjusted_original_content_length,
- data_reduction_proxy_was_used);
+ via_data_reduction_proxy);
RecordContentLengthHistograms(received_content_length,
original_content_length,
freshness_lifetime);
@@ -944,12 +736,12 @@
void ChromeNetworkDelegate::AccumulateContentLength(
int64 received_content_length, int64 original_content_length,
- bool data_reduction_proxy_was_used) {
+ bool via_data_reduction_proxy) {
DCHECK_GE(received_content_length, 0);
DCHECK_GE(original_content_length, 0);
StoreAccumulatedContentLength(received_content_length,
original_content_length,
- data_reduction_proxy_was_used);
+ via_data_reduction_proxy);
received_content_length_ += received_content_length;
original_content_length_ += original_content_length;
}
diff --git a/chrome/browser/net/network_stats.cc b/chrome/browser/net/network_stats.cc
index 4f55087..51fcd0f 100644
--- a/chrome/browser/net/network_stats.cc
+++ b/chrome/browser/net/network_stats.cc
@@ -135,7 +135,7 @@
bool has_proxy_server,
uint32 probe_bytes,
const net::CompletionCallback& finished_callback) {
- DCHECK(host_resolver);
+ CHECK(host_resolver);
histogram_port_ = histogram_port;
has_proxy_server_ = has_proxy_server;
probe_packet_bytes_ = probe_bytes;
@@ -196,8 +196,8 @@
net::RandIntCallback(),
NULL,
net::NetLog::Source());
- DCHECK(udp_socket);
- DCHECK(!socket_);
+ CHECK(udp_socket);
+ CHECK(!socket_);
socket_ = udp_socket.Pass();
const net::IPEndPoint& endpoint = addresses_.front();
@@ -265,7 +265,7 @@
}
case NAT_BIND_TEST: {
// Make sure no integer overflow.
- DCHECK_LE(maximum_NAT_idle_seconds_, 4000U);
+ CHECK_LE(maximum_NAT_idle_seconds_, 4000U);
int nat_test_idle_seconds = base::RandInt(1, maximum_NAT_idle_seconds_);
pacing_interval_ = base::TimeDelta::FromSeconds(nat_test_idle_seconds);
timeout_seconds = nat_test_idle_seconds + kReadNATTimeoutSeconds;
@@ -300,7 +300,7 @@
int rv = 0;
do {
- DCHECK(!read_buffer_.get());
+ CHECK(!read_buffer_.get());
read_buffer_ = new net::IOBuffer(kMaxMessageSize);
rv = socket_->Read(
@@ -326,8 +326,8 @@
}
bool NetworkStats::ReadComplete(int result) {
- DCHECK(socket_.get());
- DCHECK_NE(net::ERR_IO_PENDING, result);
+ CHECK(socket_.get());
+ CHECK_NE(net::ERR_IO_PENDING, result);
if (result < 0) {
// Something is wrong, finish the test.
read_buffer_ = NULL;
@@ -435,8 +435,8 @@
}
void NetworkStats::OnWriteComplete(int result) {
- DCHECK(socket_.get());
- DCHECK_NE(net::ERR_IO_PENDING, result);
+ CHECK(socket_.get());
+ CHECK_NE(net::ERR_IO_PENDING, result);
if (result < 0) {
TestPhaseComplete(WRITE_FAILED, result);
return;
@@ -446,7 +446,7 @@
void NetworkStats::UpdateSendBuffer(int bytes_sent) {
write_buffer_->DidConsume(bytes_sent);
- DCHECK_EQ(write_buffer_->BytesRemaining(), 0);
+ CHECK_EQ(write_buffer_->BytesRemaining(), 0);
write_buffer_ = NULL;
}
@@ -495,7 +495,7 @@
if (token_.timestamp_micros() != 0 &&
(status == SUCCESS || status == READ_TIMED_OUT)) {
TestType current_test = test_sequence_[current_test_index_];
- DCHECK_LT(current_test, TEST_TYPE_MAX);
+ CHECK_LT(current_test, TEST_TYPE_MAX);
if (current_test != TOKEN_REQUEST)
RecordHistograms(current_test);
else if (current_test_index_ > 0 &&
@@ -689,7 +689,7 @@
}
void NetworkStats::RecordRTTHistograms(TestType test_type, uint32 index) {
- DCHECK_LT(index, packet_rtt_.size());
+ CHECK_LT(index, packet_rtt_.size());
if (!packets_received_mask_.test(index))
return; // Probe packet never received.
@@ -741,7 +741,7 @@
GURL gurl(url);
has_pending_proxy_resolution_ = true;
- DCHECK(proxy_service_);
+ CHECK(proxy_service_);
int rv = proxy_service_->ResolveProxy(
gurl,
&proxy_info_,
@@ -783,11 +783,11 @@
return;
}
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Check that there is a network connection. We get called only if UMA upload
// to the server has succeeded.
- DCHECK(!net::NetworkChangeNotifier::IsOffline());
+ CHECK(!net::NetworkChangeNotifier::IsOffline());
CR_DEFINE_STATIC_LOCAL(scoped_refptr<base::FieldTrial>, trial, ());
static bool collect_stats = false;
@@ -801,8 +801,8 @@
chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
if (channel == chrome::VersionInfo::CHANNEL_CANARY) {
- // Enable the connectivity testing for 50% of the users in canary channel.
- probability_per_group = kDivisor / 2;
+ // Enable the connectivity testing for 20% of the users in canary channel.
+ probability_per_group = kDivisor / 5;
} else if (channel == chrome::VersionInfo::CHANNEL_DEV) {
// Enable the connectivity testing for 10% of the users in dev channel.
probability_per_group = kDivisor / 10;
@@ -835,7 +835,7 @@
++number_of_tests_done;
net::HostResolver* host_resolver = io_thread->globals()->host_resolver.get();
- DCHECK(host_resolver);
+ CHECK(host_resolver);
uint32 port_index = base::RandInt(0, arraysize(kPorts) - 1);
uint16 histogram_port = kPorts[port_index];
@@ -843,7 +843,7 @@
net::ProxyService* proxy_service =
io_thread->globals()->system_proxy_service.get();
- DCHECK(proxy_service);
+ CHECK(proxy_service);
ProxyDetector::OnResolvedCallback callback = base::Bind(
&StartNetworkStatsTest, host_resolver, server_address, histogram_port);
diff --git a/chrome/browser/net/predictor_browsertest.cc b/chrome/browser/net/predictor_browsertest.cc
index 1121318..cc31bf3 100644
--- a/chrome/browser/net/predictor_browsertest.cc
+++ b/chrome/browser/net/predictor_browsertest.cc
@@ -102,10 +102,15 @@
}
protected:
- virtual void SetUp() OVERRIDE {
- net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
- host_resolution_request_recorder_.get());
- InProcessBrowserTest::SetUp();
+ virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+ scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc(
+ host_resolution_request_recorder_.get()));
+ InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
+ }
+
+ virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
+ InProcessBrowserTest::TearDownInProcessBrowserTestFixture();
+ scoped_host_resolver_proc_.reset();
}
void LearnAboutInitialNavigation(const GURL& url) {
@@ -153,6 +158,7 @@
private:
scoped_refptr<HostResolutionRequestRecorder>
host_resolution_request_recorder_;
+ scoped_ptr<net::ScopedDefaultHostResolverProc> scoped_host_resolver_proc_;
};
IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PRE_ShutdownStartupCycle) {
diff --git a/chrome/browser/net/predictor_unittest.cc b/chrome/browser/net/predictor_unittest.cc
index 8ccc3c2..4d50dce 100644
--- a/chrome/browser/net/predictor_unittest.cc
+++ b/chrome/browser/net/predictor_unittest.cc
@@ -312,8 +312,6 @@
subresource_list->Append(new base::FundamentalValue(use_rate));
}
-static const int kLatencyNotFound = -1;
-
// For a given motivation, and subresource, find what latency is currently
// listed. This assume a well formed serialization, which has at most one such
// entry for any pair of names. If no such pair is found, then return false.
diff --git a/chrome/browser/notifications/balloon_collection_impl.cc b/chrome/browser/notifications/balloon_collection_impl.cc
index 3ee0c05..bf3efca 100644
--- a/chrome/browser/notifications/balloon_collection_impl.cc
+++ b/chrome/browser/notifications/balloon_collection_impl.cc
@@ -21,8 +21,6 @@
#include "ui/gfx/screen.h"
#include "ui/gfx/size.h"
-namespace {
-
// Portion of the screen allotted for notifications. When notification balloons
// extend over this, no new notifications are shown until some are closed.
const double kPercentBalloonFillFactor = 0.7;
@@ -30,14 +28,15 @@
// Allow at least this number of balloons on the screen.
const int kMinAllowedBalloonCount = 2;
-// Delay from the mouse leaving the balloon collection before
-// there is a relayout, in milliseconds.
-const int kRepositionDelayMs = 300;
-
// The spacing between the balloon and the panel.
const int kVerticalSpacingBetweenBalloonAndPanel = 5;
-} // namespace
+#if USE_OFFSETS
+// Delay from the mouse leaving the balloon collection before
+// there is a relayout, in milliseconds.
+const int kRepositionDelayMs = 300;
+#endif // USE_OFFSETS
+
BalloonCollectionImpl::BalloonCollectionImpl()
#if USE_OFFSETS
diff --git a/chrome/browser/notifications/fullscreen_notification_blocker.cc b/chrome/browser/notifications/fullscreen_notification_blocker.cc
index 8122b1f..0d5b350 100644
--- a/chrome/browser/notifications/fullscreen_notification_blocker.cc
+++ b/chrome/browser/notifications/fullscreen_notification_blocker.cc
@@ -25,6 +25,11 @@
if (ash::Shell::HasInstance()) {
ash::internal::RootWindowController* controller =
ash::internal::RootWindowController::ForTargetRootWindow();
+
+ // During shutdown |controller| can be NULL.
+ if (!controller)
+ return false;
+
const aura::Window* fullscreen_window =
controller->GetTopmostFullscreenWindow();
diff --git a/chrome/browser/notifications/message_center_notification_manager.cc b/chrome/browser/notifications/message_center_notification_manager.cc
index ccc9121..7aa64dc 100644
--- a/chrome/browser/notifications/message_center_notification_manager.cc
+++ b/chrome/browser/notifications/message_center_notification_manager.cc
@@ -23,7 +23,6 @@
#include "chrome/common/extensions/extension_set.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
-#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "ui/gfx/image/image_skia.h"
@@ -36,11 +35,11 @@
#include "chrome/browser/notifications/login_state_notification_blocker_chromeos.h"
#endif
-namespace {
+#if defined(OS_WIN)
// 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
+#endif
MessageCenterNotificationManager::MessageCenterNotificationManager(
message_center::MessageCenter* message_center,
@@ -53,7 +52,8 @@
weak_factory_(this),
#endif
settings_provider_(settings_provider.Pass()),
- system_observer_(this) {
+ system_observer_(this),
+ stats_collector_(message_center) {
#if defined(OS_WIN)
first_run_pref_.Init(prefs::kMessageCenterShowedFirstRunBalloon, local_state);
#endif
@@ -156,6 +156,7 @@
if (iter == profile_notifications_.end())
return false;
+ RemoveProfileNotification(iter->second);
message_center_->RemoveNotification(id, /* by_user */ false);
return true;
}
@@ -186,7 +187,9 @@
loopiter != profile_notifications_.end(); ) {
NotificationMap::iterator curiter = loopiter++;
if ((*curiter).second->notification().origin_url() == source) {
- message_center_->RemoveNotification(curiter->first, /* by_user */ false);
+ const std::string id = curiter->first;
+ RemoveProfileNotification(curiter->second);
+ message_center_->RemoveNotification(id, /* by_user */ false);
removed = true;
}
}
@@ -201,7 +204,9 @@
loopiter != profile_notifications_.end(); ) {
NotificationMap::iterator curiter = loopiter++;
if (profile == (*curiter).second->profile()) {
- message_center_->RemoveNotification(curiter->first, /* by_user */ false);
+ const std::string id = curiter->first;
+ RemoveProfileNotification(curiter->second);
+ message_center_->RemoveNotification(id, /* by_user */ false);
removed = true;
}
}
@@ -217,9 +222,6 @@
void MessageCenterNotificationManager::OnNotificationRemoved(
const std::string& notification_id,
bool by_user) {
- // Do not call FindProfileNotification(). Some tests create notifications
- // directly to MessageCenter, but this method will be called for the removals
- // of such notifications.
NotificationMap::const_iterator iter =
profile_notifications_.find(notification_id);
if (iter != profile_notifications_.end())
@@ -232,21 +234,10 @@
void MessageCenterNotificationManager::OnCenterVisibilityChanged(
message_center::Visibility visibility) {
- switch (visibility) {
- case message_center::VISIBILITY_TRANSIENT:
#if defined(OS_WIN)
- CheckFirstRunTimer();
+ if (visibility == message_center::VISIBILITY_TRANSIENT)
+ CheckFirstRunTimer();
#endif
- break;
- case message_center::VISIBILITY_MESSAGE_CENTER:
- content::RecordAction(
- content::UserMetricsAction("Notifications.ShowMessageCenter"));
- break;
- case message_center::VISIBILITY_SETTINGS:
- content::RecordAction(
- content::UserMetricsAction("Notifications.ShowSettings"));
- break;
- }
}
void MessageCenterNotificationManager::OnNotificationUpdated(
diff --git a/chrome/browser/notifications/message_center_notification_manager.h b/chrome/browser/notifications/message_center_notification_manager.h
index 35094cc..c124570 100644
--- a/chrome/browser/notifications/message_center_notification_manager.h
+++ b/chrome/browser/notifications/message_center_notification_manager.h
@@ -14,6 +14,7 @@
#include "base/prefs/pref_member.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
+#include "chrome/browser/notifications/message_center_stats_collector.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_system_observer.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
@@ -227,6 +228,9 @@
NotificationSystemObserver system_observer_;
+ // Keeps track of all notification statistics for UMA purposes.
+ MessageCenterStatsCollector stats_collector_;
+
DISALLOW_COPY_AND_ASSIGN(MessageCenterNotificationManager);
};
diff --git a/chrome/browser/notifications/message_center_stats_collector.cc b/chrome/browser/notifications/message_center_stats_collector.cc
new file mode 100644
index 0000000..f0257a9
--- /dev/null
+++ b/chrome/browser/notifications/message_center_stats_collector.cc
@@ -0,0 +1,138 @@
+// Copyright 2013 The Chromium 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_stats_collector.h"
+
+#include <string>
+
+#include "base/metrics/histogram.h"
+#include "content/public/browser/user_metrics.h"
+#include "ui/message_center/message_center.h"
+
+MessageCenterStatsCollector::NotificationStats::NotificationStats() {}
+
+MessageCenterStatsCollector::NotificationStats::NotificationStats(
+ const std::string& id) : id_(id) {
+ for (size_t i = 0; i < NOTIFICATION_ACTION_COUNT; i++) {
+ actions_[i] = false;
+ }
+}
+
+MessageCenterStatsCollector::NotificationStats::~NotificationStats() {}
+
+void MessageCenterStatsCollector::NotificationStats::CollectAction(
+ NotificationActionType type) {
+ DCHECK(!id_.empty());
+
+ UMA_HISTOGRAM_ENUMERATION("Notifications.Actions",
+ type,
+ NOTIFICATION_ACTION_COUNT);
+ actions_[type] = true;
+}
+
+void MessageCenterStatsCollector::NotificationStats::RecordAggregateStats() {
+ DCHECK(!id_.empty());
+
+ for (size_t i = 0; i < NOTIFICATION_ACTION_COUNT; i++) {
+ if (!actions_[i])
+ continue;
+ UMA_HISTOGRAM_ENUMERATION("Notifications.PerNotificationActions",
+ i,
+ NOTIFICATION_ACTION_COUNT);
+ }
+}
+
+MessageCenterStatsCollector::MessageCenterStatsCollector(
+ message_center::MessageCenter* message_center)
+ : message_center_(message_center) {
+ message_center_->AddObserver(this);
+}
+
+MessageCenterStatsCollector::~MessageCenterStatsCollector() {
+ message_center_->RemoveObserver(this);
+}
+
+void MessageCenterStatsCollector::OnNotificationAdded(
+ const std::string& notification_id) {
+ stats_[notification_id] = NotificationStats(notification_id);
+
+ StatsCollection::iterator iter = stats_.find(notification_id);
+ DCHECK(iter != stats_.end());
+
+ stats_[notification_id].CollectAction(NOTIFICATION_ACTION_ADD);
+}
+
+void MessageCenterStatsCollector::OnNotificationRemoved(
+ const std::string& notification_id, bool by_user) {
+ StatsCollection::iterator iter = stats_.find(notification_id);
+ if (iter == stats_.end())
+ return;
+ NotificationStats& notification_stat = iter->second;
+ notification_stat.CollectAction(by_user ?
+ NOTIFICATION_ACTION_CLOSE_BY_USER :
+ NOTIFICATION_ACTION_CLOSE_BY_SYSTEM);
+ notification_stat.RecordAggregateStats();
+ stats_.erase(notification_id);
+}
+
+void MessageCenterStatsCollector::OnNotificationUpdated(
+ const std::string& notification_id) {
+ StatsCollection::iterator iter = stats_.find(notification_id);
+ if (iter == stats_.end())
+ return;
+ NotificationStats& notification_stat = iter->second;
+
+ notification_stat.CollectAction(NOTIFICATION_ACTION_UPDATE);
+}
+
+void MessageCenterStatsCollector::OnNotificationClicked(
+ const std::string& notification_id) {
+ StatsCollection::iterator iter = stats_.find(notification_id);
+ if (iter == stats_.end())
+ return;
+ NotificationStats& notification_stat = iter->second;
+
+ notification_stat.CollectAction(NOTIFICATION_ACTION_CLICK);
+}
+
+void MessageCenterStatsCollector::OnNotificationButtonClicked(
+ const std::string& notification_id,
+ int button_index) {
+ StatsCollection::iterator iter = stats_.find(notification_id);
+ if (iter == stats_.end())
+ return;
+ NotificationStats& notification_stat = iter->second;
+
+ notification_stat.CollectAction(NOTIFICATION_ACTION_BUTTON_CLICK);
+}
+
+void MessageCenterStatsCollector::OnNotificationDisplayed(
+ const std::string& notification_id) {
+ StatsCollection::iterator iter = stats_.find(notification_id);
+ if (iter == stats_.end())
+ return;
+ NotificationStats& notification_stat = iter->second;
+
+ notification_stat.CollectAction(NOTIFICATION_ACTION_DISPLAY);
+}
+
+void MessageCenterStatsCollector::OnCenterVisibilityChanged(
+ message_center::Visibility visibility) {
+ switch (visibility) {
+ case message_center::VISIBILITY_TRANSIENT:
+ break;
+ case message_center::VISIBILITY_MESSAGE_CENTER:
+ content::RecordAction(
+ content::UserMetricsAction("Notifications.ShowMessageCenter"));
+ break;
+ case message_center::VISIBILITY_SETTINGS:
+ content::RecordAction(
+ content::UserMetricsAction("Notifications.ShowSettings"));
+ break;
+ }
+}
+
+void MessageCenterStatsCollector::OnQuietModeChanged(bool in_quiet_mode) {
+}
+
diff --git a/chrome/browser/notifications/message_center_stats_collector.h b/chrome/browser/notifications/message_center_stats_collector.h
new file mode 100644
index 0000000..463b7ed
--- /dev/null
+++ b/chrome/browser/notifications/message_center_stats_collector.h
@@ -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.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_MESSAGE_CENTER_STATS_COLLECTOR_H_
+#define CHROME_BROWSER_NOTIFICATIONS_MESSAGE_CENTER_STATS_COLLECTOR_H_
+
+#include <set>
+#include <string>
+
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/message_center_observer.h"
+#include "ui/message_center/message_center_types.h"
+
+namespace message_center {
+class MessageCenter;
+}
+
+// MessageCenterStatsCollector sends both raw and per-notification statistics
+// to the UMA servers, if the user has opted in. It observes the message center
+// to gather its data.
+class MessageCenterStatsCollector
+ : public message_center::MessageCenterObserver {
+ public:
+ enum NotificationActionType {
+ NOTIFICATION_ACTION_UNKNOWN,
+ NOTIFICATION_ACTION_ADD,
+ NOTIFICATION_ACTION_UPDATE,
+ NOTIFICATION_ACTION_CLICK,
+ NOTIFICATION_ACTION_BUTTON_CLICK,
+ NOTIFICATION_ACTION_DISPLAY,
+ NOTIFICATION_ACTION_CLOSE_BY_USER,
+ NOTIFICATION_ACTION_CLOSE_BY_SYSTEM,
+ // NOTE: Add new action types only immediately above this line. Also,
+ // make sure the enum list in tools/histogram/histograms.xml is
+ // updated with any change in here.
+ NOTIFICATION_ACTION_COUNT
+ };
+
+ explicit MessageCenterStatsCollector(
+ message_center::MessageCenter* message_center);
+ virtual ~MessageCenterStatsCollector();
+
+ private:
+ // Represents the aggregate stats for each notification.
+ class NotificationStats {
+ public:
+ // Default constructor for map.
+ NotificationStats();
+
+ explicit NotificationStats(const std::string& id);
+ virtual ~NotificationStats();
+
+ // Called when we get an action from the message center.
+ void CollectAction(NotificationActionType type);
+
+ // Sends aggregate data to UMA.
+ void RecordAggregateStats();
+
+ private:
+ std::string id_;
+ bool actions_[NOTIFICATION_ACTION_COUNT];
+ };
+
+ // MessageCenterObserver
+ virtual void OnNotificationAdded(const std::string& notification_id) OVERRIDE;
+ virtual void OnNotificationRemoved(const std::string& notification_id,
+ bool by_user) OVERRIDE;
+ virtual void OnNotificationUpdated(
+ const std::string& notification_id) OVERRIDE;
+ virtual void OnNotificationClicked(
+ const std::string& notification_id) OVERRIDE;
+ virtual void OnNotificationButtonClicked(const std::string& notification_id,
+ int button_index) OVERRIDE;
+ virtual void OnNotificationDisplayed(
+ const std::string& notification_id) OVERRIDE;
+ virtual void OnCenterVisibilityChanged(
+ message_center::Visibility visibility) OVERRIDE;
+ virtual void OnQuietModeChanged(bool in_quiet_mode) OVERRIDE;
+
+ // Weak, global.
+ message_center::MessageCenter* message_center_;
+
+ typedef std::map<std::string,NotificationStats> StatsCollection;
+ StatsCollection stats_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageCenterStatsCollector);
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_MESSAGE_CENTER_STATS_COLLECTOR_H_
diff --git a/chrome/browser/notifications/notification_browsertest.cc b/chrome/browser/notifications/notification_browsertest.cc
index da54243..b246ebb 100644
--- a/chrome/browser/notifications/notification_browsertest.cc
+++ b/chrome/browser/notifications/notification_browsertest.cc
@@ -528,7 +528,7 @@
ASSERT_EQ(1, GetNotificationCount());
if (message_center::IsRichNotificationEnabled()) {
message_center::NotificationList::Notifications notifications =
- message_center::MessageCenter::Get()->GetNotifications();
+ message_center::MessageCenter::Get()->GetVisibleNotifications();
EXPECT_EQ(ASCIIToUTF16("My Title"), (*notifications.rbegin())->title());
EXPECT_EQ(ASCIIToUTF16("My Body"), (*notifications.rbegin())->message());
} else {
@@ -555,7 +555,7 @@
if (message_center::IsRichNotificationEnabled()) {
message_center::NotificationList::Notifications notifications =
- message_center::MessageCenter::Get()->GetNotifications();
+ message_center::MessageCenter::Get()->GetVisibleNotifications();
message_center::MessageCenter::Get()->RemoveNotification(
(*notifications.rbegin())->id(),
true); // by_user
@@ -737,7 +737,7 @@
EXPECT_EQ(1, GetNotificationCount());
if (message_center::IsRichNotificationEnabled()) {
message_center::NotificationList::Notifications notifications =
- message_center::MessageCenter::Get()->GetNotifications();
+ message_center::MessageCenter::Get()->GetVisibleNotifications();
message_center::MessageCenter::Get()->RemoveNotification(
(*notifications.rbegin())->id(),
true); // by_user
@@ -935,7 +935,7 @@
if (message_center::IsRichNotificationEnabled()) {
ASSERT_EQ(1, GetNotificationCount());
message_center::NotificationList::Notifications notifications =
- message_center::MessageCenter::Get()->GetNotifications();
+ message_center::MessageCenter::Get()->GetVisibleNotifications();
EXPECT_EQ(ASCIIToUTF16("Title2"), (*notifications.rbegin())->title());
EXPECT_EQ(ASCIIToUTF16("Body2"), (*notifications.rbegin())->message());
} else {
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc
index 922cf0a..acd0f25 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc
@@ -21,11 +21,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/message_center/notification_types.h"
-namespace {
const char kTestNotificationId[] = "SomeRandomNotificationId";
-const int kNotificationPriority = static_cast<int>(
- message_center::LOW_PRIORITY);
-} // namespace
class StubChromeNotifierService : public notifier::ChromeNotifierService {
public:
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
index 69834c1..a8ce03c 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
@@ -41,9 +41,6 @@
namespace {
-const int kNotificationPriority = static_cast<int>(
- message_center::LOW_PRIORITY);
-
// Extract notification id from syncer::SyncData.
std::string GetNotificationId(const SyncData& sync_data) {
SyncedNotificationSpecifics specifics = sync_data.GetSpecifics().
@@ -657,13 +654,7 @@
}
-// Failing new test on Win. http://crbug.com/294658
-#if defined(OS_WIN)
-#define MAYBE_InitializePrefsTest DISABLED_InitializePrefsTest
-#else
-#define MAYBE_InitializePrefsTest InitializePrefsTest
-#endif
-TEST_F(ChromeNotifierServiceTest, MAYBE_InitializePrefsTest) {
+TEST_F(ChromeNotifierServiceTest, InitializePrefsTest) {
StubNotificationUIManager notification_manager;
// The CTOR will call InitializePrefs().
ChromeNotifierService notifier(profile_.get(), ¬ification_manager);
@@ -684,7 +675,7 @@
notifier.profile()->GetPrefs()->GetList(
prefs::kInitializedSyncedNotificationSendingServices);
iter = initialized_set->Find(service_name_value);
- EXPECT_NE(enabled_set->end(), iter);
+ EXPECT_NE(initialized_set->end(), iter);
}
TEST_F(ChromeNotifierServiceTest,
diff --git a/chrome/browser/password_manager/login_database.cc b/chrome/browser/password_manager/login_database.cc
index 929f7cd..6830bc0 100644
--- a/chrome/browser/password_manager/login_database.cc
+++ b/chrome/browser/password_manager/login_database.cc
@@ -185,16 +185,22 @@
"ADD COLUMN possible_usernames BLOB")) {
return false;
}
+ meta_table_.SetVersionNumber(2);
// Fall through.
case 2:
if (!db_.Execute("ALTER TABLE logins ADD COLUMN times_used INTEGER")) {
return false;
}
+ meta_table_.SetVersionNumber(3);
// Fall through.
case 3:
- if (!db_.Execute("ALTER TABLE logins ADD COLUMN form_data BLOB")) {
+ // We need to check if the column exists because of
+ // https://crbug.com/295851
+ if (!db_.DoesColumnExist("logins", "form_data") &&
+ !db_.Execute("ALTER TABLE logins ADD COLUMN form_data BLOB")) {
return false;
}
+ meta_table_.SetVersionNumber(4);
// Fall through.
case kCurrentVersionNumber:
// Already up to date
@@ -203,8 +209,6 @@
NOTREACHED();
return false;
}
- meta_table_.SetVersionNumber(kCurrentVersionNumber);
- return true;
}
bool LoginDatabase::InitLoginsTable() {
@@ -295,7 +299,8 @@
bool LoginDatabase::AddLogin(const PasswordForm& form) {
std::string encrypted_password;
- if (!EncryptedString(form.password_value, &encrypted_password))
+ if (EncryptedString(form.password_value, &encrypted_password) !=
+ ENCRYPTION_RESULT_SUCCESS)
return false;
// You *must* change LoginTableColumns if this query changes.
@@ -338,7 +343,8 @@
bool LoginDatabase::UpdateLogin(const PasswordForm& form, int* items_changed) {
std::string encrypted_password;
- if (!EncryptedString(form.password_value, &encrypted_password))
+ if (EncryptedString(form.password_value, &encrypted_password) !=
+ ENCRYPTION_RESULT_SUCCESS)
return false;
sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
@@ -409,13 +415,16 @@
return s.Run();
}
-bool LoginDatabase::InitPasswordFormFromStatement(PasswordForm* form,
- sql::Statement& s) const {
+LoginDatabase::EncryptionResult LoginDatabase::InitPasswordFormFromStatement(
+ PasswordForm* form,
+ sql::Statement& s) const {
std::string encrypted_password;
s.ColumnBlobAsString(COLUMN_PASSWORD_VALUE, &encrypted_password);
string16 decrypted_password;
- if (!DecryptedString(encrypted_password, &decrypted_password))
- return false;
+ EncryptionResult encryption_result =
+ DecryptedString(encrypted_password, &decrypted_password);
+ if (encryption_result != ENCRYPTION_RESULT_SUCCESS)
+ return encryption_result;
std::string tmp = s.ColumnString(COLUMN_ORIGIN_URL);
form->origin = GURL(tmp);
@@ -449,7 +458,7 @@
s.ColumnByteLength(COLUMN_FORM_DATA));
PickleIterator form_data_iter(form_data_pickle);
autofill::DeserializeFormData(&form_data_iter, &form->form_data);
- return true;
+ return ENCRYPTION_RESULT_SUCCESS;
}
bool LoginDatabase::GetLogins(const PasswordForm& form,
@@ -502,8 +511,12 @@
while (s.Step()) {
scoped_ptr<PasswordForm> new_form(new PasswordForm());
- if (!InitPasswordFormFromStatement(new_form.get(), s))
+ EncryptionResult result = InitPasswordFormFromStatement(new_form.get(), s);
+ if (result == ENCRYPTION_RESULT_SERVICE_FAILURE)
return false;
+ if (result == ENCRYPTION_RESULT_ITEM_FAILURE)
+ continue;
+ DCHECK(result == ENCRYPTION_RESULT_SUCCESS);
if (public_suffix_domain_matching_) {
if (!SchemeMatches(new_form, form) ||
!RegistryControlledDomainMatches(new_form, form) ||
@@ -548,8 +561,12 @@
while (s.Step()) {
scoped_ptr<PasswordForm> new_form(new PasswordForm());
- if (!InitPasswordFormFromStatement(new_form.get(), s))
+ EncryptionResult result = InitPasswordFormFromStatement(new_form.get(), s);
+ if (result == ENCRYPTION_RESULT_SERVICE_FAILURE)
return false;
+ if (result == ENCRYPTION_RESULT_ITEM_FAILURE)
+ continue;
+ DCHECK(result == ENCRYPTION_RESULT_SUCCESS);
forms->push_back(new_form.release());
}
return s.Succeeded();
@@ -581,8 +598,12 @@
while (s.Step()) {
scoped_ptr<PasswordForm> new_form(new PasswordForm());
- if (!InitPasswordFormFromStatement(new_form.get(), s))
+ EncryptionResult result = InitPasswordFormFromStatement(new_form.get(), s);
+ if (result == ENCRYPTION_RESULT_SERVICE_FAILURE)
return false;
+ if (result == ENCRYPTION_RESULT_ITEM_FAILURE)
+ continue;
+ DCHECK(result == ENCRYPTION_RESULT_SUCCESS);
forms->push_back(new_form.release());
}
return s.Succeeded();
diff --git a/chrome/browser/password_manager/login_database.h b/chrome/browser/password_manager/login_database.h
index b62a5ec..792d6c3 100644
--- a/chrome/browser/password_manager/login_database.h
+++ b/chrome/browser/password_manager/login_database.h
@@ -79,28 +79,43 @@
private:
friend class LoginDatabaseTest;
+ // Result values for encryption/decryption actions.
+ enum EncryptionResult {
+ // Success.
+ ENCRYPTION_RESULT_SUCCESS,
+ // Failure for a specific item (e.g., the encrypted value was manually
+ // moved from another machine, and can't be decrypted on this machine).
+ // This is presumed to be a permanent failure.
+ ENCRYPTION_RESULT_ITEM_FAILURE,
+ // A service-level failure (e.g., on a platform using a keyring, the keyring
+ // is temporarily unavailable).
+ // This is presumed to be a temporary failure.
+ ENCRYPTION_RESULT_SERVICE_FAILURE,
+ };
+
// Encrypts plain_text, setting the value of cipher_text and returning true if
// successful, or returning false and leaving cipher_text unchanged if
// encryption fails (e.g., if the underlying OS encryption system is
// temporarily unavailable).
- bool EncryptedString(const string16& plain_text,
- std::string* cipher_text) const;
+ EncryptionResult EncryptedString(const string16& plain_text,
+ std::string* cipher_text) const;
// Decrypts cipher_text, setting the value of plain_text and returning true if
// successful, or returning false and leaving plain_text unchanged if
// decryption fails (e.g., if the underlying OS encryption system is
// temporarily unavailable).
- bool DecryptedString(const std::string& cipher_text,
- string16* plain_text) const;
+ EncryptionResult DecryptedString(const std::string& cipher_text,
+ string16* plain_text) const;
bool InitLoginsTable();
bool MigrateOldVersionsAsNeeded();
// Fills |form| from the values in the given statement (which is assumed to
// be of the form used by the Get*Logins methods).
- // Returns true if |form| was successfully filled.
- bool InitPasswordFormFromStatement(autofill::PasswordForm* form,
- sql::Statement& s) const;
+ // Returns the EncryptionResult from decrypting the password in |s|; if not
+ // ENCRYPTION_RESULT_SUCCESS, |form| is not filled.
+ EncryptionResult InitPasswordFormFromStatement(autofill::PasswordForm* form,
+ sql::Statement& s) const;
// Loads all logins whose blacklist setting matches |blacklisted| into
// |forms|.
diff --git a/chrome/browser/password_manager/login_database_mac.cc b/chrome/browser/password_manager/login_database_mac.cc
index fbf8f6e..d8bb994 100644
--- a/chrome/browser/password_manager/login_database_mac.cc
+++ b/chrome/browser/password_manager/login_database_mac.cc
@@ -8,14 +8,16 @@
// rest of the database as a suplemental storage system to complement Keychain,
// providing storage of fields Keychain doesn't allow.
-bool LoginDatabase::EncryptedString(const string16& plain_text,
- std::string* cipher_text) const {
+LoginDatabase::EncryptionResult LoginDatabase::EncryptedString(
+ const string16& plain_text,
+ std::string* cipher_text) const {
*cipher_text = std::string();
- return true;
+ return ENCRYPTION_RESULT_SUCCESS;
}
-bool LoginDatabase::DecryptedString(const std::string& cipher_text,
- string16* plain_text) const {
+LoginDatabase::EncryptionResult LoginDatabase::DecryptedString(
+ const std::string& cipher_text,
+ string16* plain_text) const {
*plain_text = string16();
- return true;
+ return ENCRYPTION_RESULT_SUCCESS;
}
diff --git a/chrome/browser/password_manager/login_database_posix.cc b/chrome/browser/password_manager/login_database_posix.cc
index 99eb621..a093576 100644
--- a/chrome/browser/password_manager/login_database_posix.cc
+++ b/chrome/browser/password_manager/login_database_posix.cc
@@ -8,14 +8,16 @@
// TODO: Actually encrypt passwords on Linux.
-bool LoginDatabase::EncryptedString(const string16& plain_text,
- std::string* cipher_text) const {
+LoginDatabase::EncryptionResult LoginDatabase::EncryptedString(
+ const string16& plain_text,
+ std::string* cipher_text) const {
*cipher_text = UTF16ToUTF8(plain_text);
- return true;
+ return ENCRYPTION_RESULT_SUCCESS;
}
-bool LoginDatabase::DecryptedString(const std::string& cipher_text,
- string16* plain_text) const {
+LoginDatabase::EncryptionResult LoginDatabase::DecryptedString(
+ const std::string& cipher_text,
+ string16* plain_text) const {
*plain_text = UTF8ToUTF16(cipher_text);
- return true;
+ return ENCRYPTION_RESULT_SUCCESS;
}
diff --git a/chrome/browser/password_manager/login_database_win.cc b/chrome/browser/password_manager/login_database_win.cc
index 9862abc..13a48be 100644
--- a/chrome/browser/password_manager/login_database_win.cc
+++ b/chrome/browser/password_manager/login_database_win.cc
@@ -6,12 +6,18 @@
#include "chrome/browser/password_manager/login_database.h"
#include "components/webdata/encryptor/encryptor.h"
-bool LoginDatabase::EncryptedString(const string16& plain_text,
- std::string* cipher_text) const {
- return Encryptor::EncryptString16(plain_text, cipher_text);
+LoginDatabase::EncryptionResult LoginDatabase::EncryptedString(
+ const string16& plain_text,
+ std::string* cipher_text) const {
+ if (Encryptor::EncryptString16(plain_text, cipher_text))
+ return ENCRYPTION_RESULT_SUCCESS;
+ return ENCRYPTION_RESULT_ITEM_FAILURE;
}
-bool LoginDatabase::DecryptedString(const std::string& cipher_text,
- string16* plain_text) const {
- return Encryptor::DecryptString16(cipher_text, plain_text);
+LoginDatabase::EncryptionResult LoginDatabase::DecryptedString(
+ const std::string& cipher_text,
+ string16* plain_text) const {
+ if (Encryptor::DecryptString16(cipher_text, plain_text))
+ return ENCRYPTION_RESULT_SUCCESS;
+ return ENCRYPTION_RESULT_ITEM_FAILURE;
}
diff --git a/chrome/browser/password_manager/password_form_manager.cc b/chrome/browser/password_manager/password_form_manager.cc
index b28ba21..0d0772b 100644
--- a/chrome/browser/password_manager/password_form_manager.cc
+++ b/chrome/browser/password_manager/password_form_manager.cc
@@ -281,7 +281,8 @@
// copies to a minimum here.
int best_score = 0;
- std::vector<PasswordForm> empties; // Empty-path matches in result set.
+ // These credentials will be in the final result regardless of score.
+ std::vector<PasswordForm> credentials_to_keep;
for (size_t i = 0; i < logins_result.size(); i++) {
if (IgnoreResult(*logins_result[i])) {
delete logins_result[i];
@@ -304,9 +305,19 @@
if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) &&
(observed_form_.signon_realm == logins_result[i]->origin.spec()) &&
(current_score > 0) && (!logins_result[i]->blacklisted_by_user)) {
- empties.push_back(*logins_result[i]);
+ credentials_to_keep.push_back(*logins_result[i]);
}
+ // Always keep generated passwords as part of the result set. If a user
+ // generates a password on a signup form, it should show on a login form
+ // even if they have a previous login saved.
+ // TODO(gcasto): We don't want to cut credentials that were saved on signup
+ // forms even if they weren't generated, but currently it's hard to
+ // distinguish between those forms and two different login forms on the
+ // same domain. Filed http://crbug.com/294468 to look into this.
+ if (logins_result[i]->type == PasswordForm::TYPE_GENERATED)
+ credentials_to_keep.push_back(*logins_result[i]);
+
if (current_score < best_score) {
delete logins_result[i];
continue;
@@ -332,11 +343,12 @@
return;
}
- for (std::vector<PasswordForm>::const_iterator it = empties.begin();
- it != empties.end(); ++it) {
+ for (std::vector<PasswordForm>::const_iterator it =
+ credentials_to_keep.begin();
+ it != credentials_to_keep.end(); ++it) {
// If we don't already have a result with the same username, add the
- // lower-scored empty-path match (if it had equal score it would already be
- // in best_matches_).
+ // lower-scored match (if it had equal score it would already be in
+ // best_matches_).
if (best_matches_.find(it->username_value) == best_matches_.end())
best_matches_[it->username_value] = new PasswordForm(*it);
}
diff --git a/chrome/browser/password_manager/password_form_manager_unittest.cc b/chrome/browser/password_manager/password_form_manager_unittest.cc
index a2d98d3..6cc4f07 100644
--- a/chrome/browser/password_manager/password_form_manager_unittest.cc
+++ b/chrome/browser/password_manager/password_form_manager_unittest.cc
@@ -50,7 +50,17 @@
const autofill::PasswordForm& form_for_autofill,
const autofill::PasswordFormMap& best_matches,
const autofill::PasswordForm& preferred_match,
- bool wait_for_username) const OVERRIDE {}
+ bool wait_for_username) const OVERRIDE {
+ best_matches_ = best_matches;
+ }
+
+ const autofill::PasswordFormMap& GetLatestBestMatches() {
+ return best_matches_;
+ }
+
+ private:
+ // Marked mutable to get around constness of Autofill().
+ mutable autofill::PasswordFormMap best_matches_;
};
} // namespace
@@ -513,6 +523,41 @@
EXPECT_EQ(0u, manager->num_sent_messages());
}
+TEST_F(PasswordFormManagerTest, TestForceInclusionOfGeneratedPasswords) {
+ TestPasswordManagerDelegate delegate(profile());
+ TestPasswordManager password_manager(&delegate);
+ scoped_ptr<TestPasswordFormManager> manager(new TestPasswordFormManager(
+ profile(), &password_manager, *observed_form(), false));
+
+ // Simulate having two matches for this origin, one of which was from a form
+ // with different HTML tags for elements. Because of scoring differences,
+ // only the first form will be sent to Autofill().
+ std::vector<PasswordForm*> results;
+ results.push_back(CreateSavedMatch(false));
+ results.push_back(CreateSavedMatch(false));
+ results[1]->username_value = ASCIIToUTF16("other@gmail.com");
+ results[1]->password_element = ASCIIToUTF16("signup_password");
+ results[1]->username_element = ASCIIToUTF16("signup_username");
+ SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
+ SimulateResponseFromPasswordStore(manager.get(), results);
+ EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size());
+ results.clear();
+
+ // Same thing, except this time the credentials that don't match quite as
+ // well are generated. They should now be sent to Autofill().
+ manager.reset(new TestPasswordFormManager(
+ profile(), &password_manager, *observed_form(), false));
+ results.push_back(CreateSavedMatch(false));
+ results.push_back(CreateSavedMatch(false));
+ results[1]->username_value = ASCIIToUTF16("other@gmail.com");
+ results[1]->password_element = ASCIIToUTF16("signup_password");
+ results[1]->username_element = ASCIIToUTF16("signup_username");
+ results[1]->type = PasswordForm::TYPE_GENERATED;
+ SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
+ SimulateResponseFromPasswordStore(manager.get(), results);
+ EXPECT_EQ(2u, password_manager.GetLatestBestMatches().size());
+}
+
TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernames) {
scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
profile(), NULL, NULL, *observed_form(), false));
diff --git a/chrome/browser/password_manager/password_store_win_unittest.cc b/chrome/browser/password_manager/password_store_win_unittest.cc
index b05b468..0a6e8ad 100644
--- a/chrome/browser/password_manager/password_store_win_unittest.cc
+++ b/chrome/browser/password_manager/password_store_win_unittest.cc
@@ -150,12 +150,12 @@
// PasswordStore, WDS schedule work on this thread.
content::TestBrowserThread db_thread_;
- scoped_ptr<LoginDatabase> login_db_;
+ base::ScopedTempDir temp_dir_;
scoped_ptr<TestingProfile> profile_;
+ scoped_ptr<LoginDatabase> login_db_;
scoped_refptr<WebDataService> wds_;
scoped_refptr<WebDatabaseService> wdbs_;
scoped_refptr<PasswordStore> store_;
- base::ScopedTempDir temp_dir_;
};
ACTION(STLDeleteElements0) {
diff --git a/chrome/browser/plugins/plugin_info_message_filter.cc b/chrome/browser/plugins/plugin_info_message_filter.cc
index 9a15415..0b349c0 100644
--- a/chrome/browser/plugins/plugin_info_message_filter.cc
+++ b/chrome/browser/plugins/plugin_info_message_filter.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/content_settings.h"
+#include "chrome/common/extensions/features/simple_feature.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -30,6 +31,7 @@
#include "base/win/metro.h"
#endif
+using chrome::ChromeContentClient;
using content::PluginService;
using content::WebPluginInfo;
@@ -43,7 +45,7 @@
}
// Treat Native Client invocations like JavaScript.
- if (plugin.name == ASCIIToUTF16(chrome::ChromeContentClient::kNaClPluginName))
+ if (plugin.name == ASCIIToUTF16(ChromeContentClient::kNaClPluginName))
return true;
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
@@ -57,6 +59,28 @@
return false;
}
+// Helper for whitelisting Chrome Remote Desktop's Apps v2 builds to load the
+// Remoting Viewer plugin even though it is a trusted Pepper plugin.
+bool IsRemotingAppAndPlugin(const WebPluginInfo& plugin,
+ const GURL& policy_url) {
+ const char* kAppWhitelist[] = {
+ "2775E568AC98F9578791F1EAB65A1BF5F8CEF414",
+ "4AA3C5D69A4AECBD236CAD7884502209F0F5C169",
+ "97B23E01B2AA064E8332EE43A7A85C628AADC3F2"
+ };
+ base::FilePath remoting_path(ChromeContentClient::kRemotingViewerPluginPath);
+ if (plugin.path == remoting_path &&
+ policy_url.SchemeIs("chrome-extension") &&
+ extensions::SimpleFeature::IsIdInWhitelist(
+ policy_url.host(),
+ std::set<std::string>(kAppWhitelist,
+ kAppWhitelist + arraysize(kAppWhitelist)))) {
+ return true;
+ }
+
+ return false;
+}
+
} // namespace
PluginInfoMessageFilter::Context::Context(int render_process_id,
@@ -308,7 +332,6 @@
const std::string& resource,
ContentSetting* setting,
bool* uses_default_content_setting) const {
-
scoped_ptr<base::Value> value;
content_settings::SettingInfo info;
bool uses_plugin_specific_setting = false;
@@ -335,6 +358,13 @@
!uses_plugin_specific_setting &&
info.primary_pattern == ContentSettingsPattern::Wildcard() &&
info.secondary_pattern == ContentSettingsPattern::Wildcard();
+
+ // Temporary white-list of CRD's v2 app until crbug.com/134216 is complete.
+ if (IsRemotingAppAndPlugin(plugin, policy_url) &&
+ info.source == content_settings::SETTING_SOURCE_EXTENSION &&
+ *setting == CONTENT_SETTING_BLOCK) {
+ *setting = CONTENT_SETTING_ALLOW;
+ }
}
void PluginInfoMessageFilter::Context::MaybeGrantAccess(
diff --git a/chrome/browser/plugins/plugin_metadata.cc b/chrome/browser/plugins/plugin_metadata.cc
index 5f2fc50..75ca52a 100644
--- a/chrome/browser/plugins/plugin_metadata.cc
+++ b/chrome/browser/plugins/plugin_metadata.cc
@@ -93,12 +93,8 @@
PluginMetadata::SecurityStatus PluginMetadata::GetSecurityStatus(
const content::WebPluginInfo& plugin) const {
if (versions_.empty()) {
-#if defined(OS_LINUX)
- // On Linux, unknown plugins require authorization.
+ // Unknown plugins require authorization.
return SECURITY_STATUS_REQUIRES_AUTHORIZATION;
-#else
- return SECURITY_STATUS_UP_TO_DATE;
-#endif
}
Version version;
diff --git a/chrome/browser/plugins/plugin_metadata_unittest.cc b/chrome/browser/plugins/plugin_metadata_unittest.cc
index bb69ee7..b84843a 100644
--- a/chrome/browser/plugins/plugin_metadata_unittest.cc
+++ b/chrome/browser/plugins/plugin_metadata_unittest.cc
@@ -38,12 +38,8 @@
GURL(),
ASCIIToUTF16("ClayBrick"),
std::string());
-#if defined(OS_LINUX)
EXPECT_EQ(kRequiresAuthorization,
GetSecurityStatus(&plugin_metadata, "1.2.3"));
-#else
- EXPECT_EQ(kUpToDate, GetSecurityStatus(&plugin_metadata, "1.2.3"));
-#endif
plugin_metadata.AddVersion(Version("9.4.1"), kRequiresAuthorization);
plugin_metadata.AddVersion(Version("10"), kOutOfDate);
diff --git a/chrome/browser/policy/DEPS b/chrome/browser/policy/DEPS
index 92a7802..68b3aea 100644
--- a/chrome/browser/policy/DEPS
+++ b/chrome/browser/policy/DEPS
@@ -46,7 +46,6 @@
"+chrome/browser/search_engines/search_terms_data.h",
"+chrome/browser/search_engines/template_url.h",
"+chrome/common/extensions/extension.h",
- "+chrome/common/pref_names.h",
"+content/public/browser/notification_service.h",
],
@@ -64,7 +63,6 @@
r"configuration_policy_handler_unittest\.cc": [
"+chrome/browser/extensions/external_policy_loader.h",
- "+chrome/common/pref_names.h",
],
r"configuration_policy_pref_store_unittest\.cc": [
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index 47bba27..28c2036 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -130,9 +130,6 @@
platform_provider_.reset(CreatePlatformProvider());
- device_management_service_.reset(
- new DeviceManagementService(GetDeviceManagementUrl()));
-
#if defined(OS_CHROMEOS)
// CryptohomeLibrary or DBusThreadManager may be uninitialized on unit tests.
if (chromeos::CryptohomeLibrary::IsInitialized() &&
@@ -182,6 +179,8 @@
local_state_ = local_state;
request_context_ = request_context;
+ device_management_service_.reset(
+ new DeviceManagementService(request_context, GetDeviceManagementUrl()));
device_management_service_->ScheduleInitialization(
kServiceInitializationStartupDelay);
diff --git a/chrome/browser/policy/cloud/DEPS b/chrome/browser/policy/cloud/DEPS
index 6dc0064..bac91b5 100644
--- a/chrome/browser/policy/cloud/DEPS
+++ b/chrome/browser/policy/cloud/DEPS
@@ -88,20 +88,13 @@
],
r"device_management_service\.cc": [
- "+chrome/browser/browser_process.h",
"+chrome/browser/net/basic_http_user_agent_settings.h",
"+chrome/browser/net/chrome_net_log.h",
"+chrome/common/chrome_version_info.h",
- "+content/public/browser/browser_thread.h",
"+content/public/common/content_client.h",
"+chrome/browser/chromeos/system/statistics_provider.h",
],
- r"device_management_service_unittest\.cc": [
- "+chrome/test/base/testing_browser_process.h",
- "+content/public/test/test_browser_thread_bundle.h",
- ],
-
r"test_request_interceptor\.cc": [
"+content/public/browser/browser_thread.h",
"+content/public/test/test_utils.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
index 104ee85..6ee7178 100644
--- a/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.cc
@@ -16,9 +16,7 @@
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_token_service.h"
-#if defined(OS_ANDROID)
-#include "chrome/browser/signin/android_profile_oauth2_token_service.h"
-#else
+#if !defined(OS_ANDROID)
#include "google_apis/gaia/oauth2_access_token_consumer.h"
#include "google_apis/gaia/oauth2_access_token_fetcher.h"
#endif
@@ -45,13 +43,7 @@
TokenServiceHelper();
void FetchAccessToken(
-#if defined(OS_ANDROID)
- // TODO(atwilson): Remove this when StartRequestForUsername() is merged
- // into the base OAuth2TokenService class.
- AndroidProfileOAuth2TokenService* token_service,
-#else
OAuth2TokenService* token_service,
-#endif
const std::string& username,
const StringCallback& callback);
@@ -70,29 +62,21 @@
CloudPolicyClientRegistrationHelper::TokenServiceHelper::TokenServiceHelper() {}
void CloudPolicyClientRegistrationHelper::TokenServiceHelper::FetchAccessToken(
-#if defined(OS_ANDROID)
- AndroidProfileOAuth2TokenService* token_service,
-#else
OAuth2TokenService* token_service,
-#endif
- const std::string& username,
+ const std::string& account_id,
const StringCallback& callback) {
DCHECK(!token_request_);
// Either the caller must supply a username, or the user must be signed in
// already.
- DCHECK(!username.empty() || token_service->RefreshTokenIsAvailable());
+ DCHECK(!account_id.empty());
+ DCHECK(token_service->RefreshTokenIsAvailable(account_id));
+
callback_ = callback;
OAuth2TokenService::ScopeSet scopes;
scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth);
scopes.insert(kServiceScopeGetUserInfo);
-
-#if defined(OS_ANDROID)
- token_request_ =
- token_service->StartRequestForUsername(username, scopes, this);
-#else
- token_request_ = token_service->StartRequest(scopes, this);
-#endif
+ token_request_ = token_service->StartRequest(account_id, scopes, this);
}
void CloudPolicyClientRegistrationHelper::TokenServiceHelper::OnGetTokenSuccess(
@@ -195,12 +179,8 @@
void CloudPolicyClientRegistrationHelper::StartRegistration(
-#if defined(OS_ANDROID)
- AndroidProfileOAuth2TokenService* token_service,
-#else
OAuth2TokenService* token_service,
-#endif
- const std::string& username,
+ const std::string& account_id,
const base::Closure& callback) {
DVLOG(1) << "Starting registration process with username";
DCHECK(!client_->is_registered());
@@ -210,7 +190,7 @@
token_service_helper_.reset(new TokenServiceHelper());
token_service_helper_->FetchAccessToken(
token_service,
- username,
+ account_id,
base::Bind(&CloudPolicyClientRegistrationHelper::OnTokenFetched,
base::Unretained(this)));
}
diff --git a/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h b/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h
index cb26ed5..47f0201 100644
--- a/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h
+++ b/chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h
@@ -15,7 +15,6 @@
#include "chrome/browser/policy/cloud/user_info_fetcher.h"
#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
-class AndroidProfileOAuth2TokenService;
class OAuth2TokenService;
namespace net {
@@ -43,18 +42,11 @@
// Starts the client registration process. This version uses the
// supplied OAuth2TokenService to mint the new token for the userinfo
- // and DM services, using the |username| account.
+ // and DM services, using the |account_id|.
// |callback| is invoked when the registration is complete.
void StartRegistration(
-#if defined(OS_ANDROID)
- // TODO(atwilson): Remove this when the Android StartRequestForUsername()
- // API is folded into the base OAuth2TokenService class (when that class
- // is made multi-account aware).
- AndroidProfileOAuth2TokenService* token_service,
-#else
OAuth2TokenService* token_service,
-#endif
- const std::string& username,
+ const std::string& account_id,
const base::Closure& callback);
#if !defined(OS_ANDROID)
diff --git a/chrome/browser/policy/cloud/cloud_policy_client_unittest.cc b/chrome/browser/policy/cloud/cloud_policy_client_unittest.cc
index bafcc3d..5f80c5d 100644
--- a/chrome/browser/policy/cloud/cloud_policy_client_unittest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_client_unittest.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "chrome/browser/policy/cloud/mock_cloud_policy_client.h"
#include "chrome/browser/policy/cloud/mock_device_management_service.h"
#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
@@ -187,6 +188,7 @@
em::DeviceManagementResponse unregistration_response_;
em::DeviceManagementResponse upload_certificate_response_;
+ base::MessageLoop loop_;
std::string client_id_;
PolicyNamespaceKey policy_ns_key_;
MockDeviceManagementService service_;
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
index be4e021..e0fb8a5 100644
--- a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
@@ -51,18 +51,13 @@
namespace policy {
-namespace {
-
const char kDMToken[] = "dmtoken";
const char kDeviceID[] = "deviceid";
const char kTestExtension[] = "kjmkgkdkpedkejedfhmfcenooemhbpbo";
-const char kTestExtension2[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
const base::FilePath::CharType kTestExtensionPath[] =
FILE_PATH_LITERAL("extensions/managed_extension");
-const base::FilePath::CharType kTestExtension2Path[] =
- FILE_PATH_LITERAL("extensions/managed_extension2");
const char kTestPolicy[] =
"{"
@@ -71,6 +66,11 @@
" }"
"}";
+#if defined(OS_CHROMEOS)
+const char kTestExtension2[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
+const base::FilePath::CharType kTestExtension2Path[] =
+ FILE_PATH_LITERAL("extensions/managed_extension2");
+
const char kTestPolicyJSON[] = "{\"Name\":\"disable_all_the_things\"}";
const char kTestPolicy2[] =
@@ -81,8 +81,7 @@
"}";
const char kTestPolicy2JSON[] = "{\"Another\":\"turn_it_off\"}";
-
-} // namespace
+#endif // defined(OS_CHROMEOS)
class ComponentCloudPolicyTest : public ExtensionBrowserTest {
protected:
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 d01b453..deb7724 100644
--- a/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc
+++ b/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc
@@ -24,7 +24,7 @@
#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 "components/policy/core/common/policy_schema.h"
+#include "components/policy/core/common/schema.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread.h"
#include "net/url_request/test_url_fetcher_factory.h"
@@ -44,7 +44,6 @@
const char kTestExtension[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
const char kTestExtension2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
-const char kTestExtension3[] = "cccccccccccccccccccccccccccccccc";
const char kTestDownload[] = "http://example.com/getpolicy?id=123";
const char kTestDownload2[] = "http://example.com/getpolicy?id=456";
@@ -61,7 +60,6 @@
const char kTestSchema[] =
"{"
- " \"$schema\": \"http://json-schema.org/draft-03/schema#\","
" \"type\": \"object\","
" \"properties\": {"
" \"Name\": { \"type\": \"string\" },"
@@ -194,9 +192,9 @@
return builder_.GetBlob();
}
- scoped_ptr<PolicySchema> CreateTestSchema() {
+ scoped_ptr<SchemaOwner> CreateTestSchema() {
std::string error;
- scoped_ptr<PolicySchema> schema = PolicySchema::Parse(kTestSchema, &error);
+ scoped_ptr<SchemaOwner> schema = SchemaOwner::Parse(kTestSchema, &error);
EXPECT_TRUE(schema) << error;
return schema.Pass();
}
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_store.cc b/chrome/browser/policy/cloud/component_cloud_policy_store.cc
index 3a9c5d6..334f9d6 100644
--- a/chrome/browser/policy/cloud/component_cloud_policy_store.cc
+++ b/chrome/browser/policy/cloud/component_cloud_policy_store.cc
@@ -27,7 +27,6 @@
const char kValue[] = "Value";
const char kLevel[] = "Level";
-const char kMandatory[] = "Mandatory";
const char kRecommended[] = "Recommended";
const struct DomainConstants {
diff --git a/chrome/browser/policy/cloud/device_management_service.cc b/chrome/browser/policy/cloud/device_management_service.cc
index 1b23c7c..4e13def 100644
--- a/chrome/browser/policy/cloud/device_management_service.cc
+++ b/chrome/browser/policy/cloud/device_management_service.cc
@@ -12,11 +12,9 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
-#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/basic_http_user_agent_settings.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "chrome/common/chrome_version_info.h"
-#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_client.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
@@ -37,8 +35,6 @@
#include "chrome/browser/chromeos/system/statistics_provider.h"
#endif
-using content::BrowserThread;
-
namespace em = enterprise_management;
namespace policy {
@@ -254,8 +250,8 @@
class DeviceManagementRequestContextGetter
: public net::URLRequestContextGetter {
public:
- explicit DeviceManagementRequestContextGetter(
- net::URLRequestContextGetter* base_context_getter)
+ DeviceManagementRequestContextGetter(
+ scoped_refptr<net::URLRequestContextGetter> base_context_getter)
: base_context_getter_(base_context_getter) {}
// Overridden from net::URLRequestContextGetter:
@@ -267,14 +263,14 @@
virtual ~DeviceManagementRequestContextGetter() {}
private:
- scoped_ptr<net::URLRequestContext> context_;
scoped_refptr<net::URLRequestContextGetter> base_context_getter_;
+ scoped_ptr<net::URLRequestContext> context_;
};
net::URLRequestContext*
DeviceManagementRequestContextGetter::GetURLRequestContext() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(GetNetworkTaskRunner()->RunsTasksOnCurrentThread());
if (!context_.get()) {
context_.reset(new DeviceManagementRequestContext(
base_context_getter_->GetURLRequestContext()));
@@ -285,7 +281,7 @@
scoped_refptr<base::SingleThreadTaskRunner>
DeviceManagementRequestContextGetter::GetNetworkTaskRunner() const {
- return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
+ return base_context_getter_->GetNetworkTaskRunner();
}
} // namespace
@@ -568,8 +564,8 @@
if (initialized_)
return;
DCHECK(!request_context_getter_.get());
- request_context_getter_ = new DeviceManagementRequestContextGetter(
- g_browser_process->system_request_context());
+ request_context_getter_ =
+ new DeviceManagementRequestContextGetter(request_context_);
initialized_ = true;
while (!queued_jobs_.empty()) {
@@ -589,8 +585,10 @@
}
DeviceManagementService::DeviceManagementService(
+ scoped_refptr<net::URLRequestContextGetter> request_context,
const std::string& server_url)
- : server_url_(server_url),
+ : request_context_(request_context),
+ server_url_(server_url),
initialized_(false),
weak_ptr_factory_(this) {
}
diff --git a/chrome/browser/policy/cloud/device_management_service.h b/chrome/browser/policy/cloud/device_management_service.h
index 2280166..cc7e08e 100644
--- a/chrome/browser/policy/cloud/device_management_service.h
+++ b/chrome/browser/policy/cloud/device_management_service.h
@@ -99,7 +99,9 @@
// requests.
class DeviceManagementService : public net::URLFetcherDelegate {
public:
- explicit DeviceManagementService(const std::string& server_url);
+ DeviceManagementService(
+ scoped_refptr<net::URLRequestContextGetter> request_context,
+ const std::string& server_url);
virtual ~DeviceManagementService();
// The ID of URLFetchers created by the DeviceManagementService. This can be
@@ -144,10 +146,13 @@
// callback.
void RemoveJob(DeviceManagementRequestJobImpl* job);
+ // The request context is wrapped by the |request_context_getter_|.
+ scoped_refptr<net::URLRequestContextGetter> request_context_;
+
// Server at which to contact the service.
const std::string server_url_;
- // The request context we use.
+ // The request context we use. This is a wrapper of |request_context_|.
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
// The jobs we currently have in flight.
diff --git a/chrome/browser/policy/cloud/device_management_service_browsertest.cc b/chrome/browser/policy/cloud/device_management_service_browsertest.cc
index 8ddd1ba..5042686 100644
--- a/chrome/browser/policy/cloud/device_management_service_browsertest.cc
+++ b/chrome/browser/policy/cloud/device_management_service_browsertest.cc
@@ -7,19 +7,23 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
#include "chrome/browser/policy/cloud/device_management_service.h"
#include "chrome/browser/policy/cloud/test_request_interceptor.h"
#include "chrome/browser/policy/test/local_policy_test_server.h"
#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/browser/browser_thread.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_test_job.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using content::BrowserThread;
using testing::DoAll;
using testing::Invoke;
using testing::InvokeWithoutArgs;
@@ -135,7 +139,9 @@
virtual void SetUpOnMainThread() OVERRIDE {
std::string service_url((this->*(GetParam()))());
- service_.reset(new DeviceManagementService(service_url));
+ service_.reset(new DeviceManagementService(
+ g_browser_process->system_request_context(),
+ service_url));
service_->ScheduleInitialization(0);
}
diff --git a/chrome/browser/policy/cloud/device_management_service_unittest.cc b/chrome/browser/policy/cloud/device_management_service_unittest.cc
index 2838bfc..e341e6e 100644
--- a/chrome/browser/policy/cloud/device_management_service_unittest.cc
+++ b/chrome/browser/policy/cloud/device_management_service_unittest.cc
@@ -6,12 +6,12 @@
#include <vector>
#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
#include "chrome/browser/policy/cloud/device_management_service.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -49,6 +49,8 @@
class DeviceManagementServiceTestBase : public testing::Test {
protected:
DeviceManagementServiceTestBase() {
+ request_context_ =
+ new net::TestURLRequestContextGetter(loop_.message_loop_proxy());
ResetService();
InitializeService();
}
@@ -59,7 +61,7 @@
}
void ResetService() {
- service_.reset(new DeviceManagementService(kServiceUrl));
+ service_.reset(new DeviceManagementService(request_context_, kServiceUrl));
}
void InitializeService() {
@@ -159,11 +161,10 @@
MOCK_METHOD1(OnJobRetry, void(DeviceManagementRequestJob*));
+ base::MessageLoop loop_;
+ scoped_refptr<net::TestURLRequestContextGetter> request_context_;
net::TestURLFetcherFactory factory_;
scoped_ptr<DeviceManagementService> service_;
-
- private:
- content::TestBrowserThreadBundle thread_bundle_;
};
struct FailedRequestParams {
diff --git a/chrome/browser/policy/cloud/mock_device_management_service.cc b/chrome/browser/policy/cloud/mock_device_management_service.cc
index eac6bda..55f5c5d 100644
--- a/chrome/browser/policy/cloud/mock_device_management_service.cc
+++ b/chrome/browser/policy/cloud/mock_device_management_service.cc
@@ -4,8 +4,10 @@
#include "chrome/browser/policy/cloud/mock_device_management_service.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/string_util.h"
#include "net/base/net_errors.h"
+#include "net/url_request/url_request_test_util.h"
using testing::Action;
@@ -117,7 +119,9 @@
MockDeviceManagementJob::~MockDeviceManagementJob() {}
MockDeviceManagementService::MockDeviceManagementService()
- : DeviceManagementService(std::string()) {}
+ : DeviceManagementService(new net::TestURLRequestContextGetter(
+ base::MessageLoopProxy::current()),
+ std::string()) {}
MockDeviceManagementService::~MockDeviceManagementService() {}
diff --git a/chrome/browser/policy/cloud/policy_builder.h b/chrome/browser/policy/cloud/policy_builder.h
index 6f01e4c..5f3b530 100644
--- a/chrome/browser/policy/cloud/policy_builder.h
+++ b/chrome/browser/policy/cloud/policy_builder.h
@@ -11,13 +11,10 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/policy/proto/cloud/chrome_extension_policy.pb.h"
#include "chrome/browser/policy/proto/cloud/device_management_local.pb.h"
#include "crypto/rsa_private_key.h"
-
-namespace enterprise_management {
-class CloudPolicySettings;
-class ExternalPolicyData;
-} // namespace enterprise_management
+#include "policy/proto/cloud_policy.pb.h"
namespace policy {
diff --git a/chrome/browser/policy/cloud/resource_cache.cc b/chrome/browser/policy/cloud/resource_cache.cc
index b71ff46..6d8bd24 100644
--- a/chrome/browser/policy/cloud/resource_cache.cc
+++ b/chrome/browser/policy/cloud/resource_cache.cc
@@ -8,6 +8,7 @@
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/logging.h"
+#include "base/safe_numerics.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
@@ -79,9 +80,10 @@
// 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.
+ int size = base::checked_numeric_cast<int>(data.size());
return VerifyKeyPathAndGetSubkeyPath(key, true, subkey, &subkey_path) &&
base::DeleteFile(subkey_path, false) &&
- file_util::WriteFile(subkey_path, data.data(), data.size());
+ (file_util::WriteFile(subkey_path, data.data(), size) == size);
}
bool ResourceCache::Load(const std::string& key,
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service.cc b/chrome/browser/policy/cloud/user_policy_signin_service.cc
index 3ab2fba..7075d14 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service.cc
@@ -42,7 +42,8 @@
// ProfileOAuth2TokenService 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(!oauth2_token_service_->RefreshTokenIsAvailable());
+ DCHECK(!oauth2_token_service_->RefreshTokenIsAvailable(
+ oauth2_token_service_->GetPrimaryAccountId()));
// 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
@@ -148,7 +149,8 @@
DVLOG_IF(1, manager->IsClientRegistered())
<< "Client already registered - not fetching DMToken";
if (!manager->IsClientRegistered()) {
- if (!oauth2_token_service_->RefreshTokenIsAvailable()) {
+ if (!oauth2_token_service_->RefreshTokenIsAvailable(
+ oauth2_token_service_->GetPrimaryAccountId())) {
// No token yet - this class listens for OnRefreshTokenAvailable()
// and will re-attempt registration once the token is available.
DLOG(WARNING) << "No OAuth Refresh Token - delaying policy download";
@@ -176,7 +178,7 @@
enterprise_management::DeviceRegisterRequest::BROWSER));
registration_helper_->StartRegistration(
oauth2_token_service_,
- GetSigninManager()->GetAuthenticatedUsername(),
+ oauth2_token_service_->GetPrimaryAccountId(),
base::Bind(&UserPolicySigninService::OnRegistrationComplete,
base::Unretained(this)));
}
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_android.cc b/chrome/browser/policy/cloud/user_policy_signin_service_android.cc
index 6029c8f..8c42603 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_android.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_android.cc
@@ -41,7 +41,7 @@
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> request_context,
DeviceManagementService* device_management_service,
- AndroidProfileOAuth2TokenService* token_service)
+ ProfileOAuth2TokenService* token_service)
: UserPolicySigninServiceBase(profile,
local_state,
request_context,
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_android.h b/chrome/browser/policy/cloud/user_policy_signin_service_android.h
index 4ae9716..003cf4b 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_android.h
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_android.h
@@ -14,7 +14,7 @@
#include "base/memory/weak_ptr.h"
#include "chrome/browser/policy/cloud/user_policy_signin_service_base.h"
-class AndroidProfileOAuth2TokenService;
+class ProfileOAuth2TokenService;
class Profile;
namespace net {
@@ -34,7 +34,7 @@
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> request_context,
DeviceManagementService* device_management_service,
- AndroidProfileOAuth2TokenService* token_service);
+ ProfileOAuth2TokenService* token_service);
virtual ~UserPolicySigninService();
// Registers a CloudPolicyClient for fetching policy for |username|.
@@ -68,7 +68,7 @@
// Weak pointer to the token service used to authenticate the
// CloudPolicyClient during registration.
- AndroidProfileOAuth2TokenService* oauth2_token_service_;
+ ProfileOAuth2TokenService* oauth2_token_service_;
DISALLOW_COPY_AND_ASSIGN(UserPolicySigninService);
};
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 8416b06..965635d 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -18,6 +18,7 @@
#include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
#include "chrome/browser/signin/fake_signin_manager.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager.h"
@@ -41,10 +42,8 @@
#if defined(OS_ANDROID)
#include "chrome/browser/policy/cloud/user_policy_signin_service_android.h"
-#include "chrome/browser/signin/android_profile_oauth2_token_service.h"
#else
#include "chrome/browser/policy/cloud/user_policy_signin_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
#endif
namespace em = enterprise_management;
@@ -89,59 +88,6 @@
}
};
-#if defined(OS_ANDROID)
-// TODO(atwilson): Remove this when ProfileOAuth2TokenService supports
-// usernames.
-class FakeAndroidProfileOAuth2TokenService
- : public AndroidProfileOAuth2TokenService {
- public:
- explicit FakeAndroidProfileOAuth2TokenService(Profile* profile) {
- Initialize(profile);
- }
-
- static BrowserContextKeyedService* Build(content::BrowserContext* profile) {
- return new FakeAndroidProfileOAuth2TokenService(
- static_cast<Profile*>(profile));
- }
-
- // AndroidProfileOAuth2TokenService overrides:
- virtual void FetchOAuth2TokenWithUsername(
- RequestImpl* request,
- const std::string& username,
- const OAuth2TokenService::ScopeSet& scope) OVERRIDE {
- ASSERT_TRUE(!HasPendingRequest());
- ASSERT_EQ(kTestUser, username);
- ASSERT_EQ(2U, scope.size());
- EXPECT_EQ(1U, scope.count(GaiaConstants::kDeviceManagementServiceOAuth));
- EXPECT_EQ(1U, scope.count(
- "https://www.googleapis.com/auth/userinfo.email"));
- pending_request_ = request->AsWeakPtr();
- }
-
- void IssueToken(const std::string& token) {
- ASSERT_TRUE(HasPendingRequest());
- GoogleServiceAuthError error = GoogleServiceAuthError::AuthErrorNone();
- if (token.empty())
- error = GoogleServiceAuthError::FromServiceError("fail");
- if (pending_request_) {
- pending_request_->InformConsumer(
- error,
- token,
- base::Time::Now() + base::TimeDelta::FromDays(1));
- }
- pending_request_.reset();
- }
-
- bool HasPendingRequest() const {
- return pending_request_;
- }
-
- private:
- base::WeakPtr<RequestImpl> pending_request_;
-};
-
-#endif
-
class UserPolicySigninServiceTest : public testing::Test {
public:
UserPolicySigninServiceTest()
@@ -157,6 +103,12 @@
}
void RegisterPolicyClientWithCallback(UserPolicySigninService* service) {
+ // Policy client registration on Android depends on Token Service having
+ // a valid login token, while on other platforms, the login refresh token
+ // is specified directly.
+#if defined(OS_ANDROID)
+ GetTokenService()->IssueRefreshToken("oauth2_login_refresh_token");
+#endif
service->RegisterPolicyClient(
kTestUser,
#if !defined(OS_ANDROID)
@@ -188,13 +140,8 @@
builder.SetPrefService(scoped_ptr<PrefServiceSyncable>(prefs.Pass()));
builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
SigninManagerFake::Build);
-#if defined(OS_ANDROID)
- builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
- FakeAndroidProfileOAuth2TokenService::Build);
-#else
builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
FakeProfileOAuth2TokenService::Build);
-#endif
profile_ = builder.Build().Pass();
signin_manager_ = static_cast<SigninManagerFake*>(
@@ -225,37 +172,24 @@
run_loop.RunUntilIdle();
}
-#if defined(OS_ANDROID)
- FakeAndroidProfileOAuth2TokenService* GetTokenService() {
- ProfileOAuth2TokenService* service =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
- return static_cast<FakeAndroidProfileOAuth2TokenService*>(service);
- }
-#else
FakeProfileOAuth2TokenService* GetTokenService() {
ProfileOAuth2TokenService* service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
return static_cast<FakeProfileOAuth2TokenService*>(service);
}
-#endif
bool IsRequestActive() {
-#if defined(OS_ANDROID)
- if (GetTokenService()->HasPendingRequest())
- return true;
-#else
if (!GetTokenService()->GetPendingRequests().empty())
return true;
-#endif
return url_factory_.GetFetcherByID(0);
}
void MakeOAuthTokenFetchSucceed() {
-#if defined(OS_ANDROID)
- ASSERT_TRUE(GetTokenService()->HasPendingRequest());
- GetTokenService()->IssueToken("fake_token");
-#else
ASSERT_TRUE(IsRequestActive());
+#if defined(OS_ANDROID)
+ GetTokenService()->IssueTokenForAllPendingRequests("access_token",
+ base::Time::Now());
+#else
net::TestURLFetcher* fetcher = url_factory_.GetFetcherByID(0);
fetcher->set_response_code(net::HTTP_OK);
fetcher->SetResponseString(kValidTokenResponse);
@@ -626,8 +560,9 @@
// Cause the access token fetch to fail - callback should be invoked.
#if defined(OS_ANDROID)
- ASSERT_TRUE(GetTokenService()->HasPendingRequest());
- GetTokenService()->IssueToken("");
+ ASSERT_TRUE(!GetTokenService()->GetPendingRequests().empty());
+ GetTokenService()->IssueErrorForAllPendingRequests(
+ GoogleServiceAuthError::FromServiceError("fail"));
#else
net::TestURLFetcher* fetcher = url_factory_.GetFetcherByID(0);
fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, -1));
diff --git a/chrome/browser/policy/configuration_policy_handler.cc b/chrome/browser/policy/configuration_policy_handler.cc
index 30bcc9c..a708757 100644
--- a/chrome/browser/policy/configuration_policy_handler.cc
+++ b/chrome/browser/policy/configuration_policy_handler.cc
@@ -28,7 +28,6 @@
#include "chrome/browser/search_engines/search_terms_data.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
#include "grit/generated_resources.h"
#include "policy/policy_constants.h"
@@ -57,69 +56,9 @@
int error_message_id;
};
-// Maps a policy type to a preference path, and to the expected value type.
-struct DefaultSearchSimplePolicyHandlerEntry {
- const char* policy_name;
- const char* preference_path;
- base::Value::Type value_type;
-};
-
// Static data -----------------------------------------------------------------
-// List of policy types to preference names, for policies affecting the default
-// search provider.
-const DefaultSearchSimplePolicyHandlerEntry kDefaultSearchPolicyMap[] = {
- { key::kDefaultSearchProviderEnabled,
- prefs::kDefaultSearchProviderEnabled,
- Value::TYPE_BOOLEAN },
- { key::kDefaultSearchProviderName,
- prefs::kDefaultSearchProviderName,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderKeyword,
- prefs::kDefaultSearchProviderKeyword,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderSearchURL,
- prefs::kDefaultSearchProviderSearchURL,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderSuggestURL,
- prefs::kDefaultSearchProviderSuggestURL,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderInstantURL,
- prefs::kDefaultSearchProviderInstantURL,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderIconURL,
- prefs::kDefaultSearchProviderIconURL,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderEncodings,
- prefs::kDefaultSearchProviderEncodings,
- Value::TYPE_LIST },
- { key::kDefaultSearchProviderAlternateURLs,
- prefs::kDefaultSearchProviderAlternateURLs,
- Value::TYPE_LIST },
- { key::kDefaultSearchProviderSearchTermsReplacementKey,
- prefs::kDefaultSearchProviderSearchTermsReplacementKey,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderImageURL,
- prefs::kDefaultSearchProviderImageURL,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderNewTabURL,
- prefs::kDefaultSearchProviderNewTabURL,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderSearchURLPostParams,
- prefs::kDefaultSearchProviderSearchURLPostParams,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderSuggestURLPostParams,
- prefs::kDefaultSearchProviderSuggestURLPostParams,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderInstantURLPostParams,
- prefs::kDefaultSearchProviderInstantURLPostParams,
- Value::TYPE_STRING },
- { key::kDefaultSearchProviderImageURLPostParams,
- prefs::kDefaultSearchProviderImageURLPostParams,
- Value::TYPE_STRING },
-};
-
// List of entries determining which proxy policies can be specified, depending
// on the ProxyMode.
const ProxyModeValidationEntry kProxyModeValidationMap[] = {
@@ -239,6 +178,7 @@
return true;
}
+
// IntRangePolicyHandlerBase implementation ------------------------------------
IntRangePolicyHandlerBase::IntRangePolicyHandlerBase(
@@ -292,6 +232,7 @@
return true;
}
+
// StringToIntEnumListPolicyHandler implementation -----------------------------
StringToIntEnumListPolicyHandler::StringToIntEnumListPolicyHandler(
@@ -369,6 +310,7 @@
return true;
}
+
// IntRangePolicyHandler implementation ----------------------------------------
IntRangePolicyHandler::IntRangePolicyHandler(const char* policy_name,
@@ -395,6 +337,7 @@
}
}
+
// IntPercentageToDoublePolicyHandler implementation ---------------------------
IntPercentageToDoublePolicyHandler::IntPercentageToDoublePolicyHandler(
@@ -423,6 +366,7 @@
}
}
+
// ExtensionListPolicyHandler implementation -----------------------------------
ExtensionListPolicyHandler::ExtensionListPolicyHandler(const char* policy_name,
@@ -501,12 +445,14 @@
return true;
}
+
// ExtensionInstallForcelistPolicyHandler implementation -----------------------
-ExtensionInstallForcelistPolicyHandler::
- ExtensionInstallForcelistPolicyHandler()
- : TypeCheckingPolicyHandler(key::kExtensionInstallForcelist,
- base::Value::TYPE_LIST) {}
+ExtensionInstallForcelistPolicyHandler::ExtensionInstallForcelistPolicyHandler(
+ const char* pref_name)
+ : TypeCheckingPolicyHandler(key::kExtensionInstallForcelist,
+ base::Value::TYPE_LIST),
+ pref_name_(pref_name) {}
ExtensionInstallForcelistPolicyHandler::
~ExtensionInstallForcelistPolicyHandler() {}
@@ -527,7 +473,7 @@
if (CheckAndGetValue(policies, NULL, &value) &&
value &&
ParseList(value, dict.get(), NULL)) {
- prefs->SetValue(prefs::kExtensionInstallForceList, dict.release());
+ prefs->SetValue(pref_name_, dict.release());
}
}
@@ -592,6 +538,7 @@
return true;
}
+
// ExtensionURLPatternListPolicyHandler implementation -------------------------
ExtensionURLPatternListPolicyHandler::ExtensionURLPatternListPolicyHandler(
@@ -652,6 +599,7 @@
prefs->SetValue(pref_path_, value->DeepCopy());
}
+
// SimplePolicyHandler implementation ------------------------------------------
SimplePolicyHandler::SimplePolicyHandler(
@@ -677,10 +625,9 @@
// SyncPolicyHandler implementation --------------------------------------------
-SyncPolicyHandler::SyncPolicyHandler()
- : TypeCheckingPolicyHandler(key::kSyncDisabled,
- Value::TYPE_BOOLEAN) {
-}
+SyncPolicyHandler::SyncPolicyHandler(const char* pref_name)
+ : TypeCheckingPolicyHandler(key::kSyncDisabled, Value::TYPE_BOOLEAN),
+ pref_name_(pref_name) {}
SyncPolicyHandler::~SyncPolicyHandler() {
}
@@ -690,16 +637,15 @@
const Value* value = policies.GetValue(policy_name());
bool disable_sync;
if (value && value->GetAsBoolean(&disable_sync) && disable_sync)
- prefs->SetValue(prefs::kSyncManaged, value->DeepCopy());
+ prefs->SetValue(pref_name_, value->DeepCopy());
}
// AutofillPolicyHandler implementation ----------------------------------------
-AutofillPolicyHandler::AutofillPolicyHandler()
- : TypeCheckingPolicyHandler(key::kAutoFillEnabled,
- Value::TYPE_BOOLEAN) {
-}
+AutofillPolicyHandler::AutofillPolicyHandler(const char* pref_name)
+ : TypeCheckingPolicyHandler(key::kAutoFillEnabled, Value::TYPE_BOOLEAN),
+ pref_name_(pref_name) {}
AutofillPolicyHandler::~AutofillPolicyHandler() {
}
@@ -708,22 +654,23 @@
PrefValueMap* prefs) {
const Value* value = policies.GetValue(policy_name());
bool auto_fill_enabled;
- if (value && value->GetAsBoolean(&auto_fill_enabled) && !auto_fill_enabled) {
- prefs->SetValue(autofill::prefs::kAutofillEnabled,
- Value::CreateBooleanValue(false));
- }
+ if (value && value->GetAsBoolean(&auto_fill_enabled) && !auto_fill_enabled)
+ prefs->SetValue(pref_name_, Value::CreateBooleanValue(false));
}
// Android doesn't support these policies, and doesn't have a policy_path_parser
// implementation.
#if !defined(OS_ANDROID)
+
// DownloadDirPolicyHandler implementation -------------------------------------
-DownloadDirPolicyHandler::DownloadDirPolicyHandler()
- : TypeCheckingPolicyHandler(key::kDownloadDirectory,
- Value::TYPE_STRING) {
-}
+DownloadDirPolicyHandler::DownloadDirPolicyHandler(
+ const char* default_directory_pref_name,
+ const char* prompt_for_download_pref_name)
+ : TypeCheckingPolicyHandler(key::kDownloadDirectory, Value::TYPE_STRING),
+ default_directory_pref_name_(default_directory_pref_name),
+ prompt_for_download_pref_name_(prompt_for_download_pref_name) {}
DownloadDirPolicyHandler::~DownloadDirPolicyHandler() {
}
@@ -743,19 +690,18 @@
// lead to an empty path value after expansion (e.g. "\"\"").
if (expanded_value.empty())
expanded_value = DownloadPrefs::GetDefaultDownloadDirectory().value();
- prefs->SetValue(prefs::kDownloadDefaultDirectory,
+ prefs->SetValue(default_directory_pref_name_,
Value::CreateStringValue(expanded_value));
- prefs->SetValue(prefs::kPromptForDownload,
+ prefs->SetValue(prompt_for_download_pref_name_,
Value::CreateBooleanValue(false));
}
// DiskCacheDirPolicyHandler implementation ------------------------------------
-DiskCacheDirPolicyHandler::DiskCacheDirPolicyHandler()
- : TypeCheckingPolicyHandler(key::kDiskCacheDir,
- Value::TYPE_STRING) {
-}
+DiskCacheDirPolicyHandler::DiskCacheDirPolicyHandler(const char* pref_name)
+ : TypeCheckingPolicyHandler(key::kDiskCacheDir, Value::TYPE_STRING),
+ pref_name_(pref_name) {}
DiskCacheDirPolicyHandler::~DiskCacheDirPolicyHandler() {
}
@@ -767,19 +713,22 @@
if (value && value->GetAsString(&string_value)) {
base::FilePath::StringType expanded_value =
policy::path_parser::ExpandPathVariables(string_value);
- prefs->SetValue(prefs::kDiskCacheDir,
- Value::CreateStringValue(expanded_value));
+ prefs->SetValue(pref_name_, Value::CreateStringValue(expanded_value));
}
}
#endif // !defined(OS_ANDROID)
+
// FileSelectionDialogsHandler implementation ----------------------------------
-FileSelectionDialogsHandler::FileSelectionDialogsHandler()
+FileSelectionDialogsHandler::FileSelectionDialogsHandler(
+ const char* allow_dialogs_pref_name,
+ const char* prompt_for_download_pref_name)
: TypeCheckingPolicyHandler(key::kAllowFileSelectionDialogs,
- Value::TYPE_BOOLEAN) {
-}
+ Value::TYPE_BOOLEAN),
+ allow_dialogs_pref_name_(allow_dialogs_pref_name),
+ prompt_for_download_pref_name_(prompt_for_download_pref_name) {}
FileSelectionDialogsHandler::~FileSelectionDialogsHandler() {
}
@@ -789,11 +738,11 @@
bool allow_dialogs;
const Value* value = policies.GetValue(policy_name());
if (value && value->GetAsBoolean(&allow_dialogs)) {
- prefs->SetValue(prefs::kAllowFileSelectionDialogs,
+ prefs->SetValue(allow_dialogs_pref_name_,
Value::CreateBooleanValue(allow_dialogs));
// Disallow selecting the download location if file dialogs are disabled.
if (!allow_dialogs) {
- prefs->SetValue(prefs::kPromptForDownload,
+ prefs->SetValue(prompt_for_download_pref_name_,
Value::CreateBooleanValue(false));
}
}
@@ -802,8 +751,8 @@
// IncognitoModePolicyHandler implementation -----------------------------------
-IncognitoModePolicyHandler::IncognitoModePolicyHandler() {
-}
+IncognitoModePolicyHandler::IncognitoModePolicyHandler(const char* pref_name)
+ : pref_name_(pref_name) {}
IncognitoModePolicyHandler::~IncognitoModePolicyHandler() {
}
@@ -854,7 +803,7 @@
if (availability->GetAsInteger(&int_value) &&
IncognitoModePrefs::IntToAvailability(int_value,
&availability_enum_value)) {
- prefs->SetValue(prefs::kIncognitoModeAvailability,
+ prefs->SetValue(pref_name_,
Value::CreateIntegerValue(availability_enum_value));
} else {
NOTREACHED();
@@ -864,9 +813,9 @@
// kIncognitoEnabled.
bool enabled = true;
if (deprecated_enabled->GetAsBoolean(&enabled)) {
- prefs->SetInteger(prefs::kIncognitoModeAvailability,
- enabled ? IncognitoModePrefs::ENABLED :
- IncognitoModePrefs::DISABLED);
+ prefs->SetInteger(
+ pref_name_,
+ enabled ? IncognitoModePrefs::ENABLED : IncognitoModePrefs::DISABLED);
} else {
NOTREACHED();
}
@@ -876,10 +825,11 @@
// DefaultSearchEncodingsPolicyHandler implementation --------------------------
-DefaultSearchEncodingsPolicyHandler::DefaultSearchEncodingsPolicyHandler()
+DefaultSearchEncodingsPolicyHandler::DefaultSearchEncodingsPolicyHandler(
+ const char* pref_name)
: TypeCheckingPolicyHandler(key::kDefaultSearchProviderEncodings,
- Value::TYPE_LIST) {
-}
+ Value::TYPE_LIST),
+ pref_name_(pref_name) {}
DefaultSearchEncodingsPolicyHandler::~DefaultSearchEncodingsPolicyHandler() {
}
@@ -904,23 +854,29 @@
}
}
std::string encodings = JoinString(string_parts, ';');
- prefs->SetValue(prefs::kDefaultSearchProviderEncodings,
- Value::CreateStringValue(encodings));
+ prefs->SetValue(pref_name(), Value::CreateStringValue(encodings));
}
// DefaultSearchPolicyHandler implementation -----------------------------------
-DefaultSearchPolicyHandler::DefaultSearchPolicyHandler() {
- for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
- const char* policy_name = kDefaultSearchPolicyMap[i].policy_name;
+DefaultSearchPolicyHandler::DefaultSearchPolicyHandler(
+ const char* id_pref_name,
+ const char* prepopulate_id_pref_name,
+ const PolicyToPreferenceMapEntry policy_to_pref_map[])
+ : id_pref_name_(id_pref_name),
+ prepopulate_id_pref_name_(prepopulate_id_pref_name),
+ policy_to_pref_map_(policy_to_pref_map) {
+ for (size_t i = 0; i < DEFAULT_SEARCH_KEY_SIZE; ++i) {
+ const char* policy_name = policy_to_pref_map[i].policy_name;
if (policy_name == key::kDefaultSearchProviderEncodings) {
- handlers_.push_back(new DefaultSearchEncodingsPolicyHandler());
+ handlers_.push_back(new DefaultSearchEncodingsPolicyHandler(
+ policy_to_pref_map[i].preference_path));
} else {
- handlers_.push_back(
- new SimplePolicyHandler(policy_name,
- kDefaultSearchPolicyMap[i].preference_path,
- kDefaultSearchPolicyMap[i].value_type));
+ handlers_.push_back(new SimplePolicyHandler(
+ policy_name,
+ policy_to_pref_map[i].preference_path,
+ policy_to_pref_map[i].value_type));
}
}
}
@@ -937,8 +893,11 @@
if (DefaultSearchProviderIsDisabled(policies)) {
// Add an error for all specified default search policies except
// DefaultSearchProviderEnabled.
- for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
- const char* policy_name = kDefaultSearchPolicyMap[i].policy_name;
+
+ for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
+ handlers_.begin();
+ handler != handlers_.end(); ++handler) {
+ const char* policy_name = (*handler)->policy_name();
if (policy_name != key::kDefaultSearchProviderEnabled &&
HasDefaultSearchPolicy(policies, policy_name)) {
errors->AddError(policy_name, IDS_POLICY_DEFAULT_SEARCH_DISABLED);
@@ -957,33 +916,33 @@
return false;
}
+#define PREF_FOR(x) policy_to_pref_map_[x].preference_path
void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
PrefValueMap* prefs) {
if (DefaultSearchProviderIsDisabled(policies)) {
- prefs->SetBoolean(prefs::kDefaultSearchProviderEnabled, false);
+ prefs->SetBoolean(PREF_FOR(DEFAULT_SEARCH_ENABLED), false);
// If default search is disabled, the other fields are ignored.
- prefs->SetString(prefs::kDefaultSearchProviderName, std::string());
- prefs->SetString(prefs::kDefaultSearchProviderSearchURL, std::string());
- prefs->SetString(prefs::kDefaultSearchProviderSuggestURL, std::string());
- prefs->SetString(prefs::kDefaultSearchProviderIconURL, std::string());
- prefs->SetString(prefs::kDefaultSearchProviderEncodings, std::string());
- prefs->SetString(prefs::kDefaultSearchProviderKeyword, std::string());
- prefs->SetString(prefs::kDefaultSearchProviderInstantURL, std::string());
- prefs->SetString(prefs::kDefaultSearchProviderNewTabURL, std::string());
- prefs->SetValue(prefs::kDefaultSearchProviderAlternateURLs,
- new ListValue());
- prefs->SetString(prefs::kDefaultSearchProviderSearchTermsReplacementKey,
- std::string());
- prefs->SetString(prefs::kDefaultSearchProviderImageURL, std::string());
- prefs->SetString(prefs::kDefaultSearchProviderSearchURLPostParams,
- std::string());
- prefs->SetString(prefs::kDefaultSearchProviderSuggestURLPostParams,
- std::string());
- prefs->SetString(prefs::kDefaultSearchProviderInstantURLPostParams,
- std::string());
- prefs->SetString(prefs::kDefaultSearchProviderImageURLPostParams,
- std::string());
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_NAME), std::string());
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_SEARCH_URL), std::string());
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_SUGGEST_URL), std::string());
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_ICON_URL), std::string());
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_ENCODINGS), std::string());
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_KEYWORD), std::string());
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_INSTANT_URL), std::string());
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_NEW_TAB_URL), std::string());
+ prefs->SetValue(PREF_FOR(DEFAULT_SEARCH_ALTERNATE_URLS), new ListValue());
+ prefs->SetString(
+ PREF_FOR(DEFAULT_SEARCH_TERMS_REPLACEMENT_KEY), std::string());
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_IMAGE_URL), std::string());
+ prefs->SetString(
+ PREF_FOR(DEFAULT_SEARCH_SEARCH_URL_POST_PARAMS), std::string());
+ prefs->SetString(
+ PREF_FOR(DEFAULT_SEARCH_SUGGEST_URL_POST_PARAMS), std::string());
+ prefs->SetString(
+ PREF_FOR(DEFAULT_SEARCH_INSTANT_URL_POST_PARAMS), std::string());
+ prefs->SetString(
+ PREF_FOR(DEFAULT_SEARCH_IMAGE_URL_POST_PARAMS), std::string());
} else {
// The search URL is required. The other entries are optional. Just make
// sure that they are all specified via policy, so that the regular prefs
@@ -991,29 +950,36 @@
const Value* dummy;
std::string url;
if (DefaultSearchURLIsValid(policies, &dummy, &url)) {
- for (std::vector<ConfigurationPolicyHandler*>::const_iterator handler =
- handlers_.begin(); handler != handlers_.end(); ++handler)
- (*handler)->ApplyPolicySettings(policies, prefs);
- EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderSuggestURL);
- EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderIconURL);
- EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderEncodings);
- EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderKeyword);
- EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderInstantURL);
- EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderNewTabURL);
- EnsureListPrefExists(prefs, prefs::kDefaultSearchProviderAlternateURLs);
- EnsureStringPrefExists(prefs,
- prefs::kDefaultSearchProviderSearchTermsReplacementKey);
- EnsureStringPrefExists(prefs,
- prefs::kDefaultSearchProviderImageURL);
- EnsureStringPrefExists(prefs,
- prefs::kDefaultSearchProviderSearchURLPostParams);
- EnsureStringPrefExists(prefs,
- prefs::kDefaultSearchProviderSuggestURLPostParams);
- EnsureStringPrefExists(prefs,
- prefs::kDefaultSearchProviderInstantURLPostParams);
- EnsureStringPrefExists(prefs,
- prefs::kDefaultSearchProviderImageURLPostParams);
+ for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
+ handlers_.begin();
+ handler != handlers_.end(); ++handler) {
+ (*handler)->ApplyPolicySettings(policies, prefs);
+ }
+
+ EnsureStringPrefExists(prefs, PREF_FOR(DEFAULT_SEARCH_SUGGEST_URL));
+ EnsureStringPrefExists(prefs, PREF_FOR(DEFAULT_SEARCH_ICON_URL));
+ EnsureStringPrefExists(prefs, PREF_FOR(DEFAULT_SEARCH_ENCODINGS));
+ EnsureStringPrefExists(prefs, PREF_FOR(DEFAULT_SEARCH_KEYWORD));
+ EnsureStringPrefExists(prefs, PREF_FOR(DEFAULT_SEARCH_INSTANT_URL));
+ EnsureStringPrefExists(prefs, PREF_FOR(DEFAULT_SEARCH_NEW_TAB_URL));
+ EnsureListPrefExists(prefs, PREF_FOR(DEFAULT_SEARCH_ALTERNATE_URLS));
+ EnsureStringPrefExists(
+ prefs,
+ PREF_FOR(DEFAULT_SEARCH_TERMS_REPLACEMENT_KEY));
+ EnsureStringPrefExists(prefs, PREF_FOR(DEFAULT_SEARCH_IMAGE_URL));
+ EnsureStringPrefExists(
+ prefs,
+ PREF_FOR(DEFAULT_SEARCH_SEARCH_URL_POST_PARAMS));
+ EnsureStringPrefExists(
+ prefs,
+ PREF_FOR(DEFAULT_SEARCH_SUGGEST_URL_POST_PARAMS));
+ EnsureStringPrefExists(
+ prefs,
+ PREF_FOR(DEFAULT_SEARCH_INSTANT_URL_POST_PARAMS));
+ EnsureStringPrefExists(
+ prefs,
+ PREF_FOR(DEFAULT_SEARCH_IMAGE_URL_POST_PARAMS));
// For the name and keyword, default to the host if not specified. If
// there is no host (file: URLs? Not sure), use "_" to guarantee that the
@@ -1022,17 +988,18 @@
std::string host(GURL(url).host());
if (host.empty())
host = "_";
- if (!prefs->GetString(prefs::kDefaultSearchProviderName, &name) ||
- name.empty())
- prefs->SetString(prefs::kDefaultSearchProviderName, host);
- if (!prefs->GetString(prefs::kDefaultSearchProviderKeyword, &keyword) ||
- keyword.empty())
- prefs->SetString(prefs::kDefaultSearchProviderKeyword, host);
+ if (!prefs->GetString(PREF_FOR(DEFAULT_SEARCH_NAME), &name) ||
+ name.empty()) {
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_NAME), host);
+ }
+ if (!prefs->GetString(PREF_FOR(DEFAULT_SEARCH_KEYWORD), &keyword) ||
+ keyword.empty()) {
+ prefs->SetString(PREF_FOR(DEFAULT_SEARCH_KEYWORD), host);
+ }
// And clear the IDs since these are not specified via policy.
- prefs->SetString(prefs::kDefaultSearchProviderID, std::string());
- prefs->SetString(prefs::kDefaultSearchProviderPrepopulateID,
- std::string());
+ prefs->SetString(id_pref_name_, std::string());
+ prefs->SetString(prepopulate_id_pref_name_, std::string());
}
}
content::NotificationService::current()->Notify(
@@ -1040,12 +1007,14 @@
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
}
+#undef PREF_FOR
bool DefaultSearchPolicyHandler::CheckIndividualPolicies(
const PolicyMap& policies,
PolicyErrorMap* errors) {
- std::vector<ConfigurationPolicyHandler*>::const_iterator handler;
- for (handler = handlers_.begin() ; handler != handlers_.end(); ++handler) {
+ for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
+ handlers_.begin();
+ handler != handlers_.end(); ++handler) {
if (!(*handler)->CheckPolicySettings(policies, errors))
return false;
}
@@ -1060,8 +1029,10 @@
bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified(
const PolicyMap& policies) {
- for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
- if (policies.Get(kDefaultSearchPolicyMap[i].policy_name))
+ for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
+ handlers_.begin();
+ handler != handlers_.end(); ++handler) {
+ if (policies.Get((*handler)->policy_name()))
return true;
}
return false;
@@ -1116,8 +1087,8 @@
// DictionaryValue. Once Dictionary policies are fully supported, the individual
// proxy policies will be deprecated. http://crbug.com/108996
-ProxyPolicyHandler::ProxyPolicyHandler() {
-}
+ProxyPolicyHandler::ProxyPolicyHandler(const char* pref_name)
+ : pref_name_(pref_name) {}
ProxyPolicyHandler::~ProxyPolicyHandler() {
}
@@ -1233,15 +1204,16 @@
switch (proxy_mode) {
case ProxyPrefs::MODE_DIRECT:
- prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateDirect());
+ prefs->SetValue(pref_name_, ProxyConfigDictionary::CreateDirect());
break;
case ProxyPrefs::MODE_AUTO_DETECT:
- prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect());
+ prefs->SetValue(pref_name_, ProxyConfigDictionary::CreateAutoDetect());
break;
case ProxyPrefs::MODE_PAC_SCRIPT: {
std::string pac_url_string;
if (pac_url && pac_url->GetAsString(&pac_url_string)) {
- prefs->SetValue(prefs::kProxy,
+ prefs->SetValue(
+ pref_name_,
ProxyConfigDictionary::CreatePacScript(pac_url_string, false));
} else {
NOTREACHED();
@@ -1254,15 +1226,14 @@
if (server->GetAsString(&proxy_server)) {
if (bypass_list)
bypass_list->GetAsString(&bypass_list_string);
- prefs->SetValue(prefs::kProxy,
+ prefs->SetValue(pref_name_,
ProxyConfigDictionary::CreateFixedServers(
proxy_server, bypass_list_string));
}
break;
}
case ProxyPrefs::MODE_SYSTEM:
- prefs->SetValue(prefs::kProxy,
- ProxyConfigDictionary::CreateSystem());
+ prefs->SetValue(pref_name_, ProxyConfigDictionary::CreateSystem());
break;
case ProxyPrefs::kModeCount:
NOTREACHED();
@@ -1394,8 +1365,8 @@
// JavascriptPolicyHandler implementation --------------------------------------
-JavascriptPolicyHandler::JavascriptPolicyHandler() {
-}
+JavascriptPolicyHandler::JavascriptPolicyHandler(const char* pref_name)
+ : pref_name_(pref_name) {}
JavascriptPolicyHandler::~JavascriptPolicyHandler() {
}
@@ -1446,16 +1417,15 @@
}
}
- if (setting != CONTENT_SETTING_DEFAULT) {
- prefs->SetValue(prefs::kManagedDefaultJavaScriptSetting,
- Value::CreateIntegerValue(setting));
- }
+ if (setting != CONTENT_SETTING_DEFAULT)
+ prefs->SetValue(pref_name_, Value::CreateIntegerValue(setting));
}
+
// URLBlacklistPolicyHandler implementation ------------------------------------
-URLBlacklistPolicyHandler::URLBlacklistPolicyHandler() {
-}
+URLBlacklistPolicyHandler::URLBlacklistPolicyHandler(const char* pref_name)
+ : pref_name_(pref_name) {}
URLBlacklistPolicyHandler::~URLBlacklistPolicyHandler() {
}
@@ -1517,15 +1487,18 @@
}
if (disabled_schemes_policy || url_blacklist_policy)
- prefs->SetValue(prefs::kUrlBlacklist, merged_url_blacklist.release());
+ prefs->SetValue(pref_name_, merged_url_blacklist.release());
}
+
// RestoreOnStartupPolicyHandler implementation --------------------------------
-RestoreOnStartupPolicyHandler::RestoreOnStartupPolicyHandler()
- : TypeCheckingPolicyHandler(key::kRestoreOnStartup,
- Value::TYPE_INTEGER) {
-}
+RestoreOnStartupPolicyHandler::RestoreOnStartupPolicyHandler(
+ const char* restore_on_startup_pref_name,
+ const char* startup_url_list_pref_name)
+ : TypeCheckingPolicyHandler(key::kRestoreOnStartup, Value::TYPE_INTEGER),
+ restore_on_startup_pref_name_(restore_on_startup_pref_name),
+ startup_url_list_pref_name_(startup_url_list_pref_name) {}
RestoreOnStartupPolicyHandler::~RestoreOnStartupPolicyHandler() {
}
@@ -1542,7 +1515,7 @@
if (restore_on_startup == SessionStartupPref::kPrefValueHomePage)
ApplyPolicySettingsFromHomePage(policies, prefs);
else
- prefs->SetInteger(prefs::kRestoreOnStartup, restore_on_startup);
+ prefs->SetInteger(restore_on_startup_pref_name_, restore_on_startup);
}
}
@@ -1562,7 +1535,7 @@
return;
if (homepage_is_new_tab_page) {
- prefs->SetInteger(prefs::kRestoreOnStartup,
+ prefs->SetInteger(restore_on_startup_pref_name_,
SessionStartupPref::kPrefValueNewTab);
} else {
const base::Value* homepage_value =
@@ -1574,9 +1547,9 @@
}
ListValue* url_list = new ListValue();
url_list->Append(homepage_value->DeepCopy());
- prefs->SetInteger(prefs::kRestoreOnStartup,
+ prefs->SetInteger(restore_on_startup_pref_name_,
SessionStartupPref::kPrefValueURLs);
- prefs->SetValue(prefs::kURLsToRestoreOnStartup, url_list);
+ prefs->SetValue(startup_url_list_pref_name_, url_list);
}
}
diff --git a/chrome/browser/policy/configuration_policy_handler.h b/chrome/browser/policy/configuration_policy_handler.h
index bd87dc0..0fc8755 100644
--- a/chrome/browser/policy/configuration_policy_handler.h
+++ b/chrome/browser/policy/configuration_policy_handler.h
@@ -21,6 +21,13 @@
class PolicyErrorMap;
class PolicyMap;
+// Maps a policy type to a preference path, and to the expected value type.
+struct PolicyToPreferenceMapEntry {
+ const char* const policy_name;
+ const char* const preference_path;
+ const base::Value::Type value_type;
+};
+
// An abstract super class that subclasses should implement to map policies to
// their corresponding preferences, and to check whether the policies are valid.
class ConfigurationPolicyHandler {
@@ -59,21 +66,20 @@
public:
TypeCheckingPolicyHandler(const char* policy_name,
base::Value::Type value_type);
+ virtual ~TypeCheckingPolicyHandler();
// ConfigurationPolicyHandler methods:
virtual bool CheckPolicySettings(const PolicyMap& policies,
PolicyErrorMap* errors) OVERRIDE;
- protected:
- virtual ~TypeCheckingPolicyHandler();
+ const char* policy_name() const;
+ protected:
// Runs policy checks and returns the policy value if successful.
bool CheckAndGetValue(const PolicyMap& policies,
PolicyErrorMap* errors,
const Value** value);
- const char* policy_name() const;
-
private:
// The name of the policy.
const char* policy_name_;
@@ -254,7 +260,7 @@
class ExtensionInstallForcelistPolicyHandler
: public TypeCheckingPolicyHandler {
public:
- ExtensionInstallForcelistPolicyHandler();
+ explicit ExtensionInstallForcelistPolicyHandler(const char* pref_name);
virtual ~ExtensionInstallForcelistPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -269,6 +275,7 @@
base::DictionaryValue* extension_dict,
PolicyErrorMap* errors);
+ const char* pref_name_;
DISALLOW_COPY_AND_ASSIGN(ExtensionInstallForcelistPolicyHandler);
};
@@ -295,7 +302,7 @@
// ConfigurationPolicyHandler for the SyncDisabled policy.
class SyncPolicyHandler : public TypeCheckingPolicyHandler {
public:
- SyncPolicyHandler();
+ explicit SyncPolicyHandler(const char* pref_name);
virtual ~SyncPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -303,13 +310,14 @@
PrefValueMap* prefs) OVERRIDE;
private:
+ const char* pref_name_;
DISALLOW_COPY_AND_ASSIGN(SyncPolicyHandler);
};
// ConfigurationPolicyHandler for the AutofillEnabled policy.
class AutofillPolicyHandler : public TypeCheckingPolicyHandler {
public:
- AutofillPolicyHandler();
+ explicit AutofillPolicyHandler(const char* pref_name);
virtual ~AutofillPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -317,6 +325,7 @@
PrefValueMap* prefs) OVERRIDE;
private:
+ const char* pref_name_;
DISALLOW_COPY_AND_ASSIGN(AutofillPolicyHandler);
};
@@ -325,7 +334,8 @@
// ConfigurationPolicyHandler for the DownloadDirectory policy.
class DownloadDirPolicyHandler : public TypeCheckingPolicyHandler {
public:
- DownloadDirPolicyHandler();
+ DownloadDirPolicyHandler(const char* default_directory_pref_name,
+ const char* prompt_for_download_pref_name);
virtual ~DownloadDirPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -333,13 +343,15 @@
PrefValueMap* prefs) OVERRIDE;
private:
+ const char* default_directory_pref_name_;
+ const char* prompt_for_download_pref_name_;
DISALLOW_COPY_AND_ASSIGN(DownloadDirPolicyHandler);
};
// ConfigurationPolicyHandler for the DiskCacheDir policy.
class DiskCacheDirPolicyHandler : public TypeCheckingPolicyHandler {
public:
- explicit DiskCacheDirPolicyHandler();
+ explicit DiskCacheDirPolicyHandler(const char* pref_name);
virtual ~DiskCacheDirPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -347,6 +359,7 @@
PrefValueMap* prefs) OVERRIDE;
private:
+ const char* pref_name_;
DISALLOW_COPY_AND_ASSIGN(DiskCacheDirPolicyHandler);
};
@@ -355,7 +368,8 @@
// ConfigurationPolicyHandler for the FileSelectionDialogsHandler policy.
class FileSelectionDialogsHandler : public TypeCheckingPolicyHandler {
public:
- FileSelectionDialogsHandler();
+ FileSelectionDialogsHandler(const char* allow_dialogs_pref_name,
+ const char* prompt_for_download_pref_name);
virtual ~FileSelectionDialogsHandler();
// ConfigurationPolicyHandler methods:
@@ -363,13 +377,15 @@
PrefValueMap* prefs) OVERRIDE;
private:
+ const char* allow_dialogs_pref_name_;
+ const char* prompt_for_download_pref_name_;
DISALLOW_COPY_AND_ASSIGN(FileSelectionDialogsHandler);
};
// ConfigurationPolicyHandler for the incognito mode policies.
class IncognitoModePolicyHandler : public ConfigurationPolicyHandler {
public:
- IncognitoModePolicyHandler();
+ explicit IncognitoModePolicyHandler(const char* pref_name);
virtual ~IncognitoModePolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -382,27 +398,62 @@
IncognitoModePrefs::Availability GetAvailabilityValueAsEnum(
const Value* availability);
+ const char* pref_name_;
DISALLOW_COPY_AND_ASSIGN(IncognitoModePolicyHandler);
};
// ConfigurationPolicyHandler for the DefaultSearchEncodings policy.
class DefaultSearchEncodingsPolicyHandler : public TypeCheckingPolicyHandler {
public:
- DefaultSearchEncodingsPolicyHandler();
+ explicit DefaultSearchEncodingsPolicyHandler(const char* pref_name);
virtual ~DefaultSearchEncodingsPolicyHandler();
// ConfigurationPolicyHandler methods:
virtual void ApplyPolicySettings(const PolicyMap& policies,
PrefValueMap* prefs) OVERRIDE;
+ const char* pref_name() const { return pref_name_; }
+
private:
+ const char* pref_name_;
DISALLOW_COPY_AND_ASSIGN(DefaultSearchEncodingsPolicyHandler);
};
+enum DefaultSearchKey {
+ DEFAULT_SEARCH_ENABLED,
+ DEFAULT_SEARCH_NAME,
+ DEFAULT_SEARCH_KEYWORD,
+ DEFAULT_SEARCH_SEARCH_URL,
+ DEFAULT_SEARCH_SUGGEST_URL,
+ DEFAULT_SEARCH_INSTANT_URL,
+ DEFAULT_SEARCH_ICON_URL,
+ DEFAULT_SEARCH_ENCODINGS,
+ DEFAULT_SEARCH_ALTERNATE_URLS,
+ DEFAULT_SEARCH_TERMS_REPLACEMENT_KEY,
+ DEFAULT_SEARCH_IMAGE_URL,
+ DEFAULT_SEARCH_NEW_TAB_URL,
+ DEFAULT_SEARCH_SEARCH_URL_POST_PARAMS,
+ DEFAULT_SEARCH_SUGGEST_URL_POST_PARAMS,
+ DEFAULT_SEARCH_INSTANT_URL_POST_PARAMS,
+ DEFAULT_SEARCH_IMAGE_URL_POST_PARAMS,
+ // Must be last.
+ DEFAULT_SEARCH_KEY_SIZE,
+};
+
// ConfigurationPolicyHandler for the default search policies.
class DefaultSearchPolicyHandler : public ConfigurationPolicyHandler {
public:
- DefaultSearchPolicyHandler();
+ // Constructs a new handler for the DefaultSearch policy with the specified
+ // preference names.
+ // |id_pref_name|: Pref name for the search provider ID.
+ // |prepopulate_id_pref_name|: Pref name for the prepopulated provider ID.
+ // |policy_to_pref_map|: Defines the pref names for respective policy keys.
+ // Must contain exactly DEFAULT_SEARCH_KEY_SIZE entries and be ordered
+ // according to the DefaultSearchKey enum.
+ DefaultSearchPolicyHandler(
+ const char* id_pref_name,
+ const char* prepopulate_id_pref_name,
+ const PolicyToPreferenceMapEntry policy_to_pref_map[]);
virtual ~DefaultSearchPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -442,7 +493,11 @@
void EnsureListPrefExists(PrefValueMap* prefs, const std::string& path);
// The ConfigurationPolicyHandler handlers for each default search policy.
- std::vector<ConfigurationPolicyHandler*> handlers_;
+ std::vector<TypeCheckingPolicyHandler*> handlers_;
+
+ const char* id_pref_name_;
+ const char* prepopulate_id_pref_name_;
+ const PolicyToPreferenceMapEntry* policy_to_pref_map_; // weak
DISALLOW_COPY_AND_ASSIGN(DefaultSearchPolicyHandler);
};
@@ -468,7 +523,7 @@
MODE_COUNT
};
- ProxyPolicyHandler();
+ explicit ProxyPolicyHandler(const char* pref_name);
virtual ~ProxyPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -488,13 +543,14 @@
PolicyErrorMap* errors,
std::string* mode_value);
+ const char* pref_name_;
DISALLOW_COPY_AND_ASSIGN(ProxyPolicyHandler);
};
// Handles JavaScript policies.
class JavascriptPolicyHandler : public ConfigurationPolicyHandler {
public:
- JavascriptPolicyHandler();
+ explicit JavascriptPolicyHandler(const char* pref_name);
virtual ~JavascriptPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -504,13 +560,14 @@
PrefValueMap* prefs) OVERRIDE;
private:
+ const char* pref_name_;
DISALLOW_COPY_AND_ASSIGN(JavascriptPolicyHandler);
};
// Handles URLBlacklist policies.
class URLBlacklistPolicyHandler : public ConfigurationPolicyHandler {
public:
- URLBlacklistPolicyHandler();
+ explicit URLBlacklistPolicyHandler(const char* pref_name);
virtual ~URLBlacklistPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -520,13 +577,15 @@
PrefValueMap* prefs) OVERRIDE;
private:
+ const char* pref_name_;
DISALLOW_COPY_AND_ASSIGN(URLBlacklistPolicyHandler);
};
// Handles RestoreOnStartup policy.
class RestoreOnStartupPolicyHandler : public TypeCheckingPolicyHandler {
public:
- RestoreOnStartupPolicyHandler();
+ RestoreOnStartupPolicyHandler(const char* restore_on_startup_pref_name,
+ const char* startup_url_list_pref_name);
virtual ~RestoreOnStartupPolicyHandler();
// ConfigurationPolicyHandler methods:
@@ -539,6 +598,8 @@
void ApplyPolicySettingsFromHomePage(const PolicyMap& policies,
PrefValueMap* prefs);
+ const char* restore_on_startup_pref_name_;
+ const char* startup_url_list_pref_name_;
DISALLOW_COPY_AND_ASSIGN(RestoreOnStartupPolicyHandler);
};
diff --git a/chrome/browser/policy/configuration_policy_handler_list.cc b/chrome/browser/policy/configuration_policy_handler_list.cc
index b46454e..e19d451 100644
--- a/chrome/browser/policy/configuration_policy_handler_list.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list.cc
@@ -6,6 +6,7 @@
#include <limits>
+#include "base/basictypes.h"
#include "base/prefs/pref_value_map.h"
#include "base/stl_util.h"
#include "base/values.h"
@@ -33,16 +34,64 @@
namespace policy {
-namespace {
-
-// Maps a policy type to a preference path, and to the expected value type.
-// This is the entry type of |kSimplePolicyMap| below.
-struct PolicyToPreferenceMapEntry {
- const char* policy_name;
- const char* preference_path;
- base::Value::Type value_type;
+// List of policy types to preference names, for policies affecting the default
+// search provider.
+const PolicyToPreferenceMapEntry kDefaultSearchPolicyMap[] = {
+ { key::kDefaultSearchProviderEnabled,
+ prefs::kDefaultSearchProviderEnabled,
+ Value::TYPE_BOOLEAN },
+ { key::kDefaultSearchProviderName,
+ prefs::kDefaultSearchProviderName,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderKeyword,
+ prefs::kDefaultSearchProviderKeyword,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderSearchURL,
+ prefs::kDefaultSearchProviderSearchURL,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderSuggestURL,
+ prefs::kDefaultSearchProviderSuggestURL,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderInstantURL,
+ prefs::kDefaultSearchProviderInstantURL,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderIconURL,
+ prefs::kDefaultSearchProviderIconURL,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderEncodings,
+ prefs::kDefaultSearchProviderEncodings,
+ Value::TYPE_LIST },
+ { key::kDefaultSearchProviderAlternateURLs,
+ prefs::kDefaultSearchProviderAlternateURLs,
+ Value::TYPE_LIST },
+ { key::kDefaultSearchProviderSearchTermsReplacementKey,
+ prefs::kDefaultSearchProviderSearchTermsReplacementKey,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderImageURL,
+ prefs::kDefaultSearchProviderImageURL,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderNewTabURL,
+ prefs::kDefaultSearchProviderNewTabURL,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderSearchURLPostParams,
+ prefs::kDefaultSearchProviderSearchURLPostParams,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderSuggestURLPostParams,
+ prefs::kDefaultSearchProviderSuggestURLPostParams,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderInstantURLPostParams,
+ prefs::kDefaultSearchProviderInstantURLPostParams,
+ Value::TYPE_STRING },
+ { key::kDefaultSearchProviderImageURLPostParams,
+ prefs::kDefaultSearchProviderImageURLPostParams,
+ Value::TYPE_STRING },
};
+COMPILE_ASSERT(DEFAULT_SEARCH_KEY_SIZE == arraysize(kDefaultSearchPolicyMap),
+ wrong_policy_map_size);
+
+namespace {
+
// List of policy types to preference names. This is used for simple policies
// that directly map to a single preference.
const PolicyToPreferenceMapEntry kSimplePolicyMap[] = {
@@ -417,6 +466,9 @@
{ key::kAttestationEnabledForUser,
prefs::kAttestationEnabled,
Value::TYPE_BOOLEAN },
+ { key::kChromeOsMultiProfileUserBehavior,
+ prefs::kMultiProfileUserBehavior,
+ Value::TYPE_STRING },
#endif // defined(OS_CHROMEOS)
#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
@@ -452,15 +504,23 @@
kSimplePolicyMap[i].value_type));
}
- handlers_.push_back(new AutofillPolicyHandler());
- handlers_.push_back(new DefaultSearchPolicyHandler());
- handlers_.push_back(new FileSelectionDialogsHandler());
- handlers_.push_back(new IncognitoModePolicyHandler());
- handlers_.push_back(new JavascriptPolicyHandler());
- handlers_.push_back(new ProxyPolicyHandler());
- handlers_.push_back(new RestoreOnStartupPolicyHandler());
- handlers_.push_back(new SyncPolicyHandler());
- handlers_.push_back(new URLBlacklistPolicyHandler());
+ handlers_.push_back(
+ new AutofillPolicyHandler(autofill::prefs::kAutofillEnabled));
+ handlers_.push_back(
+ new DefaultSearchPolicyHandler(prefs::kDefaultSearchProviderID,
+ prefs::kDefaultSearchProviderPrepopulateID,
+ kDefaultSearchPolicyMap));
+ handlers_.push_back(new FileSelectionDialogsHandler(
+ prefs::kAllowFileSelectionDialogs, prefs::kPromptForDownload));
+ handlers_.push_back(
+ new IncognitoModePolicyHandler(prefs::kIncognitoModeAvailability));
+ handlers_.push_back(
+ new JavascriptPolicyHandler(prefs::kManagedDefaultJavaScriptSetting));
+ handlers_.push_back(new ProxyPolicyHandler(prefs::kProxy));
+ handlers_.push_back(new RestoreOnStartupPolicyHandler(
+ prefs::kRestoreOnStartup, prefs::kURLsToRestoreOnStartup));
+ handlers_.push_back(new SyncPolicyHandler(prefs::kSyncManaged));
+ handlers_.push_back(new URLBlacklistPolicyHandler(prefs::kUrlBlacklist));
handlers_.push_back(
new ExtensionListPolicyHandler(key::kExtensionInstallWhitelist,
@@ -470,16 +530,15 @@
new ExtensionListPolicyHandler(key::kExtensionInstallBlacklist,
prefs::kExtensionInstallDenyList,
true));
- handlers_.push_back(new ExtensionInstallForcelistPolicyHandler());
- handlers_.push_back(
- new ExtensionURLPatternListPolicyHandler(
- key::kExtensionInstallSources,
- prefs::kExtensionAllowedInstallSites));
- handlers_.push_back(
- new StringToIntEnumListPolicyHandler(
- key::kExtensionAllowedTypes, prefs::kExtensionAllowedTypes,
- kExtensionAllowedTypesMap,
- kExtensionAllowedTypesMap + arraysize(kExtensionAllowedTypesMap)));
+ handlers_.push_back(new ExtensionInstallForcelistPolicyHandler(
+ prefs::kExtensionInstallForceList));
+ handlers_.push_back(new ExtensionURLPatternListPolicyHandler(
+ key::kExtensionInstallSources, prefs::kExtensionAllowedInstallSites));
+ handlers_.push_back(new StringToIntEnumListPolicyHandler(
+ key::kExtensionAllowedTypes,
+ prefs::kExtensionAllowedTypes,
+ kExtensionAllowedTypesMap,
+ kExtensionAllowedTypesMap + arraysize(kExtensionAllowedTypesMap)));
#if defined(OS_CHROMEOS)
handlers_.push_back(
new ExtensionListPolicyHandler(key::kAttestationExtensionWhitelist,
@@ -488,8 +547,9 @@
#endif // defined(OS_CHROMEOS)
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
- handlers_.push_back(new DiskCacheDirPolicyHandler());
- handlers_.push_back(new DownloadDirPolicyHandler());
+ handlers_.push_back(new DiskCacheDirPolicyHandler(prefs::kDiskCacheDir));
+ handlers_.push_back(new DownloadDirPolicyHandler(
+ prefs::kDownloadDefaultDirectory, prefs::kPromptForDownload));
#endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
#if defined(OS_CHROMEOS)
diff --git a/chrome/browser/policy/configuration_policy_handler_list.h b/chrome/browser/policy/configuration_policy_handler_list.h
index 82e31b2..599fd9a 100644
--- a/chrome/browser/policy/configuration_policy_handler_list.h
+++ b/chrome/browser/policy/configuration_policy_handler_list.h
@@ -16,6 +16,12 @@
class ConfigurationPolicyHandler;
class PolicyErrorMap;
class PolicyMap;
+struct PolicyToPreferenceMapEntry;
+
+// Declares the array of policy key to preference name mappings. Contains
+// exactly DEFAULT_SEARCH_KEY entries, which are sorted according to the order
+// of entries in the DefaultSearchKey enum.
+extern const PolicyToPreferenceMapEntry kDefaultSearchPolicyMap[];
// Converts policies to their corresponding preferences. Also does error
// checking and cleans up policy values for displaying.
diff --git a/chrome/browser/policy/configuration_policy_handler_list_unittest.cc b/chrome/browser/policy/configuration_policy_handler_list_unittest.cc
new file mode 100644
index 0000000..c37e94f
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_handler_list_unittest.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/policy/configuration_policy_handler.h"
+#include "chrome/browser/policy/configuration_policy_handler_list.h"
+#include "policy/policy_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace policy {
+
+TEST(DefaultSearchPolicyHandlerTest, PolicyToPreferenceMapInitialization) {
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_ENABLED].policy_name,
+ (const char * const)key::kDefaultSearchProviderEnabled);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_NAME].policy_name,
+ (const char * const)key::kDefaultSearchProviderName);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_KEYWORD].policy_name,
+ (const char * const)key::kDefaultSearchProviderKeyword);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_SEARCH_URL].policy_name,
+ (const char * const)key::kDefaultSearchProviderSearchURL);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_SUGGEST_URL].policy_name,
+ (const char * const)key::kDefaultSearchProviderSuggestURL);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_INSTANT_URL].policy_name,
+ (const char * const)key::kDefaultSearchProviderInstantURL);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_ICON_URL].policy_name,
+ (const char * const)key::kDefaultSearchProviderIconURL);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_ENCODINGS].policy_name,
+ (const char * const)key::kDefaultSearchProviderEncodings);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_ALTERNATE_URLS].policy_name,
+ (const char * const)key::kDefaultSearchProviderAlternateURLs);
+ EXPECT_EQ(
+ kDefaultSearchPolicyMap[DEFAULT_SEARCH_TERMS_REPLACEMENT_KEY].policy_name,
+ (const char * const)key::kDefaultSearchProviderSearchTermsReplacementKey);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_IMAGE_URL].policy_name,
+ (const char * const)key::kDefaultSearchProviderImageURL);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_NEW_TAB_URL].policy_name,
+ (const char * const)key::kDefaultSearchProviderNewTabURL);
+ EXPECT_EQ(kDefaultSearchPolicyMap[DEFAULT_SEARCH_SEARCH_URL_POST_PARAMS]
+ .policy_name,
+ (const char * const)key::kDefaultSearchProviderSearchURLPostParams);
+ EXPECT_EQ(
+ kDefaultSearchPolicyMap[DEFAULT_SEARCH_SUGGEST_URL_POST_PARAMS]
+ .policy_name,
+ (const char * const)key::kDefaultSearchProviderSuggestURLPostParams);
+ EXPECT_EQ(
+ kDefaultSearchPolicyMap[DEFAULT_SEARCH_INSTANT_URL_POST_PARAMS]
+ .policy_name,
+ (const char * const)key::kDefaultSearchProviderInstantURLPostParams);
+ EXPECT_EQ(
+ kDefaultSearchPolicyMap[DEFAULT_SEARCH_IMAGE_URL_POST_PARAMS].policy_name,
+ (const char * const)key::kDefaultSearchProviderImageURLPostParams);
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_handler_unittest.cc b/chrome/browser/policy/configuration_policy_handler_unittest.cc
index 44426ca..703b8b8 100644
--- a/chrome/browser/policy/configuration_policy_handler_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_handler_unittest.cc
@@ -10,7 +10,6 @@
#include "chrome/browser/policy/external_data_fetcher.h"
#include "chrome/browser/policy/policy_error_map.h"
#include "chrome/browser/policy/policy_map.h"
-#include "chrome/common/pref_names.h"
#include "policy/policy_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -32,8 +31,10 @@
PolicyMap policy_map;
PolicyErrorMap errors;
StringToIntEnumListPolicyHandler handler(
- key::kExtensionAllowedTypes, prefs::kExtensionAllowedTypes,
- kTestTypeMap, kTestTypeMap + arraysize(kTestTypeMap));
+ key::kExtensionAllowedTypes,
+ kTestPref,
+ kTestTypeMap,
+ kTestTypeMap + arraysize(kTestTypeMap));
policy_map.Set(key::kExtensionAllowedTypes, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, list.DeepCopy(), NULL);
@@ -72,13 +73,15 @@
PrefValueMap prefs;
base::Value* value;
StringToIntEnumListPolicyHandler handler(
- key::kExtensionAllowedTypes, prefs::kExtensionAllowedTypes,
- kTestTypeMap, kTestTypeMap + arraysize(kTestTypeMap));
+ key::kExtensionAllowedTypes,
+ kTestPref,
+ kTestTypeMap,
+ kTestTypeMap + arraysize(kTestTypeMap));
policy_map.Set(key::kExtensionAllowedTypes, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, list.DeepCopy(), NULL);
handler.ApplyPolicySettings(policy_map, &prefs);
- EXPECT_TRUE(prefs.GetValue(prefs::kExtensionAllowedTypes, &value));
+ EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
EXPECT_TRUE(base::Value::Equals(&expected, value));
list.AppendString("two");
@@ -86,14 +89,14 @@
policy_map.Set(key::kExtensionAllowedTypes, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, list.DeepCopy(), NULL);
handler.ApplyPolicySettings(policy_map, &prefs);
- EXPECT_TRUE(prefs.GetValue(prefs::kExtensionAllowedTypes, &value));
+ EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
EXPECT_TRUE(base::Value::Equals(&expected, value));
list.AppendString("invalid");
policy_map.Set(key::kExtensionAllowedTypes, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, list.DeepCopy(), NULL);
handler.ApplyPolicySettings(policy_map, &prefs);
- EXPECT_TRUE(prefs.GetValue(prefs::kExtensionAllowedTypes, &value));
+ EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
EXPECT_TRUE(base::Value::Equals(&expected, value));
}
@@ -486,9 +489,8 @@
base::ListValue list;
PolicyMap policy_map;
PolicyErrorMap errors;
- ExtensionListPolicyHandler handler(key::kExtensionInstallBlacklist,
- prefs::kExtensionInstallDenyList,
- true);
+ ExtensionListPolicyHandler handler(
+ key::kExtensionInstallBlacklist, kTestPref, true);
policy_map.Set(key::kExtensionInstallBlacklist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, list.DeepCopy(), NULL);
@@ -525,9 +527,8 @@
PolicyMap policy_map;
PrefValueMap prefs;
base::Value* value = NULL;
- ExtensionListPolicyHandler handler(key::kExtensionInstallBlacklist,
- prefs::kExtensionInstallDenyList,
- false);
+ ExtensionListPolicyHandler handler(
+ key::kExtensionInstallBlacklist, kTestPref, false);
policy.Append(Value::CreateStringValue("abcdefghijklmnopabcdefghijklmnop"));
expected.Append(Value::CreateStringValue("abcdefghijklmnopabcdefghijklmnop"));
@@ -535,14 +536,14 @@
policy_map.Set(key::kExtensionInstallBlacklist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, policy.DeepCopy(), NULL);
handler.ApplyPolicySettings(policy_map, &prefs);
- EXPECT_TRUE(prefs.GetValue(prefs::kExtensionInstallDenyList, &value));
+ EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
EXPECT_TRUE(base::Value::Equals(&expected, value));
policy.Append(Value::CreateStringValue("invalid"));
policy_map.Set(key::kExtensionInstallBlacklist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, policy.DeepCopy(), NULL);
handler.ApplyPolicySettings(policy_map, &prefs);
- EXPECT_TRUE(prefs.GetValue(prefs::kExtensionInstallDenyList, &value));
+ EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
EXPECT_TRUE(base::Value::Equals(&expected, value));
}
@@ -550,7 +551,7 @@
base::ListValue list;
PolicyMap policy_map;
PolicyErrorMap errors;
- ExtensionInstallForcelistPolicyHandler handler;
+ ExtensionInstallForcelistPolicyHandler handler(kTestPref);
policy_map.Set(key::kExtensionInstallForcelist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, list.DeepCopy(), NULL);
@@ -597,16 +598,16 @@
PolicyMap policy_map;
PrefValueMap prefs;
base::Value* value = NULL;
- ExtensionInstallForcelistPolicyHandler handler;
+ ExtensionInstallForcelistPolicyHandler handler(kTestPref);
handler.ApplyPolicySettings(policy_map, &prefs);
- EXPECT_FALSE(prefs.GetValue(prefs::kExtensionInstallForceList, &value));
+ EXPECT_FALSE(prefs.GetValue(kTestPref, &value));
EXPECT_FALSE(value);
policy_map.Set(key::kExtensionInstallForcelist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, policy.DeepCopy(), NULL);
handler.ApplyPolicySettings(policy_map, &prefs);
- EXPECT_TRUE(prefs.GetValue(prefs::kExtensionInstallForceList, &value));
+ EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
EXPECT_TRUE(base::Value::Equals(&expected, value));
policy.AppendString("abcdefghijklmnopabcdefghijklmnop;http://example.com");
@@ -615,14 +616,14 @@
policy_map.Set(key::kExtensionInstallForcelist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, policy.DeepCopy(), NULL);
handler.ApplyPolicySettings(policy_map, &prefs);
- EXPECT_TRUE(prefs.GetValue(prefs::kExtensionInstallForceList, &value));
+ EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
EXPECT_TRUE(base::Value::Equals(&expected, value));
policy.AppendString("invalid");
policy_map.Set(key::kExtensionInstallForcelist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, policy.DeepCopy(), NULL);
handler.ApplyPolicySettings(policy_map, &prefs);
- EXPECT_TRUE(prefs.GetValue(prefs::kExtensionInstallForceList, &value));
+ EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
EXPECT_TRUE(base::Value::Equals(&expected, value));
}
@@ -630,9 +631,8 @@
base::ListValue list;
PolicyMap policy_map;
PolicyErrorMap errors;
- ExtensionURLPatternListPolicyHandler handler(
- key::kExtensionInstallSources,
- prefs::kExtensionAllowedInstallSites);
+ ExtensionURLPatternListPolicyHandler handler(key::kExtensionInstallSources,
+ kTestPref);
policy_map.Set(key::kExtensionInstallSources, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, list.DeepCopy(), NULL);
@@ -678,15 +678,14 @@
PolicyMap policy_map;
PrefValueMap prefs;
base::Value* value = NULL;
- ExtensionURLPatternListPolicyHandler handler(
- key::kExtensionInstallSources,
- prefs::kExtensionAllowedInstallSites);
+ ExtensionURLPatternListPolicyHandler handler(key::kExtensionInstallSources,
+ kTestPref);
list.Append(Value::CreateStringValue("https://corp.monkey.net/*"));
policy_map.Set(key::kExtensionInstallSources, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, list.DeepCopy(), NULL);
handler.ApplyPolicySettings(policy_map, &prefs);
- ASSERT_TRUE(prefs.GetValue(prefs::kExtensionAllowedInstallSites, &value));
+ ASSERT_TRUE(prefs.GetValue(kTestPref, &value));
EXPECT_TRUE(base::Value::Equals(&list, value));
}
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 81a2776..74012a6 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -178,8 +178,6 @@
const char kAdBlockCrxId[] = "dojnnbeimaimaojcialkkgajdnefpgcn";
const char kHostedAppCrxId[] = "kbmnembihfiondgfjekmnmcbddelicoi";
-const base::FilePath::CharType kGoodCrxManifestName[] =
- FILE_PATH_LITERAL("good_update_manifest.xml");
const base::FilePath::CharType kGood2CrxManifestName[] =
FILE_PATH_LITERAL("good2_update_manifest.xml");
const base::FilePath::CharType kGoodV1CrxManifestName[] =
@@ -188,8 +186,11 @@
FILE_PATH_LITERAL("good_unpacked");
const base::FilePath::CharType kAppUnpackedExt[] =
FILE_PATH_LITERAL("app");
+
+#if !defined(OS_MACOSX)
const base::FilePath::CharType kUnpackedFullscreenAppName[] =
FILE_PATH_LITERAL("fullscreen_app");
+#endif // !defined(OS_MACOSX)
// Filters requests to the hosts in |urls| and redirects them to the test data
// dir through URLRequestMockHTTPJobs.
@@ -1569,7 +1570,7 @@
// Test policy-installed extensions are reloaded when killed.
BackgroundContentsService::
- SetCrashDelaysForForceInstalledAppsAndExtensionsForTesting(0, 0);
+ SetRestartDelayForForceInstalledAppsAndExtensionsForTesting(0);
content::WindowedNotificationObserver extension_crashed_observer(
chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
content::NotificationService::AllSources());
@@ -1616,7 +1617,13 @@
// Checks that a click on an extension CRX download triggers the extension
// installation prompt without further user interaction when the source is
// whitelisted by policy.
-IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionInstallSources) {
+// Flaky on windows; http://crbug.com/295729 .
+#if defined(OS_WIN)
+#define MAYBE_ExtensionInstallSources DISABLED_ExtensionInstallSources
+#else
+#define MAYBE_ExtensionInstallSources ExtensionInstallSources
+#endif
+IN_PROC_BROWSER_TEST_F(PolicyTest, MAYBE_ExtensionInstallSources) {
CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
diff --git a/chrome/browser/policy/policy_domain_descriptor.cc b/chrome/browser/policy/policy_domain_descriptor.cc
index c841a55..f054710 100644
--- a/chrome/browser/policy/policy_domain_descriptor.cc
+++ b/chrome/browser/policy/policy_domain_descriptor.cc
@@ -9,19 +9,18 @@
#include "base/values.h"
#include "chrome/browser/policy/policy_bundle.h"
#include "chrome/browser/policy/policy_map.h"
-#include "components/policy/core/common/policy_schema.h"
namespace policy {
namespace {
-bool Matches(const PolicySchema* schema, const base::Value& value) {
- if (!schema) {
+bool Matches(Schema schema, const base::Value& value) {
+ if (!schema.valid()) {
// Schema not found, invalid entry.
return false;
}
- if (!value.IsType(schema->type()))
+ if (!value.IsType(schema.type()))
return false;
const base::DictionaryValue* dict = NULL;
@@ -29,13 +28,13 @@
if (value.GetAsDictionary(&dict)) {
for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
it.Advance()) {
- if (!Matches(schema->GetSchemaForProperty(it.key()), it.value()))
+ if (!Matches(schema.GetProperty(it.key()), it.value()))
return false;
}
} else if (value.GetAsList(&list)) {
for (base::ListValue::const_iterator it = list->begin();
it != list->end(); ++it) {
- if (!*it || !Matches(schema->GetSchemaForItems(), **it))
+ if (!*it || !Matches(schema.GetItems(), **it))
return false;
}
}
@@ -50,10 +49,11 @@
void PolicyDomainDescriptor::RegisterComponent(
const std::string& component_id,
- scoped_ptr<PolicySchema> schema) {
- const PolicySchema*& entry = schema_map_[component_id];
+ scoped_ptr<SchemaOwner> schema) {
+ SchemaOwner*& entry = schema_owner_map_[component_id];
delete entry;
entry = schema.release();
+ schema_map_[component_id] = entry ? entry->schema() : Schema();
}
void PolicyDomainDescriptor::FilterBundle(PolicyBundle* bundle) const {
@@ -76,18 +76,17 @@
// TODO(joaodasilva): if a component is registered but doesn't have a schema
// then its policies aren't filtered. This behavior is enabled for M29 to
// allow a graceful update of the Legacy Browser Support extension; it'll
- // be removed for M30. http://crbug.com/240704
- if (!it_schema->second)
+ // be removed for M32. http://crbug.com/240704
+ Schema schema = it_schema->second;
+ if (!schema.valid())
continue;
- const PolicySchema* component_schema = it_schema->second;
PolicyMap* map = it_bundle->second;
for (PolicyMap::const_iterator it_map = map->begin();
it_map != map->end();) {
const std::string& policy_name = it_map->first;
const base::Value* policy_value = it_map->second.value;
- const PolicySchema* policy_schema =
- component_schema->GetSchemaForProperty(policy_name);
+ Schema policy_schema = schema.GetProperty(policy_name);
++it_map;
if (!policy_value || !Matches(policy_schema, *policy_value))
map->Erase(policy_name);
@@ -96,7 +95,7 @@
}
PolicyDomainDescriptor::~PolicyDomainDescriptor() {
- STLDeleteValues(&schema_map_);
+ STLDeleteValues(&schema_owner_map_);
}
} // namespace policy
diff --git a/chrome/browser/policy/policy_domain_descriptor.h b/chrome/browser/policy/policy_domain_descriptor.h
index daa3d56..2106633 100644
--- a/chrome/browser/policy/policy_domain_descriptor.h
+++ b/chrome/browser/policy/policy_domain_descriptor.h
@@ -12,18 +12,18 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/policy/policy_service.h"
+#include "components/policy/core/common/schema.h"
namespace policy {
class PolicyBundle;
-class PolicySchema;
// For each policy domain, this class keeps the complete list of valid
-// components for that domain, and the PolicySchema for each component.
+// components for that domain, and the Schema for each component.
class PolicyDomainDescriptor
: public base::RefCountedThreadSafe<PolicyDomainDescriptor> {
public:
- typedef std::map<std::string, const PolicySchema*> SchemaMap;
+ typedef std::map<std::string, Schema> SchemaMap;
explicit PolicyDomainDescriptor(PolicyDomain domain);
@@ -34,17 +34,21 @@
// |schema|. This registration overrides any previously set schema for this
// component.
void RegisterComponent(const std::string& component_id,
- scoped_ptr<PolicySchema> schema);
+ scoped_ptr<SchemaOwner> schema);
// Removes all the policies in |bundle| that don't match this descriptor.
// Policies of domains other than |domain_| are ignored.
void FilterBundle(PolicyBundle* bundle) const;
private:
+ typedef std::map<std::string, SchemaOwner*> SchemaOwnerMap;
+
friend class base::RefCountedThreadSafe<PolicyDomainDescriptor>;
+
~PolicyDomainDescriptor();
PolicyDomain domain_;
+ SchemaOwnerMap schema_owner_map_;
SchemaMap schema_map_;
DISALLOW_COPY_AND_ASSIGN(PolicyDomainDescriptor);
diff --git a/chrome/browser/policy/policy_domain_descriptor_unittest.cc b/chrome/browser/policy/policy_domain_descriptor_unittest.cc
index 9a03f8e..4ef89fc 100644
--- a/chrome/browser/policy/policy_domain_descriptor_unittest.cc
+++ b/chrome/browser/policy/policy_domain_descriptor_unittest.cc
@@ -13,7 +13,6 @@
#include "chrome/browser/policy/external_data_manager.h"
#include "chrome/browser/policy/policy_bundle.h"
#include "chrome/browser/policy/policy_map.h"
-#include "components/policy/core/common/policy_schema.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
@@ -37,9 +36,8 @@
EXPECT_TRUE(descriptor->components().empty());
std::string error;
- scoped_ptr<PolicySchema> schema = PolicySchema::Parse(
+ scoped_ptr<SchemaOwner> schema = SchemaOwner::Parse(
"{"
- " \"$schema\":\"http://json-schema.org/draft-03/schema#\","
" \"type\":\"object\","
" \"properties\": {"
" \"Array\": {"
@@ -147,4 +145,74 @@
EXPECT_TRUE(bundle.Equals(empty_bundle));
}
+TEST_F(PolicyDomainDescriptorTest, LegacyComponents) {
+ scoped_refptr<PolicyDomainDescriptor> descriptor =
+ new PolicyDomainDescriptor(POLICY_DOMAIN_EXTENSIONS);
+ EXPECT_EQ(POLICY_DOMAIN_EXTENSIONS, descriptor->domain());
+ EXPECT_TRUE(descriptor->components().empty());
+
+ std::string error;
+ scoped_ptr<SchemaOwner> schema = SchemaOwner::Parse(
+ "{"
+ " \"type\":\"object\","
+ " \"properties\": {"
+ " \"String\": { \"type\": \"string\" }"
+ " }"
+ "}", &error);
+ ASSERT_TRUE(schema) << error;
+
+ descriptor->RegisterComponent("with-schema", schema.Pass());
+ descriptor->RegisterComponent("without-schema", scoped_ptr<SchemaOwner>());
+
+ EXPECT_EQ(2u, descriptor->components().size());
+
+ // |bundle| contains policies loaded by a policy provider.
+ PolicyBundle bundle;
+
+ // Known components with schemas are filtered.
+ PolicyNamespace extension_ns(POLICY_DOMAIN_EXTENSIONS, "with-schema");
+ bundle.Get(extension_ns).Set("String",
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateStringValue("value 1"),
+ NULL);
+
+ // Known components without a schema are not filtered.
+ PolicyNamespace without_schema_ns(POLICY_DOMAIN_EXTENSIONS, "without-schema");
+ bundle.Get(without_schema_ns).Set("Schemaless",
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateStringValue("value 2"),
+ NULL);
+
+ // Other namespaces aren't filtered.
+ PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
+ bundle.Get(chrome_ns).Set("ChromePolicy",
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateStringValue("value 3"),
+ NULL);
+
+ PolicyBundle expected_bundle;
+ expected_bundle.MergeFrom(bundle);
+
+ // Unknown policies of known components with a schema are removed.
+ bundle.Get(extension_ns).Set("Surprise",
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateStringValue("value 4"),
+ NULL);
+
+ // Unknown components are removed.
+ PolicyNamespace unknown_ns(POLICY_DOMAIN_EXTENSIONS, "unknown");
+ bundle.Get(unknown_ns).Set("Surprise",
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateStringValue("value 5"),
+ NULL);
+
+ descriptor->FilterBundle(&bundle);
+ EXPECT_TRUE(bundle.Equals(expected_bundle));
+}
+
} // namespace policy
diff --git a/chrome/browser/policy/policy_loader_mac.cc b/chrome/browser/policy/policy_loader_mac.cc
index 29774f0..2d8e220 100644
--- a/chrome/browser/policy/policy_loader_mac.cc
+++ b/chrome/browser/policy/policy_loader_mac.cc
@@ -21,7 +21,7 @@
#include "chrome/browser/policy/policy_load_status.h"
#include "chrome/browser/policy/policy_map.h"
#include "chrome/browser/policy/preferences_mac.h"
-#include "components/policy/core/common/policy_schema.h"
+#include "components/policy/core/common/schema.h"
#include "policy/policy_constants.h"
using base::mac::CFCast;
@@ -210,29 +210,22 @@
void PolicyLoaderMac::LoadPolicyForComponent(
const std::string& bundle_id_string,
- const PolicySchema* schema,
+ Schema schema,
PolicyMap* policy) {
// TODO(joaodasilva): extensions may be registered in a PolicyDomainDescriptor
- // without a PolicySchema, to allow a graceful update of the Legacy Browser
- // Support extension on Windows. Remove this temporary check once that support
- // is removed.
- if (!schema)
+ // without a schema, to allow a graceful update of the Legacy Browser Support
+ // extension on Windows. Remove this check once that support is removed.
+ if (!schema.valid())
return;
base::ScopedCFTypeRef<CFStringRef> bundle_id(
base::SysUTF8ToCFStringRef(bundle_id_string));
preferences_->AppSynchronize(bundle_id);
- const PolicySchemaMap* map = schema->GetProperties();
- if (!map) {
- NOTREACHED();
- return;
- }
-
- for (PolicySchemaMap::const_iterator it = map->begin();
- it != map->end(); ++it) {
+ for (Schema::Iterator it = schema.GetPropertiesIterator();
+ !it.IsAtEnd(); it.Advance()) {
base::ScopedCFTypeRef<CFStringRef> pref_name(
- base::SysUTF8ToCFStringRef(it->first));
+ base::SysUTF8ToCFStringRef(it.key()));
base::ScopedCFTypeRef<CFPropertyListRef> value(
preferences_->CopyAppValue(pref_name, bundle_id));
if (!value.get())
@@ -242,9 +235,10 @@
PolicyLevel level = forced ? POLICY_LEVEL_MANDATORY :
POLICY_LEVEL_RECOMMENDED;
scoped_ptr<base::Value> policy_value(CreateValueFromProperty(value));
- if (policy_value)
- policy->Set(it->first, level, POLICY_SCOPE_USER,
+ if (policy_value) {
+ policy->Set(it.key(), level, POLICY_SCOPE_USER,
policy_value.release(), NULL);
+ }
}
}
diff --git a/chrome/browser/policy/policy_loader_mac.h b/chrome/browser/policy/policy_loader_mac.h
index 104ec90..68da9e4 100644
--- a/chrome/browser/policy/policy_loader_mac.h
+++ b/chrome/browser/policy/policy_loader_mac.h
@@ -25,7 +25,7 @@
class PolicyDomainDescriptor;
class PolicyMap;
-class PolicySchema;
+class Schema;
struct PolicyDefinitionList;
// A policy loader that loads policies from the Mac preferences system, and
@@ -63,7 +63,7 @@
// Loads the policies described in |schema| from the bundle identified by
// |bundle_id_string|, and stores them in |policy|.
void LoadPolicyForComponent(const std::string& bundle_id_string,
- const PolicySchema* schema,
+ Schema schema,
PolicyMap* policy);
// List of recognized policies.
diff --git a/chrome/browser/policy/policy_service_impl_unittest.cc b/chrome/browser/policy/policy_service_impl_unittest.cc
index c34cb2b..c7854d5 100644
--- a/chrome/browser/policy/policy_service_impl_unittest.cc
+++ b/chrome/browser/policy/policy_service_impl_unittest.cc
@@ -15,7 +15,7 @@
#include "chrome/browser/policy/mock_configuration_policy_provider.h"
#include "chrome/browser/policy/mock_policy_service.h"
#include "chrome/browser/policy/policy_domain_descriptor.h"
-#include "components/policy/core/common/policy_schema.h"
+#include "components/policy/core/common/schema.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -627,9 +627,8 @@
// Register another namespace.
std::string error;
- scoped_ptr<PolicySchema> schema = PolicySchema::Parse(
+ scoped_ptr<SchemaOwner> schema = SchemaOwner::Parse(
"{"
- " \"$schema\":\"http://json-schema.org/draft-03/schema#\","
" \"type\":\"object\","
" \"properties\": {"
" \"Boolean\": { \"type\": \"boolean\" },"
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 4e7cc93..744f414 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -118,6 +118,10 @@
#include "chrome/browser/ui/cocoa/extensions/browser_actions_controller_prefs.h"
#endif
+#if defined(ENABLE_MDNS)
+#include "chrome/browser/ui/webui/local_discovery/local_discovery_ui.h"
+#endif
+
#if defined(TOOLKIT_VIEWS)
#include "chrome/browser/ui/browser_view_prefs.h"
#include "chrome/browser/ui/tabs/tab_strip_layout_type_prefs.h"
@@ -136,6 +140,8 @@
#include "chrome/browser/chromeos/extensions/echo_private_api.h"
#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/chromeos/login/multi_profile_first_run_notification.h"
+#include "chrome/browser/chromeos/login/multi_profile_user_controller.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/user_image_manager.h"
#include "chrome/browser/chromeos/login/user_image_sync_observer.h"
@@ -276,6 +282,7 @@
chromeos::language_prefs::RegisterPrefs(registry);
chromeos::KioskAppManager::RegisterPrefs(registry);
chromeos::LoginUtils::RegisterPrefs(registry);
+ chromeos::MultiProfileUserController::RegisterPrefs(registry);
chromeos::Preferences::RegisterPrefs(registry);
chromeos::proxy_config::RegisterPrefs(registry);
chromeos::RegisterDisplayLocalStatePrefs(registry);
@@ -340,7 +347,6 @@
SessionStartupPref::RegisterProfilePrefs(registry);
TemplateURLPrepopulateData::RegisterProfilePrefs(registry);
TranslatePrefs::RegisterProfilePrefs(registry);
- extensions::ActivityLog::RegisterProfilePrefs(registry);
#if defined(ENABLE_AUTOFILL_DIALOG)
autofill::AutofillDialogController::RegisterProfilePrefs(registry);
@@ -350,6 +356,10 @@
policy::URLBlacklistManager::RegisterProfilePrefs(registry);
#endif
+#if defined(ENABLE_EXTENSIONS)
+ extensions::ActivityLog::RegisterProfilePrefs(registry);
+#endif
+
#if defined(ENABLE_MANAGED_USERS)
ManagedUserService::RegisterProfilePrefs(registry);
ManagedUserSyncService::RegisterProfilePrefs(registry);
@@ -400,6 +410,8 @@
#if defined(OS_CHROMEOS)
chromeos::attestation::PlatformVerificationFlow::RegisterProfilePrefs(
registry);
+ chromeos::MultiProfileFirstRunNotification::RegisterProfilePrefs(registry);
+ chromeos::MultiProfileUserController::RegisterProfilePrefs(registry);
chromeos::Preferences::RegisterProfilePrefs(registry);
chromeos::proxy_config::RegisterProfilePrefs(registry);
chromeos::UserImageSyncObserver::RegisterProfilePrefs(registry);
@@ -431,6 +443,10 @@
std::string(),
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
#endif
+
+#if defined(ENABLE_MDNS)
+ LocalDiscoveryUI::RegisterProfilePrefs(registry);
+#endif
}
void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
diff --git a/chrome/browser/prefs/pref_metrics_service.cc b/chrome/browser/prefs/pref_metrics_service.cc
index 82af366..2ee5e1a 100644
--- a/chrome/browser/prefs/pref_metrics_service.cc
+++ b/chrome/browser/prefs/pref_metrics_service.cc
@@ -83,16 +83,14 @@
// The following code might cause callbacks into this instance before we exit
// the constructor. This instance should be initialized at this point.
-
- // Android has no GetDeviceId.
-#if !defined(OS_ANDROID)
+#if defined(OS_WIN) || defined(OS_MACOSX)
// We need the machine id to compute pref value hashes. Fetch that, and then
// call CheckTrackedPreferences in the callback.
extensions::api::DeviceId::GetDeviceId(
"PrefMetricsService", // non-empty string to obfuscate the device id.
Bind(&PrefMetricsService::GetDeviceIdCallback,
weak_factory_.GetWeakPtr()));
-#endif // !defined(OS_ANDROID)
+#endif // defined(OS_WIN) || defined(OS_MACOSX)
}
// For unit testing only.
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index daa0ae1..86f2f94 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -15,6 +15,7 @@
#include "base/values.h"
#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/browsing_data_remover.h"
+#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
@@ -50,6 +51,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/web_contents.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
@@ -360,6 +362,10 @@
return quit_message_loop_on_destruction_;
}
+ void set_quit_message_loop_on_destruction(bool quit) {
+ quit_message_loop_on_destruction_ = quit;
+ }
+
private:
virtual void OnRenderViewHostCreated(
RenderViewHost* new_render_view_host) OVERRIDE {
@@ -623,6 +629,26 @@
url, never_respond_handler.Pass());
}
+// A ContentBrowserClient that cancels all prerenderers on OpenURL.
+class TestContentBrowserClient : public chrome::ChromeContentBrowserClient {
+ public:
+ TestContentBrowserClient() {}
+ virtual ~TestContentBrowserClient() {}
+
+ // chrome::ChromeContentBrowserClient implementation.
+ virtual bool ShouldAllowOpenURL(content::SiteInstance* site_instance,
+ const GURL& url) OVERRIDE {
+ PrerenderManagerFactory::GetForProfile(
+ Profile::FromBrowserContext(site_instance->GetBrowserContext()))
+ ->CancelAllPrerenders();
+ return chrome::ChromeContentBrowserClient::ShouldAllowOpenURL(site_instance,
+ url);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestContentBrowserClient);
+};
+
} // namespace
// Many of these tests are flaky. See http://crbug.com/249179
@@ -1804,6 +1830,31 @@
NavigateToDestURL();
}
+// Checks that the referrer is set when prerendering is cancelled.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelReferrer) {
+ scoped_ptr<TestContentBrowserClient> test_content_browser_client(
+ new TestContentBrowserClient);
+ content::ContentBrowserClient* original_browser_client =
+ content::SetBrowserClientForTesting(test_content_browser_client.get());
+
+ PrerenderTestURL("files/prerender/prerender_referrer.html",
+ FINAL_STATUS_CANCELLED,
+ 1);
+ GetPrerenderContents()->set_quit_message_loop_on_destruction(false);
+ OpenDestURLViaClick();
+
+ bool display_test_result = false;
+ WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ web_contents,
+ "window.domAutomationController.send(DidDisplayPass())",
+ &display_test_result));
+ EXPECT_TRUE(display_test_result);
+
+ content::SetBrowserClientForTesting(original_browser_client);
+}
+
// Checks that popups on a prerendered page cause cancellation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPopup) {
PrerenderTestURL("files/prerender/prerender_popup.html",
@@ -2783,6 +2834,32 @@
NavigateToDestURL();
}
+// Checks that the referrer policy is used when prerendering is cancelled.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelReferrerPolicy) {
+ scoped_ptr<TestContentBrowserClient> test_content_browser_client(
+ new TestContentBrowserClient);
+ content::ContentBrowserClient* original_browser_client =
+ content::SetBrowserClientForTesting(test_content_browser_client.get());
+
+ set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html");
+ PrerenderTestURL("files/prerender/prerender_referrer_policy.html",
+ FINAL_STATUS_CANCELLED,
+ 1);
+ GetPrerenderContents()->set_quit_message_loop_on_destruction(false);
+ OpenDestURLViaClick();
+
+ bool display_test_result = false;
+ WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ web_contents,
+ "window.domAutomationController.send(DidDisplayPass())",
+ &display_test_result));
+ EXPECT_TRUE(display_test_result);
+
+ content::SetBrowserClientForTesting(original_browser_client);
+}
+
// Test interaction of the webNavigation and tabs API with prerender.
class PrerenderBrowserTestWithExtensions : public PrerenderBrowserTest,
public ExtensionApiTest {
diff --git a/chrome/browser/prerender/prerender_final_status.h b/chrome/browser/prerender/prerender_final_status.h
index 8e989c6..beb1421 100644
--- a/chrome/browser/prerender/prerender_final_status.h
+++ b/chrome/browser/prerender/prerender_final_status.h
@@ -31,8 +31,8 @@
FINAL_STATUS_RATE_LIMIT_EXCEEDED = 16,
// Obsolete: FINAL_STATUS_PENDING_SKIPPED = 17,
// Obsolete: FINAL_STATUS_CONTROL_GROUP = 18,
- FINAL_STATUS_HTML5_MEDIA = 19,
- FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED = 20,
+ // Obsolete: FINAL_STATUS_HTML5_MEDIA = 19,
+ // Obsolete: FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED = 20,
FINAL_STATUS_RENDERER_CRASHED = 21,
FINAL_STATUS_UNSUPPORTED_SCHEME = 22,
FINAL_STATUS_INVALID_HTTP_METHOD = 23,
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index c0f8a08..215ee3f 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -616,8 +616,7 @@
active_prerenders_.weak_erase(it);
}
- // Destroy the old WebContents relatively promptly to reduce resource usage,
- // and in the case of HTML5 media, reduce the chance of playing any sound.
+ // Destroy the old WebContents relatively promptly to reduce resource usage.
PostCleanupTask();
}
diff --git a/chrome/browser/prerender/prerender_render_view_host_observer.cc b/chrome/browser/prerender/prerender_render_view_host_observer.cc
index 7317b61..6445cc4 100644
--- a/chrome/browser/prerender/prerender_render_view_host_observer.cc
+++ b/chrome/browser/prerender/prerender_render_view_host_observer.cc
@@ -33,8 +33,6 @@
bool handled = true;
// The following messages we do want to consume.
IPC_BEGIN_MESSAGE_MAP(PrerenderRenderViewHostObserver, message)
- IPC_MESSAGE_HANDLER(ChromeViewHostMsg_MaybeCancelPrerenderForHTML5Media,
- OnMaybeCancelPrerenderForHTML5Media)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CancelPrerenderForPrinting,
OnCancelPrerenderForPrinting)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -47,18 +45,8 @@
return handled;
}
-// The base class declares this as protected so this is just here to make it
-// public so it is visible to the caller.
-bool PrerenderRenderViewHostObserver::Send(IPC::Message* message) {
- return content::RenderViewHostObserver::Send(message);
-}
-
-void PrerenderRenderViewHostObserver::OnMaybeCancelPrerenderForHTML5Media() {
- prerender_contents_->Destroy(FINAL_STATUS_HTML5_MEDIA);
-}
-
void PrerenderRenderViewHostObserver::OnCancelPrerenderForPrinting() {
prerender_contents_->Destroy(FINAL_STATUS_WINDOW_PRINT);
}
-}
+} // namespace prerender
diff --git a/chrome/browser/prerender/prerender_render_view_host_observer.h b/chrome/browser/prerender/prerender_render_view_host_observer.h
index c804b86..79339fe 100644
--- a/chrome/browser/prerender/prerender_render_view_host_observer.h
+++ b/chrome/browser/prerender/prerender_render_view_host_observer.h
@@ -5,12 +5,9 @@
#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_RENDER_VIEW_HOST_OBSERVER_H_
#define CHROME_BROWSER_PRERENDER_PRERENDER_RENDER_VIEW_HOST_OBSERVER_H_
-#include <vector>
-
#include "content/public/browser/render_view_host_observer.h"
namespace content {
-struct FaviconURL;
class RenderViewHost;
}
@@ -31,7 +28,6 @@
virtual void RenderViewHostDestroyed(content::RenderViewHost* rvh) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual bool Send(IPC::Message* message) OVERRIDE;
void set_prerender_contents(PrerenderContents* prerender_contents) {
prerender_contents_ = prerender_contents;
@@ -39,8 +35,6 @@
private:
// Message handlers.
-
- void OnMaybeCancelPrerenderForHTML5Media();
void OnCancelPrerenderForPrinting();
// The associated prerender contents.
diff --git a/chrome/browser/prerender/prerender_tracker.cc b/chrome/browser/prerender/prerender_tracker.cc
index a490ac9..ff45256 100644
--- a/chrome/browser/prerender/prerender_tracker.cc
+++ b/chrome/browser/prerender/prerender_tracker.cc
@@ -189,6 +189,17 @@
return possibly_prerendering_io_thread_set_.count(child_route_id_pair) > 0;
}
+void PrerenderTracker::UpdatePrerenderStateForTransfer(int old_child_id,
+ int old_route_id,
+ int new_child_id,
+ int new_route_id) {
+ ChildRouteIdPair old_pair(old_child_id, old_route_id);
+ ChildRouteIdPair new_pair(new_child_id, new_route_id);
+
+ RemovePrerenderOnIOThread(old_pair);
+ AddPrerenderOnIOThread(new_pair);
+}
+
void PrerenderTracker::AddPrerenderOnIOThread(
const ChildRouteIdPair& child_route_id_pair) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
diff --git a/chrome/browser/prerender/prerender_tracker.h b/chrome/browser/prerender/prerender_tracker.h
index 81557f3..8460643 100644
--- a/chrome/browser/prerender/prerender_tracker.h
+++ b/chrome/browser/prerender/prerender_tracker.h
@@ -68,6 +68,14 @@
// been displayed or destroyed is still prerendering.
bool IsPrerenderingOnIOThread(int child_id, int route_id) const;
+ // Updates the state for whether a RenderView is prerendering when a
+ // navigation is transferred from one RenderView to another in a different
+ // process.
+ void UpdatePrerenderStateForTransfer(int old_child_id,
+ int old_route_id,
+ int new_child_id,
+ int new_route_id);
+
private:
friend class PrerenderContents;
FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerNull);
diff --git a/chrome/browser/printing/print_dialog_cloud_unittest.cc b/chrome/browser/printing/print_dialog_cloud_unittest.cc
index 09b7b95..c6d3153 100644
--- a/chrome/browser/printing/print_dialog_cloud_unittest.cc
+++ b/chrome/browser/printing/print_dialog_cloud_unittest.cc
@@ -43,11 +43,9 @@
using testing::_;
using ui::ExternalWebDialogUI;
-static const char* const kPDFTestFile = "printing/cloud_print_unittest.pdf";
-static const char* const kEmptyPDFTestFile =
- "printing/cloud_print_emptytest.pdf";
-static const char* const kMockJobTitle = "Mock Job Title";
-static const char* const kMockPrintTicket = "Resolution=300";
+const char kPDFTestFile[] = "printing/cloud_print_unittest.pdf";
+const char kMockJobTitle[] = "Mock Job Title";
+const char kMockPrintTicket[] = "Resolution=300";
base::FilePath GetTestDataFileName() {
diff --git a/chrome/browser/printing/print_dialog_gtk.cc b/chrome/browser/printing/print_dialog_gtk.cc
index a06b3ec..ff22fe3 100644
--- a/chrome/browser/printing/print_dialog_gtk.cc
+++ b/chrome/browser/printing/print_dialog_gtk.cc
@@ -4,10 +4,7 @@
#include "chrome/browser/printing/print_dialog_gtk.h"
-#include <fcntl.h>
#include <gtk/gtkunixprint.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <string>
#include <vector>
@@ -15,6 +12,7 @@
#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/file_util_proxy.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/utf_string_conversions.h"
@@ -36,6 +34,33 @@
const char kDuplexTumble[] = "DuplexTumble";
const char kDuplexNoTumble[] = "DuplexNoTumble";
+class StickyPrintSettingGtk {
+ public:
+ StickyPrintSettingGtk() : last_used_settings_(gtk_print_settings_new()) {
+ }
+ ~StickyPrintSettingGtk() {
+ NOTREACHED(); // Intended to be used with a Leaky LazyInstance.
+ }
+
+ GtkPrintSettings* settings() {
+ return last_used_settings_;
+ }
+
+ void SetLastUsedSettings(GtkPrintSettings* settings) {
+ DCHECK(last_used_settings_);
+ g_object_unref(last_used_settings_);
+ last_used_settings_ = gtk_print_settings_copy(settings);
+ }
+
+ private:
+ GtkPrintSettings* last_used_settings_;
+
+ DISALLOW_COPY_AND_ASSIGN(StickyPrintSettingGtk);
+};
+
+base::LazyInstance<StickyPrintSettingGtk>::Leaky g_last_used_settings =
+ LAZY_INSTANCE_INITIALIZER;
+
// Helper class to track GTK printers.
class GtkPrinterList {
public:
@@ -59,13 +84,13 @@
// Can return NULL if the printer cannot be found due to:
// - Printer list out of sync with printer dialog UI.
// - Querying for non-existant printers like 'Print to PDF'.
- GtkPrinter* GetPrinterWithName(const char* name) {
- if (!name || !*name)
+ GtkPrinter* GetPrinterWithName(const std::string& name) {
+ if (name.empty())
return NULL;
for (std::vector<GtkPrinter*>::iterator it = printers_.begin();
it < printers_.end(); ++it) {
- if (strcmp(name, gtk_printer_get_name(*it)) == 0) {
+ if (gtk_printer_get_name(*it) == name) {
return *it;
}
}
@@ -132,8 +157,9 @@
DCHECK(!page_setup_);
DCHECK(!printer_);
- // |gtk_settings_| is a new object.
- gtk_settings_ = gtk_print_settings_new();
+ // |gtk_settings_| is a new copy.
+ gtk_settings_ =
+ gtk_print_settings_copy(g_last_used_settings.Get().settings());
page_setup_ = gtk_page_setup_new();
// No page range to initialize for default settings.
@@ -165,12 +191,14 @@
bool is_cloud_print = job_settings.HasKey(printing::kSettingCloudPrintId);
- if (!gtk_settings_)
- gtk_settings_ = gtk_print_settings_new();
+ if (!gtk_settings_) {
+ gtk_settings_ =
+ gtk_print_settings_copy(g_last_used_settings.Get().settings());
+ }
if (!print_to_pdf && !is_cloud_print) {
scoped_ptr<GtkPrinterList> printer_list(new GtkPrinterList);
- printer_ = printer_list->GetPrinterWithName(device_name.c_str());
+ printer_ = printer_list->GetPrinterWithName(device_name);
if (printer_) {
g_object_ref(printer_);
gtk_print_settings_set_printer(gtk_settings_,
@@ -254,6 +282,8 @@
TRUE);
gtk_print_unix_dialog_set_has_selection(GTK_PRINT_UNIX_DIALOG(dialog_),
has_selection);
+ gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog_),
+ gtk_settings_);
g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
gtk_widget_show(dialog_);
}
@@ -389,6 +419,9 @@
return;
}
+ // Save the settings for next time.
+ g_last_used_settings.Get().SetLastUsedSettings(gtk_settings_);
+
GtkPrintJob* print_job = gtk_print_job_new(
UTF16ToUTF8(document_name).c_str(),
printer_,
diff --git a/chrome/browser/printing/print_system_task_proxy.cc b/chrome/browser/printing/print_system_task_proxy.cc
index 2b8ad4e..74819f7 100644
--- a/chrome/browser/printing/print_system_task_proxy.cc
+++ b/chrome/browser/printing/print_system_task_proxy.cc
@@ -24,17 +24,11 @@
using content::BrowserThread;
-namespace {
-
const char kPrinterId[] = "printerId";
const char kDisableColorOption[] = "disableColorOption";
const char kSetDuplexAsDefault[] = "setDuplexAsDefault";
-const char kPrinterColorModelForBlack[] = "printerColorModelForBlack";
-const char kPrinterColorModelForColor[] = "printerColorModelForColor";
const char kPrinterDefaultDuplexValue[] = "printerDefaultDuplexValue";
-} // namespace
-
PrintSystemTaskProxy::PrintSystemTaskProxy(
const base::WeakPtr<PrintPreviewHandler>& handler,
printing::PrintBackend* print_backend,
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index b3351bf..534fa4e 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -43,12 +43,10 @@
using base::TimeDelta;
using content::BrowserThread;
-namespace {
-
+#if defined(OS_WIN)
// Limits memory usage by raster to 64 MiB.
const int kMaxRasterSizeInPixels = 16*1024*1024;
-
-} // namespace
+#endif
namespace printing {
diff --git a/chrome/browser/process_singleton.h b/chrome/browser/process_singleton.h
index 1594cd5..94d45d1 100644
--- a/chrome/browser/process_singleton.h
+++ b/chrome/browser/process_singleton.h
@@ -24,9 +24,9 @@
#include "base/threading/non_thread_safe.h"
#include "ui/gfx/native_widget_types.h"
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
#include "base/files/scoped_temp_dir.h"
-#endif // defined(OS_LINUX) || defined(OS_OPENBSD)
+#endif
#if defined(OS_WIN)
#include "base/win/message_window.h"
@@ -88,9 +88,9 @@
// Clear any lock state during shutdown.
void Cleanup();
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
static void DisablePromptForTesting();
-#endif // defined(OS_LINUX) || defined(OS_OPENBSD)
+#endif
protected:
// Notify another process, if available.
@@ -99,7 +99,7 @@
// On Windows, Create() has to be called before this.
NotifyResult NotifyOtherProcess();
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
// Exposed for testing. We use a timeout on Linux, and in tests we want
// this timeout to be short.
NotifyResult NotifyOtherProcessWithTimeout(const CommandLine& command_line,
@@ -111,7 +111,7 @@
void OverrideCurrentPidForTesting(base::ProcessId pid);
void OverrideKillCallbackForTesting(
const base::Callback<void(int)>& callback);
-#endif // defined(OS_LINUX) || defined(OS_OPENBSD)
+#endif
private:
#if !defined(OS_MACOSX)
@@ -130,7 +130,7 @@
bool is_virtualized_; // Stuck inside Microsoft Softricity VM environment.
HANDLE lock_file_;
base::FilePath user_data_dir_;
-#elif defined(OS_LINUX) || defined(OS_OPENBSD)
+#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
// Return true if the given pid is one of our child processes.
// Assumes that the current pid is the root of all pids of the current
// instance.
diff --git a/chrome/browser/profile_resetter/jtl_foundation.cc b/chrome/browser/profile_resetter/jtl_foundation.cc
new file mode 100644
index 0000000..013cca1
--- /dev/null
+++ b/chrome/browser/profile_resetter/jtl_foundation.cc
@@ -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.
+
+#include "chrome/browser/profile_resetter/jtl_foundation.h"
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+
+namespace jtl_foundation {
+
+Hasher::Hasher(const std::string& seed) : hmac_(crypto::HMAC::SHA256) {
+ if (!hmac_.Init(seed))
+ NOTREACHED();
+}
+
+Hasher::~Hasher() {}
+
+std::string Hasher::GetHash(const std::string& input) const {
+ if (cached_hashes_.find(input) == cached_hashes_.end()) {
+ // Calculate value.
+ unsigned char digest[kHashSizeInBytes];
+ if (!hmac_.Sign(input, digest, kHashSizeInBytes)) {
+ NOTREACHED();
+ return std::string();
+ }
+ // Instead of using the full SHA256, we only use the hex encoding of the
+ // first 16 bytes.
+ cached_hashes_[input] = base::HexEncode(digest, kHashSizeInBytes / 2);
+ DCHECK_EQ(kHashSizeInBytes, cached_hashes_[input].size());
+ }
+ return cached_hashes_[input];
+}
+
+} // namespace jtl_foundation
diff --git a/chrome/browser/profile_resetter/jtl_foundation.h b/chrome/browser/profile_resetter/jtl_foundation.h
new file mode 100644
index 0000000..0b4953d
--- /dev/null
+++ b/chrome/browser/profile_resetter/jtl_foundation.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_PROFILE_RESETTER_JTL_FOUNDATION_H_
+#define CHROME_BROWSER_PROFILE_RESETTER_JTL_FOUNDATION_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "crypto/hmac.h"
+
+namespace jtl_foundation {
+
+// A JTL (JSON Traversal Language) program is composed of one or more
+// sentences. Each sentence consists of a sequence of operations. The input of
+// the program is a hierarchical JSON data structure.
+//
+// The execution of each sentence starts at the root of an input dictionary. The
+// operations include navigation in the JSON data structure, as well as
+// comparing the current (leaf) node to fixed values. The program also has a
+// spearate dictionary as working memory, into which it can memorize data, then
+// later recall it for comparisons.
+//
+// Example program:
+// NAVIGATE_ANY
+// NAVIGATE("bar")
+// COMPARE_NODE_BOOL(1)
+// STORE_BOOL(hash("found_foo"), 1)
+// STOP_EXECUTING_SENTENCE
+//
+// Example input:
+// {
+// 'key1': 1,
+// 'key2': {'foo': 0, 'bar': false, 'baz': 2}
+// 'key3': {'foo': 0, 'bar': true, 'baz': 2}
+// 'key4': {'foo': 0, 'bar': true, 'baz': 2}
+// }
+//
+// This program navigates from the root of the dictionary to all children
+// ("key1", "key2", "key3", "key4") and executes the remaining program on each
+// of the children. The navigation happens in depth-first pre-order. On each of
+// the children it tries to navigate into the child "bar", which fails for
+// "key1", so execution stops for this sub-branch. On key2 the program navigates
+// to "bar" and moves the execution context to this node which has the value
+// "false". Therefore, the following COMPARE_NODE_BOOL is not fulfilled and the
+// execution does not continue on this branch, so we back track and proceed with
+// "key3" and its "bar" child. For this node, COMPARE_NODE_BOOL is fulfilled and
+// the execution continues to store "found_foo = true" into the working memory
+// of the interpreter. Next the interpreter executes STOP_EXECUTING_SENTENCE
+// which prevents the traversal from descending into the "key4" branch from the
+// NAVIGATE_ANY operation and can therefore speedup the processing.
+
+// JTL byte code consists of uint8 opcodes followed by parameters. Parameters
+// are either boolean (uint8 with value \x00 or \x01), uint8s or hash strings
+// which consist of 32 bytes.
+// The following opcodes are defined:
+enum OpCodes {
+ // Continues execution with the next operation on the element of a
+ // dictionary that matches the passed key parameter. If no such element
+ // exists, the command execution returns from the current node/instruction.
+ // Parameters:
+ // - the hash value of a dictionary key.
+ NAVIGATE = 0x00,
+ // Continues execution with the next operation on each element of a
+ // dictionary or list. If no such element exists or the current element is
+ // neither a dictionary or list, the command execution returns from the
+ // current node/instruction.
+ NAVIGATE_ANY = 0x01,
+ // Continues execution with the next operation on the parent node of the
+ // current node. If the current node is the root of the input dictionary, the
+ // program execution fails with a runtime error.
+ NAVIGATE_BACK = 0x02,
+ // Stores a boolean value in the working memory.
+ // Parameters:
+ // - a 32 ASCII character parameter name.
+ // - the value to store (\x00 or \x01)
+ STORE_BOOL = 0x10,
+ // Checks whether a boolean stored in working memory matches the expected
+ // value and continues execution with the next operation in case of a match.
+ // Parameters:
+ // - a 32 ASCII character parameter name.
+ // - the expected value (\x00 or \x01).
+ // - the default value in case the working memory contains no stored
+ // entry (\x00 or\x01).
+ COMPARE_STORED_BOOL = 0x11,
+ // Same as STORE_BOOL but takes a hash instead of a boolean value as
+ // parameter.
+ STORE_HASH = 0x12,
+ // Same as COMPARE_STORED_BOOL but takes a hash instead of two boolean values
+ // as parameters.
+ COMPARE_STORED_HASH = 0x13,
+ // Compares the current node against a boolean value and continues
+ // execution with the next operation in case of a match. If the current
+ // node does not match or is not a boolean value, the program execution
+ // returns from the current node/instruction.
+ // Parameters:
+ // - a boolen value (\x00 or \x01).
+ COMPARE_NODE_BOOL = 0x20,
+ // Compares the current node against a hash value and continues execution
+ // with the next operation in case of a match. If the current node is not
+ // a string, integer or double, or if it is either but does not match, the
+ // program execution stops for the current node.
+ // Parameters:
+ // - a hash string of 32 bytes.
+ COMPARE_NODE_HASH = 0x21,
+ // Stop execution in this specific sentence.
+ STOP_EXECUTING_SENTENCE = 0x30,
+ // Separator between sentences, starts a new sentence.
+ END_OF_SENTENCE = 0x31
+};
+
+static const size_t kHashSizeInBytes = 32;
+
+// A class that provides SHA256 hash values for strings using a fixed hash seed.
+class Hasher {
+ public:
+ explicit Hasher(const std::string& seed);
+ ~Hasher();
+
+ std::string GetHash(const std::string& input) const;
+
+ private:
+ crypto::HMAC hmac_;
+ mutable std::map<std::string, std::string> cached_hashes_;
+ DISALLOW_COPY_AND_ASSIGN(Hasher);
+};
+
+} // namespace jtl_foundation
+
+#endif // CHROME_BROWSER_PROFILE_RESETTER_JTL_FOUNDATION_H_
diff --git a/chrome/browser/profile_resetter/jtl_instructions.h b/chrome/browser/profile_resetter/jtl_instructions.h
new file mode 100644
index 0000000..11c3f6c
--- /dev/null
+++ b/chrome/browser/profile_resetter/jtl_instructions.h
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium 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_JTL_INSTRUCTIONS_H_
+#define CHROME_BROWSER_PROFILE_RESETTER_JTL_INSTRUCTIONS_H_
+
+#include <string>
+
+// These are instructions to generate binary code for JTL programs.
+
+#define VALUE_FALSE std::string("\x00", 1)
+#define VALUE_TRUE std::string("\x01", 1)
+
+#define OP_NAVIGATE(key) std::string("\x00", 1) + key
+#define OP_NAVIGATE_ANY std::string("\x01", 1)
+#define OP_NAVIGATE_BACK std::string("\x02", 1)
+#define OP_STORE_BOOL(name, value) std::string("\x10") + name + value
+#define OP_COMPARE_STORED_BOOL(name, value, default_value) \
+ std::string("\x11", 1) + name + value + default_value
+#define OP_STORE_HASH(name, value) std::string("\x12") + name + value
+#define OP_COMPARE_STORED_HASH(name, value, default_value) \
+ std::string("\x13", 1) + name + value + default_value
+#define OP_COMPARE_NODE_BOOL(value) std::string("\x20", 1) + value
+#define OP_COMPARE_NODE_HASH(value) std::string("\x21", 1) + value
+#define OP_STOP_EXECUTING_SENTENCE std::string("\x30", 1)
+#define OP_END_OF_SENTENCE std::string("\x31", 1)
+
+#endif // CHROME_BROWSER_PROFILE_RESETTER_JTL_INSTRUCTIONS_H_
diff --git a/chrome/browser/profile_resetter/jtl_interpreter.cc b/chrome/browser/profile_resetter/jtl_interpreter.cc
new file mode 100644
index 0000000..df3e48a
--- /dev/null
+++ b/chrome/browser/profile_resetter/jtl_interpreter.cc
@@ -0,0 +1,483 @@
+// Copyright 2013 The Chromium 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/jtl_interpreter.h"
+
+#include "base/memory/scoped_vector.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/profile_resetter/jtl_foundation.h"
+#include "crypto/hmac.h"
+
+namespace {
+
+class ExecutionContext;
+
+// An operation in an interpreted program.
+class Operation {
+ public:
+ virtual ~Operation() {}
+ // Executes the operation on the specified context and instructs the context
+ // to continue execution with the next instruction if appropriate.
+ // Returns true if we should continue with any potential backtracking that
+ // needs to be done.
+ virtual bool Execute(ExecutionContext* context) = 0;
+};
+
+// An execution context of operations.
+class ExecutionContext {
+ public:
+ // |input| is the root of a dictionary that stores the information the
+ // sentence is evaluated on.
+ ExecutionContext(const jtl_foundation::Hasher* hasher,
+ const std::vector<Operation*>& sentence,
+ const DictionaryValue* input,
+ DictionaryValue* working_memory)
+ : hasher_(hasher),
+ sentence_(sentence),
+ next_instruction_index_(0u),
+ working_memory_(working_memory),
+ error_(false) {
+ stack_.push_back(input);
+ }
+ ~ExecutionContext() {}
+
+ // Returns true in case of success.
+ bool ContinueExecution() {
+ if (error_ || stack_.empty()) {
+ error_ = true;
+ return false;
+ }
+ if (next_instruction_index_ >= sentence_.size())
+ return true;
+
+ Operation* op = sentence_[next_instruction_index_];
+ next_instruction_index_++;
+ bool continue_traversal = op->Execute(this);
+ next_instruction_index_--;
+ return continue_traversal;
+ }
+
+ std::string GetHash(const std::string& input) {
+ return hasher_->GetHash(input);
+ }
+
+ const Value* current_node() const { return stack_.back(); }
+ std::vector<const Value*>* stack() { return &stack_; }
+ DictionaryValue* working_memory() { return working_memory_; }
+ bool error() const { return error_; }
+
+ private:
+ // A hasher used to hash node names in a dictionary.
+ const jtl_foundation::Hasher* hasher_;
+ // The sentence to be executed.
+ const std::vector<Operation*> sentence_;
+ // Position in |sentence_|.
+ size_t next_instruction_index_;
+ // A stack of Values, indicating a navigation path from the root node of
+ // |input| (see constructor) to the current node on which the
+ // sentence_[next_instruction_index_] is evaluated.
+ std::vector<const Value*> stack_;
+ // Memory into which values can be stored by the program.
+ DictionaryValue* working_memory_;
+ // Whether a runtime error occurred.
+ bool error_;
+ DISALLOW_COPY_AND_ASSIGN(ExecutionContext);
+};
+
+class NavigateOperation : public Operation {
+ public:
+ explicit NavigateOperation(const std::string hashed_key)
+ : hashed_key_(hashed_key) {}
+ virtual ~NavigateOperation() {}
+ virtual bool Execute(ExecutionContext* context) OVERRIDE {
+ const DictionaryValue* dict = NULL;
+ if (!context->current_node()->GetAsDictionary(&dict)) {
+ // Just ignore this node gracefully as this navigation is a dead end.
+ // If this NavigateOperation occurred after a NavigateAny operation, those
+ // may still be fulfillable, so we allow continuing the execution of the
+ // sentence on other nodes.
+ return true;
+ }
+ for (DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) {
+ if (context->GetHash(i.key()) != hashed_key_)
+ continue;
+ context->stack()->push_back(&i.value());
+ bool continue_traversal = context->ContinueExecution();
+ context->stack()->pop_back();
+ if (!continue_traversal)
+ return false;
+ }
+ return true;
+ }
+
+ private:
+ std::string hashed_key_;
+ DISALLOW_COPY_AND_ASSIGN(NavigateOperation);
+};
+
+class NavigateAnyOperation : public Operation {
+ public:
+ NavigateAnyOperation() {}
+ virtual ~NavigateAnyOperation() {}
+ virtual bool Execute(ExecutionContext* context) OVERRIDE {
+ const DictionaryValue* dict = NULL;
+ const ListValue* list = NULL;
+ if (context->current_node()->GetAsDictionary(&dict)) {
+ for (DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) {
+ context->stack()->push_back(&i.value());
+ bool continue_traversal = context->ContinueExecution();
+ context->stack()->pop_back();
+ if (!continue_traversal)
+ return false;
+ }
+ } else if (context->current_node()->GetAsList(&list)) {
+ for (ListValue::const_iterator i = list->begin(); i != list->end(); ++i) {
+ context->stack()->push_back(*i);
+ bool continue_traversal = context->ContinueExecution();
+ context->stack()->pop_back();
+ if (!continue_traversal)
+ return false;
+ }
+ } else {
+ // Do nothing, just ignore this node.
+ }
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NavigateAnyOperation);
+};
+
+class NavigateBackOperation : public Operation {
+ public:
+ NavigateBackOperation() {}
+ virtual ~NavigateBackOperation() {}
+ virtual bool Execute(ExecutionContext* context) OVERRIDE {
+ const Value* current_node = context->current_node();
+ context->stack()->pop_back();
+ bool continue_traversal = context->ContinueExecution();
+ context->stack()->push_back(current_node);
+ return continue_traversal;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NavigateBackOperation);
+};
+
+class StoreValue : public Operation {
+ public:
+ StoreValue(const std::string hashed_name, scoped_ptr<Value> value)
+ : hashed_name_(hashed_name),
+ value_(value.Pass()) {
+ DCHECK(IsStringUTF8(hashed_name));
+ DCHECK(value_);
+ }
+ virtual ~StoreValue() {}
+ virtual bool Execute(ExecutionContext* context) OVERRIDE {
+ context->working_memory()->Set(hashed_name_, value_->DeepCopy());
+ return context->ContinueExecution();
+ }
+
+ private:
+ std::string hashed_name_;
+ scoped_ptr<Value> value_;
+ DISALLOW_COPY_AND_ASSIGN(StoreValue);
+};
+
+class CompareStoredValue : public Operation {
+ public:
+ CompareStoredValue(const std::string hashed_name,
+ scoped_ptr<Value> value,
+ scoped_ptr<Value> default_value)
+ : hashed_name_(hashed_name),
+ value_(value.Pass()),
+ default_value_(default_value.Pass()) {
+ DCHECK(IsStringUTF8(hashed_name));
+ DCHECK(value_);
+ DCHECK(default_value_);
+ }
+ virtual ~CompareStoredValue() {}
+ virtual bool Execute(ExecutionContext* context) OVERRIDE {
+ const Value* actual_value = NULL;
+ if (!context->working_memory()->Get(hashed_name_, &actual_value))
+ actual_value = default_value_.get();
+ if (!value_->Equals(actual_value))
+ return true;
+ return context->ContinueExecution();
+ }
+
+ private:
+ std::string hashed_name_;
+ scoped_ptr<Value> value_;
+ scoped_ptr<Value> default_value_;
+ DISALLOW_COPY_AND_ASSIGN(CompareStoredValue);
+};
+
+class CompareNodeBool : public Operation {
+ public:
+ explicit CompareNodeBool(bool value) : value_(value) {}
+ virtual ~CompareNodeBool() {}
+ virtual bool Execute(ExecutionContext* context) OVERRIDE {
+ bool actual_value = false;
+ if (!context->current_node()->GetAsBoolean(&actual_value))
+ return true;
+ if (actual_value != value_)
+ return true;
+ return context->ContinueExecution();
+ }
+
+ private:
+ bool value_;
+ DISALLOW_COPY_AND_ASSIGN(CompareNodeBool);
+};
+
+class CompareNodeHash : public Operation {
+ public:
+ explicit CompareNodeHash(const std::string& hashed_value)
+ : hashed_value_(hashed_value) {}
+ virtual ~CompareNodeHash() {}
+ virtual bool Execute(ExecutionContext* context) OVERRIDE {
+ std::string actual_value;
+ int tmp_int = 0;
+ double tmp_double = 0.0;
+ if (context->current_node()->GetAsInteger(&tmp_int)) {
+ actual_value = base::IntToString(tmp_int);
+ } else if (context->current_node()->GetAsDouble(&tmp_double)) {
+ actual_value = base::DoubleToString(tmp_double);
+ } else {
+ if (!context->current_node()->GetAsString(&actual_value))
+ return true;
+ }
+ actual_value = context->GetHash(actual_value);
+ if (actual_value != hashed_value_)
+ return true;
+ return context->ContinueExecution();
+ }
+
+ private:
+ std::string hashed_value_;
+ DISALLOW_COPY_AND_ASSIGN(CompareNodeHash);
+};
+
+class StopExecutingSentenceOperation : public Operation {
+ public:
+ StopExecutingSentenceOperation() {}
+ virtual ~StopExecutingSentenceOperation() {}
+ virtual bool Execute(ExecutionContext* context) OVERRIDE {
+ return false;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StopExecutingSentenceOperation);
+};
+
+class Parser {
+ public:
+ explicit Parser(const std::string& program)
+ : program_(program),
+ next_instruction_index_(0u) {}
+ ~Parser() {}
+ bool ParseNextSentence(ScopedVector<Operation>* output) {
+ ScopedVector<Operation> operators;
+ bool sentence_ended = false;
+ while (next_instruction_index_ < program_.size() && !sentence_ended) {
+ uint8 op_code = 0;
+ if (!ReadOpCode(&op_code))
+ return false;
+ switch (static_cast<jtl_foundation::OpCodes>(op_code)) {
+ case jtl_foundation::NAVIGATE: {
+ std::string hashed_key;
+ if (!ReadHash(&hashed_key))
+ return false;
+ operators.push_back(new NavigateOperation(hashed_key));
+ break;
+ }
+ case jtl_foundation::NAVIGATE_ANY:
+ operators.push_back(new NavigateAnyOperation);
+ break;
+ case jtl_foundation::NAVIGATE_BACK:
+ operators.push_back(new NavigateBackOperation);
+ break;
+ case jtl_foundation::STORE_BOOL: {
+ std::string hashed_name;
+ if (!ReadHash(&hashed_name) || !IsStringUTF8(hashed_name))
+ return false;
+ bool value = false;
+ if (!ReadBool(&value))
+ return false;
+ operators.push_back(new StoreValue(
+ hashed_name,
+ scoped_ptr<Value>(new base::FundamentalValue(value))));
+ break;
+ }
+ case jtl_foundation::COMPARE_STORED_BOOL: {
+ std::string hashed_name;
+ if (!ReadHash(&hashed_name) || !IsStringUTF8(hashed_name))
+ return false;
+ bool value = false;
+ if (!ReadBool(&value))
+ return false;
+ bool default_value = false;
+ if (!ReadBool(&default_value))
+ return false;
+ operators.push_back(new CompareStoredValue(
+ hashed_name,
+ scoped_ptr<Value>(new base::FundamentalValue(value)),
+ scoped_ptr<Value>(new base::FundamentalValue(default_value))));
+ break;
+ }
+ case jtl_foundation::STORE_HASH: {
+ std::string hashed_name;
+ if (!ReadHash(&hashed_name) || !IsStringUTF8(hashed_name))
+ return false;
+ std::string hashed_value;
+ if (!ReadHash(&hashed_value))
+ return false;
+ operators.push_back(new StoreValue(
+ hashed_name,
+ scoped_ptr<Value>(new base::StringValue(hashed_value))));
+ break;
+ }
+ case jtl_foundation::COMPARE_STORED_HASH: {
+ std::string hashed_name;
+ if (!ReadHash(&hashed_name) || !IsStringUTF8(hashed_name))
+ return false;
+ std::string hashed_value;
+ if (!ReadHash(&hashed_value))
+ return false;
+ std::string hashed_default_value;
+ if (!ReadHash(&hashed_default_value))
+ return false;
+ operators.push_back(new CompareStoredValue(
+ hashed_name,
+ scoped_ptr<Value>(new base::StringValue(hashed_value)),
+ scoped_ptr<Value>(new base::StringValue(hashed_default_value))));
+ break;
+ }
+ case jtl_foundation::COMPARE_NODE_BOOL: {
+ bool value = false;
+ if (!ReadBool(&value))
+ return false;
+ operators.push_back(new CompareNodeBool(value));
+ break;
+ }
+ case jtl_foundation::COMPARE_NODE_HASH: {
+ std::string hashed_value;
+ if (!ReadHash(&hashed_value))
+ return false;
+ operators.push_back(new CompareNodeHash(hashed_value));
+ break;
+ }
+ case jtl_foundation::STOP_EXECUTING_SENTENCE:
+ operators.push_back(new StopExecutingSentenceOperation);
+ break;
+ case jtl_foundation::END_OF_SENTENCE:
+ sentence_ended = true;
+ break;
+ default:
+ return false;
+ }
+ }
+ output->swap(operators);
+ return true;
+ }
+
+ bool HasNextSentence() const {
+ return next_instruction_index_ < program_.size();
+ }
+
+ private:
+ // Reads an uint8 and returns whether this operation was successful.
+ bool ReadUint8(uint8* out) {
+ if (next_instruction_index_ + 1u > program_.size())
+ return false;
+ *out = static_cast<uint8>(program_[next_instruction_index_]);
+ ++next_instruction_index_;
+ return true;
+ }
+
+ // Reads an operator code and returns whether this operation was successful.
+ bool ReadOpCode(uint8* out) { return ReadUint8(out); }
+
+ bool ReadHash(std::string* out) {
+ if (next_instruction_index_ + jtl_foundation::kHashSizeInBytes >
+ program_.size()) {
+ return false;
+ }
+ char buffer[jtl_foundation::kHashSizeInBytes];
+ for (size_t i = 0; i < arraysize(buffer); ++i) {
+ buffer[i] = program_[next_instruction_index_];
+ ++next_instruction_index_;
+ }
+ *out = std::string(buffer, arraysize(buffer));
+ return true;
+ }
+
+ bool ReadBool(bool* out) {
+ uint8 value = 0;
+ if (!ReadUint8(&value))
+ return false;
+ if (value == 0)
+ *out = false;
+ else if (value == 1)
+ *out = true;
+ else
+ return false;
+ return true;
+ }
+
+ std::string program_;
+ size_t next_instruction_index_;
+ DISALLOW_COPY_AND_ASSIGN(Parser);
+};
+
+} // namespace
+
+JtlInterpreter::JtlInterpreter(
+ const std::string& hasher_seed,
+ const std::string& program,
+ const DictionaryValue* input)
+ : hasher_seed_(hasher_seed),
+ program_(program),
+ input_(input),
+ working_memory_(new DictionaryValue),
+ result_(OK) {
+ DCHECK(input->IsType(Value::TYPE_DICTIONARY));
+}
+
+JtlInterpreter::~JtlInterpreter() {}
+
+void JtlInterpreter::Execute() {
+ jtl_foundation::Hasher hasher(hasher_seed_);
+ Parser parser(program_);
+ while (parser.HasNextSentence()) {
+ ScopedVector<Operation> sentence;
+ if (!parser.ParseNextSentence(&sentence)) {
+ result_ = PARSE_ERROR;
+ return;
+ }
+ ExecutionContext context(
+ &hasher, sentence.get(), input_, working_memory_.get());
+ context.ContinueExecution();
+ if (context.error()) {
+ result_ = RUNTIME_ERROR;
+ return;
+ }
+ }
+}
+
+bool JtlInterpreter::GetOutputBoolean(const std::string& unhashed_key,
+ bool* output) const {
+ std::string hashed_key =
+ jtl_foundation::Hasher(hasher_seed_).GetHash(unhashed_key);
+ return working_memory_->GetBoolean(hashed_key, output);
+}
+
+bool JtlInterpreter::GetOutputString(const std::string& unhashed_key,
+ std::string* output) const {
+ std::string hashed_key =
+ jtl_foundation::Hasher(hasher_seed_).GetHash(unhashed_key);
+ return working_memory_->GetString(hashed_key, output);
+}
diff --git a/chrome/browser/profile_resetter/jtl_interpreter.h b/chrome/browser/profile_resetter/jtl_interpreter.h
new file mode 100644
index 0000000..4bb4219
--- /dev/null
+++ b/chrome/browser/profile_resetter/jtl_interpreter.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_BROWSER_PROFILE_RESETTER_JTL_INTERPRETER_H_
+#define CHROME_BROWSER_PROFILE_RESETTER_JTL_INTERPRETER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/values.h"
+
+// Executes a JTL program on a given dictionary.
+//
+// JTL (Json Traversal Language) programs are defined in jtl_foundation.h
+class JtlInterpreter {
+ public:
+ enum Result {
+ OK,
+ PARSE_ERROR,
+ RUNTIME_ERROR,
+ };
+
+ // |hasher_seed| is a value used in jtl_foundation::Hasher. All node names,
+ // strings, integers and doubles are hashed before being compared to hash
+ // values listed in |program|.
+ // |program| is a byte array containing a JTL program.
+ // |input| is a dictionary on which the program is evaluated.
+ JtlInterpreter(const std::string& hasher_seed,
+ const std::string& program,
+ const DictionaryValue* input);
+ ~JtlInterpreter();
+
+ void Execute();
+
+ Result result() const { return result_; }
+ const DictionaryValue* working_memory() const {
+ return working_memory_.get();
+ }
+ bool GetOutputBoolean(const std::string& unhashed_key, bool* output) const;
+ bool GetOutputString(const std::string& unhashed_key,
+ std::string* output) const;
+
+ private:
+ // Input.
+ std::string hasher_seed_;
+ std::string program_;
+ const DictionaryValue* input_;
+ // Output.
+ scoped_ptr<DictionaryValue> working_memory_;
+ Result result_;
+
+ DISALLOW_COPY_AND_ASSIGN(JtlInterpreter);
+};
+
+#endif // CHROME_BROWSER_PROFILE_RESETTER_JTL_INTERPRETER_H_
diff --git a/chrome/browser/profile_resetter/jtl_interpreter_unittest.cc b/chrome/browser/profile_resetter/jtl_interpreter_unittest.cc
new file mode 100644
index 0000000..b4fb448
--- /dev/null
+++ b/chrome/browser/profile_resetter/jtl_interpreter_unittest.cc
@@ -0,0 +1,359 @@
+// Copyright 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/profile_resetter/jtl_interpreter.h"
+
+#include "base/strings/string_util.h"
+#include "base/test/values_test_util.h"
+#include "chrome/browser/profile_resetter/jtl_foundation.h"
+#include "chrome/browser/profile_resetter/jtl_instructions.h"
+#include "crypto/hmac.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char seed[] = "foobar";
+
+#define KEY_HASH_1 GetHash("KEY_HASH_1")
+#define KEY_HASH_2 GetHash("KEY_HASH_2")
+#define KEY_HASH_3 GetHash("KEY_HASH_3")
+#define KEY_HASH_4 GetHash("KEY_HASH_4")
+
+#define VALUE_HASH_1 GetHash("VALUE_HASH_1")
+#define VALUE_HASH_2 GetHash("VALUE_HASH_2")
+
+#define VAR_HASH_1 "01234567890123456789012345678901"
+#define VAR_HASH_2 "12345678901234567890123456789012"
+
+std::string GetHash(const std::string& input) {
+ return jtl_foundation::Hasher(seed).GetHash(input);
+}
+
+// escaped_json_param may contain ' characters that are replaced with ". This
+// makes the code more readable because we need less escaping.
+#define INIT_INTERPRETER(program_param, escaped_json_param) \
+ const char* escaped_json = escaped_json_param; \
+ std::string json; \
+ ReplaceChars(escaped_json, "'", "\"", &json); \
+ scoped_ptr<Value> json_value(ParseJson(json)); \
+ JtlInterpreter interpreter( \
+ seed, \
+ program_param, \
+ static_cast<const DictionaryValue*>(json_value.get())); \
+ interpreter.Execute()
+
+using base::test::ParseJson;
+
+TEST(JtlInterpreter, Store) {
+ INIT_INTERPRETER(
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ "{ 'KEY_HASH_1': 'VALUE_HASH_1' }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+}
+
+TEST(JtlInterpreter, NavigateAndStore) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ "{ 'KEY_HASH_1': 'VALUE_HASH_1' }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+}
+
+TEST(JtlInterpreter, FailNavigate) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ "{ 'KEY_HASH_1': 'VALUE_HASH_1' }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
+}
+
+TEST(JtlInterpreter, ConsecutiveNavigate) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+}
+
+TEST(JtlInterpreter, FailConsecutiveNavigate) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ "{ 'KEY_HASH_1': 'foo' }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
+}
+
+TEST(JtlInterpreter, NavigateAnyInDictionary) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE_ANY +
+ OP_NAVIGATE(KEY_HASH_4) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ "{ 'KEY_HASH_1':"
+ " { 'KEY_HASH_2': {'KEY_HASH_3': 'VALUE_HASH_1' },"
+ " 'KEY_HASH_3': {'KEY_HASH_4': 'VALUE_HASH_1' }"
+ " } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+}
+
+TEST(JtlInterpreter, NavigateAnyInList) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE_ANY +
+ OP_NAVIGATE(KEY_HASH_4) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ "{ 'KEY_HASH_1':"
+ " [ {'KEY_HASH_3': 'VALUE_HASH_1' },"
+ " {'KEY_HASH_4': 'VALUE_HASH_1' }"
+ " ] }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+}
+
+TEST(JtlInterpreter, NavigateBack) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_NAVIGATE_BACK +
+ OP_NAVIGATE(KEY_HASH_3) +
+ OP_NAVIGATE(KEY_HASH_4) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ "{ 'KEY_HASH_1':"
+ " { 'KEY_HASH_2': {'KEY_HASH_3': 'VALUE_HASH_1' },"
+ " 'KEY_HASH_3': {'KEY_HASH_4': 'VALUE_HASH_1' }"
+ " } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+}
+
+TEST(JtlInterpreter, StoreTwoValues) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
+ OP_STORE_HASH(VAR_HASH_2, VALUE_HASH_1),
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+ base::ExpectDictStringValue(VALUE_HASH_1, *interpreter.working_memory(),
+ VAR_HASH_2);
+}
+
+TEST(JtlInterpreter, CompareStoredMatch) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_FALSE) +
+ OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2);
+}
+
+TEST(JtlInterpreter, CompareStoredMismatch) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_FALSE, VALUE_TRUE) +
+ OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+ EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
+}
+
+TEST(JtlInterpreter, CompareStoredNoValueMatchingDefault) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_TRUE) +
+ OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2);
+}
+
+TEST(JtlInterpreter, CompareStoredNoValueMismatchingDefault) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_FALSE) +
+ OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
+}
+
+TEST(JtlInterpreter, CompareBoolMatch) {
+ struct TestCase {
+ std::string expected_value;
+ const char* json;
+ bool expected_success;
+ } cases[] = {
+ { VALUE_TRUE, "{ 'KEY_HASH_1': true }", true },
+ { VALUE_FALSE, "{ 'KEY_HASH_1': false }", true },
+ { VALUE_TRUE, "{ 'KEY_HASH_1': 'abc' }", false },
+ { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false },
+ { VALUE_TRUE, "{ 'KEY_HASH_1': 1.2 }", false },
+ { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false },
+ { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
+ SCOPED_TRACE(testing::Message() << "Iteration " << i);
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_COMPARE_NODE_BOOL(cases[i].expected_value) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ cases[i].json);
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ if (cases[i].expected_success) {
+ base::ExpectDictBooleanValue(
+ true, *interpreter.working_memory(), VAR_HASH_1);
+ } else {
+ EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
+ }
+ }
+}
+
+TEST(JtlInterpreter, CompareHashString) {
+ struct TestCase {
+ std::string expected_value;
+ const char* json;
+ bool expected_success;
+ } cases[] = {
+ { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true },
+ { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false },
+ { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false },
+ { VALUE_HASH_1, "{ 'KEY_HASH_1': 1 }", false },
+ { VALUE_HASH_1, "{ 'KEY_HASH_1': 1.1 }", false },
+ { VALUE_HASH_1, "{ 'KEY_HASH_1': [1] }", false },
+ { VALUE_HASH_1, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
+
+ { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true },
+ { GetHash("1.2"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
+ { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false },
+ { GetHash("1.2"), "{ 'KEY_HASH_1': 1 }", false },
+ { GetHash("1.2"), "{ 'KEY_HASH_1': 1.3 }", false },
+ { GetHash("1.2"), "{ 'KEY_HASH_1': [1] }", false },
+ { GetHash("1.2"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
+
+ { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true },
+ { GetHash("1"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
+ { GetHash("1"), "{ 'KEY_HASH_1': true }", false },
+ { GetHash("1"), "{ 'KEY_HASH_1': 2 }", false },
+ { GetHash("1"), "{ 'KEY_HASH_1': 1.1 }", false },
+ { GetHash("1"), "{ 'KEY_HASH_1': [1] }", false },
+ { GetHash("1"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
+ SCOPED_TRACE(testing::Message() << "Iteration " << i);
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_COMPARE_NODE_HASH(cases[i].expected_value) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
+ cases[i].json);
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ if (cases[i].expected_success) {
+ base::ExpectDictBooleanValue(
+ true, *interpreter.working_memory(), VAR_HASH_1);
+ } else {
+ EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
+ }
+ }
+}
+
+TEST(JtlInterpreter, Stop) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
+ OP_STOP_EXECUTING_SENTENCE +
+ OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+ EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
+}
+
+TEST(JtlInterpreter, EndOfSentence) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE(KEY_HASH_2) +
+ OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
+ OP_END_OF_SENTENCE +
+ OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
+ base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2);
+}
+
+TEST(JtlInterpreter, InvalidBack) {
+ INIT_INTERPRETER(
+ OP_NAVIGATE(KEY_HASH_1) +
+ OP_NAVIGATE_BACK +
+ OP_NAVIGATE_BACK,
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::RUNTIME_ERROR, interpreter.result());
+}
+
+TEST(JtlInterpreter, IncorrectPrograms) {
+ std::string missing_hash;
+ std::string missing_bool;
+ std::string invalid_hash("123");
+ std::string invalid_bool("\x02", 1);
+ std::string invalid_operation("\x99", 1);
+ std::string programs[] = {
+ OP_NAVIGATE(missing_hash),
+ OP_NAVIGATE(invalid_hash),
+ OP_STORE_BOOL(VAR_HASH_1, invalid_bool),
+ OP_STORE_BOOL(missing_hash, VALUE_TRUE),
+ OP_STORE_BOOL(invalid_hash, VALUE_TRUE),
+ OP_COMPARE_STORED_BOOL(invalid_hash, VALUE_TRUE, VALUE_TRUE),
+ OP_COMPARE_STORED_BOOL(VAR_HASH_1, invalid_bool, VALUE_TRUE),
+ OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, invalid_bool),
+ OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, missing_bool),
+ OP_COMPARE_NODE_BOOL(missing_bool),
+ OP_COMPARE_NODE_BOOL(invalid_bool),
+ OP_COMPARE_NODE_HASH(missing_hash),
+ OP_COMPARE_NODE_HASH(invalid_hash),
+ invalid_operation,
+ };
+ for (size_t i = 0; i < arraysize(programs); ++i) {
+ SCOPED_TRACE(testing::Message() << "Iteration " << i);
+ INIT_INTERPRETER(programs[i],
+ "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
+ EXPECT_EQ(JtlInterpreter::PARSE_ERROR, interpreter.result());
+ }
+}
+
+TEST(JtlInterpreter, GetOutput) {
+ INIT_INTERPRETER(
+ OP_STORE_BOOL(GetHash("output1"), VALUE_TRUE) +
+ OP_STORE_HASH(GetHash("output2"), VALUE_HASH_1),
+ "{}");
+ bool output1 = false;
+ std::string output2;
+ EXPECT_TRUE(interpreter.GetOutputBoolean("output1", &output1));
+ EXPECT_EQ(true, output1);
+ EXPECT_TRUE(interpreter.GetOutputString("output2", &output2));
+ EXPECT_EQ(VALUE_HASH_1, output2);
+ EXPECT_FALSE(interpreter.GetOutputBoolean("outputxx", &output1));
+ EXPECT_FALSE(interpreter.GetOutputString("outputxx", &output2));
+}
+
+} // namespace
diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
index 00cc474..43d5a2e 100644
--- a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
+++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
@@ -77,18 +77,12 @@
void ResettableSettingsSnapshot::Subtract(
const ResettableSettingsSnapshot& snapshot) {
- std::vector<GURL> urls;
- std::set_difference(startup_.urls.begin(), startup_.urls.end(),
- snapshot.startup_.urls.begin(),
- snapshot.startup_.urls.end(),
- std::back_inserter(urls));
+ std::vector<GURL> urls = base::STLSetDifference<std::vector<GURL> >(
+ startup_.urls, snapshot.startup_.urls);
startup_.urls.swap(urls);
- ExtensionList extensions;
- std::set_difference(enabled_extensions_.begin(), enabled_extensions_.end(),
- snapshot.enabled_extensions_.begin(),
- snapshot.enabled_extensions_.end(),
- std::back_inserter(extensions));
+ ExtensionList extensions = base::STLSetDifference<ExtensionList>(
+ enabled_extensions_, snapshot.enabled_extensions_);
enabled_extensions_.swap(extensions);
}
diff --git a/chrome/browser/profiles/avatar_menu.cc b/chrome/browser/profiles/avatar_menu.cc
new file mode 100644
index 0000000..cbb2a96
--- /dev/null
+++ b/chrome/browser/profiles/avatar_menu.cc
@@ -0,0 +1,255 @@
+// 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/profiles/avatar_menu.h"
+
+#include "base/bind.h"
+#include "base/i18n/case_conversion.h"
+#include "base/metrics/field_trial.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/profiles/avatar_menu_actions.h"
+#include "chrome/browser/profiles/avatar_menu_observer.h"
+#include "chrome/browser/profiles/profile_list.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_metrics.h"
+#include "chrome/browser/profiles/profile_window.h"
+#include "chrome/browser/profiles/profiles_state.h"
+#include "chrome/browser/ui/ash/chrome_shell_delegate.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/host_desktop.h"
+#include "chrome/browser/ui/startup/startup_browser_creator.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.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(ENABLE_MANAGED_USERS)
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/managed_mode/managed_user_service_factory.h"
+#endif
+
+using content::BrowserThread;
+
+namespace {
+
+void OnProfileCreated(bool always_create,
+ chrome::HostDesktopType desktop_type,
+ Profile* profile,
+ Profile::CreateStatus status) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (status == Profile::CREATE_STATUS_INITIALIZED) {
+ profiles::FindOrCreateNewWindowForProfile(
+ profile,
+ chrome::startup::IS_NOT_PROCESS_STARTUP,
+ chrome::startup::IS_NOT_FIRST_RUN,
+ desktop_type,
+ always_create);
+ }
+}
+
+// Constants for the show profile switcher experiment
+const char kShowProfileSwitcherFieldTrialName[] = "ShowProfileSwitcher";
+const char kAlwaysShowSwitcherGroupName[] = "AlwaysShow";
+
+} // namespace
+
+AvatarMenu::AvatarMenu(ProfileInfoInterface* profile_cache,
+ AvatarMenuObserver* observer,
+ Browser* browser)
+ : profile_list_(ProfileList::Create(profile_cache)),
+ menu_actions_(AvatarMenuActions::Create()),
+ profile_info_(profile_cache),
+ observer_(observer),
+ browser_(browser) {
+ DCHECK(profile_info_);
+ // Don't DCHECK(browser_) so that unit tests can reuse this ctor.
+
+ ActiveBrowserChanged(browser_);
+
+ // Register this as an observer of the info cache.
+ registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
+ content::NotificationService::AllSources());
+}
+
+AvatarMenu::~AvatarMenu() {
+}
+
+AvatarMenu::Item::Item(size_t menu_index,
+ size_t profile_index,
+ const gfx::Image& icon)
+ : icon(icon),
+ active(false),
+ signed_in(false),
+ signin_required(false),
+ menu_index(menu_index),
+ profile_index(profile_index) {
+}
+
+AvatarMenu::Item::~Item() {
+}
+
+// static
+bool AvatarMenu::ShouldShowAvatarMenu() {
+ if (base::FieldTrialList::FindFullName(kShowProfileSwitcherFieldTrialName) ==
+ kAlwaysShowSwitcherGroupName) {
+ // We should only be in this group when multi-profiles is enabled.
+ DCHECK(profiles::IsMultipleProfilesEnabled());
+ return true;
+ }
+
+ // TODO: Eliminate this ifdef. Add a delegate interface for the menu which
+ // would also help remove the Browser dependency in AvatarMenuActions
+ // implementations.
+ if (profiles::IsMultipleProfilesEnabled()) {
+#if defined(OS_CHROMEOS)
+ // On ChromeOS the menu will be always visible when it is possible to have
+ // two users logged in at the same time.
+ return ChromeShellDelegate::instance() &&
+ ChromeShellDelegate::instance()->IsMultiProfilesEnabled();
+#else
+ return profiles::IsNewProfileManagementEnabled() ||
+ (g_browser_process->profile_manager() &&
+ g_browser_process->profile_manager()->GetNumberOfProfiles() > 1);
+#endif
+ }
+ return false;
+}
+
+bool AvatarMenu::CompareItems(const Item* item1, const Item* item2) {
+ return base::i18n::ToLower(item1->name).compare(
+ base::i18n::ToLower(item2->name)) < 0;
+}
+
+// static
+void AvatarMenu::SwitchToGuestProfileWindow(Browser* browser) {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ profile_manager->CreateProfileAsync(ProfileManager::GetGuestProfilePath(),
+ base::Bind(&OnProfileCreated,
+ false,
+ browser->host_desktop_type()),
+ string16(),
+ string16(),
+ std::string());
+}
+
+void AvatarMenu::SwitchToProfile(size_t index, bool always_create) {
+ DCHECK(profiles::IsMultipleProfilesEnabled() ||
+ index == GetActiveProfileIndex());
+ const Item& item = GetItemAt(index);
+ base::FilePath path =
+ profile_info_->GetPathOfProfileAtIndex(item.profile_index);
+
+ chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
+ if (browser_)
+ desktop_type = browser_->host_desktop_type();
+
+ profiles::SwitchToProfile(path, desktop_type, always_create);
+ ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_ICON);
+}
+
+void AvatarMenu::AddNewProfile(ProfileMetrics::ProfileAdd type) {
+ menu_actions_->AddNewProfile(type);
+}
+
+void AvatarMenu::EditProfile(size_t index) {
+ // Get the index in the profile cache from the menu index.
+ size_t profile_index = profile_list_->GetItemAt(index).profile_index;
+
+ Profile* profile = g_browser_process->profile_manager()->GetProfileByPath(
+ profile_info_->GetPathOfProfileAtIndex(profile_index));
+
+ menu_actions_->EditProfile(profile, profile_index);
+}
+
+void AvatarMenu::RebuildMenu() {
+ profile_list_->RebuildMenu();
+}
+
+size_t AvatarMenu::GetNumberOfItems() const {
+ return profile_list_->GetNumberOfItems();
+}
+
+const AvatarMenu::Item& AvatarMenu::GetItemAt(size_t index) const {
+ return profile_list_->GetItemAt(index);
+}
+size_t AvatarMenu::GetActiveProfileIndex() {
+
+ // During singleton profile deletion, this function can be called with no
+ // profiles in the model - crbug.com/102278 .
+ if (profile_list_->GetNumberOfItems() == 0)
+ return 0;
+
+ Profile* active_profile = NULL;
+ if (!browser_)
+ active_profile = ProfileManager::GetLastUsedProfile();
+ else
+ active_profile = browser_->profile();
+
+ size_t index =
+ profile_info_->GetIndexOfProfileWithPath(active_profile->GetPath());
+
+ index = profile_list_->MenuIndexFromProfileIndex(index);
+ DCHECK_LT(index, profile_list_->GetNumberOfItems());
+ return index;
+}
+
+base::string16 AvatarMenu::GetManagedUserInformation() const {
+ // |browser_| can be NULL in unit_tests.
+ if (browser_ && browser_->profile()->IsManaged()) {
+#if defined(ENABLE_MANAGED_USERS)
+ ManagedUserService* service = ManagedUserServiceFactory::GetForProfile(
+ browser_->profile());
+ base::string16 custodian = UTF8ToUTF16(service->GetCustodianEmailAddress());
+ return l10n_util::GetStringFUTF16(IDS_MANAGED_USER_INFO, custodian);
+#endif
+ }
+ return base::string16();
+}
+
+const gfx::Image& AvatarMenu::GetManagedUserIcon() const {
+ return ResourceBundle::GetSharedInstance().GetNativeImageNamed(
+ IDR_MANAGED_USER_ICON);
+}
+
+void AvatarMenu::ActiveBrowserChanged(Browser* browser) {
+ browser_ = browser;
+ menu_actions_->ActiveBrowserChanged(browser);
+
+ // If browser is not NULL, get the path of its active profile.
+ base::FilePath path;
+ if (browser)
+ path = browser->profile()->GetPath();
+ profile_list_->ActiveProfilePathChanged(path);
+}
+
+bool AvatarMenu::ShouldShowAddNewProfileLink() const {
+ return menu_actions_->ShouldShowAddNewProfileLink();
+}
+
+bool AvatarMenu::ShouldShowEditProfileLink() const {
+ return menu_actions_->ShouldShowEditProfileLink();
+}
+
+void AvatarMenu::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, type);
+ RebuildMenu();
+ if (observer_)
+ observer_->OnAvatarMenuChanged(this);
+}
+
+content::WebContents* AvatarMenu::BeginSignOut() {
+ return menu_actions_->BeginSignOut();
+}
+
+void AvatarMenu::SetLogoutURL(const std::string& logout_url) {
+ menu_actions_->SetLogoutURL(logout_url);
+}
diff --git a/chrome/browser/profiles/avatar_menu.h b/chrome/browser/profiles/avatar_menu.h
new file mode 100644
index 0000000..8e12e2a
--- /dev/null
+++ b/chrome/browser/profiles/avatar_menu.h
@@ -0,0 +1,169 @@
+// 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_PROFILES_AVATAR_MENU_H_
+#define CHROME_BROWSER_PROFILES_AVATAR_MENU_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/profiles/profile_metrics.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "ui/gfx/image/image.h"
+
+class AvatarMenuObserver;
+class Browser;
+class Profile;
+class ProfileInfoInterface;
+class ProfileList;
+class AvatarMenuActions;
+
+// This class represents the menu-like interface used to select profiles,
+// such as the bubble that appears when the avatar icon is clicked in the
+// browser window frame. This class will notify its observer when the backend
+// data changes, and the view for this model should forward actions
+// back to it in response to user events.
+class AvatarMenu : public content::NotificationObserver {
+ public:
+ // Represents an item in the menu.
+ struct Item {
+ Item(size_t menu_index, size_t profile_index, const gfx::Image& icon);
+ ~Item();
+
+ // The icon to be displayed next to the item.
+ gfx::Image icon;
+
+ // Whether or not the current browser is using this profile.
+ bool active;
+
+ // The name of this profile.
+ string16 name;
+
+ // A string representing the sync state of the profile.
+ string16 sync_state;
+
+ // Whether or not the current profile is signed in. If true, |sync_state| is
+ // expected to be the email of the signed in user.
+ bool signed_in;
+
+ // Whether or not the current profile requires sign-in before use.
+ bool signin_required;
+
+ // Whether or not the current profile is a managed user
+ // (see ManagedUserService).
+ bool managed;
+
+ // The index in the menu of this profile, used by views to refer to
+ // profiles.
+ size_t menu_index;
+
+ // The index in the |profile_cache| for this profile.
+ size_t profile_index;
+ };
+
+ // Constructor. |observer| can be NULL. |browser| can be NULL and a new one
+ // will be created if an action requires it.
+ AvatarMenu(ProfileInfoInterface* profile_cache,
+ AvatarMenuObserver* observer,
+ Browser* browser);
+ virtual ~AvatarMenu();
+
+ // True if avatar menu should be displayed.
+ static bool ShouldShowAvatarMenu();
+
+ // Sets |image| to the image corresponding to the given profile, and
+ // sets |is_rectangle| to true unless |image| is a built-in profile avatar.
+ static void GetImageForMenuButton(Profile* profile,
+ gfx::Image* image,
+ bool* is_rectangle);
+
+ // Compare items by name.
+ static bool CompareItems(const Item* item1, const Item* item2);
+
+ // Creates a new guest user window.
+ static void SwitchToGuestProfileWindow(Browser* browser);
+
+ // Opens a Browser with the specified profile in response to the user
+ // selecting an item. If |always_create| is true then a new window is created
+ // even if a window for that profile already exists.
+ void SwitchToProfile(size_t index, bool always_create);
+
+ // Creates a new profile.
+ void AddNewProfile(ProfileMetrics::ProfileAdd type);
+
+ // Opens the profile settings in response to clicking the edit button next to
+ // an item.
+ void EditProfile(size_t index);
+
+ // Rebuilds the menu from the cache.
+ void RebuildMenu();
+
+ // Gets the number of profiles.
+ size_t GetNumberOfItems() const;
+
+ // Gets the Item at the specified index.
+ const Item& GetItemAt(size_t index) const;
+
+ // Returns the index of the active profile.
+ size_t GetActiveProfileIndex();
+
+ // Returns information about a managed user which will be displayed in the
+ // avatar menu. If the profile does not belong to a managed user, an empty
+ // string will be returned.
+ base::string16 GetManagedUserInformation() const;
+
+ // Returns the icon for the managed user which will be displayed in the
+ // avatar menu.
+ const gfx::Image& GetManagedUserIcon() const;
+
+ // This menu is also used for the always-present Mac system menubar. If the
+ // last active browser changes, the menu will need to reference that browser.
+ void ActiveBrowserChanged(Browser* browser);
+
+ // Start the sign-out process for this profile.
+ content::WebContents* BeginSignOut();
+
+ // Use a different URL for logout (for testing only).
+ void SetLogoutURL(const std::string& logout_url);
+
+ // Returns true if the add profile link should be shown.
+ bool ShouldShowAddNewProfileLink() const;
+
+ // Returns true if the edit profile link should be shown.
+ bool ShouldShowEditProfileLink() const;
+
+ // content::NotificationObserver:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ // The model that provides the list of menu items.
+ scoped_ptr<ProfileList> profile_list_;
+
+ // The controller for avatar menu actions.
+ scoped_ptr<AvatarMenuActions> menu_actions_;
+
+ // The cache that provides the profile information. Weak.
+ ProfileInfoInterface* profile_info_;
+
+ // The observer of this model, which is notified of changes. Weak.
+ AvatarMenuObserver* observer_;
+
+ // Browser in which this avatar menu resides. Weak.
+ Browser* browser_;
+
+ // Listens for notifications from the ProfileInfoCache.
+ content::NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(AvatarMenu);
+};
+
+#endif // CHROME_BROWSER_PROFILES_AVATAR_MENU_H_
diff --git a/chrome/browser/profiles/avatar_menu_actions.h b/chrome/browser/profiles/avatar_menu_actions.h
new file mode 100644
index 0000000..934cac9
--- /dev/null
+++ b/chrome/browser/profiles/avatar_menu_actions.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_PROFILES_AVATAR_MENU_ACTIONS_H_
+#define CHROME_BROWSER_PROFILES_AVATAR_MENU_ACTIONS_H_
+
+#include <string>
+
+#include "chrome/browser/profiles/avatar_menu.h"
+#include "chrome/browser/profiles/profile_metrics.h"
+
+class Profile;
+
+// This interface controls the behavior of avatar menu actions.
+class AvatarMenuActions {
+ public:
+ virtual ~AvatarMenuActions() {}
+
+ static AvatarMenuActions* Create();
+
+ // Allows the user to create a new profile.
+ virtual void AddNewProfile(ProfileMetrics::ProfileAdd type) = 0;
+
+ // Allows the user to edit the profile at the given index in the cache.
+ virtual void EditProfile(Profile* profile, size_t index) = 0;
+
+ // Returns true if the add profile link should be shown.
+ virtual bool ShouldShowAddNewProfileLink() const = 0;
+
+ // Returns true if the edit profile link should be shown.
+ virtual bool ShouldShowEditProfileLink() const = 0;
+
+ // Starts the sign-out process for this profile.
+ virtual content::WebContents* BeginSignOut() = 0;
+
+ // Sets a different URL to use for logout (for testing only).
+ virtual void SetLogoutURL(const std::string& logout_url) = 0;
+
+ // Updates the browser.
+ // TODO: Delegate browser actions to remove dependency on Browser class.
+ virtual void ActiveBrowserChanged(Browser* browser) = 0;
+};
+
+#endif // CHROME_BROWSER_PROFILES_AVATAR_MENU_ACTIONS_H_
diff --git a/chrome/browser/profiles/avatar_menu_actions_desktop.cc b/chrome/browser/profiles/avatar_menu_actions_desktop.cc
new file mode 100644
index 0000000..e14f796
--- /dev/null
+++ b/chrome/browser/profiles/avatar_menu_actions_desktop.cc
@@ -0,0 +1,148 @@
+// Copyright 2013 The Chromium 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/avatar_menu_actions_desktop.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/browser_process.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/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/site_instance.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "net/base/url_util.h"
+
+namespace {
+
+class SignoutTracker : public content::WebContentsObserver {
+ public:
+ SignoutTracker(Profile* profile, const GURL& signout_landing_url,
+ content::WebContents* contents);
+
+ virtual void WebContentsDestroyed(content::WebContents* contents) OVERRIDE;
+ virtual void DidStopLoading(content::RenderViewHost* render_view_host)
+ OVERRIDE;
+
+ private:
+ scoped_ptr<content::WebContents> contents_;
+ GURL signout_landing_url_;
+ Profile* profile_;
+
+ DISALLOW_COPY_AND_ASSIGN(SignoutTracker);
+};
+
+SignoutTracker::SignoutTracker(Profile* profile,
+ const GURL& signout_landing_url,
+ content::WebContents* contents)
+ : WebContentsObserver(contents),
+ contents_(contents),
+ signout_landing_url_(signout_landing_url),
+ profile_(profile) {
+}
+
+void SignoutTracker::DidStopLoading(content::RenderViewHost* render_view_host) {
+ // Only close when we reach the final landing; ignore redirects until then.
+ if (web_contents()->GetURL() == signout_landing_url_) {
+ Observe(NULL);
+ BrowserList::CloseAllBrowsersWithProfile(profile_);
+ delete this; /* success */
+ }
+}
+
+void SignoutTracker::WebContentsDestroyed(content::WebContents* contents) {
+ delete this; /* failure */
+}
+
+} // namespace
+
+AvatarMenuActionsDesktop::AvatarMenuActionsDesktop() {
+}
+
+AvatarMenuActionsDesktop::~AvatarMenuActionsDesktop() {
+}
+
+// static
+AvatarMenuActions* AvatarMenuActions::Create() {
+ return new AvatarMenuActionsDesktop();
+}
+
+void AvatarMenuActionsDesktop::AddNewProfile(ProfileMetrics::ProfileAdd type) {
+ // TODO: Remove dependency on Browser by delegating AddNewProfile and
+ // and EditProfile actions.
+
+ Browser* settings_browser = browser_;
+ if (!settings_browser) {
+ const Browser::CreateParams params(ProfileManager::GetLastUsedProfile(),
+ chrome::GetActiveDesktop());
+ settings_browser = new Browser(params);
+ }
+ chrome::ShowSettingsSubPage(settings_browser, chrome::kCreateProfileSubPage);
+ ProfileMetrics::LogProfileAddNewUser(type);
+}
+
+void AvatarMenuActionsDesktop::EditProfile(Profile* profile, size_t index) {
+ Browser* settings_browser = browser_;
+ if (!settings_browser) {
+ settings_browser = new Browser(
+ Browser::CreateParams(profile, chrome::GetActiveDesktop()));
+ }
+ std::string page = chrome::kManageProfileSubPage;
+ page += "#";
+ page += base::IntToString(static_cast<int>(index));
+ chrome::ShowSettingsSubPage(settings_browser, page);
+}
+
+bool AvatarMenuActionsDesktop::ShouldShowAddNewProfileLink() const {
+ // |browser_| can be NULL in unit_tests.
+ return !browser_ || !browser_->profile()->IsManaged();
+}
+
+bool AvatarMenuActionsDesktop::ShouldShowEditProfileLink() const {
+ return true;
+}
+
+content::WebContents* AvatarMenuActionsDesktop::BeginSignOut() {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ Profile* current_profile = browser_->profile();
+
+ ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
+ size_t index = cache.GetIndexOfProfileWithPath(current_profile->GetPath());
+ cache.SetProfileSigninRequiredAtIndex(index, true);
+
+ std::string landing_url = signin::GetLandingURL("close", 1).spec();
+ GURL logout_url(GaiaUrls::GetInstance()->service_logout_url());
+ logout_url = net::AppendQueryParameter(logout_url, "?continue=", landing_url);
+ if (!logout_override_.empty()) {
+ // We're testing...
+ landing_url = logout_override_;
+ logout_url = GURL(logout_override_);
+ }
+
+ content::WebContents::CreateParams create_params(current_profile);
+ create_params.site_instance =
+ content::SiteInstance::CreateForURL(current_profile, logout_url);
+ content::WebContents* contents = content::WebContents::Create(create_params);
+ contents->GetController().LoadURL(
+ logout_url, content::Referrer(),
+ content::PAGE_TRANSITION_GENERATED, std::string());
+
+ // This object may be destructed when the menu closes but we need something
+ // around to finish the sign-out process and close the profile windows.
+ new SignoutTracker(current_profile, GURL(landing_url), contents);
+
+ return contents; // returned for testing purposes
+}
+
+void AvatarMenuActionsDesktop::SetLogoutURL(const std::string& logout_url) {
+ logout_override_ = logout_url;
+}
+
+void AvatarMenuActionsDesktop::ActiveBrowserChanged(Browser* browser) {
+ browser_ = browser;
+}
diff --git a/chrome/browser/profiles/avatar_menu_actions_desktop.h b/chrome/browser/profiles/avatar_menu_actions_desktop.h
new file mode 100644
index 0000000..21a1e61
--- /dev/null
+++ b/chrome/browser/profiles/avatar_menu_actions_desktop.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_PROFILES_AVATAR_MENU_ACTIONS_DESKTOP_H_
+#define CHROME_BROWSER_PROFILES_AVATAR_MENU_ACTIONS_DESKTOP_H_
+
+#include <string>
+
+#include "chrome/browser/profiles/avatar_menu_actions.h"
+#include "chrome/browser/profiles/profile_metrics.h"
+
+class Profile;
+
+// This interface controls the behavior of avatar menu actions.
+class AvatarMenuActionsDesktop : public AvatarMenuActions {
+ public:
+ AvatarMenuActionsDesktop();
+ virtual ~AvatarMenuActionsDesktop();
+
+ // AvatarMenuActions overrides:
+ virtual void AddNewProfile(ProfileMetrics::ProfileAdd type) OVERRIDE;
+ virtual void EditProfile(Profile* profile, size_t index) OVERRIDE;
+ virtual bool ShouldShowAddNewProfileLink() const OVERRIDE;
+ virtual bool ShouldShowEditProfileLink() const OVERRIDE;
+ virtual content::WebContents* BeginSignOut() OVERRIDE;
+ virtual void SetLogoutURL(const std::string& logout_url) OVERRIDE;
+ virtual void ActiveBrowserChanged(Browser* browser) OVERRIDE;
+
+ private:
+ // Browser in which this avatar menu resides. Weak.
+ Browser* browser_;
+
+ // Special "override" logout URL used to let tests work.
+ std::string logout_override_;
+
+ DISALLOW_COPY_AND_ASSIGN(AvatarMenuActionsDesktop);
+};
+
+#endif // CHROME_BROWSER_PROFILES_AVATAR_MENU_ACTIONS_DESKTOP_H_
diff --git a/chrome/browser/profiles/avatar_menu_desktop.cc b/chrome/browser/profiles/avatar_menu_desktop.cc
new file mode 100644
index 0000000..35949a5
--- /dev/null
+++ b/chrome/browser/profiles/avatar_menu_desktop.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/profiles/avatar_menu.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
+#include "chrome/browser/profiles/profile_manager.h"
+
+// static
+void AvatarMenu::GetImageForMenuButton(Profile* profile,
+ gfx::Image* image,
+ bool* is_rectangle) {
+ ProfileInfoCache& cache =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ size_t index = cache.GetIndexOfProfileWithPath(profile->GetPath());
+ if (index == std::string::npos) {
+ NOTREACHED();
+ return;
+ }
+
+ *image = cache.GetAvatarIconOfProfileAtIndex(index);
+ *is_rectangle =
+ cache.IsUsingGAIAPictureOfProfileAtIndex(index) &&
+ cache.GetGAIAPictureOfProfileAtIndex(index);
+}
diff --git a/chrome/browser/profiles/avatar_menu_model.cc b/chrome/browser/profiles/avatar_menu_model.cc
deleted file mode 100644
index a8dfcdd..0000000
--- a/chrome/browser/profiles/avatar_menu_model.cc
+++ /dev/null
@@ -1,355 +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/profiles/avatar_menu_model.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/metrics/field_trial.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/avatar_menu_model_observer.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_info_cache.h"
-#include "chrome/browser/profiles/profile_info_util.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/profiles/profile_metrics.h"
-#include "chrome/browser/profiles/profile_window.h"
-#include "chrome/browser/profiles/profiles_state.h"
-#include "chrome/browser/signin/signin_promo.h"
-#include "chrome/browser/ui/ash/chrome_shell_delegate.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/chrome_pages.h"
-#include "chrome/browser/ui/host_desktop.h"
-#include "chrome/browser/ui/startup/startup_browser_creator.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/url_constants.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/site_instance.h"
-#include "google_apis/gaia/gaia_urls.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(ENABLE_MANAGED_USERS)
-#include "chrome/browser/managed_mode/managed_user_service.h"
-#include "chrome/browser/managed_mode/managed_user_service_factory.h"
-#endif
-
-using content::BrowserThread;
-
-namespace {
-
-void OnProfileCreated(bool always_create,
- chrome::HostDesktopType desktop_type,
- Profile* profile,
- Profile::CreateStatus status) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (status == Profile::CREATE_STATUS_INITIALIZED) {
- profiles::FindOrCreateNewWindowForProfile(
- profile,
- chrome::startup::IS_NOT_PROCESS_STARTUP,
- chrome::startup::IS_NOT_FIRST_RUN,
- desktop_type,
- always_create);
- }
-}
-
-// Constants for the show profile switcher experiment
-const char kShowProfileSwitcherFieldTrialName[] = "ShowProfileSwitcher";
-const char kAlwaysShowSwitcherGroupName[] = "AlwaysShow";
-
-
-class SignoutTracker : public content::WebContentsObserver {
- public:
- SignoutTracker(Profile* profile, const GURL& signout_landing_url,
- content::WebContents* contents);
-
- virtual void WebContentsDestroyed(content::WebContents* contents) OVERRIDE;
- virtual void DidStopLoading(content::RenderViewHost* render_view_host)
- OVERRIDE;
-
- private:
- scoped_ptr<content::WebContents> contents_;
- GURL signout_landing_url_;
- Profile* profile_;
-
- DISALLOW_COPY_AND_ASSIGN(SignoutTracker);
-};
-
-
-SignoutTracker::SignoutTracker(Profile* profile,
- const GURL& signout_landing_url,
- content::WebContents* contents)
- : WebContentsObserver(contents),
- contents_(contents),
- signout_landing_url_(signout_landing_url),
- profile_(profile) {
-}
-
-void SignoutTracker::DidStopLoading(content::RenderViewHost* render_view_host) {
- // Only close when we reach the final landing; ignore redirects until then.
- if (web_contents()->GetURL() == signout_landing_url_) {
- Observe(NULL);
- BrowserList::CloseAllBrowsersWithProfile(profile_);
- delete this; /* success */
- }
-}
-
-void SignoutTracker::WebContentsDestroyed(content::WebContents* contents) {
- delete this; /* failure */
-}
-
-} // namespace
-
-AvatarMenuModel::AvatarMenuModel(ProfileInfoInterface* profile_cache,
- AvatarMenuModelObserver* observer,
- Browser* browser)
- : profile_info_(profile_cache),
- observer_(observer),
- browser_(browser) {
- DCHECK(profile_info_);
- // Don't DCHECK(browser_) so that unit tests can reuse this ctor.
-
- // Register this as an observer of the info cache.
- registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
- content::NotificationService::AllSources());
-
- // Build the initial menu.
- RebuildMenu();
-}
-
-AvatarMenuModel::~AvatarMenuModel() {
- ClearMenu();
-}
-
-AvatarMenuModel::Item::Item(size_t model_index, const gfx::Image& icon)
- : icon(icon),
- active(false),
- signed_in(false),
- signin_required(false),
- model_index(model_index) {
-}
-
-AvatarMenuModel::Item::~Item() {
-}
-
-void AvatarMenuModel::SwitchToProfile(size_t index, bool always_create) {
- DCHECK(profiles::IsMultipleProfilesEnabled() ||
- index == GetActiveProfileIndex());
- const Item& item = GetItemAt(index);
- base::FilePath path =
- profile_info_->GetPathOfProfileAtIndex(item.model_index);
-
- chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
- if (browser_)
- desktop_type = browser_->host_desktop_type();
-
- profiles::SwitchToProfile(path, desktop_type, always_create);
- ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_ICON);
-}
-
-void AvatarMenuModel::EditProfile(size_t index) {
- Browser* browser = browser_;
- if (!browser) {
- Profile* profile = g_browser_process->profile_manager()->GetProfileByPath(
- profile_info_->GetPathOfProfileAtIndex(GetItemAt(index).model_index));
- browser = new Browser(Browser::CreateParams(profile,
- chrome::GetActiveDesktop()));
- }
- std::string page = chrome::kManageProfileSubPage;
- page += "#";
- page += base::IntToString(static_cast<int>(index));
- chrome::ShowSettingsSubPage(browser, page);
-}
-
-void AvatarMenuModel::AddNewProfile(ProfileMetrics::ProfileAdd type) {
- Browser* browser = browser_;
- if (!browser) {
- const Browser::CreateParams params(ProfileManager::GetLastUsedProfile(),
- chrome::GetActiveDesktop());
- browser = new Browser(params);
- }
- chrome::ShowSettingsSubPage(browser, chrome::kCreateProfileSubPage);
- ProfileMetrics::LogProfileAddNewUser(type);
-}
-
-base::FilePath AvatarMenuModel::GetProfilePath(size_t index) {
- const Item& item = GetItemAt(index);
- return profile_info_->GetPathOfProfileAtIndex(item.model_index);
-}
-
-// static
-void AvatarMenuModel::SwitchToGuestProfileWindow(Browser* browser) {
- ProfileManager* profile_manager = g_browser_process->profile_manager();
- profile_manager->CreateProfileAsync(ProfileManager::GetGuestProfilePath(),
- base::Bind(&OnProfileCreated,
- false,
- browser->host_desktop_type()),
- string16(),
- string16(),
- std::string());
-}
-
-size_t AvatarMenuModel::GetNumberOfItems() {
- return items_.size();
-}
-
-size_t AvatarMenuModel::GetActiveProfileIndex() {
- // During singleton profile deletion, this function can be called with no
- // profiles in the model - crbug.com/102278 .
- if (items_.size() == 0)
- return 0;
-
- Profile* active_profile = NULL;
- if (!browser_)
- active_profile = ProfileManager::GetLastUsedProfile();
- else
- active_profile = browser_->profile();
-
- size_t index =
- profile_info_->GetIndexOfProfileWithPath(active_profile->GetPath());
-
- DCHECK_LT(index, items_.size());
- return index;
-}
-
-const AvatarMenuModel::Item& AvatarMenuModel::GetItemAt(size_t index) {
- DCHECK_LT(index, items_.size());
- return *items_[index];
-}
-
-bool AvatarMenuModel::ShouldShowAddNewProfileLink() const {
- // |browser_| can be NULL in unit_tests.
- return !browser_ || !browser_->profile()->IsManaged();
-}
-
-base::string16 AvatarMenuModel::GetManagedUserInformation() const {
- // |browser_| can be NULL in unit_tests.
- if (browser_ && browser_->profile()->IsManaged()) {
-#if defined(ENABLE_MANAGED_USERS)
- ManagedUserService* service = ManagedUserServiceFactory::GetForProfile(
- browser_->profile());
- base::string16 custodian = UTF8ToUTF16(service->GetCustodianEmailAddress());
- return l10n_util::GetStringFUTF16(IDS_MANAGED_USER_INFO, custodian);
-#endif
- }
- return base::string16();
-}
-
-const gfx::Image& AvatarMenuModel::GetManagedUserIcon() const {
- return ResourceBundle::GetSharedInstance().GetNativeImageNamed(
- IDR_MANAGED_USER_ICON);
-}
-
-void AvatarMenuModel::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, type);
- RebuildMenu();
- if (observer_)
- observer_->OnAvatarMenuModelChanged(this);
-}
-
-// static
-bool AvatarMenuModel::ShouldShowAvatarMenu() {
- if (base::FieldTrialList::FindFullName(kShowProfileSwitcherFieldTrialName) ==
- kAlwaysShowSwitcherGroupName) {
- // We should only be in this group when multi-profiles is enabled.
- DCHECK(profiles::IsMultipleProfilesEnabled());
- return true;
- }
- if (profiles::IsMultipleProfilesEnabled()) {
-#if defined(OS_CHROMEOS)
- // On ChromeOS the menu will be always visible when it is possible to have
- // two users logged in at the same time.
- return ChromeShellDelegate::instance() &&
- ChromeShellDelegate::instance()->IsMultiProfilesEnabled();
-#else
- return profiles::IsNewProfileManagementEnabled() ||
- (g_browser_process->profile_manager() &&
- g_browser_process->profile_manager()->GetNumberOfProfiles() > 1);
-#endif
- }
- return false;
-}
-
-void AvatarMenuModel::RebuildMenu() {
- ClearMenu();
-
- const size_t count = profile_info_->GetNumberOfProfiles();
- for (size_t i = 0; i < count; ++i) {
- bool is_gaia_picture =
- profile_info_->IsUsingGAIAPictureOfProfileAtIndex(i) &&
- profile_info_->GetGAIAPictureOfProfileAtIndex(i);
-
- gfx::Image icon = profile_info_->GetAvatarIconOfProfileAtIndex(i);
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kNewProfileManagement)) {
- // old avatar menu uses resized-small images
- icon = profiles::GetAvatarIconForMenu(icon, is_gaia_picture);
- }
-
- Item* item = new Item(i, icon);
- item->name = profile_info_->GetNameOfProfileAtIndex(i);
- item->sync_state = profile_info_->GetUserNameOfProfileAtIndex(i);
- item->signed_in = !item->sync_state.empty();
- if (!item->signed_in) {
- item->sync_state = l10n_util::GetStringUTF16(
- profile_info_->ProfileIsManagedAtIndex(i) ?
- IDS_MANAGED_USER_AVATAR_LABEL : IDS_PROFILES_LOCAL_PROFILE_STATE);
- }
- if (browser_) {
- base::FilePath path = profile_info_->GetPathOfProfileAtIndex(i);
- item->active = browser_->profile()->GetPath() == path;
- }
- item->signin_required = profile_info_->ProfileIsSigninRequiredAtIndex(i);
- items_.push_back(item);
- }
-}
-
-void AvatarMenuModel::ClearMenu() {
- STLDeleteElements(&items_);
-}
-
-
-content::WebContents* AvatarMenuModel::BeginSignOut() {
- ProfileManager* profile_manager = g_browser_process->profile_manager();
- Profile* current_profile = browser_->profile();
-
- ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
- size_t index = cache.GetIndexOfProfileWithPath(current_profile->GetPath());
- cache.SetProfileSigninRequiredAtIndex(index, true);
-
- std::string landing_url = signin::GetLandingURL("close", 1).spec();
- GURL logout_url(GaiaUrls::GetInstance()->service_logout_url().Resolve(
- "?continue=" + landing_url));
- if (!logout_override_.empty()) {
- // We're testing...
- landing_url = logout_override_;
- logout_url = GURL(logout_override_);
- }
-
- content::WebContents::CreateParams create_params(current_profile);
- create_params.site_instance =
- content::SiteInstance::CreateForURL(current_profile, logout_url);
- content::WebContents* contents = content::WebContents::Create(create_params);
- contents->GetController().LoadURL(
- logout_url, content::Referrer(),
- content::PAGE_TRANSITION_GENERATED, std::string());
-
- // This object may be destructed when the menu closes but we need something
- // around to finish the sign-out process and close the profile windows.
- new SignoutTracker(current_profile, GURL(landing_url), contents);
-
- return contents; // returned for testing purposes
-}
diff --git a/chrome/browser/profiles/avatar_menu_model.h b/chrome/browser/profiles/avatar_menu_model.h
deleted file mode 100644
index 95668b4..0000000
--- a/chrome/browser/profiles/avatar_menu_model.h
+++ /dev/null
@@ -1,155 +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_PROFILES_AVATAR_MENU_MODEL_H_
-#define CHROME_BROWSER_PROFILES_AVATAR_MENU_MODEL_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/strings/string16.h"
-#include "chrome/browser/profiles/profile_metrics.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "ui/gfx/image/image.h"
-
-class AvatarMenuModelObserver;
-class Browser;
-class Profile;
-class ProfileInfoInterface;
-
-// This class is the model for the menu-like interface that appears when the
-// avatar icon is clicked in the browser window frame. This class will notify
-// its observer when the backend data changes, and the controller/view for this
-// model should forward actions back to it in response to user events.
-class AvatarMenuModel : public content::NotificationObserver {
- public:
- // Represents an item in the menu.
- struct Item {
- Item(size_t model_index, const gfx::Image& icon);
- ~Item();
-
- // The icon to be displayed next to the item.
- gfx::Image icon;
-
- // Whether or not the current browser is using this profile.
- bool active;
-
- // The name of this profile.
- string16 name;
-
- // A string representing the sync state of the profile.
- string16 sync_state;
-
- // Whether or not the current profile is signed in. If true, |sync_state| is
- // expected to be the email of the signed in user.
- bool signed_in;
-
- // Whether or not the current profile requires sign-in before use.
- bool signin_required;
-
- // The index in the |profile_cache| that this Item represents.
- size_t model_index;
- };
-
- // Constructor. |observer| can be NULL. |browser| can be NULL and a new one
- // will be created if an action requires it.
- AvatarMenuModel(ProfileInfoInterface* profile_cache,
- AvatarMenuModelObserver* observer,
- Browser* browser);
- virtual ~AvatarMenuModel();
-
- // Actions performed by the view that the controller forwards back to the
- // model:
- // Opens a Browser with the specified profile in response to the user
- // selecting an item. If |always_create| is true then a new window is created
- // even if a window for that profile already exists.
- void SwitchToProfile(size_t index, bool always_create);
- // Opens the profile settings in response to clicking the edit button next to
- // an item.
- void EditProfile(size_t index);
- // Creates a new profile.
- void AddNewProfile(ProfileMetrics::ProfileAdd type);
- // Creates a new guest user window.
- static void SwitchToGuestProfileWindow(Browser* browser);
-
- // Gets the path associated with the profile at |index|.
- base::FilePath GetProfilePath(size_t index);
-
- // Gets the number of profiles.
- size_t GetNumberOfItems();
-
- // Returns the index of the active profile.
- size_t GetActiveProfileIndex();
-
- // Gets the an Item at a specified index.
- const Item& GetItemAt(size_t index);
-
- // Returns true if the add profile link should be shown.
- bool ShouldShowAddNewProfileLink() const;
-
- // Returns information about a managed user which will be displayed in the
- // avatar menu. If the profile does not belong to a managed user, an empty
- // string will be returned.
- base::string16 GetManagedUserInformation() const;
-
- // Returns the icon for the managed user which will be displayed in the
- // avatar menu.
- const gfx::Image& GetManagedUserIcon() const;
-
- // This model is also used for the always-present Mac system menubar. As the
- // last active browser changes, the model needs to update accordingly.
- void set_browser(Browser* browser) { browser_ = browser; }
-
- // content::NotificationObserver:
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
-
- // True if avatar menu should be displayed.
- static bool ShouldShowAvatarMenu();
-
- // Start the sign-out process for this profile.
- // Parameter |logout_override| alows changing the destination URL for the
- // sign-out process and return value (the WebContents executing the sign-out)
- // are for testing; pass NULL for normal use.
- content::WebContents* BeginSignOut();
-
- // Use a different URL for logout (for testing only).
- void SetLogoutURL(const std::string& logout_url) {
- logout_override_ = logout_url;
- }
-
- private:
- // Rebuilds the menu from the cache and notifies the |observer_|.
- void RebuildMenu();
-
- // Clears the list of items, deleting each.
- void ClearMenu();
-
- // The cache that provides the profile information. Weak.
- ProfileInfoInterface* profile_info_;
-
- // The observer of this model, which is notified of changes. Weak.
- AvatarMenuModelObserver* observer_;
-
- // Browser in which this avatar menu resides. Weak.
- Browser* browser_;
-
- // List of built "menu items."
- std::vector<Item*> items_;
-
- // Listens for notifications from the ProfileInfoCache.
- content::NotificationRegistrar registrar_;
-
- // Special "override" logout URL used to let tests work.
- std::string logout_override_;
-
- DISALLOW_COPY_AND_ASSIGN(AvatarMenuModel);
-};
-
-#endif // CHROME_BROWSER_PROFILES_AVATAR_MENU_MODEL_H_
diff --git a/chrome/browser/profiles/avatar_menu_model_observer.h b/chrome/browser/profiles/avatar_menu_model_observer.h
deleted file mode 100644
index e6586c3..0000000
--- a/chrome/browser/profiles/avatar_menu_model_observer.h
+++ /dev/null
@@ -1,19 +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_PROFILES_AVATAR_MENU_MODEL_OBSERVER_H_
-#define CHROME_BROWSER_PROFILES_AVATAR_MENU_MODEL_OBSERVER_H_
-
-class AvatarMenuModel;
-
-// Delegate interface for objects that want to be notified when the
-// AvatarMenuModel changes.
-class AvatarMenuModelObserver {
- public:
- virtual ~AvatarMenuModelObserver() {}
-
- virtual void OnAvatarMenuModelChanged(AvatarMenuModel* avatar_menu_model) = 0;
-};
-
-#endif // CHROME_BROWSER_PROFILES_AVATAR_MENU_MODEL_OBSERVER_H_
diff --git a/chrome/browser/profiles/avatar_menu_observer.h b/chrome/browser/profiles/avatar_menu_observer.h
new file mode 100644
index 0000000..5a4b286
--- /dev/null
+++ b/chrome/browser/profiles/avatar_menu_observer.h
@@ -0,0 +1,19 @@
+// 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_PROFILES_AVATAR_MENU_OBSERVER_H_
+#define CHROME_BROWSER_PROFILES_AVATAR_MENU_OBSERVER_H_
+
+class AvatarMenu;
+
+// Delegate interface for objects that want to be notified when the
+// AvatarMenu changes.
+class AvatarMenuObserver {
+ public:
+ virtual ~AvatarMenuObserver() {}
+
+ virtual void OnAvatarMenuChanged(AvatarMenu* avatar_menu) = 0;
+};
+
+#endif // CHROME_BROWSER_PROFILES_AVATAR_MENU_OBSERVER_H_
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 7dc3f10..edfb33a 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -134,7 +134,9 @@
#include "chrome/browser/ui/gesture_prefs_observer_factory_aura.h"
#endif
-#if !defined(OS_ANDROID)
+#if defined(OS_ANDROID)
+#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
+#else
#include "chrome/browser/media_galleries/media_galleries_preferences_factory.h"
#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
#endif
@@ -185,6 +187,9 @@
captive_portal::CaptivePortalServiceFactory::GetInstance();
#endif
ChromeGeolocationPermissionContextFactory::GetInstance();
+#if defined(OS_ANDROID)
+ ProtectedMediaIdentifierPermissionContextFactory::GetInstance();
+#endif
#if defined(OS_CHROMEOS)
chromeos::NetworkingPrivateEventRouterFactory::GetInstance();
#endif
diff --git a/chrome/browser/profiles/file_path_verifier_win.cc b/chrome/browser/profiles/file_path_verifier_win.cc
new file mode 100644
index 0000000..53b9e12
--- /dev/null
+++ b/chrome/browser/profiles/file_path_verifier_win.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/browser/profiles/file_path_verifier_win.h"
+
+#include <windows.h>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/metrics/histogram.h"
+
+namespace internal {
+
+PathComparisonReason ComparePathsIgnoreCase(const base::FilePath& path1,
+ const base::FilePath& path2) {
+ PathComparisonReason reason = PATH_COMPARISON_FAILED_UNKNOWN;
+
+ if (base::FilePath::CompareEqualIgnoreCase(path1.value(), path2.value())) {
+ reason = PATH_COMPARISON_EQUAL;
+ } else if (base::FilePath::CompareEqualIgnoreCase(path1.BaseName().value(),
+ path2.BaseName().value())) {
+ reason = PATH_COMPARISON_FAILED_SAMEBASE;
+ } else if (base::FilePath::CompareEqualIgnoreCase(path1.DirName().value(),
+ path2.DirName().value())) {
+ reason = PATH_COMPARISON_FAILED_SAMEDIR;
+ }
+
+ return reason;
+}
+
+} // namespace internal
+
+void VerifyFileAtPath(const base::FilePath& file,
+ const std::string& metric_suffix) {
+ // This enum is used in UMA histograms and should never be re-ordered.
+ enum FileVerificationResult {
+ FILE_VERIFICATION_SUCCESS,
+ FILE_VERIFICATION_FILE_NOT_FOUND,
+ FILE_VERIFICATION_INTERNAL_ERROR,
+ FILE_VERIFICATION_FAILED_UNKNOWN,
+ FILE_VERIFICATION_FAILED_SAMEBASE,
+ FILE_VERIFICATION_FAILED_SAMEDIR,
+ NUM_FILE_VERIFICATION_RESULTS
+ } file_verification_result = FILE_VERIFICATION_FAILED_UNKNOWN;
+
+ base::FilePath normalized_path;
+ if (!file_util::NormalizeFilePath(file, &normalized_path)) {
+ if (::GetLastError() == ERROR_FILE_NOT_FOUND)
+ file_verification_result = FILE_VERIFICATION_FILE_NOT_FOUND;
+ else
+ file_verification_result = FILE_VERIFICATION_INTERNAL_ERROR;
+ } else {
+ internal::PathComparisonReason path_comparison_reason =
+ internal::ComparePathsIgnoreCase(file, normalized_path);
+ switch (path_comparison_reason) {
+ case internal::PATH_COMPARISON_EQUAL:
+ file_verification_result = FILE_VERIFICATION_SUCCESS;
+ break;
+ case internal::PATH_COMPARISON_FAILED_SAMEBASE:
+ file_verification_result = FILE_VERIFICATION_FAILED_SAMEBASE;
+ break;
+ case internal::PATH_COMPARISON_FAILED_SAMEDIR:
+ file_verification_result = FILE_VERIFICATION_FAILED_SAMEDIR;
+ break;
+ }
+ }
+
+ // Note: This leaks memory, which is the expected behavior as the factory
+ // creates and owns the histogram.
+ base::HistogramBase* histogram =
+ base::LinearHistogram::FactoryGet(
+ "Stability.FileAtPath." + metric_suffix,
+ 1,
+ NUM_FILE_VERIFICATION_RESULTS,
+ NUM_FILE_VERIFICATION_RESULTS + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ histogram->Add(file_verification_result);
+}
diff --git a/chrome/browser/profiles/file_path_verifier_win.h b/chrome/browser/profiles/file_path_verifier_win.h
new file mode 100644
index 0000000..bacd5aa
--- /dev/null
+++ b/chrome/browser/profiles/file_path_verifier_win.h
@@ -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.
+
+#ifndef CHROME_BROWSER_PROFILES_FILE_PATH_VERIFIER_WIN_H_
+#define CHROME_BROWSER_PROFILES_FILE_PATH_VERIFIER_WIN_H_
+
+#include <string>
+
+namespace base {
+class FilePath;
+}
+
+namespace internal {
+
+enum PathComparisonReason {
+ PATH_COMPARISON_EQUAL,
+ PATH_COMPARISON_FAILED_UNKNOWN,
+ PATH_COMPARISON_FAILED_SAMEBASE, // Not the same path, but same BaseName.
+ PATH_COMPARISON_FAILED_SAMEDIR, // Not the same path, but same DirName.
+};
+
+// Returns a PathComparisonReason based on the result of comparing |path1|
+// and |path2| case-insensitively.
+PathComparisonReason ComparePathsIgnoreCase(const base::FilePath& path1,
+ const base::FilePath& path2);
+
+} // namespace internal
+
+// Verifies that |file| is found as expected on disk and reports the result via
+// a UMA stat with suffix |metric_suffix|.
+void VerifyFileAtPath(const base::FilePath& file,
+ const std::string& metric_suffix);
+
+#endif // CHROME_BROWSER_PROFILES_FILE_PATH_VERIFIER_WIN_H_
diff --git a/chrome/browser/profiles/file_path_verifier_win_unittest.cc b/chrome/browser/profiles/file_path_verifier_win_unittest.cc
new file mode 100644
index 0000000..e2c922f
--- /dev/null
+++ b/chrome/browser/profiles/file_path_verifier_win_unittest.cc
@@ -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.
+
+#include "chrome/browser/profiles/file_path_verifier_win.h"
+
+#include "base/files/file_path.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(FilePathVerifierTest, ComparePathsIgnoreCase) {
+ const struct PathComparisonReasonTestData {
+ const base::FilePath::CharType* inputs[2];
+ internal::PathComparisonReason expected;
+ } cases[] = {
+ { { FILE_PATH_LITERAL("test/foo.bar"),
+ FILE_PATH_LITERAL("test/foo.bar") },
+ internal::PATH_COMPARISON_EQUAL},
+ { { FILE_PATH_LITERAL("test\\foo.bar"),
+ FILE_PATH_LITERAL("test\\foo.bar") },
+ internal::PATH_COMPARISON_EQUAL},
+ { { FILE_PATH_LITERAL("test/foo.bar"),
+ FILE_PATH_LITERAL("test/foo.baz") },
+ internal::PATH_COMPARISON_FAILED_SAMEDIR},
+ { { FILE_PATH_LITERAL("test/foo.bar"),
+ FILE_PATH_LITERAL("test/joe/foo.bar") },
+ internal::PATH_COMPARISON_FAILED_SAMEBASE},
+ { { FILE_PATH_LITERAL("test/foo.bar"),
+ FILE_PATH_LITERAL("jack/bar.buz") },
+ internal::PATH_COMPARISON_FAILED_UNKNOWN},
+ };
+
+ for (size_t i = 0; i < arraysize(cases); ++i) {
+ base::FilePath p1(cases[i].inputs[0]);
+ base::FilePath p2(cases[i].inputs[1]);
+ internal::PathComparisonReason reason =
+ internal::ComparePathsIgnoreCase(p1, p2);
+ EXPECT_EQ(cases[i].expected, reason) <<
+ "i: " << i << ", p1: " << p1.value() << ", p2: " << p2.value();
+ }
+}
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc
index e4270db..b122208 100644
--- a/chrome/browser/profiles/profile_downloader.cc
+++ b/chrome/browser/profiles/profile_downloader.cc
@@ -16,6 +16,7 @@
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_downloader_delegate.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "content/public/browser/browser_thread.h"
@@ -51,6 +52,9 @@
const char kGivenNamePath[] = "given_name";
+// Path in JSON dictionary to user's preferred locale.
+const char kLocalePath[] = "locale";
+
// Path format for specifying thumbnail's size.
const char kThumbnailSizeFormat[] = "s%d-c";
// Default thumbnail size.
@@ -124,18 +128,24 @@
} // namespace
-// static
-bool ProfileDownloader::GetProfileNameAndImageURL(const std::string& data,
- string16* full_name,
- string16* given_name,
- std::string* url,
- int image_size) {
+// Parses the entry response and gets the name and profile image URL.
+// |data| should be the JSON formatted data return by the response.
+// Returns false to indicate a parsing error.
+bool ProfileDownloader::ParseProfileJSON(const std::string& data,
+ string16* full_name,
+ string16* given_name,
+ std::string* url,
+ int image_size,
+ std::string* profile_locale) {
DCHECK(full_name);
DCHECK(given_name);
DCHECK(url);
+ DCHECK(profile_locale);
+
*full_name = string16();
*given_name = string16();
*url = std::string();
+ *profile_locale = std::string();
int error_code = -1;
std::string error_message;
@@ -156,6 +166,7 @@
root_dictionary->GetString(kFullNamePath, full_name);
root_dictionary->GetString(kGivenNamePath, given_name);
+ root_dictionary->GetString(kLocalePath, profile_locale);
std::string url_string;
if (root_dictionary->GetString(kPhotoThumbnailURLPath, &url_string)) {
@@ -217,7 +228,8 @@
return;
}
- if (service->RefreshTokenIsAvailable()) {
+ if (service->RefreshTokenIsAvailable(
+ service->GetPrimaryAccountId())) {
StartFetchingOAuth2AccessToken();
} else {
service->AddObserver(this);
@@ -232,6 +244,10 @@
return profile_given_name_;
}
+std::string ProfileDownloader::GetProfileLocale() const {
+ return profile_locale_;
+}
+
SkBitmap ProfileDownloader::GetProfilePicture() const {
return profile_picture_;
}
@@ -264,9 +280,10 @@
Profile* profile = delegate_->GetBrowserProfile();
OAuth2TokenService::ScopeSet scopes;
scopes.insert(kAPIScope);
- oauth2_access_token_request_ =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile)
- ->StartRequestWithContext(profile->GetRequestContext(), scopes, this);
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+ oauth2_access_token_request_ = token_service->StartRequest(
+ token_service->GetPrimaryAccountId(), scopes, this);
}
ProfileDownloader::~ProfileDownloader() {}
@@ -291,11 +308,12 @@
if (source == user_entry_fetcher_.get()) {
std::string image_url;
- if (!GetProfileNameAndImageURL(data,
- &profile_full_name_,
- &profile_given_name_,
- &image_url,
- delegate_->GetDesiredImageSideLength())) {
+ if (!ParseProfileJSON(data,
+ &profile_full_name_,
+ &profile_given_name_,
+ &image_url,
+ delegate_->GetDesiredImageSideLength(),
+ &profile_locale_)) {
delegate_->OnProfileDownloadFailure(
this, ProfileDownloaderDelegate::SERVICE_ERROR);
return;
diff --git a/chrome/browser/profiles/profile_downloader.h b/chrome/browser/profiles/profile_downloader.h
index 952fd2e..326331c 100644
--- a/chrome/browser/profiles/profile_downloader.h
+++ b/chrome/browser/profiles/profile_downloader.h
@@ -54,6 +54,9 @@
// if the name is "Pat Smith", the given name is "Pat".
virtual string16 GetProfileGivenName() const;
+ // On successful download this returns G+ locale preference of the user.
+ virtual std::string GetProfileLocale() const;
+
// On successful download this returns the profile picture of the user.
// For users with no profile picture set (that is, they have the default
// profile picture) this will return an Null bitmap.
@@ -90,15 +93,15 @@
virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) OVERRIDE;
- // Parses the entry response and gets the full name, the given name,
- // and profile image URL. |data| should be the JSON formatted data returned
- // by the response. Returns false to indicate a parsing error.
- static bool GetProfileNameAndImageURL(const std::string& data,
- string16* full_name,
- string16* given_name,
- std::string* url,
- int image_size);
-
+ // Parses the entry response and gets the name, profile image URL and locale.
+ // |data| should be the JSON formatted data return by the response.
+ // Returns false to indicate a parsing error.
+ static bool ParseProfileJSON(const std::string& data,
+ string16* full_name,
+ string16* given_name,
+ std::string* url,
+ int image_size,
+ std::string* profile_locale);
// Returns true if the image url is url of the default profile picture.
static bool IsDefaultProfileImageURL(const std::string& url);
@@ -119,6 +122,7 @@
scoped_ptr<OAuth2TokenService::Request> oauth2_access_token_request_;
string16 profile_full_name_;
string16 profile_given_name_;
+ std::string profile_locale_;
SkBitmap profile_picture_;
PictureStatus picture_status_;
std::string picture_url_;
diff --git a/chrome/browser/profiles/profile_downloader_unittest.cc b/chrome/browser/profiles/profile_downloader_unittest.cc
index 43efa27..8460fe8 100644
--- a/chrome/browser/profiles/profile_downloader_unittest.cc
+++ b/chrome/browser/profiles/profile_downloader_unittest.cc
@@ -11,16 +11,30 @@
std::string GetJSonData(const std::string& full_name,
const std::string& given_name,
- const std::string& url) {
+ const std::string& url,
+ const std::string& locale) {
std::stringstream stream;
+ bool started = false;
+
stream << "{ ";
- if (!full_name.empty())
- stream << "\"name\": \"" << full_name << "\", ";
- if (!given_name.empty())
- stream << "\"given_name\": \"" << given_name << "\", ";
- if (!url.empty())
- stream << "\"picture\": \"" << url << "\", ";
- stream << "\"locale\": \"en-US\" }";
+ if (!full_name.empty()) {
+ stream << "\"name\": \"" << full_name << "\"";
+ started = true;
+ }
+ if (!given_name.empty()) {
+ stream << (started ? ", " : "") << "\"given_name\": \"" << given_name
+ << "\"";
+ started = true;
+ }
+ if (!url.empty()) {
+ stream << (started ? ", " : "") << "\"picture\": \"" << url << "\"";
+ started = true;
+ }
+
+ if (!locale.empty())
+ stream << (started ? ", " : "") << "\"locale\": \"" << locale << "\"";
+
+ stream << " }";
return stream.str();
}
@@ -34,20 +48,23 @@
virtual ~ProfileDownloaderTest() {
}
- void VerifyWithNameAndURL(const std::string& full_name,
- const std::string& given_name,
- const std::string& url,
- const std::string& expected_url,
- bool is_valid) {
+ void VerifyWithAccountData(const std::string& full_name,
+ const std::string& given_name,
+ const std::string& url,
+ const std::string& expected_url,
+ const std::string& locale,
+ bool is_valid) {
string16 parsed_full_name;
string16 parsed_given_name;
std::string parsed_url;
- bool result = ProfileDownloader::GetProfileNameAndImageURL(
- GetJSonData(full_name, given_name, url),
+ std::string parsed_locale;
+ bool result = ProfileDownloader::ParseProfileJSON(
+ GetJSonData(full_name, given_name, url, locale),
&parsed_full_name,
&parsed_given_name,
&parsed_url,
- 32);
+ 32,
+ &parsed_locale);
EXPECT_EQ(is_valid, result);
std::string parsed_full_name_utf8 = UTF16ToUTF8(parsed_full_name);
std::string parsed_given_name_utf8 = UTF16ToUTF8(parsed_given_name);
@@ -55,52 +72,86 @@
EXPECT_EQ(full_name, parsed_full_name_utf8);
EXPECT_EQ(given_name, parsed_given_name_utf8);
EXPECT_EQ(expected_url, parsed_url);
+ EXPECT_EQ(locale, parsed_locale);
}
};
TEST_F(ProfileDownloaderTest, ParseData) {
// URL without size specified.
- VerifyWithNameAndURL(
+ VerifyWithAccountData(
"Pat Smith",
"Pat",
"https://example.com/--Abc/AAAAAAAAAAI/AAAAAAAAACQ/Efg/photo.jpg",
"https://example.com/--Abc/AAAAAAAAAAI/AAAAAAAAACQ/Efg/s32-c/photo.jpg",
+ "en-US",
true);
// URL with size specified.
- VerifyWithNameAndURL(
+ VerifyWithAccountData(
"Pat Smith",
"Pat",
"http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/abc12/s64-c/1234567890.jpg",
"http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/abc12/s32-c/1234567890.jpg",
+ "en-US",
true);
// URL with unknown format.
- VerifyWithNameAndURL(
+ VerifyWithAccountData("Pat Smith",
+ "Pat",
+ "http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/",
+ "http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/",
+ "en-US",
+ true);
+
+ // Try different locales. URL with size specified.
+ VerifyWithAccountData(
"Pat Smith",
"Pat",
- "http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/",
- "http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/",
+ "http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/abc12/s64-c/1234567890.jpg",
+ "http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/abc12/s32-c/1234567890.jpg",
+ "jp",
true);
+ // URL with unknown format.
+ VerifyWithAccountData("Pat Smith",
+ "Pat",
+ "http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/",
+ "http://lh0.ggpht.com/-abcd1aBCDEf/AAAA/AAA_A/",
+ "fr",
+ true);
+
// Data with only name.
- VerifyWithNameAndURL("Pat Smith", "Pat", std::string(), std::string(), true);
+ VerifyWithAccountData(
+ "Pat Smith", "Pat", std::string(), std::string(), std::string(), true);
// Data with only URL.
- VerifyWithNameAndURL(
+ VerifyWithAccountData(
std::string(),
std::string(),
"https://example.com/--Abc/AAAAAAAAAAI/AAAAAAAAACQ/Efg/photo.jpg",
"https://example.com/--Abc/AAAAAAAAAAI/AAAAAAAAACQ/Efg/s32-c/photo.jpg",
+ std::string(),
true);
- // Data without name or URL.
- VerifyWithNameAndURL(
- std::string(), std::string(), std::string(), std::string(), false);
+ // Data with only locale.
+ VerifyWithAccountData(
+ std::string(), std::string(), std::string(), std::string(), "fr", false);
+
+ // Data without name or URL or locale.
+ VerifyWithAccountData(std::string(),
+ std::string(),
+ std::string(),
+ std::string(),
+ std::string(),
+ false);
// Data with an invalid URL.
- VerifyWithNameAndURL(
- std::string(), std::string(), "invalid url", std::string(), false);
+ VerifyWithAccountData(std::string(),
+ std::string(),
+ "invalid url",
+ std::string(),
+ std::string(),
+ false);
}
TEST_F(ProfileDownloaderTest, DefaultURL) {
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index a6790df..a4c9ad0 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -113,6 +113,7 @@
#endif
#if defined(OS_WIN)
+#include "chrome/browser/profiles/file_path_verifier_win.h"
#include "chrome/installer/util/install_util.h"
#endif
@@ -243,6 +244,17 @@
return std::string();
}
+void SchedulePrefsFileVerification(const base::FilePath& prefs_file) {
+#if defined(OS_WIN)
+ // Only do prefs file verification on Windows.
+ const int kVerifyPrefsFileDelaySeconds = 60;
+ BrowserThread::GetBlockingPool()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&VerifyFileAtPath, prefs_file, "Preferences"),
+ base::TimeDelta::FromSeconds(kVerifyPrefsFileDelaySeconds));
+#endif
+}
+
} // namespace
// static
@@ -780,6 +792,8 @@
predictor_));
}
+ SchedulePrefsFileVerification(GetPrefFilePath());
+
ChromeVersionService::OnProfileLoaded(prefs_.get(), IsNewProfile());
DoFinalInit();
}
@@ -1054,7 +1068,9 @@
// (2) on next login we assume that synchronization is already completed
// and we may finalize initialization.
GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale);
- if (!backup_locale.empty())
+ if (!new_locale.empty())
+ GetPrefs()->SetString(prefs::kApplicationLocale, new_locale);
+ else if (!backup_locale.empty())
GetPrefs()->SetString(prefs::kApplicationLocale, backup_locale);
do_update_pref = false;
}
diff --git a/chrome/browser/profiles/profile_info_util.cc b/chrome/browser/profiles/profile_info_util.cc
index 680334c..1f56b3d 100644
--- a/chrome/browser/profiles/profile_info_util.cc
+++ b/chrome/browser/profiles/profile_info_util.cc
@@ -15,15 +15,15 @@
const int kAvatarIconBorder = 2;
gfx::Image GetSizedAvatarIconWithBorder(const gfx::Image& image,
- bool is_gaia_picture,
+ bool is_rectangle,
int width, int height) {
- if (!is_gaia_picture)
+ if (!is_rectangle)
return image;
int length = std::min(width, height) - kAvatarIconBorder;
SkBitmap bmp = skia::ImageOperations::Resize(
*image.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, length, length);
- gfx::Canvas canvas(gfx::Size(width, height), ui::SCALE_FACTOR_100P, false);
+ gfx::Canvas canvas(gfx::Size(width, height), 1.0f, false);
// Draw the icon centered on the canvas.
int x = (width - length) / 2;
@@ -38,22 +38,22 @@
}
gfx::Image GetAvatarIconForMenu(const gfx::Image& image,
- bool is_gaia_picture) {
+ bool is_rectangle) {
return GetSizedAvatarIconWithBorder(
- image, is_gaia_picture, kAvatarIconWidth, kAvatarIconHeight);
+ image, is_rectangle, kAvatarIconWidth, kAvatarIconHeight);
}
gfx::Image GetAvatarIconForWebUI(const gfx::Image& image,
- bool is_gaia_picture) {
- if (!is_gaia_picture)
+ bool is_rectangle) {
+ if (!is_rectangle)
return image;
int length =
std::min(kAvatarIconWidth, kAvatarIconHeight) - kAvatarIconBorder;
SkBitmap bmp = skia::ImageOperations::Resize(
*image.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, length, length);
- gfx::Canvas canvas(gfx::Size(kAvatarIconWidth, kAvatarIconHeight),
- ui::SCALE_FACTOR_100P, false);
+ gfx::Canvas canvas(
+ gfx::Size(kAvatarIconWidth, kAvatarIconHeight), 1.0f, false);
// Draw the icon centered on the canvas.
int x = (kAvatarIconWidth - length) / 2;
@@ -64,18 +64,17 @@
}
gfx::Image GetAvatarIconForTitleBar(const gfx::Image& image,
- bool is_gaia_picture,
+ bool is_rectangle,
int dst_width,
int dst_height) {
- if (!is_gaia_picture)
+ if (!is_rectangle)
return image;
int length = std::min(std::min(kAvatarIconWidth, kAvatarIconHeight),
std::min(dst_width, dst_height)) - kAvatarIconBorder;
SkBitmap bmp = skia::ImageOperations::Resize(
*image.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, length, length);
- gfx::Canvas canvas(gfx::Size(dst_width, dst_height), ui::SCALE_FACTOR_100P,
- false);
+ gfx::Canvas canvas(gfx::Size(dst_width, dst_height), 1.0f, false);
// Draw the icon on the bottom center of the canvas.
int x1 = (dst_width - length) / 2;
@@ -102,4 +101,4 @@
return gfx::Image(gfx::ImageSkia(canvas.ExtractImageRep()));
}
-} // namespace
+} // namespace profiles
diff --git a/chrome/browser/profiles/profile_info_util.h b/chrome/browser/profiles/profile_info_util.h
index f33d2b3..da04a11 100644
--- a/chrome/browser/profiles/profile_info_util.h
+++ b/chrome/browser/profiles/profile_info_util.h
@@ -17,24 +17,24 @@
// Note that no checks are done on the width/height so make sure they're
// reasonable values; in the range of 16-256 is probably best.
gfx::Image GetSizedAvatarIconWithBorder(const gfx::Image& image,
- bool is_gaia_picture,
+ bool is_rectangle,
int width, int height);
// Returns a version of |image| suitable for use in menus.
gfx::Image GetAvatarIconForMenu(const gfx::Image& image,
- bool is_gaia_picture);
+ bool is_rectangle);
// Returns a version of |image| suitable for use in WebUI.
gfx::Image GetAvatarIconForWebUI(const gfx::Image& image,
- bool is_gaia_picture);
+ bool is_rectangle);
// Returns a version of |image| suitable for use in title bars. The returned
// image is scaled to fit |dst_width| and |dst_height|.
gfx::Image GetAvatarIconForTitleBar(const gfx::Image& image,
- bool is_gaia_picture,
+ bool is_rectangle,
int dst_width,
int dst_height);
-}
+} // namespace profiles
#endif // CHROME_BROWSER_PROFILES_PROFILE_INFO_UTIL_H_
diff --git a/chrome/browser/profiles/profile_info_util_unittest.cc b/chrome/browser/profiles/profile_info_util_unittest.cc
index ef0067e..47020ff 100644
--- a/chrome/browser/profiles/profile_info_util_unittest.cc
+++ b/chrome/browser/profiles/profile_info_util_unittest.cc
@@ -21,12 +21,12 @@
EXPECT_FALSE(gfx::test::IsEmpty(result));
EXPECT_TRUE(gfx::test::IsEqual(profile_image, result));
- // Test that a GAIA picture is changed.
- gfx::Image gaia_picture(gfx::test::CreateImage());
+ // Test that a rectangular picture (e.g., GAIA image) is changed.
+ gfx::Image rect_picture(gfx::test::CreateImage());
gfx::Image result2 =
- profiles::GetSizedAvatarIconWithBorder(gaia_picture, true, 50, 50);
+ profiles::GetSizedAvatarIconWithBorder(rect_picture, true, 50, 50);
EXPECT_FALSE(gfx::test::IsEmpty(result2));
- EXPECT_FALSE(gfx::test::IsEqual(gaia_picture, result2));
+ EXPECT_FALSE(gfx::test::IsEqual(rect_picture, result2));
}
TEST(ProfileInfoUtilTest, MenuIcon) {
@@ -37,11 +37,11 @@
EXPECT_FALSE(gfx::test::IsEmpty(result));
EXPECT_TRUE(gfx::test::IsEqual(profile_image, result));
- // Test that a GAIA picture is changed.
- gfx::Image gaia_picture(gfx::test::CreateImage());
- gfx::Image result2 = profiles::GetAvatarIconForMenu(gaia_picture, true);
+ // Test that a rectangular picture is changed.
+ gfx::Image rect_picture(gfx::test::CreateImage());
+ gfx::Image result2 = profiles::GetAvatarIconForMenu(rect_picture, true);
EXPECT_FALSE(gfx::test::IsEmpty(result2));
- EXPECT_FALSE(gfx::test::IsEqual(gaia_picture, result2));
+ EXPECT_FALSE(gfx::test::IsEqual(rect_picture, result2));
}
TEST(ProfileInfoUtilTest, WebUIIcon) {
@@ -52,11 +52,11 @@
EXPECT_FALSE(gfx::test::IsEmpty(result));
EXPECT_TRUE(gfx::test::IsEqual(profile_image, result));
- // Test that a GAIA picture is changed.
- gfx::Image gaia_picture(gfx::test::CreateImage());
- gfx::Image result2 = profiles::GetAvatarIconForWebUI(gaia_picture, true);
+ // Test that a rectangular picture is changed.
+ gfx::Image rect_picture(gfx::test::CreateImage());
+ gfx::Image result2 = profiles::GetAvatarIconForWebUI(rect_picture, true);
EXPECT_FALSE(gfx::test::IsEmpty(result2));
- EXPECT_FALSE(gfx::test::IsEqual(gaia_picture, result2));
+ EXPECT_FALSE(gfx::test::IsEqual(rect_picture, result2));
}
TEST(ProfileInfoUtilTest, TitleBarIcon) {
@@ -68,12 +68,12 @@
EXPECT_FALSE(gfx::test::IsEmpty(result));
EXPECT_TRUE(gfx::test::IsEqual(profile_image, result));
- // Test that a GAIA picture is changed.
- gfx::Image gaia_picture(gfx::test::CreateImage());
+ // Test that a rectangular picture is changed.
+ gfx::Image rect_picture(gfx::test::CreateImage());
gfx::Image result2 = profiles::GetAvatarIconForTitleBar(
- gaia_picture, true, 100, 40);
+ rect_picture, true, 100, 40);
EXPECT_FALSE(gfx::test::IsEmpty(result2));
- EXPECT_FALSE(gfx::test::IsEqual(gaia_picture, result2));
+ EXPECT_FALSE(gfx::test::IsEqual(rect_picture, result2));
}
} // namespace
diff --git a/chrome/browser/profiles/profile_list.h b/chrome/browser/profiles/profile_list.h
new file mode 100644
index 0000000..7092d20
--- /dev/null
+++ b/chrome/browser/profiles/profile_list.h
@@ -0,0 +1,35 @@
+// 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_PROFILES_PROFILE_LIST_H_
+#define CHROME_BROWSER_PROFILES_PROFILE_LIST_H_
+
+#include "chrome/browser/profiles/avatar_menu.h"
+
+class ProfileInfoInterface;
+
+// This model represents the profiles added to Chrome.
+class ProfileList {
+ public:
+ virtual ~ProfileList() {}
+
+ static ProfileList* Create(ProfileInfoInterface* profile_cache);
+
+ // Returns the number of profiles in the model.
+ virtual size_t GetNumberOfItems() const = 0;
+
+ // Returns the Item at the specified index.
+ virtual const AvatarMenu::Item& GetItemAt(size_t index) const = 0;
+
+ // Rebuilds the menu from the data source.
+ virtual void RebuildMenu() = 0;
+
+ // Returns the index in the menu of the specified profile.
+ virtual size_t MenuIndexFromProfileIndex(size_t index) = 0;
+
+ // Updates the path of the active browser's profile.
+ virtual void ActiveProfilePathChanged(base::FilePath& path) = 0;
+};
+
+#endif // CHROME_BROWSER_PROFILES_PROFILE_LIST_H_
diff --git a/chrome/browser/profiles/profile_list_desktop.cc b/chrome/browser/profiles/profile_list_desktop.cc
new file mode 100644
index 0000000..e94d375
--- /dev/null
+++ b/chrome/browser/profiles/profile_list_desktop.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/profiles/profile_list_desktop.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
+#include "chrome/browser/profiles/profile_info_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+ProfileListDesktop::ProfileListDesktop(ProfileInfoInterface* profile_cache)
+ : profile_info_(profile_cache) {
+}
+
+ProfileListDesktop::~ProfileListDesktop() {
+ ClearMenu();
+}
+
+// static
+ProfileList* ProfileList::Create(ProfileInfoInterface* profile_cache) {
+ return new ProfileListDesktop(profile_cache);
+}
+
+size_t ProfileListDesktop::GetNumberOfItems() const {
+ return items_.size();
+}
+
+const AvatarMenu::Item& ProfileListDesktop::GetItemAt(size_t index) const {
+ DCHECK_LT(index, items_.size());
+ return *items_[index];
+}
+
+void ProfileListDesktop::RebuildMenu() {
+ ClearMenu();
+
+ const size_t count = profile_info_->GetNumberOfProfiles();
+ for (size_t i = 0; i < count; ++i) {
+ bool is_gaia_picture =
+ profile_info_->IsUsingGAIAPictureOfProfileAtIndex(i) &&
+ profile_info_->GetGAIAPictureOfProfileAtIndex(i);
+
+ gfx::Image icon = profile_info_->GetAvatarIconOfProfileAtIndex(i);
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kNewProfileManagement)) {
+ // old avatar menu uses resized-small images
+ icon = profiles::GetAvatarIconForMenu(icon, is_gaia_picture);
+ }
+
+ AvatarMenu::Item* item = new AvatarMenu::Item(i, i, icon);
+ item->name = profile_info_->GetNameOfProfileAtIndex(i);
+ item->sync_state = profile_info_->GetUserNameOfProfileAtIndex(i);
+ item->managed = profile_info_->ProfileIsManagedAtIndex(i);
+ item->signed_in = !item->sync_state.empty();
+ if (!item->signed_in) {
+ item->sync_state = l10n_util::GetStringUTF16(
+ item->managed ? IDS_MANAGED_USER_AVATAR_LABEL :
+ IDS_PROFILES_LOCAL_PROFILE_STATE);
+ }
+ item->active = profile_info_->GetPathOfProfileAtIndex(i) ==
+ active_profile_path_;
+ item->signin_required = profile_info_->ProfileIsSigninRequiredAtIndex(i);
+ items_.push_back(item);
+ }
+}
+
+size_t ProfileListDesktop::MenuIndexFromProfileIndex(size_t index) {
+ // Menu indices correspond to indices in profile cache.
+ return index;
+}
+
+void ProfileListDesktop::ActiveProfilePathChanged(base::FilePath& path) {
+ active_profile_path_ = path;
+}
+
+void ProfileListDesktop::ClearMenu() {
+ STLDeleteElements(&items_);
+}
diff --git a/chrome/browser/profiles/profile_list_desktop.h b/chrome/browser/profiles/profile_list_desktop.h
new file mode 100644
index 0000000..f0e85ca
--- /dev/null
+++ b/chrome/browser/profiles/profile_list_desktop.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_PROFILES_PROFILE_LIST_DESKTOP_H_
+#define CHROME_BROWSER_PROFILES_PROFILE_LIST_DESKTOP_H_
+
+#include "chrome/browser/profiles/profile_list.h"
+
+#include <vector>
+
+class Browser;
+class ProfileInfoInterface;
+
+// This model represents the profiles added to desktop Chrome.
+class ProfileListDesktop : public ProfileList {
+ public:
+ explicit ProfileListDesktop(ProfileInfoInterface* profile_cache);
+ virtual ~ProfileListDesktop();
+
+ // ProfileList overrides:
+ virtual size_t GetNumberOfItems() const OVERRIDE;
+ virtual const AvatarMenu::Item& GetItemAt(size_t index) const OVERRIDE;
+ virtual void RebuildMenu() OVERRIDE;
+ virtual size_t MenuIndexFromProfileIndex(size_t index) OVERRIDE;
+ virtual void ActiveProfilePathChanged(base::FilePath& path) OVERRIDE;
+
+ private:
+ void ClearMenu();
+
+ // The cache that provides the profile information. Weak.
+ ProfileInfoInterface* profile_info_;
+
+ // The path of the currently active profile.
+ base::FilePath active_profile_path_;
+
+ // List of built "menu items."
+ std::vector<AvatarMenu::Item*> items_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileListDesktop);
+};
+
+#endif // CHROME_BROWSER_PROFILES_PROFILE_LIST_DESKTOP_H_
diff --git a/chrome/browser/profiles/avatar_menu_model_browsertest.cc b/chrome/browser/profiles/profile_list_desktop_browsertest.cc
similarity index 78%
rename from chrome/browser/profiles/avatar_menu_model_browsertest.cc
rename to chrome/browser/profiles/profile_list_desktop_browsertest.cc
index 2be0903..683ee3d 100644
--- a/chrome/browser/profiles/avatar_menu_model_browsertest.cc
+++ b/chrome/browser/profiles/profile_list_desktop_browsertest.cc
@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/profiles/avatar_menu_model.h"
-
#include "base/command_line.h"
#include "base/path_service.h"
#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/ui/browser.h"
@@ -27,9 +26,28 @@
base::MessageLoop::current()->Quit();
}
-typedef InProcessBrowserTest AvatarMenuModelTest;
+} // namespace
-IN_PROC_BROWSER_TEST_F(AvatarMenuModelTest, SignOut) {
+class ProfileListDesktopBrowserTest : public InProcessBrowserTest {
+ public:
+ ProfileListDesktopBrowserTest() {}
+
+ AvatarMenu* GetAvatarMenu(ProfileInfoCache* cache) {
+ // Reset the menu.
+ avatar_menu_.reset(new AvatarMenu(
+ cache,
+ NULL,
+ browser()));
+ return avatar_menu_.get();
+ }
+
+ private:
+ scoped_ptr<AvatarMenu> avatar_menu_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileListDesktopBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(ProfileListDesktopBrowserTest, SignOut) {
if (!profiles::IsMultipleProfilesEnabled())
return;
@@ -38,7 +56,8 @@
ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
size_t index = cache.GetIndexOfProfileWithPath(current_profile->GetPath());
- AvatarMenuModel model(&cache, NULL, browser());
+ AvatarMenu* menu = GetAvatarMenu(&cache);
+ menu->RebuildMenu();
BrowserList* browser_list =
BrowserList::GetInstance(chrome::GetActiveDesktop());
@@ -48,15 +67,15 @@
content::Source<Browser>(browser()));
EXPECT_FALSE(cache.ProfileIsSigninRequiredAtIndex(index));
- model.SetLogoutURL("about:blank");
- model.BeginSignOut();
+ menu->SetLogoutURL("about:blank");
+ menu->BeginSignOut();
EXPECT_TRUE(cache.ProfileIsSigninRequiredAtIndex(index));
window_close_observer.Wait(); // rely on test time-out for failure indication
EXPECT_EQ(0U, browser_list->size());
}
-IN_PROC_BROWSER_TEST_F(AvatarMenuModelTest, SwitchToProfile) {
+IN_PROC_BROWSER_TEST_F(ProfileListDesktopBrowserTest, SwitchToProfile) {
#if defined(OS_WIN) && defined(USE_ASH)
// Disable this test in Metro+Ash for now (http://crbug.com/262796).
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
@@ -84,27 +103,25 @@
content::RunMessageLoop();
ASSERT_EQ(cache.GetNumberOfProfiles(), 2U);
- AvatarMenuModel model(&cache, NULL, browser());
+ AvatarMenu* menu = GetAvatarMenu(&cache);
+ menu->RebuildMenu();
BrowserList* browser_list =
BrowserList::GetInstance(chrome::GetActiveDesktop());
EXPECT_EQ(1U, browser_list->size());
EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath());
// Open a browser window for the first profile.
- model.SwitchToProfile(cache.GetIndexOfProfileWithPath(path_profile1), false);
+ menu->SwitchToProfile(cache.GetIndexOfProfileWithPath(path_profile1), false);
EXPECT_EQ(1U, browser_list->size());
EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath());
// Open a browser window for the second profile.
- model.SwitchToProfile(cache.GetIndexOfProfileWithPath(path_profile2), false);
+ menu->SwitchToProfile(cache.GetIndexOfProfileWithPath(path_profile2), false);
EXPECT_EQ(2U, browser_list->size());
// Switch to the first profile without opening a new window.
- model.SwitchToProfile(cache.GetIndexOfProfileWithPath(path_profile1), false);
+ menu->SwitchToProfile(cache.GetIndexOfProfileWithPath(path_profile1), false);
EXPECT_EQ(2U, browser_list->size());
EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath());
EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath());
-
}
-
-} // namespace
diff --git a/chrome/browser/profiles/avatar_menu_model_unittest.cc b/chrome/browser/profiles/profile_list_desktop_unittest.cc
similarity index 63%
rename from chrome/browser/profiles/avatar_menu_model_unittest.cc
rename to chrome/browser/profiles/profile_list_desktop_unittest.cc
index 3a140f8..f1d923b 100644
--- a/chrome/browser/profiles/avatar_menu_model_unittest.cc
+++ b/chrome/browser/profiles/profile_list_desktop_unittest.cc
@@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/profile_list_desktop.h"
+
+#include <string>
#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/avatar_menu_observer.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/test/base/testing_browser_process.h"
@@ -20,25 +22,27 @@
namespace {
-class MockObserver : public AvatarMenuModelObserver {
+class MockObserver : public AvatarMenuObserver {
public:
MockObserver() : count_(0) {}
virtual ~MockObserver() {}
- virtual void OnAvatarMenuModelChanged(
- AvatarMenuModel* avatar_menu_model) OVERRIDE{
+ virtual void OnAvatarMenuChanged(
+ AvatarMenu* avatar_menu) OVERRIDE {
++count_;
}
- int change_count() { return count_; }
+ int change_count() const { return count_; }
private:
int count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockObserver);
};
-class AvatarMenuModelTest : public testing::Test {
+class ProfileListDesktopTest : public testing::Test {
public:
- AvatarMenuModelTest()
+ ProfileListDesktopTest()
: manager_(TestingBrowserProcess::GetGlobal()) {
}
@@ -50,15 +54,34 @@
#endif
}
- Browser* browser() { return NULL; }
+ AvatarMenu* GetAvatarMenu() {
+ // Reset the MockObserver.
+ mock_observer_.reset(new MockObserver());
+ EXPECT_EQ(0, change_count());
+
+ // Reset the model.
+ avatar_menu_.reset(new AvatarMenu(
+ manager()->profile_info_cache(),
+ mock_observer_.get(),
+ NULL));
+ avatar_menu_->RebuildMenu();
+ EXPECT_EQ(0, change_count());
+ return avatar_menu_.get();
+ }
TestingProfileManager* manager() { return &manager_; }
+ int change_count() const { return mock_observer_->change_count(); }
+
private:
TestingProfileManager manager_;
+ scoped_ptr<MockObserver> mock_observer_;
+ scoped_ptr<AvatarMenu> avatar_menu_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileListDesktopTest);
};
-TEST_F(AvatarMenuModelTest, InitialCreation) {
+TEST_F(ProfileListDesktopTest, InitialCreation) {
string16 name1(ASCIIToUTF16("Test 1"));
string16 name2(ASCIIToUTF16("Test 2"));
@@ -67,24 +90,21 @@
manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
name2, 0, std::string());
- MockObserver observer;
- EXPECT_EQ(0, observer.change_count());
+ AvatarMenu* model = GetAvatarMenu();
+ EXPECT_EQ(0, change_count());
- AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser());
- EXPECT_EQ(0, observer.change_count());
+ ASSERT_EQ(2U, model->GetNumberOfItems());
- ASSERT_EQ(2U, model.GetNumberOfItems());
-
- const AvatarMenuModel::Item& item1 = model.GetItemAt(0);
- EXPECT_EQ(0U, item1.model_index);
+ const AvatarMenu::Item& item1 = model->GetItemAt(0);
+ EXPECT_EQ(0U, item1.menu_index);
EXPECT_EQ(name1, item1.name);
- const AvatarMenuModel::Item& item2 = model.GetItemAt(1);
- EXPECT_EQ(1U, item2.model_index);
+ const AvatarMenu::Item& item2 = model->GetItemAt(1);
+ EXPECT_EQ(1U, item2.menu_index);
EXPECT_EQ(name2, item2.name);
}
-TEST_F(AvatarMenuModelTest, ActiveItem) {
+TEST_F(ProfileListDesktopTest, ActiveItem) {
string16 name1(ASCIIToUTF16("Test 1"));
string16 name2(ASCIIToUTF16("Test 2"));
@@ -93,15 +113,14 @@
manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
name2, 0, std::string());
- MockObserver observer;
- AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser());
- ASSERT_EQ(2U, model.GetNumberOfItems());
+ AvatarMenu* model = GetAvatarMenu();
+ ASSERT_EQ(2U, model->GetNumberOfItems());
// TODO(jeremy): Expand test to verify active profile index other than 0
// crbug.com/100871
- ASSERT_EQ(0U, model.GetActiveProfileIndex());
+ ASSERT_EQ(0U, model->GetActiveProfileIndex());
}
-TEST_F(AvatarMenuModelTest, ModifyingNameResortsCorrectly) {
+TEST_F(ProfileListDesktopTest, ModifyingNameResortsCorrectly) {
string16 name1(ASCIIToUTF16("Alpha"));
string16 name2(ASCIIToUTF16("Beta"));
string16 newname1(ASCIIToUTF16("Gamma"));
@@ -111,34 +130,33 @@
manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
name2, 0, std::string());
- MockObserver observer;
- AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser());
- EXPECT_EQ(0, observer.change_count());
+ AvatarMenu* model = GetAvatarMenu();
+ EXPECT_EQ(0, change_count());
- ASSERT_EQ(2U, model.GetNumberOfItems());
+ ASSERT_EQ(2U, model->GetNumberOfItems());
- const AvatarMenuModel::Item& item1 = model.GetItemAt(0);
- EXPECT_EQ(0U, item1.model_index);
+ const AvatarMenu::Item& item1 = model->GetItemAt(0);
+ EXPECT_EQ(0U, item1.menu_index);
EXPECT_EQ(name1, item1.name);
- const AvatarMenuModel::Item& item2 = model.GetItemAt(1);
- EXPECT_EQ(1U, item2.model_index);
+ const AvatarMenu::Item& item2 = model->GetItemAt(1);
+ EXPECT_EQ(1U, item2.menu_index);
EXPECT_EQ(name2, item2.name);
// Change name of the first profile, to trigger resorting of the profiles:
// now the first model should be named "beta", and the second be "gamma".
manager()->profile_info_cache()->SetNameOfProfileAtIndex(0, newname1);
- const AvatarMenuModel::Item& item1next = model.GetItemAt(0);
- EXPECT_GT(observer.change_count(), 1);
- EXPECT_EQ(0U, item1next.model_index);
+ const AvatarMenu::Item& item1next = model->GetItemAt(0);
+ EXPECT_GT(change_count(), 1);
+ EXPECT_EQ(0U, item1next.menu_index);
EXPECT_EQ(name2, item1next.name);
- const AvatarMenuModel::Item& item2next = model.GetItemAt(1);
- EXPECT_EQ(1U, item2next.model_index);
+ const AvatarMenu::Item& item2next = model->GetItemAt(1);
+ EXPECT_EQ(1U, item2next.menu_index);
EXPECT_EQ(newname1, item2next.name);
}
-TEST_F(AvatarMenuModelTest, ChangeOnNotify) {
+TEST_F(ProfileListDesktopTest, ChangeOnNotify) {
string16 name1(ASCIIToUTF16("Test 1"));
string16 name2(ASCIIToUTF16("Test 2"));
@@ -147,12 +165,9 @@
manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
name2, 0, std::string());
- MockObserver observer;
- EXPECT_EQ(0, observer.change_count());
-
- AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser());
- EXPECT_EQ(0, observer.change_count());
- EXPECT_EQ(2U, model.GetNumberOfItems());
+ AvatarMenu* model = GetAvatarMenu();
+ EXPECT_EQ(0, change_count());
+ EXPECT_EQ(2U, model->GetNumberOfItems());
string16 name3(ASCIIToUTF16("Test 3"));
manager()->CreateTestingProfile("p3", scoped_ptr<PrefServiceSyncable>(),
@@ -163,23 +178,25 @@
// profiles after the name change, and changing the avatar.
// On Windows, an extra change happens to set the shortcut name for the
// profile.
- EXPECT_GE(observer.change_count(), 4);
- ASSERT_EQ(3U, model.GetNumberOfItems());
+ // TODO(michaelpg): Determine why five changes happen on ChromeOS and
+ // investigate other platforms.
+ EXPECT_GE(change_count(), 4);
+ ASSERT_EQ(3U, model->GetNumberOfItems());
- const AvatarMenuModel::Item& item1 = model.GetItemAt(0);
- EXPECT_EQ(0U, item1.model_index);
+ const AvatarMenu::Item& item1 = model->GetItemAt(0);
+ EXPECT_EQ(0U, item1.menu_index);
EXPECT_EQ(name1, item1.name);
- const AvatarMenuModel::Item& item2 = model.GetItemAt(1);
- EXPECT_EQ(1U, item2.model_index);
+ const AvatarMenu::Item& item2 = model->GetItemAt(1);
+ EXPECT_EQ(1U, item2.menu_index);
EXPECT_EQ(name2, item2.name);
- const AvatarMenuModel::Item& item3 = model.GetItemAt(2);
- EXPECT_EQ(2U, item3.model_index);
+ const AvatarMenu::Item& item3 = model->GetItemAt(2);
+ EXPECT_EQ(2U, item3.menu_index);
EXPECT_EQ(name3, item3.name);
}
-TEST_F(AvatarMenuModelTest, ShowAvatarMenuInTrial) {
+TEST_F(ProfileListDesktopTest, ShowAvatarMenuInTrial) {
// If multiprofile mode is not enabled, the trial will not be enabled, so it
// isn't tested.
if (!profiles::IsMultipleProfilesEnabled())
@@ -189,18 +206,18 @@
base::FieldTrialList::CreateFieldTrial("ShowProfileSwitcher", "AlwaysShow");
#if defined(OS_CHROMEOS)
- EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu());
+ EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu());
#else
- EXPECT_TRUE(AvatarMenuModel::ShouldShowAvatarMenu());
+ EXPECT_TRUE(AvatarMenu::ShouldShowAvatarMenu());
#endif
}
-TEST_F(AvatarMenuModelTest, DontShowAvatarMenu) {
+TEST_F(ProfileListDesktopTest, DontShowAvatarMenu) {
string16 name1(ASCIIToUTF16("Test 1"));
manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(),
name1, 0, std::string());
- EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu());
+ EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu());
// If multiprofile mode is enabled, there are no other cases when we wouldn't
// show the menu.
@@ -211,10 +228,10 @@
manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(),
name2, 0, std::string());
- EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu());
+ EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu());
}
-TEST_F(AvatarMenuModelTest, ShowAvatarMenu) {
+TEST_F(ProfileListDesktopTest, ShowAvatarMenu) {
// If multiprofile mode is not enabled then the menu is never shown.
if (!profiles::IsMultipleProfilesEnabled())
return;
@@ -228,13 +245,13 @@
name2, 0, std::string());
#if defined(OS_CHROMEOS)
- EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu());
+ EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu());
#else
- EXPECT_TRUE(AvatarMenuModel::ShouldShowAvatarMenu());
+ EXPECT_TRUE(AvatarMenu::ShouldShowAvatarMenu());
#endif
}
-TEST_F(AvatarMenuModelTest, SyncState) {
+TEST_F(ProfileListDesktopTest, SyncState) {
// If multiprofile mode is not enabled then the menu is never shown.
if (!profiles::IsMultipleProfilesEnabled())
return;
@@ -247,18 +264,19 @@
manager()->profile_info_cache()->AddProfileToCache(
cache->GetUserDataDir().AppendASCII("p2"), ASCIIToUTF16("Test 2"),
string16(), 0, "TEST_ID");
- MockObserver observer;
- AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser());
- EXPECT_EQ(2U, model.GetNumberOfItems());
+
+ AvatarMenu* model = GetAvatarMenu();
+ model->RebuildMenu();
+ EXPECT_EQ(2U, model->GetNumberOfItems());
// Now check that the sync_state of a managed user shows the managed user
// avatar label instead.
base::string16 managed_user_label =
l10n_util::GetStringUTF16(IDS_MANAGED_USER_AVATAR_LABEL);
- const AvatarMenuModel::Item& item1 = model.GetItemAt(0);
+ const AvatarMenu::Item& item1 = model->GetItemAt(0);
EXPECT_NE(item1.sync_state, managed_user_label);
- const AvatarMenuModel::Item& item2 = model.GetItemAt(1);
+ const AvatarMenu::Item& item2 = model->GetItemAt(1);
EXPECT_EQ(item2.sync_state, managed_user_label);
}
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index bca991b..f84ac95 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -166,6 +166,13 @@
// Returns the full path to be used for guest profiles.
static base::FilePath GetGuestProfilePath();
+ // Get the path of the next profile directory and increment the internal
+ // count.
+ // Lack of side effects:
+ // This function doesn't actually create the directory or touch the file
+ // system.
+ base::FilePath GenerateNextProfileDirectoryPath();
+
// Returns a ProfileInfoCache object which can be used to get information
// about profiles without having to load them from disk.
ProfileInfoCache& GetProfileInfoCache();
@@ -280,13 +287,6 @@
// For ChromeOS, determines if profile should be otr.
bool ShouldGoOffTheRecord(Profile* profile);
- // Get the path of the next profile directory and increment the internal
- // count.
- // Lack of side effects:
- // This function doesn't actually create the directory or touch the file
- // system.
- base::FilePath GenerateNextProfileDirectoryPath();
-
void RunCallbacks(const std::vector<CreateCallback>& callbacks,
Profile* profile,
Profile::CreateStatus status);
diff --git a/chrome/browser/profiles/profile_window.cc b/chrome/browser/profiles/profile_window.cc
index 1cdbdcf..41ddea9 100644
--- a/chrome/browser/profiles/profile_window.cc
+++ b/chrome/browser/profiles/profile_window.cc
@@ -87,6 +87,18 @@
std::string());
}
+void CreateAndSwitchToNewProfile(chrome::HostDesktopType desktop_type) {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath();
+ profile_manager->CreateProfileAsync(new_path,
+ base::Bind(&OpenBrowserWindowForProfile,
+ true,
+ desktop_type),
+ string16(),
+ string16(),
+ std::string());
+}
+
void CloseGuestProfileWindows() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
Profile* profile = profile_manager->GetProfileByPath(
diff --git a/chrome/browser/profiles/profile_window.h b/chrome/browser/profiles/profile_window.h
index 9efc146..77fc4e2 100644
--- a/chrome/browser/profiles/profile_window.h
+++ b/chrome/browser/profiles/profile_window.h
@@ -34,6 +34,10 @@
chrome::HostDesktopType desktop_type,
bool always_create);
+// Creates a new profile from the next available profile directory, and
+// opens a new browser window for the profile once it is ready.
+void CreateAndSwitchToNewProfile(chrome::HostDesktopType desktop_type);
+
// Closes all browser windows that belong to the guest profile.
void CloseGuestProfileWindows();
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc
index 19409de..72e1295 100644
--- a/chrome/browser/profiles/profiles_state.cc
+++ b/chrome/browser/profiles/profiles_state.cc
@@ -11,6 +11,10 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/user_manager.h"
+#endif
+
namespace profiles {
bool IsMultipleProfilesEnabled() {
@@ -18,8 +22,7 @@
return false;
#endif
#if defined(OS_CHROMEOS)
- if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles))
- return false;
+ return chromeos::UserManager::IsMultipleProfilesAllowed();
#endif
return true;
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc
index d33d618..56383bf 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -50,6 +50,7 @@
void AddActionToExtensionActivityLog(
Profile* profile,
scoped_refptr<extensions::Action> action) {
+#if defined(ENABLE_EXTENSIONS)
// 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.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
@@ -66,6 +67,7 @@
extensions::ActivityLog::GetInstance(profile);
activity_log->LogAction(action);
}
+#endif
}
} // namespace
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 c9de2fa..1abde62 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -228,15 +228,15 @@
// Abort any prerenders that spawn requests that use invalid HTTP methods
// or invalid schemes.
if (prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id)) {
- if (!prerender::PrerenderManager::IsValidHttpMethod(method)) {
- prerender_tracker_->TryCancelOnIOThread(
- child_id, route_id, prerender::FINAL_STATUS_INVALID_HTTP_METHOD);
+ if (!prerender::PrerenderManager::IsValidHttpMethod(method) &&
+ prerender_tracker_->TryCancelOnIOThread(
+ child_id, route_id, prerender::FINAL_STATUS_INVALID_HTTP_METHOD)) {
return false;
}
- if (!prerender::PrerenderManager::DoesSubresourceURLHaveValidScheme(url)) {
+ if (!prerender::PrerenderManager::DoesSubresourceURLHaveValidScheme(url) &&
+ prerender_tracker_->TryCancelOnIOThread(
+ child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME)) {
ReportUnsupportedPrerenderScheme(url);
- prerender_tracker_->TryCancelOnIOThread(
- child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME);
return false;
}
}
@@ -251,11 +251,7 @@
ResourceType::Type resource_type,
int child_id,
int route_id,
- bool is_continuation_of_transferred_request,
ScopedVector<content::ResourceThrottle>* throttles) {
- if (is_continuation_of_transferred_request)
- ChromeURLRequestUserData::Delete(request);
-
ChromeURLRequestUserData* user_data =
ChromeURLRequestUserData::Create(request);
bool is_prerendering = prerender_tracker_->IsPrerenderingOnIOThread(
@@ -328,6 +324,20 @@
}
}
+void ChromeResourceDispatcherHostDelegate::WillTransferRequestToNewProcess(
+ int old_child_id,
+ int old_route_id,
+ int old_request_id,
+ int new_child_id,
+ int new_route_id,
+ int new_request_id) {
+ if (prerender_tracker_->IsPrerenderingOnIOThread(old_child_id,
+ old_route_id)) {
+ prerender_tracker_->UpdatePrerenderStateForTransfer(
+ old_child_id, old_route_id, new_child_id, new_route_id);
+ }
+}
+
void ChromeResourceDispatcherHostDelegate::DownloadStarting(
net::URLRequest* request,
content::ResourceContext* resource_context,
@@ -423,11 +433,11 @@
return false;
#else
- if (prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id)) {
+ if (prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id) &&
+ prerender_tracker_->TryCancel(
+ child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME)) {
ReportPrerenderSchemeCancelReason(
PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL);
- prerender_tracker_->TryCancel(
- child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME);
return false;
}
@@ -645,10 +655,10 @@
if (!prerender::PrerenderManager::DoesURLHaveValidScheme(redirect_url) &&
ResourceRequestInfo::ForRequest(request)->GetAssociatedRenderView(
&child_id, &route_id) &&
- prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id)) {
+ prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id) &&
+ prerender_tracker_->TryCancel(
+ child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME)) {
ReportUnsupportedPrerenderScheme(redirect_url);
- prerender_tracker_->TryCancel(
- child_id, route_id, prerender::FINAL_STATUS_UNSUPPORTED_SCHEME);
request->Cancel();
}
}
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 ed4fd83..26cb32a 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
@@ -50,8 +50,14 @@
ResourceType::Type resource_type,
int child_id,
int route_id,
- bool is_continuation_of_transferred_request,
ScopedVector<content::ResourceThrottle>* throttles) OVERRIDE;
+ virtual void WillTransferRequestToNewProcess(
+ int old_child_id,
+ int old_route_id,
+ int old_request_id,
+ int new_child_id,
+ int new_route_id,
+ int new_request_id) OVERRIDE;
virtual void DownloadStarting(
net::URLRequest* request,
content::ResourceContext* resource_context,
diff --git a/chrome/browser/renderer_host/pepper/device_id_fetcher.cc b/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
index 585d62d..7e66690 100644
--- a/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
+++ b/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
@@ -36,6 +36,28 @@
const uint32_t kSaltLength = 32;
+void GetMachineIDAsync(const DeviceIDFetcher::IDCallback& callback) {
+ std::string result;
+#if defined(OS_WIN) && defined(ENABLE_RLZ)
+ rlz_lib::GetMachineId(&result);
+#elif defined(OS_CHROMEOS)
+ result = chromeos::CryptohomeLibrary::Get()->GetSystemSalt();
+ if (result.empty()) {
+ // cryptohome must not be running; re-request after a delay.
+ const int64 kRequestSystemSaltDelayMs = 500;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&GetMachineIDAsync, callback),
+ base::TimeDelta::FromMilliseconds(kRequestSystemSaltDelayMs));
+ return;
+ }
+#else
+ // Not implemented for other platforms.
+ NOTREACHED();
+#endif
+ callback.Run(result);
+}
+
} // namespace
DeviceIDFetcher::DeviceIDFetcher(int render_process_id)
@@ -80,8 +102,6 @@
return profile_path.AppendASCII(kDRMIdentifierFile);
}
-// TODO(raymes): Change this to just return the device id salt and call it with
-// PostTaskAndReply once the legacy ChromeOS codepath is removed.
void DeviceIDFetcher::CheckPrefsOnUIThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -113,27 +133,35 @@
#if defined(OS_CHROMEOS)
// Try the legacy path first for ChromeOS. We pass the new salt in as well
// in case the legacy id doesn't exist.
- BrowserThread::PostBlockingPoolTask(FROM_HERE,
- base::Bind(&DeviceIDFetcher::ComputeOnBlockingPool, this,
+ BrowserThread::PostBlockingPoolTask(
+ FROM_HERE,
+ base::Bind(&DeviceIDFetcher::LegacyComputeOnBlockingPool,
+ this,
profile->GetPath(), salt));
#else
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&DeviceIDFetcher::ComputeOnIOThread, this, salt));
+ // Get the machine ID and call ComputeOnUIThread with salt + machine_id.
+ GetMachineIDAsync(base::Bind(&DeviceIDFetcher::ComputeOnUIThread,
+ this, salt));
#endif
}
+void DeviceIDFetcher::ComputeOnUIThread(const std::string& salt,
+ const std::string& machine_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-void DeviceIDFetcher::ComputeOnIOThread(const std::string& salt) {
- std::vector<uint8> salt_bytes;
- if (!base::HexStringToBytes(salt, &salt_bytes))
- salt_bytes.clear();
+ if (machine_id.empty()) {
+ LOG(ERROR) << "Empty machine id";
+ RunCallbackOnIOThread(std::string());
+ return;
+ }
// Build the identifier as follows:
// SHA256(machine-id||service||SHA256(machine-id||service||salt))
- std::string machine_id = GetMachineID();
- if (machine_id.empty() || salt_bytes.size() != kSaltLength) {
- NOTREACHED();
+ std::vector<uint8> salt_bytes;
+ if (!base::HexStringToBytes(salt, &salt_bytes))
+ salt_bytes.clear();
+ if (salt_bytes.size() != kSaltLength) {
+ LOG(ERROR) << "Unexpected salt bytes length: " << salt_bytes.size();
RunCallbackOnIOThread(std::string());
return;
}
@@ -159,8 +187,9 @@
// TODO(raymes): This is temporary code to migrate ChromeOS devices to the new
// scheme for generating device IDs. Delete this once we are sure most ChromeOS
// devices have been migrated.
-void DeviceIDFetcher::ComputeOnBlockingPool(const base::FilePath& profile_path,
- const std::string& salt) {
+void DeviceIDFetcher::LegacyComputeOnBlockingPool(
+ const base::FilePath& profile_path,
+ const std::string& salt) {
std::string id;
// First check if the legacy device ID file exists on ChromeOS. If it does, we
// should just return that.
@@ -171,13 +200,15 @@
return;
}
}
- // If we didn't find an ID, go back to the new code path to generate an ID.
+ // If we didn't find an ID, get the machine ID and call the new code path to
+ // generate an ID.
BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&DeviceIDFetcher::ComputeOnIOThread, this, salt));
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&GetMachineIDAsync,
+ base::Bind(&DeviceIDFetcher::ComputeOnUIThread,
+ this, salt)));
}
-
void DeviceIDFetcher::RunCallbackOnIOThread(const std::string& id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
@@ -189,19 +220,4 @@
callback_.Run(id);
}
-std::string DeviceIDFetcher::GetMachineID() {
-#if defined(OS_WIN) && defined(ENABLE_RLZ)
- std::string result;
- rlz_lib::GetMachineId(&result);
- return result;
-#elif defined(OS_CHROMEOS)
- chromeos::CryptohomeLibrary* c_home = chromeos::CryptohomeLibrary::Get();
- return c_home->GetSystemSalt();
-#else
- // Not implemented for other platforms.
- NOTREACHED();
- return "";
-#endif
-}
-
} // namespace chrome
diff --git a/chrome/browser/renderer_host/pepper/device_id_fetcher.h b/chrome/browser/renderer_host/pepper/device_id_fetcher.h
index 1373bdf..6df647d 100644
--- a/chrome/browser/renderer_host/pepper/device_id_fetcher.h
+++ b/chrome/browser/renderer_host/pepper/device_id_fetcher.h
@@ -50,23 +50,21 @@
~DeviceIDFetcher();
// Checks the preferences for DRM (whether DRM is enabled and getting the drm
- // salt) on the UI thread. These are passed to |ComputeOnIOThread|.
+ // salt) on the UI thread.
void CheckPrefsOnUIThread();
- // Compute the device ID on the IO thread with the given salt.
- void ComputeOnIOThread(const std::string& salt);
+ // Compute the device ID on the UI thread with the given salt and machine ID.
+ void ComputeOnUIThread(const std::string& salt,
+ const std::string& machine_id);
+
// Legacy method used to get the device ID for ChromeOS.
- void ComputeOnBlockingPool(const base::FilePath& profile_path,
- const std::string& salt);
+ void LegacyComputeOnBlockingPool(const base::FilePath& profile_path,
+ const std::string& salt);
// Runs the callback passed into Start() on the IO thread with the device ID
// or the empty string on failure.
void RunCallbackOnIOThread(const std::string& id);
- // Helper which returns an ID unique to the system. Returns an empty string if
- // the call fails.
- std::string GetMachineID();
-
friend class base::RefCountedThreadSafe<DeviceIDFetcher>;
// The callback to run when the ID has been fetched.
diff --git a/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.cc b/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.cc
deleted file mode 100644
index 667fd4a..0000000
--- a/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.cc
+++ /dev/null
@@ -1,63 +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/renderer_host/pepper/pepper_flash_device_id_host.h"
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "content/public/browser/browser_ppapi_host.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/host/dispatch_host_message.h"
-#include "ppapi/host/host_message_context.h"
-#include "ppapi/host/ppapi_host.h"
-#include "ppapi/proxy/ppapi_messages.h"
-
-using content::BrowserPpapiHost;
-
-namespace chrome {
-
-PepperFlashDeviceIDHost::PepperFlashDeviceIDHost(BrowserPpapiHost* host,
- PP_Instance instance,
- PP_Resource resource)
- : ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource),
- weak_factory_(this){
- int render_process_id, unused;
- host->GetRenderViewIDsForInstance(instance, &render_process_id, &unused);
- fetcher_ = new DeviceIDFetcher(render_process_id);
-}
-
-PepperFlashDeviceIDHost::~PepperFlashDeviceIDHost() {
-}
-
-int32_t PepperFlashDeviceIDHost::OnResourceMessageReceived(
- const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) {
- IPC_BEGIN_MESSAGE_MAP(PepperFlashDeviceIDHost, msg)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDeviceID_GetDeviceID,
- OnHostMsgGetDeviceID)
- IPC_END_MESSAGE_MAP()
- return PP_ERROR_FAILED;
-}
-
-int32_t PepperFlashDeviceIDHost::OnHostMsgGetDeviceID(
- const ppapi::host::HostMessageContext* context) {
- if (!fetcher_->Start(base::Bind(&PepperFlashDeviceIDHost::GotDeviceID,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext()))) {
- return PP_ERROR_INPROGRESS;
- }
- return PP_OK_COMPLETIONPENDING;
-}
-
-void PepperFlashDeviceIDHost::GotDeviceID(
- ppapi::host::ReplyMessageContext reply_context,
- const std::string& id) {
- reply_context.params.set_result(
- id.empty() ? PP_ERROR_FAILED : PP_OK);
- host()->SendReply(reply_context,
- PpapiPluginMsg_FlashDeviceID_GetDeviceIDReply(id));
-}
-
-} // namespace chrome
diff --git a/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.h b/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.h
deleted file mode 100644
index cde310c..0000000
--- a/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.h
+++ /dev/null
@@ -1,55 +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_RENDERER_HOST_PEPPER_PEPPER_FLASH_DEVICE_ID_HOST_H_
-#define CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FLASH_DEVICE_ID_HOST_H_
-
-#include <string>
-
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
-#include "ppapi/host/host_message_context.h"
-#include "ppapi/host/resource_host.h"
-
-namespace content {
-class BrowserPpapiHost;
-}
-
-namespace IPC {
-class Message;
-}
-
-namespace chrome {
-
-class PepperFlashDeviceIDHost : public ppapi::host::ResourceHost {
- public:
- PepperFlashDeviceIDHost(content::BrowserPpapiHost* host,
- PP_Instance instance,
- PP_Resource resource);
- virtual ~PepperFlashDeviceIDHost();
-
- // ResourceHost override.
- virtual int32_t OnResourceMessageReceived(
- const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
-
- private:
- // IPC message handler.
- int32_t OnHostMsgGetDeviceID(const ppapi::host::HostMessageContext* context);
-
- // Called by the fetcher when the device ID was retrieved, or the empty string
- // on error.
- void GotDeviceID(ppapi::host::ReplyMessageContext reply_context,
- const std::string& contents);
-
- scoped_refptr<DeviceIDFetcher> fetcher_;
-
- base::WeakPtrFactory<PepperFlashDeviceIDHost> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperFlashDeviceIDHost);
-};
-
-} // namespace chrome
-
-#endif // CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FLASH_DEVICE_ID_HOST_H_
diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc
index a0f57f9..212a669 100644
--- a/chrome/browser/renderer_preferences_util.cc
+++ b/chrome/browser/renderer_preferences_util.cc
@@ -19,21 +19,20 @@
#include "ui/gfx/gtk_util.h"
#endif
-#if defined(USE_AURA)
-#include "ui/views/controls/textfield/native_textfield_views.h"
+#if defined(TOOLKIT_VIEWS)
+#include "ui/views/controls/textfield/textfield.h"
+#endif
+
+#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/themes/theme_service_factory.h"
+#include "ui/views/linux_ui/linux_ui.h"
#endif
namespace renderer_preferences_util {
namespace {
-#if defined(TOOLKIT_GTK)
-// Dividing GTK's cursor blink cycle time (in milliseconds) by this value yields
-// an appropriate value for content::RendererPreferences::caret_blink_interval.
-// This matches the logic in the WebKit GTK port.
-const double kGtkCursorBlinkCycleFactor = 2000.0;
-#endif // defined(TOOLKIT_GTK)
-
#if defined(OS_LINUX) || defined(OS_ANDROID)
content::RendererPreferencesHintingEnum GetRendererPreferencesHintingEnum(
gfx::FontRenderParams::Hinting hinting) {
@@ -100,6 +99,10 @@
prefs->inactive_selection_fg_color =
theme_service->get_inactive_selection_fg_color();
+ // Dividing GTK's cursor blink cycle time (in milliseconds) by this value
+ // yields an appropriate value for RendererPreferences::caret_blink_interval.
+ // This matches the logic in the WebKit GTK port.
+ const double kGtkCursorBlinkCycleFactor = 2000.0;
const base::TimeDelta cursor_blink_time = gfx::GetCursorBlinkCycle();
prefs->caret_blink_interval =
cursor_blink_time.InMilliseconds() ?
@@ -115,11 +118,6 @@
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.
- prefs->caret_blink_interval =
- views::NativeTextfieldViews::kCursorBlinkCycleMs / 2.0 / 1000;
prefs->touchpad_fling_profile[0] =
pref_service->GetDouble(prefs::kFlingCurveTouchpadAlpha);
@@ -135,6 +133,32 @@
pref_service->GetDouble(prefs::kFlingCurveTouchscreenGamma);
#endif
+#if defined(TOOLKIT_VIEWS)
+ prefs->caret_blink_interval = views::Textfield::GetCaretBlinkMs() / 1000.0;
+#endif
+
+#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ views::LinuxUI* linux_ui = views::LinuxUI::instance();
+ if (linux_ui) {
+ if (ThemeServiceFactory::GetForProfile(profile)->UsingNativeTheme()) {
+ prefs->focus_ring_color = linux_ui->GetFocusRingColor();
+ prefs->thumb_active_color = linux_ui->GetThumbActiveColor();
+ prefs->thumb_inactive_color = linux_ui->GetThumbInactiveColor();
+ prefs->track_color = linux_ui->GetTrackColor();
+ prefs->active_selection_bg_color = linux_ui->GetActiveSelectionBgColor();
+ prefs->active_selection_fg_color = linux_ui->GetActiveSelectionFgColor();
+ prefs->inactive_selection_bg_color =
+ linux_ui->GetInactiveSelectionBgColor();
+ prefs->inactive_selection_fg_color =
+ linux_ui->GetInactiveSelectionFgColor();
+ }
+
+ // If we have a linux_ui object, set the caret blink interval regardless of
+ // whether we're in native theme mode.
+ prefs->caret_blink_interval = linux_ui->GetCursorBlinkInterval();
+ }
+#endif
+
#if defined(OS_LINUX) || defined(OS_ANDROID)
const gfx::FontRenderParams& params = gfx::GetDefaultWebKitFontRenderParams();
prefs->should_antialias_text = params.antialiasing;
@@ -145,6 +169,11 @@
prefs->subpixel_rendering =
GetRendererPreferencesSubpixelRenderingEnum(params.subpixel_rendering);
#endif
+
+#if !defined(OS_MACOSX)
+ prefs->plugin_fullscreen_allowed =
+ pref_service->GetBoolean(prefs::kFullscreenAllowed);
+#endif
}
-} // renderer_preferences_util
+} // namespace renderer_preferences_util
diff --git a/chrome/browser/resources/about_credits.tmpl b/chrome/browser/resources/about_credits.tmpl
index 877aca9..2797246 100644
--- a/chrome/browser/resources/about_credits.tmpl
+++ b/chrome/browser/resources/about_credits.tmpl
@@ -50,6 +50,9 @@
.licence h3 {
margin-top:0px;
}
+.licence pre {
+ white-space: pre-wrap;
+}
</style>
</head>
<body>
diff --git a/chrome/browser/resources/apps_debugger/images/2x/search.png b/chrome/browser/resources/apps_debugger/images/2x/search.png
index bf26fe1..cf37201 100644
--- a/chrome/browser/resources/apps_debugger/images/2x/search.png
+++ b/chrome/browser/resources/apps_debugger/images/2x/search.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/2x/search_clear.png b/chrome/browser/resources/apps_debugger/images/2x/search_clear.png
index 28f8e0d..d01c24d 100644
--- a/chrome/browser/resources/apps_debugger/images/2x/search_clear.png
+++ b/chrome/browser/resources/apps_debugger/images/2x/search_clear.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/2x/search_clear_active.png b/chrome/browser/resources/apps_debugger/images/2x/search_clear_active.png
index 9952208..5190800 100644
--- a/chrome/browser/resources/apps_debugger/images/2x/search_clear_active.png
+++ b/chrome/browser/resources/apps_debugger/images/2x/search_clear_active.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/2x/search_clear_hover.png b/chrome/browser/resources/apps_debugger/images/2x/search_clear_hover.png
index 77ac1c0..171bbf9 100644
--- a/chrome/browser/resources/apps_debugger/images/2x/search_clear_hover.png
+++ b/chrome/browser/resources/apps_debugger/images/2x/search_clear_hover.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/search.png b/chrome/browser/resources/apps_debugger/images/search.png
index 51cbca0..63039fa 100644
--- a/chrome/browser/resources/apps_debugger/images/search.png
+++ b/chrome/browser/resources/apps_debugger/images/search.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/search_clear.png b/chrome/browser/resources/apps_debugger/images/search_clear.png
index b22b66b..679bd2c 100644
--- a/chrome/browser/resources/apps_debugger/images/search_clear.png
+++ b/chrome/browser/resources/apps_debugger/images/search_clear.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/search_clear_active.png b/chrome/browser/resources/apps_debugger/images/search_clear_active.png
index 77ffb94..b669a17 100644
--- a/chrome/browser/resources/apps_debugger/images/search_clear_active.png
+++ b/chrome/browser/resources/apps_debugger/images/search_clear_active.png
Binary files differ
diff --git a/chrome/browser/resources/apps_debugger/images/search_clear_hover.png b/chrome/browser/resources/apps_debugger/images/search_clear_hover.png
index 872ea1b..e0906b7 100644
--- a/chrome/browser/resources/apps_debugger/images/search_clear_hover.png
+++ b/chrome/browser/resources/apps_debugger/images/search_clear_hover.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/about_os_credits.html b/chrome/browser/resources/chromeos/about_os_credits.html
index 26f99e1..4cb7c2a 100644
--- a/chrome/browser/resources/chromeos/about_os_credits.html
+++ b/chrome/browser/resources/chromeos/about_os_credits.html
@@ -82,32 +82,6 @@
<h2>List of packages used in Google Chrome OS:</h2>
<!-- Chromium <3s the following projects -->
<div class="product">
-<span class="title">Linux-2.6</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.kernel.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">X.Org-1.9.3</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.x.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#X'>Gentoo Package Stock License X</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">acl-2.2.51</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://savannah.nongnu.org/projects/acl">homepage</a></span>
@@ -134,19 +108,6 @@
<div class="product">
-<span class="title">alsa-headers-1.0.25</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.alsa-project.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">alsa-lib-1.0.25</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.alsa-project.org/">homepage</a></span>
@@ -187,43 +148,6 @@
<div class="product">
-<span class="title">argparse-1.2.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://code.google.com/p/argparse/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license argparse-1.2.1/LICENSE.txt:
-
-argparse is (c) 2006-2009 Steven J. Bethard <steven.bethard@gmail.com>.
-
-The argparse module was contributed to Python as of Python 2.7 and thus
-was licensed under the Python license. Same license applies to all files in
-the argparse package project.
-
-For details about the Python License, please see doc/Python-License.txt.
-
-History
--------
-
-Before (and including) argparse 1.1, the argparse package was licensed under
-Apache License v2.0.
-
-After argparse 1.1, all project files from the argparse project were deleted
-due to license compatibility issues between Apache License 2.0 and GNU GPL v2.
-
-The project repository then had a clean start with some files taken from
-Python 2.7.1, so definitely all files are under Python License now.
-
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-<li><a href='#PSF-2'>Gentoo Package Stock License PSF-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">ath3k-0.0.1</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.atheros.com/">homepage</a></span>
@@ -276,65 +200,13 @@
<div class="product">
-<span class="title">autoconf-2.13</span>
+<span class="title">avahi-0.6.31</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gnu.org/software/autoconf/autoconf.html">homepage</a></span>
+<span class="homepage"><a href="http://avahi.org/">homepage</a></span>
<div class="licence">
<pre></pre>
<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">autoconf-2.68</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gnu.org/software/autoconf/autoconf.html">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-3'>Gentoo Package Stock License GPL-3</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">autoconf-wrapper-10</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gentoo.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">automake-1.11.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://sources.redhat.com/automake/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">automake-wrapper-5</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gentoo.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
+<li><a href='#LGPL-2.1'>Gentoo Package Stock License LGPL-2.1</a></li>
</ul>
</div>
</div>
@@ -380,36 +252,23 @@
<div class="product">
-<span class="title">binutils-2.22</span>
+<span class="title">bluez-5.4</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://sources.redhat.com/binutils/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-3'>Gentoo Package Stock License GPL-3</a></li>
-<li><a href='#LGPL-3'>Gentoo Package Stock License LGPL-3</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">binutils-config-3</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gentoo.org/">homepage</a></span>
+<span class="homepage"><a href="http://www.bluez.org/">homepage</a></span>
<div class="licence">
<pre></pre>
<ul>
<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
+<li><a href='#LGPL-2.1'>Gentoo Package Stock License LGPL-2.1</a></li>
</ul>
</div>
</div>
<div class="product">
-<span class="title">bluez-5.4</span>
+<span class="title">brltty-4.5</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.bluez.org/">homepage</a></span>
+<span class="homepage"><a href="http://mielke.cc/brltty/">homepage</a></span>
<div class="licence">
<pre></pre>
<ul>
@@ -434,19 +293,6 @@
<div class="product">
-<span class="title">busybox-1.21.0</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.busybox.net/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">bzip2-1.0.6</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.bzip.org/">homepage</a></span>
@@ -533,7 +379,7 @@
<div class="product">
-<span class="title">chinese-input-1.0.0.0</span>
+<span class="title">chinese-input-1.1.0.0</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.google.com/inputtools/">homepage</a></span>
<div class="licence">
@@ -546,7 +392,7 @@
<div class="product">
-<span class="title">chromeos-hangul-1.0.0.12</span>
+<span class="title">chromeos-hangul-1.1.0.0</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="https://code.google.com/p/google-input-tools/">homepage</a></span>
<div class="licence">
@@ -559,7 +405,7 @@
<div class="product">
-<span class="title">chromeos-keyboards-1.1.3.0</span>
+<span class="title">chromeos-keyboards-1.1.4.0</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="https://code.google.com/p/google-input-tools">homepage</a></span>
<div class="licence">
@@ -585,6 +431,19 @@
<div class="product">
+<span class="title">coreboot-2013.04</span>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<span class="homepage"><a href="http://www.coreboot.org/">homepage</a></span>
+<div class="licence">
+<pre></pre>
+<ul>
+<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
+</ul>
+</div>
+</div>
+
+
+<div class="product">
<span class="title">coreutils-8.20</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.gnu.org/software/coreutils/">homepage</a></span>
@@ -683,6 +542,118 @@
<div class="product">
+<span class="title">crosextrafonts-carlito-20130920</span>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<span class="homepage"><a href="">homepage</a></span>
+<div class="licence">
+<pre>Scanned Source license crosextrafonts-carlito-20130920/LICENSE:
+
+Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Carlito".
+
+This Font Software is licensed under the SIL Open Font License,
+Version 1.1 as shown below.
+
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+
+PREAMBLE The goals of the Open Font License (OFL) are to stimulate
+worldwide development of collaborative font projects, to support the font
+creation efforts of academic and linguistic communities, and to provide
+a free and open framework in which fonts may be shared and improved in
+partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves.
+The fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply to
+any document created using the fonts or their derivatives.
+
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such.
+This may include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components
+as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting ? in part or in whole ?
+any of the components of the Original Version, by changing formats or
+by porting the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical writer
+or other person who contributed to the Font Software.
+
+
+PERMISSION & CONDITIONS
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,in
+ Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+ redistributed and/or sold with any software, provided that each copy
+ contains the above copyright notice and this license. These can be
+ included either as stand-alone text files, human-readable headers or
+ in the appropriate machine-readable metadata fields within text or
+ binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+ Name(s) unless explicit written permission is granted by the
+ corresponding Copyright Holder. This restriction only applies to the
+ primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+ Software shall not be used to promote, endorse or advertise any
+ Modified Version, except to acknowledge the contribution(s) of the
+ Copyright Holder(s) and the Author(s) or with their explicit written
+ permission.
+
+5) The Font Software, modified or unmodified, in part or in whole, must
+ be distributed entirely under this license, and must not be distributed
+ under any other license. The requirement for fonts to remain under
+ this license does not apply to any document created using the Font
+ Software.
+
+
+
+TERMINATION
+This license becomes null and void if any of the above conditions are not met.
+
+
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
+DEALINGS IN THE FONT SOFTWARE.
+
+
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+</pre>
+<ul>
+<li><a href='#OFL-1.1'>Gentoo Package Stock License OFL-1.1</a></li>
+</ul>
+</div>
+</div>
+
+
+<div class="product">
<span class="title">ctemplate-1.0</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://code.google.com/p/google-ctemplate/">homepage</a></span>
@@ -768,15 +739,15 @@
<div class="product">
-<span class="title">curl-7.23.1</span>
+<span class="title">curl-7.31.0</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://curl.haxx.se/">homepage</a></span>
<div class="licence">
-<pre>Scanned Source license curl-7.23.1/COPYING:
+<pre>Scanned Source license curl-7.31.0/COPYING:
COPYRIGHT AND PERMISSION NOTICE
-Copyright (c) 1996 - 2011, Daniel Stenberg, <daniel@haxx.se>.
+Copyright (c) 1996 - 2013, Daniel Stenberg, <daniel@haxx.se>.
All rights reserved.
@@ -906,7 +877,7 @@
<div class="product">
-<span class="title">dbus-glib-0.100</span>
+<span class="title">dbus-glib-0.100.2</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://dbus.freedesktop.org/">homepage</a></span>
<div class="licence">
@@ -920,32 +891,6 @@
<div class="product">
-<span class="title">ddccontrol-0.4.2</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://ddccontrol.sourceforge.net/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">ddccontrol-db-20061014</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://ddccontrol.sourceforge.net/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">dejavu-2.33</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://dejavu.sourceforge.net/">homepage</a></span>
@@ -972,20 +917,7 @@
<div class="product">
-<span class="title">diffutils-3.2</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gnu.org/software/diffutils/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">dmidecode-2.10</span>
+<span class="title">dmidecode-2.11</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.nongnu.org/dmidecode/">homepage</a></span>
<div class="licence">
@@ -998,19 +930,6 @@
<div class="product">
-<span class="title">docbook-xml-dtd-4.1.2</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.docbook.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#as-is'>Gentoo Package Stock License as-is</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">dosfstools-3.0.9</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.daniel-baumann.ch/software/dosfstools/">homepage</a></span>
@@ -2465,19 +2384,6 @@
<div class="product">
-<span class="title">eselect-opengl-1.2.4</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gentoo.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">eselect-python-20100321</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.gentoo.org">homepage</a></span>
@@ -2632,156 +2538,6 @@
<div class="product">
-<span class="title">flex-2.5.35_p10</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://flex.sourceforge.net/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#FLEX'>Gentoo Package Stock License FLEX</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">font-util-1.2.0</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://xorg.freedesktop.org/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license font-util-1.2.0/COPYING:
-
-Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
- ------------------------------------------------------------------------
-
-Copyright (c) 2003 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Ben Collver <collver1@attbi.com>.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
- ------------------------------------------------------------------------
-
-Copyright (c) 2006 Martin Husemann.
-Copyright (c) 2007 Joerg Sonnenberger.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior
- written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
- ------------------------------------------------------------------------
-
-Copyright 2005 Red Hat, Inc
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the copyright holders shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from the copyright holders.
-
- ------------------------------------------------------------------------
-
-Copyright (c) 1991-2003 Unicode, Inc. All Rights reserved.
-
-This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
-No claims are made as to fitness for any particular purpose. No
-warranties of any kind are expressed or implied. The recipient
-agrees to determine applicability of information provided. If this
-file has been provided on optical media by Unicode, Inc., the sole
-remedy for any claim will be exchange of defective media within 90
-days of receipt.
-
-Unicode, Inc. hereby grants the right to freely use the information
-supplied in this file in the creation of products supporting the
-Unicode Standard, and to make copies of this file in any form for
-internal or external distribution as long as this notice remains
-attached.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">fontconfig-2.7.1</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://fontconfig.org/">homepage</a></span>
@@ -2835,13 +2591,15 @@
<div class="product">
-<span class="title">gdbm-1.9.1</span>
+<span class="title">gcc-libs-0.0.1</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gnu.org/software/gdbm/">homepage</a></span>
+<span class="homepage"><a href="">homepage</a></span>
<div class="licence">
<pre></pre>
<ul>
<li><a href='#GPL-3'>Gentoo Package Stock License GPL-3</a></li>
+<li><a href='#LGPL-3'>Gentoo Package Stock License LGPL-3</a></li>
+<li><a href='#FDL-1.2'>Gentoo Package Stock License FDL-1.2</a></li>
</ul>
</div>
</div>
@@ -3159,19 +2917,6 @@
<div class="product">
-<span class="title">glproto-1.4.14</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.x.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#SGI-B-2.0'>Gentoo Package Stock License SGI-B-2.0</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">glu-9.0.0</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://cgit.freedesktop.org/mesa/glu/">homepage</a></span>
@@ -3185,292 +2930,6 @@
<div class="product">
-<span class="title">gmock-1.6.0</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://code.google.com/p/googlemock/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license gmock-1.6.0/COPYING:
-
-Copyright 2008, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license gmock-1.6.0/gtest/COPYING:
-
-Copyright 2008, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license gmock-1.6.0/scripts/generator/COPYING:
-
-
- 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] Neal Norwitz
- Portions Copyright [2007] Google Inc.
-
- 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.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">gmp-5.0.2_p1</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://gmplib.org/">homepage</a></span>
@@ -3497,51 +2956,6 @@
<div class="product">
-<span class="title">gtest-1.6.0</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://code.google.com/p/googletest/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license gtest-1.6.0/COPYING:
-
-Copyright 2008, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">gtk+-2.20.1</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.gtk.org/">homepage</a></span>
@@ -3555,20 +2969,6 @@
<div class="product">
-<span class="title">gtk-doc-am-1.18</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gtk.org/gtk-doc/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-<li><a href='#FDL-1.1'>Gentoo Package Stock License FDL-1.1</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">gzip-1.5</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.gnu.org/software/gzip/">homepage</a></span>
@@ -3690,11 +3090,11 @@
<div class="product">
-<span class="title">hdparm-9.20</span>
+<span class="title">hdparm-9.39</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://sourceforge.net/projects/hdparm/">homepage</a></span>
<div class="licence">
-<pre>Scanned Source license hdparm-9.20/LICENSE.TXT:
+<pre>Scanned Source license hdparm-9.39/LICENSE.TXT:
BSD-Style Open Source License:
@@ -3708,7 +3108,7 @@
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Scanned Source license hdparm-9.20/debian/copyright:
+Scanned Source license hdparm-9.39/debian/copyright:
This package was debianized by Christopher L Cheney <ccheney@debian.org> on
Wed, 21 Nov 2001 15:51:14 -0600.
@@ -3731,19 +3131,6 @@
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
</pre>
<ul>
-<li><a href='#as-is'>Gentoo Package Stock License as-is</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">htpdate-1.0.4</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.clevervest.com/htp/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
</ul>
</div>
@@ -3777,32 +3164,6 @@
<div class="product">
-<span class="title">ibus-english-m-0.0.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://github.com/yusukes/ibus-zinnia">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#Apache-2.0'>Gentoo Package Stock License Apache-2.0</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">ibus-m17n-1.3.3</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://code.google.com/p/ibus/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">iniparser-3.0b</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://ndevilla.free.fr/iniparser/">homepage</a></span>
@@ -3841,7 +3202,7 @@
<div class="product">
-<span class="title">input-tools-0.0.1</span>
+<span class="title">input-tools-2.4.1.0</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.google.com/inputtools">homepage</a></span>
<div class="licence">
@@ -3854,19 +3215,6 @@
<div class="product">
-<span class="title">intltool-0.41.0</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://edge.launchpad.net/intltool/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">iotools-1.4</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://code.google.com/p/iotools/">homepage</a></span>
@@ -3939,32 +3287,6 @@
<div class="product">
-<span class="title">jsonrpclib-0_pre20110820</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="https://github.com/joshmarshall/jsonrpclib">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#Apache-2.0'>Gentoo Package Stock License Apache-2.0</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">kbd-1.15.3</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://freshmeat.net/projects/kbd/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">keyutils-1.1</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.kernel.org/">homepage</a></span>
@@ -4098,19 +3420,6 @@
<div class="product">
-<span class="title">ladspa-sdk-1.13</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.ladspa.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#LGPL-2.1'>Gentoo Package Stock License LGPL-2.1</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">laptop-mode-tools-1.59</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.samwel.tk/laptop_mode/">homepage</a></span>
@@ -4124,836 +3433,6 @@
<div class="product">
-<span class="title">leveldb-0.0.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://code.google.com/p/leveldb/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license leveldb-0.0.1/LICENSE:
-
-Copyright (c) 2011 The LevelDB Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">libaio-0.3.109</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.kernel.org/pub/linux/kernel/people/andrea/libaio/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#LGPL-2'>Gentoo Package Stock License LGPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">libatomic_ops-7.2d</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.hpl.hp.com/research/linux/atomic_ops/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license gc-7.2/libatomic_ops/COPYING:
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license gc-7.2/libatomic_ops/doc/COPYING:
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license gc-7.2/libatomic_ops/doc/LICENSING.txt:
-
-Our intent is to make it easy to use libatomic_ops, in
-both free and proprietary software. Hence most code that we expect to be
-linked into a client application is covered by an MIT-style license.
-
-A few library routines are covered by the GNU General Public License.
-These are put into a separate library, libatomic_ops_gpl.a .
-
-The low-level part of the library is mostly covered by the following
-license:
-
-----------------------------------------
-
-Copyright (c) ...
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
---------------------------------
-
-A few files in the sysdeps directory were inherited in part from the
-Boehm-Demers-Weiser conservative garbage collector, and are covered by
-its license, which is similar in spirit:
-
---------------------------------
-
-Copyright (c) ...
-
-THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
-OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
-
-Permission is hereby granted to use or copy this program
-for any purpose, provided the above notices are retained on all copies.
-Permission to modify the code and to distribute modified code is granted,
-provided the above notices are retained, and a notice that the code was
-modified is included with the above copyright notice.
-
-----------------------------------
-
-A few files are covered by the GNU General Public License. (See file
-"COPYING".) This applies only to test code, sample applications,
-and the libatomic_ops_gpl portion of the library.
-Thus libatomic_ops_gpl should generally not be linked into proprietary code.
-(This distinction was motivated by patent considerations.)
-
-It is possible that the license of the GPL pieces may be changed for
-future versions to make them more consistent with the rest of the package.
-If you submit patches, and have strong preferences about licensing, please
-express them.
-
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-<li><a href='#boehm-gc'>Gentoo Package Stock License boehm-gc</a></li>
-<li><a href='#GPL-2+'>Gentoo Package Stock License GPL-2+</a></li>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">libcap-2.17</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.friedhoff.org/posixfilecaps.html">homepage</a></span>
@@ -5058,13 +3537,13 @@
<div class="product">
-<span class="title">libchewing-0.3.2</span>
+<span class="title">libdaemon-0.14</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://chewing.csie.net/">homepage</a></span>
+<span class="homepage"><a href="http://0pointer.de/lennart/projects/libdaemon/">homepage</a></span>
<div class="licence">
<pre></pre>
<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
+<li><a href='#LGPL-2.1'>Gentoo Package Stock License LGPL-2.1</a></li>
</ul>
</div>
</div>
@@ -5193,19 +3672,6 @@
<div class="product">
-<span class="title">libhangul-0.0.10</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://kldp.net/projects/hangul/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#LGPL-2.1'>Gentoo Package Stock License LGPL-2.1</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">libmnl-1.0.3</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://netfilter.org/projects/libmnl">homepage</a></span>
@@ -6031,19 +4497,6 @@
<div class="product">
-<span class="title">libtool-2.4</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gnu.org/software/libtool/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">libusb-0.1.12</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://libusb.sourceforge.net/">homepage</a></span>
@@ -6268,17 +4721,17 @@
<div class="product">
-<span class="title">libxml2-2.7.8</span>
+<span class="title">libxml2-2.9.1</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.xmlsoft.org/">homepage</a></span>
<div class="licence">
-<pre>Scanned Source license libxml2-2.7.8/COPYING:
+<pre>Scanned Source license libxml2-2.9.1/COPYING:
Except where otherwise noted in the source code (e.g. the files hash.c,
list.c and the trio files, which are covered by a similar licence but
with different Copyright notices) all the files are:
- Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved.
+ Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -6293,24 +4746,20 @@
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
-NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Daniel Veillard shall not
-be used in advertising or otherwise to promote the sale, use or other deal-
-ings in this Software without prior written authorization from him.
-
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Scanned Source license libxml2-2.7.8/Copyright:
+Scanned Source license libxml2-2.9.1/Copyright:
Except where otherwise noted in the source code (e.g. the files hash.c,
list.c and the trio files, which are covered by a similar licence but
with different Copyright notices) all the files are:
- Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved.
+ Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -6325,14 +4774,10 @@
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
-NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Daniel Veillard shall not
-be used in advertising or otherwise to promote the sale, use or other deal-
-ings in this Software without prior written authorization from him.
-
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
</pre>
@@ -6344,6 +4789,19 @@
<div class="product">
+<span class="title">Linux-2.6</span>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<span class="homepage"><a href="http://www.kernel.org/">homepage</a></span>
+<div class="licence">
+<pre></pre>
+<ul>
+<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
+</ul>
+</div>
+</div>
+
+
+<div class="product">
<span class="title">linux-headers-3.4</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.kernel.org/">homepage</a></span>
@@ -6357,219 +4815,6 @@
<div class="product">
-<span class="title">llvm-3.2</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://llvm.org/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license llvm-3.2.src/LICENSE.TXT:
-
-==============================================================================
-LLVM Release License
-==============================================================================
-University of Illinois/NCSA
-Open Source License
-
-Copyright (c) 2003-2012 University of Illinois at Urbana-Champaign.
-All rights reserved.
-
-Developed by:
-
- LLVM Team
-
- University of Illinois at Urbana-Champaign
-
- http://llvm.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal with
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimers.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimers in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the names of the LLVM Team, University of Illinois at
- Urbana-Champaign, nor the names of its contributors may be used to
- endorse or promote products derived from this Software without specific
- prior written permission.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
-SOFTWARE.
-
-==============================================================================
-Copyrights and Licenses for Third Party Software Distributed with LLVM:
-==============================================================================
-The LLVM software contains code written by third parties. Such software will
-have its own individual LICENSE.TXT file in the directory in which it appears.
-This file will describe the copyrights, license, and restrictions which apply
-to that code.
-
-The disclaimer of warranty in the University of Illinois Open Source License
-applies to all code in the LLVM Distribution, and nothing in any of the
-other licenses gives permission to use the names of the LLVM Team or the
-University of Illinois to endorse or promote products derived from this
-Software.
-
-The following pieces of software have additional or alternate copyrights,
-licenses, and/or restrictions:
-
-Program Directory
-------- ---------
-Autoconf llvm/autoconf
- llvm/projects/ModuleMaker/autoconf
- llvm/projects/sample/autoconf
-CellSPU backend llvm/lib/Target/CellSPU/README.txt
-Google Test llvm/utils/unittest/googletest
-OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
-pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license llvm-3.2.src/autoconf/LICENSE.TXT:
-
-------------------------------------------------------------------------------
-Autoconf Files
-------------------------------------------------------------------------------
-All autoconf files are licensed under the LLVM license with the following
-additions:
-
-llvm/autoconf/install-sh:
- This script is licensed under the LLVM license, with the following
- additional copyrights and restrictions:
-
- Copyright 1991 by the Massachusetts Institute of Technology
-
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation, and that the name of M.I.T. not be used in advertising or
- publicity pertaining to distribution of the software without specific,
- written prior permission. M.I.T. makes no representations about the
- suitability of this software for any purpose. It is provided "as is"
- without express or implied warranty.
-
-Please see the source files for additional copyrights.
-
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license llvm-3.2.src/include/llvm/Support/LICENSE.TXT:
-
-LLVM System Interface Library
--------------------------------------------------------------------------------
-The LLVM System Interface Library is licensed under the Illinois Open Source
-License and has the following additional copyright:
-
-Copyright (C) 2004 eXtensible Systems, Inc.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license llvm-3.2.src/projects/sample/autoconf/LICENSE.TXT:
-
-------------------------------------------------------------------------------
-Autoconf Files
-------------------------------------------------------------------------------
-All autoconf files are licensed under the LLVM license with the following
-additions:
-
-llvm/autoconf/install-sh:
- This script is licensed under the LLVM license, with the following
- additional copyrights and restrictions:
-
- Copyright 1991 by the Massachusetts Institute of Technology
-
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation, and that the name of M.I.T. not be used in advertising or
- publicity pertaining to distribution of the software without specific,
- written prior permission. M.I.T. makes no representations about the
- suitability of this software for any purpose. It is provided "as is"
- without express or implied warranty.
-
-Please see the source files for additional copyrights.
-
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license llvm-3.2.src/test/YAMLParser/LICENSE.txt:
-
-Copyright (c) 2006 Kirill Simonov
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license llvm-3.2.src/utils/unittest/googletest/LICENSE.TXT:
-
-Copyright 2008, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-<li><a href='#UoI-NCSA'>Gentoo Package Stock License UoI-NCSA</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">lohitfonts-cros-2.5.0</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://fedorahosted.org/lohit">homepage</a></span>
@@ -6721,101 +4966,6 @@
<div class="product">
-<span class="title">m17n-contrib-1.1.10</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.m17n.org/m17n-lib/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#LGPL-2.1'>Gentoo Package Stock License LGPL-2.1</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">m17n-db-1.6.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.m17n.org/m17n-lib/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#LGPL-2.1'>Gentoo Package Stock License LGPL-2.1</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">m17n-lib-1.6.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.m17n.org/m17n-lib/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#LGPL-2.1'>Gentoo Package Stock License LGPL-2.1</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">m2crypto-0.21.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://chandlerproject.org/bin/view/Projects/MeTooCrypto">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license M2Crypto-0.21.1/LICENCE:
-
-Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.
-
-Portions copyright (c) 2004-2006 Open Source Applications Foundation.
-All rights reserved.
-
-Portions copyright (c) 2005-2006 Vrije Universiteit Amsterdam.
-All rights reserved.
-
-Copyright (c) 2008-2010 Heikki Toivonen. All rights reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation.
-
-THE AUTHOR PROVIDES THIS SOFTWARE ``AS IS'' AND ANY EXPRESSED OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">make-3.82</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gnu.org/software/make/make.html">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-3'>Gentoo Package Stock License GPL-3</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">marvell_sd8787-14.64.2.47</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.marvell.com/">homepage</a></span>
@@ -6870,19 +5020,6 @@
<div class="product">
-<span class="title">mime-types-8</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gentoo.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">ml-anjalioldlipi-0.740</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="https://sites.google.com/site/cibu/anjalioldlipi-font">homepage</a></span>
@@ -7138,19 +5275,6 @@
<div class="product">
-<span class="title">netifaces-0.8</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://alastairs-place.net/netifaces/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#netiface'>Gentoo Package Stock License netiface</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">notofonts-20130514</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="">homepage</a></span>
@@ -7668,32 +5792,6 @@
<div class="product">
-<span class="title">patch-2.6.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gnu.org/software/patch/patch.html">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">pax-utils-0.4</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://hardened.gentoo.org/pax-utils.xml">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">pciutils-3.1.10</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://mj.ucw.cz/sw/pciutils/">homepage</a></span>
@@ -7746,58 +5844,6 @@
<div class="product">
-<span class="title">popt-1.16</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://rpm5.org/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license popt-1.16/COPYING:
-
-Copyright (c) 1998 Red Hat Software
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from the X Consortium.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">portage-2.1.11.50</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gentoo.org/proj/en/portage/index.xml">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">ppp-2.4.5</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.samba.org/ppp">homepage</a></span>
@@ -7850,577 +5896,6 @@
<div class="product">
-<span class="title">python-2.7.3</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.python.org/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license Python-2.7.3/LICENSE:
-
-A. HISTORY OF THE SOFTWARE
-==========================
-
-Python was created in the early 1990s by Guido van Rossum at Stichting
-Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
-as a successor of a language called ABC. Guido remains Python's
-principal author, although it includes many contributions from others.
-
-In 1995, Guido continued his work on Python at the Corporation for
-National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
-in Reston, Virginia where he released several versions of the
-software.
-
-In May 2000, Guido and the Python core development team moved to
-BeOpen.com to form the BeOpen PythonLabs team. In October of the same
-year, the PythonLabs team moved to Digital Creations (now Zope
-Corporation, see http://www.zope.com). In 2001, the Python Software
-Foundation (PSF, see http://www.python.org/psf/) was formed, a
-non-profit organization created specifically to own Python-related
-Intellectual Property. Zope Corporation is a sponsoring member of
-the PSF.
-
-All Python releases are Open Source (see http://www.opensource.org for
-the Open Source Definition). Historically, most, but not all, Python
-releases have also been GPL-compatible; the table below summarizes
-the various releases.
-
- Release Derived Year Owner GPL-
- from compatible? (1)
-
- 0.9.0 thru 1.2 1991-1995 CWI yes
- 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
- 1.6 1.5.2 2000 CNRI no
- 2.0 1.6 2000 BeOpen.com no
- 1.6.1 1.6 2001 CNRI yes (2)
- 2.1 2.0+1.6.1 2001 PSF no
- 2.0.1 2.0+1.6.1 2001 PSF yes
- 2.1.1 2.1+2.0.1 2001 PSF yes
- 2.2 2.1.1 2001 PSF yes
- 2.1.2 2.1.1 2002 PSF yes
- 2.1.3 2.1.2 2002 PSF yes
- 2.2.1 2.2 2002 PSF yes
- 2.2.2 2.2.1 2002 PSF yes
- 2.2.3 2.2.2 2003 PSF yes
- 2.3 2.2.2 2002-2003 PSF yes
- 2.3.1 2.3 2002-2003 PSF yes
- 2.3.2 2.3.1 2002-2003 PSF yes
- 2.3.3 2.3.2 2002-2003 PSF yes
- 2.3.4 2.3.3 2004 PSF yes
- 2.3.5 2.3.4 2005 PSF yes
- 2.4 2.3 2004 PSF yes
- 2.4.1 2.4 2005 PSF yes
- 2.4.2 2.4.1 2005 PSF yes
- 2.4.3 2.4.2 2006 PSF yes
- 2.4.4 2.4.3 2006 PSF yes
- 2.5 2.4 2006 PSF yes
- 2.5.1 2.5 2007 PSF yes
- 2.5.2 2.5.1 2008 PSF yes
- 2.5.3 2.5.2 2008 PSF yes
- 2.6 2.5 2008 PSF yes
- 2.6.1 2.6 2008 PSF yes
- 2.6.2 2.6.1 2009 PSF yes
- 2.6.3 2.6.2 2009 PSF yes
- 2.6.4 2.6.3 2009 PSF yes
- 2.6.5 2.6.4 2010 PSF yes
- 2.7 2.6 2010 PSF yes
-
-Footnotes:
-
-(1) GPL-compatible doesn't mean that we're distributing Python under
- the GPL. All Python licenses, unlike the GPL, let you distribute
- a modified version without making your changes open source. The
- GPL-compatible licenses make it possible to combine Python with
- other software that is released under the GPL; the others don't.
-
-(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
- because its license has a choice of law clause. According to
- CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
- is "not incompatible" with the GPL.
-
-Thanks to the many outside volunteers who have worked under Guido's
-direction to make these releases possible.
-
-
-B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
-===============================================================
-
-PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
---------------------------------------------
-
-1. This LICENSE AGREEMENT is between the Python Software Foundation
-("PSF"), and the Individual or Organization ("Licensee") accessing and
-otherwise using this software ("Python") in source or binary form and
-its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, PSF hereby
-grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
-analyze, test, perform and/or display publicly, prepare derivative works,
-distribute, and otherwise use Python alone or in any derivative version,
-provided, however, that PSF's License Agreement and PSF's notice of copyright,
-i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-2011, 2012 Python Software Foundation; All Rights Reserved" are retained in Python
-alone or in any derivative version prepared by Licensee.
-
-3. In the event Licensee prepares a derivative work that is based on
-or incorporates Python or any part thereof, and wants to make
-the derivative work available to others as provided herein, then
-Licensee hereby agrees to include in any such work a brief summary of
-the changes made to Python.
-
-4. PSF is making Python available to Licensee on an "AS IS"
-basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
-IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
-DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
-FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
-INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
-FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
-A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
-OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material
-breach of its terms and conditions.
-
-7. Nothing in this License Agreement shall be deemed to create any
-relationship of agency, partnership, or joint venture between PSF and
-Licensee. This License Agreement does not grant permission to use PSF
-trademarks or trade name in a trademark sense to endorse or promote
-products or services of Licensee, or any third party.
-
-8. By copying, installing or otherwise using Python, Licensee
-agrees to be bound by the terms and conditions of this License
-Agreement.
-
-
-BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
--------------------------------------------
-
-BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
-
-1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
-office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
-Individual or Organization ("Licensee") accessing and otherwise using
-this software in source or binary form and its associated
-documentation ("the Software").
-
-2. Subject to the terms and conditions of this BeOpen Python License
-Agreement, BeOpen hereby grants Licensee a non-exclusive,
-royalty-free, world-wide license to reproduce, analyze, test, perform
-and/or display publicly, prepare derivative works, distribute, and
-otherwise use the Software alone or in any derivative version,
-provided, however, that the BeOpen Python License is retained in the
-Software, alone or in any derivative version prepared by Licensee.
-
-3. BeOpen is making the Software available to Licensee on an "AS IS"
-basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
-IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
-DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
-FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
-INFRINGE ANY THIRD PARTY RIGHTS.
-
-4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
-SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
-AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
-DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-5. This License Agreement will automatically terminate upon a material
-breach of its terms and conditions.
-
-6. This License Agreement shall be governed by and interpreted in all
-respects by the law of the State of California, excluding conflict of
-law provisions. Nothing in this License Agreement shall be deemed to
-create any relationship of agency, partnership, or joint venture
-between BeOpen and Licensee. This License Agreement does not grant
-permission to use BeOpen trademarks or trade names in a trademark
-sense to endorse or promote products or services of Licensee, or any
-third party. As an exception, the "BeOpen Python" logos available at
-http://www.pythonlabs.com/logos.html may be used according to the
-permissions granted on that web page.
-
-7. By copying, installing or otherwise using the software, Licensee
-agrees to be bound by the terms and conditions of this License
-Agreement.
-
-
-CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
----------------------------------------
-
-1. This LICENSE AGREEMENT is between the Corporation for National
-Research Initiatives, having an office at 1895 Preston White Drive,
-Reston, VA 20191 ("CNRI"), and the Individual or Organization
-("Licensee") accessing and otherwise using Python 1.6.1 software in
-source or binary form and its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, CNRI
-hereby grants Licensee a nonexclusive, royalty-free, world-wide
-license to reproduce, analyze, test, perform and/or display publicly,
-prepare derivative works, distribute, and otherwise use Python 1.6.1
-alone or in any derivative version, provided, however, that CNRI's
-License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
-1995-2001 Corporation for National Research Initiatives; All Rights
-Reserved" are retained in Python 1.6.1 alone or in any derivative
-version prepared by Licensee. Alternately, in lieu of CNRI's License
-Agreement, Licensee may substitute the following text (omitting the
-quotes): "Python 1.6.1 is made available subject to the terms and
-conditions in CNRI's License Agreement. This Agreement together with
-Python 1.6.1 may be located on the Internet using the following
-unique, persistent identifier (known as a handle): 1895.22/1013. This
-Agreement may also be obtained from a proxy server on the Internet
-using the following URL: http://hdl.handle.net/1895.22/1013".
-
-3. In the event Licensee prepares a derivative work that is based on
-or incorporates Python 1.6.1 or any part thereof, and wants to make
-the derivative work available to others as provided herein, then
-Licensee hereby agrees to include in any such work a brief summary of
-the changes made to Python 1.6.1.
-
-4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
-basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
-IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
-DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
-FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
-INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
-1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
-A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
-OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material
-breach of its terms and conditions.
-
-7. This License Agreement shall be governed by the federal
-intellectual property law of the United States, including without
-limitation the federal copyright law, and, to the extent such
-U.S. federal law does not apply, by the law of the Commonwealth of
-Virginia, excluding Virginia's conflict of law provisions.
-Notwithstanding the foregoing, with regard to derivative works based
-on Python 1.6.1 that incorporate non-separable material that was
-previously distributed under the GNU General Public License (GPL), the
-law of the Commonwealth of Virginia shall govern this License
-Agreement only as to issues arising under or with respect to
-Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
-License Agreement shall be deemed to create any relationship of
-agency, partnership, or joint venture between CNRI and Licensee. This
-License Agreement does not grant permission to use CNRI trademarks or
-trade name in a trademark sense to endorse or promote products or
-services of Licensee, or any third party.
-
-8. By clicking on the "ACCEPT" button where indicated, or by copying,
-installing or otherwise using Python 1.6.1, Licensee agrees to be
-bound by the terms and conditions of this License Agreement.
-
- ACCEPT
-
-
-CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
---------------------------------------------------
-
-Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
-The Netherlands. All rights reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Stichting Mathematisch
-Centrum or CWI not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
-FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license Python-2.7.3/Modules/_ctypes/darwin/LICENSE:
-
-Copyright (c) 2002 Jorge Acereda <jacereda@users.sourceforge.net> &
- Peter O'Gorman <ogorman@users.sourceforge.net>
-
-Portions may be copyright others, see the AUTHORS file included with this
-distribution.
-
-Maintained by Peter O'Gorman <ogorman@users.sourceforge.net>
-
-Bug Reports and other queries should go to <ogorman@users.sourceforge.net>
-
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license Python-2.7.3/Modules/_ctypes/libffi/LICENSE:
-
-libffi - Copyright (c) 1996-2009 Anthony Green, Red Hat, Inc and others.
-See source files for details.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-``Software''), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license Python-2.7.3/Modules/_ctypes/libffi_msvc/LICENSE:
-
-libffi - Copyright (c) 1996-2003 Red Hat, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-``Software''), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license Python-2.7.3/Modules/_ctypes/libffi_osx/LICENSE:
-
-libffi - Copyright (c) 1996-2003 Red Hat, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-``Software''), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license Python-2.7.3/Modules/expat/COPYING:
-
-Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
- and Clark Cooper
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license Python-2.7.3/Tools/pybench/LICENSE:
-
-pybench License
----------------
-
-This copyright notice and license applies to all files in the pybench
-directory of the pybench distribution.
-
-Copyright (c), 1997-2006, Marc-Andre Lemburg (mal@lemburg.com)
-Copyright (c), 2000-2006, eGenix.com Software GmbH (info@egenix.com)
-
- All Rights Reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee or royalty is hereby
-granted, provided that the above copyright notice appear in all copies
-and that both that copyright notice and this permission notice appear
-in supporting documentation or portions thereof, including
-modifications, that you make.
-
-THE AUTHOR MARC-ANDRE LEMBURG DISCLAIMS ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
-INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
-FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-<li><a href='#PSF-2'>Gentoo Package Stock License PSF-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">python-evdev-0.3.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://gvalkov.github.com/python-evdev/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license python-evdev-0.3.1/LICENSE:
-
-Copyright (c) 2012 Georgi Valkov. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- 3. Neither the name of author nor the names of its contributors may
- be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL GEORGI VALKOV BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">python-updater-0.10</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gentoo.org/proj/en/Python/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">pyyaml-3.09</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://pyyaml.org/wiki/PyYAML">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license PyYAML-3.09/LICENSE:
-
-Copyright (c) 2006 Kirill Simonov
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">ragel-6.7</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.complang.org/ragel/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">readline-6.2_p1</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html">homepage</a></span>
@@ -8491,19 +5966,6 @@
<div class="product">
-<span class="title">rsync-3.0.8</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://rsync.samba.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-3'>Gentoo Package Stock License GPL-3</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">rsyslog-5.8.11</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.rsyslog.com/">homepage</a></span>
@@ -8519,19 +5981,6 @@
<div class="product">
-<span class="title">sandbox-2.6</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.gentoo.org/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">sbc-1.0</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://git.kernel.org/?p=bluetooth/sbc.git">homepage</a></span>
@@ -8546,43 +5995,6 @@
<div class="product">
-<span class="title">scons-2.0.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.scons.org/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license scons-2.0.1/LICENSE.txt:
-
-Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The SCons Foundation
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">sed-4.2.1</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://sed.sourceforge.net/">homepage</a></span>
@@ -8596,74 +6008,6 @@
<div class="product">
-<span class="title">setproctitle-1.1.6</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://code.google.com/p/py-setproctitle/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license setproctitle-1.1.6/COPYRIGHT:
-
-Copyright (c) 2009-2012, Daniele Varrazzo <daniele.varrazzo@gmail.com>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-* The name of Daniele Varrazzo may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">setuptools-0.6.14</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://pypi.python.org/pypi/distribute">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#PSF-2'>Gentoo Package Stock License PSF-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
-<span class="title">sgml-common-0.6.3</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.iso.ch/cate/3524030.html">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">shadow-4.1.2.2</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://shadow.pld.org.pl/">homepage</a></span>
@@ -8851,42 +6195,6 @@
<div class="product">
-<span class="title">simplejson-2.5.0</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://undefined.org/python/#simplejson">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license simplejson-2.5.0/LICENSE.txt:
-
-Copyright (c) 2006 Bob Ippolito
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">smartmontools-5.42</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://smartmontools.sourceforge.net/">homepage</a></span>
@@ -8965,19 +6273,6 @@
<div class="product">
-<span class="title">stressapptest-1.0.4</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://code.google.com/p/stressapptest/">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#Apache-2.0'>Gentoo Package Stock License Apache-2.0</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">strongswan-5.0.2</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.strongswan.org/">homepage</a></span>
@@ -9131,532 +6426,6 @@
<div class="product">
-<span class="title">swig-2.0.4</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://www.swig.org/">homepage</a></span>
-<div class="licence">
-<pre>Scanned Source license swig-2.0.4/CCache/COPYING:
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- Appendix: How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) 19yy <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) 19yy name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license swig-2.0.4/CCache/debian/copyright:
-
-This package was debianized by Paul Russell <prussell@debian.org> on
-Sun, 31 Mar 2002 14:08:57 +0200.
-
-It was downloaded from http://ccache.samba.org/ftp/ccache/
-
-The ccache-zlib patch was downloaded from http://www.gustaebel.de/lars/ccache/
-
-Upstream Author: Andrew Tridgell <tridge@samba.org>
-
-Copyright: 2002-2005 Andrew Tridgell <tridge@samba.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA
-
-You are free to distribute this software under the terms of the GNU General
-Public License. On Debian systems, the complete text of the GNU General
-Public License can be found in /usr/share/common-licenses/GPL file.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license swig-2.0.4/COPYRIGHT:
-
-SWIG Copyright and Authors
---------------------------
-
-Copyright (c) 1995-2011 The SWIG Developers
-Copyright (c) 2005-2006 Arizona Board of Regents (University of Arizona).
-Copyright (c) 1998-2005 University of Chicago.
-Copyright (c) 1995-1998 The University of Utah and the Regents of the University of California
-
-Portions also copyrighted by:
- Network Applied Communication Laboratory, Inc
- Information-technology Promotion Agency, Japan
-
-Active SWIG Developers:
- William Fulton (wsf@fultondesigns.co.uk) (SWIG core, Java, C#, Windows, Cygwin)
- Olly Betts (olly@survex.com) (PHP)
- Joseph Wang (joequant@gmail.com) (R)
- Xavier Delacour (xavier.delacour@gmail.com) (Octave)
- David Nadlinger (code@klickverbot.at) (D)
-
-Past SWIG developers and major contributors include:
- Dave Beazley (dave-swig@dabeaz.com) (SWIG core, Python, Tcl, Perl)
- Henning Thielemann (swig@henning-thielemann.de) (Modula3)
- Matthias Köppe (mkoeppe@mail.math.uni-magdeburg.de) (Guile, MzScheme)
- Luigi Ballabio (luigi.ballabio@fastwebnet.it) (STL wrapping)
- Mikel Bancroft (mikel@franz.com) (Allegro CL)
- Surendra Singhi (efuzzyone@netscape.net) (CLISP, CFFI)
- Marcelo Matus (mmatus@acms.arizona.edu) (SWIG core, Python, UTL[python,perl,tcl,ruby])
- Art Yerkes (ayerkes@speakeasy.net) (Ocaml)
- Lyle Johnson (lyle@users.sourceforge.net) (Ruby)
- Charlie Savage (cfis@interserv.com) (Ruby)
- Thien-Thi Nguyen (ttn@glug.org) (build/test/misc)
- Richard Palmer (richard@magicality.org) (PHP)
- Sam Liddicott - Ananova Ltd (saml@liddicott.com) (PHP)
- Tim Hockin - Sun Microsystems (thockin@sun.com) (PHP)
- Kevin Ruland (PHP)
- Shibukawa Yoshiki (Japanese Translation)
- Jason Stewart (jason@openinformatics.com) (Perl5)
- Loic Dachary (Perl5)
- David Fletcher (Perl5)
- Gary Holt (Perl5)
- Masaki Fukushima (Ruby)
- Scott Michel (scottm@cs.ucla.edu) (Java directors)
- Tiger Feng (songyanf@cs.uchicago.edu) (SWIG core)
- Mark Rose (mrose@stm.lbl.gov) (Directors)
- Jonah Beckford (beckford@usermail.com) (CHICKEN)
- Ahmon Dancy (dancy@franz.com) (Allegro CL)
- Dirk Gerrits (Allegro CL)
- Neil Cawse (C#)
- Harco de Hilster (Java)
- Alexey Dyachenko (dyachenko@fromru.com) (Tcl)
- Bob Techentin (Tcl)
- Martin Froehlich <MartinFroehlich@ACM.org> (Guile)
- Marcio Luis Teixeira <marciot@holly.colostate.edu> (Guile)
- Duncan Temple Lang (R)
- Miklos Vajna <vmiklos@frugalware.org> (PHP directors)
- Mark Gossage (mark@gossage.cjb.net) (Lua)
- Gonzalo Garramuno (ggarra@advancedsl.com.ar) (Ruby, Ruby's UTL)
- John Lenz (Guile, MzScheme updates, Chicken module, runtime system)
- Ian Lance Taylor (Go)
- Vadim Zeitlin (PCRE)
- Stefan Zager (szager@gmail.com) (Python)
-
-Past contributors include:
- James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
- Kovuk, Oleg Tolmatcev, Tal Shalif, Lluis Padro, Chris Seatory, Igor Bely, Robin Dunn,
- Edward Zimmermann, David Ascher, Dominique Dumont, Pier Giorgio Esposito, Hasan Baran Kovuk,
- Klaus Wiederänders
- (See CHANGES and CHANGES.current and the bug tracker for a more complete list).
-
-Past students:
- Songyan Feng (Chicago).
- Xinghua Shi (Chicago).
- Jing Cao (Chicago).
- Aquinas Hobor (Chicago).
-
-Historically, the following people contributed to early versions of SWIG.
-Peter Lomdahl, Brad Holian, Shujia Zhou, Niels Jensen, and Tim Germann
-at Los Alamos National Laboratory were the first users. Patrick
-Tullmann at the University of Utah suggested the idea of automatic
-documentation generation. John Schmidt and Kurtis Bleeker at the
-University of Utah tested out the early versions. Chris Johnson
-supported SWIG's developed at the University of Utah. John Buckman,
-Larry Virden, and Tom Schwaller provided valuable input on the first
-releases and improving the portability of SWIG. David Fletcher and
-Gary Holt have provided a great deal of input on improving SWIG's
-Perl5 implementation. Kevin Butler contributed the first Windows NT
-port.
-
-Early bug reports and patches:
-Adam Hupp, Arthur Smyles, Brad Clements, Brett Williams, Buck Hodges,
-Burkhard Kloss, Chia-Liang Kao, Craig Files, Dennis Marsa, Dieter Baron,
-Drake Diedrich, Fleur Diana Dragan, Gary Pennington, Geoffrey Hort, Gerald Williams,
-Greg Anderson, Greg Kochanski, Greg Troxel, Henry Rowley, Irina Kotlova,
-Israel Taller, James Bailey, Jim Fulton, Joel Reed, Jon Travis,
-Junio Hamano, Justin Heyes-Jones, Karl Forner, Keith Davidson,
-Krzysztof Kozminski, Larry Virden, Luke J Crook, Magnus Ljung, Marc Zonzon,
-Mark Howson, Micahel Scharf, Michel Sanner, Mike Romberg, Mike Simons,
-Mike Weiblen, Paul Brannan, Ram Bhamidipaty, Reinhard Fobbe, Rich Wales,
-Richard Salz, Roy Lecates, Rudy Albachten, Scott Drummonds
-Scott Michel, Shaun Lowry, Steve Galser, Tarn Weisner Burton,
-Thomas Weidner, Tony Seward, Uwe Steinmann, Vadim Chugunov, Wyss Clemens,
-Zhong Ren.
-
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-Scanned Source license swig-2.0.4/LICENSE:
-
-SWIG is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version. See the LICENSE-GPL file for
-the full terms of the GNU General Public license version 3.
-
-Portions of SWIG are also licensed under the terms of the licenses
-in the file LICENSE-UNIVERSITIES. You must observe the terms of
-these licenses, as well as the terms of the GNU General Public License,
-when you distribute SWIG.
-
-The SWIG library and examples, under the Lib and Examples top level
-directories, are distributed under the following terms:
-
- You may copy, modify, distribute, and make derivative works based on
- this software, in source code or object code form, without
- restriction. If you distribute the software to others, you may do
- so according to the terms of your choice. This software is offered as
- is, without warranty of any kind.
-
-See the COPYRIGHT file for a list of contributors to SWIG and their
-copyright notices.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
-<ul>
-<li><a href='#GPL-3'>Gentoo Package Stock License GPL-3</a></li>
-<li><a href='#as-is'>Gentoo Package Stock License as-is</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">syslinux-3.83</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://syslinux.zytor.com/">homepage</a></span>
@@ -9696,7 +6465,7 @@
<div class="product">
-<span class="title">timezone-data-2012j</span>
+<span class="title">timezone-data-2013d</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.iana.org/time-zones">homepage</a></span>
<div class="licence">
@@ -9790,6 +6559,19 @@
<div class="product">
+<span class="title">u-boot-2013.06</span>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<span class="homepage"><a href="http://www.denx.de/wiki/U-Boot">homepage</a></span>
+<div class="licence">
+<pre></pre>
+<ul>
+<li><a href='#GPL-2+'>Gentoo Package Stock License GPL-2+</a></li>
+</ul>
+</div>
+</div>
+
+
+<div class="product">
<span class="title">udev-171</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html">homepage</a></span>
@@ -9803,19 +6585,6 @@
<div class="product">
-<span class="title">unittest2-0.5.1</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://pypi.python.org/pypi/unittest2">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#BSD-Google'>Gentoo Package Stock License BSD-Google</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">unrar-4.2.4</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://www.rarlab.com/rar_add.htm">homepage</a></span>
@@ -10385,47 +7154,13 @@
<div class="product">
-<span class="title">xcb-proto-1.7.1</span>
+<span class="title">X.Org-1.9.3</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://xcb.freedesktop.org/">homepage</a></span>
+<span class="homepage"><a href="http://www.x.org/">homepage</a></span>
<div class="licence">
-<pre>Scanned Source license xcb-proto-1.7.1/COPYING:
-
-Copyright (C) 2001-2006 Bart Massey, Jamey Sharp, and Josh Triplett.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall
-be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
-BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the names of the authors
-or their institutions shall not be used in advertising or
-otherwise to promote the sale, use or other dealings in this
-Software without prior written authorization from the
-authors.
-
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-</pre>
+<pre></pre>
<ul>
-
+<li><a href='#X'>Gentoo Package Stock License X</a></li>
</ul>
</div>
</div>
@@ -10652,19 +7387,6 @@
<div class="product">
-<span class="title">xxd-1.10</span>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<span class="homepage"><a href="http://ftp.uni-erlangen.de/pub/utilities/etc/?order=s">homepage</a></span>
-<div class="licence">
-<pre></pre>
-<ul>
-<li><a href='#GPL-2'>Gentoo Package Stock License GPL-2</a></li>
-</ul>
-</div>
-</div>
-
-
-<div class="product">
<span class="title">xz-utils-4.999.9_beta</span>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<span class="homepage"><a href="http://tukaani.org/xz/">homepage</a></span>
@@ -10824,7 +7546,7 @@
</pre>
<div class="license-packages">
-Used by these packages: sys-apps/dbus-1.6.8-r3 dev-libs/dbus-glib-0.100
+Used by these packages: sys-apps/dbus-1.6.8-r4 dev-libs/dbus-glib-0.100.2
</div>
</div>
</div>
@@ -11515,7 +8237,7 @@
</pre>
<div class="license-packages">
-Used by these packages: app-i18n/chinese-input-1.0.0.0-r1 app-i18n/chromeos-hangul-1.0.0.12 app-i18n/chromeos-keyboards-1.1.3.0-r1 media-fonts/croscorefonts-1.23.0 media-fonts/crosextrafonts-20130214 media-fonts/droidfonts-cros-20121206 app-i18n/ibus-english-m-0.0.1-r3 dev-python/jsonrpclib-0_pre20110820-r1 media-fonts/notofonts-20130514 dev-libs/protobuf-2.3.0-r4 app-admin/rsyslog-5.8.11 dev-util/stressapptest-1.0.4
+Used by these packages: app-i18n/chinese-input-1.1.0.0-r2 app-i18n/chromeos-hangul-1.1.0.0-r5 app-i18n/chromeos-keyboards-1.1.4.0-r2 media-fonts/croscorefonts-1.23.0 media-fonts/crosextrafonts-20130214 media-fonts/droidfonts-cros-20121206 media-fonts/notofonts-20130514 dev-libs/protobuf-2.3.0-r4 app-admin/rsyslog-5.8.11
</div>
</div>
</div>
@@ -11735,6 +8457,52 @@
</div>
<div class="product">
+<a name="as-is" class="title">Gentoo Package Provided Stock License as-is</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+Note: This license label is deprecated, so don't use it for new packages.
+Unfortunately, "as-is" has been (ab)used also for non-free software and
+you cannot rely on it. Please check the upstream license instead.
+
+"as-is" in its originally intended sense is now covered by the OSI-approved
+"HPND" (Historical Permission Notice and Disclaimer).
+
+---------------------------------------------------------------------------
+
+This is a generic place holder for a class of licenses that boil down to do
+no guarantees and all you get is what you have. The language is usually
+similar to:
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appears in all copies and that both the
+ copyright notice and this permission notice appear in supporting
+ documentation, and that the same name not be used in advertising or
+ publicity pertaining to distribution of the software without specific,
+ written prior permission. We make no representations about the
+ suitability of this software for any purpose. It is provided "as is"
+ without express or implied warranty.
+
+
+You will need to check the license that came with the software for the exact
+specifics. Generally you are free to do most anything you want with "as is"
+software but you should not take this license as legal advice.
+
+Note: Most all license have an "as is" clause. For our purposes this does
+not make all software in this category. This category is for software with
+very little restrictions.
+
+The information in this license about licenses is presented "as is". :-P
+
+</pre>
+<div class="license-packages">
+Used by these packages: net-wireless/crda-1.1.1-r1 net-wireless/iw-3.6-r1 media-libs/libpng-1.2.49-r1 net-misc/openssh-5.2_p1-r10 dev-db/sqlite-3.6.22-r3 net-wireless/wireless-regdb-20101124-r1 app-arch/xz-utils-4.999.9_beta
+</div>
+</div>
+</div>
+
+<div class="product">
<a name="Atheros" class="title">Gentoo Package Provided Stock License Atheros</a>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<div class="licence">
@@ -11767,248 +8535,6 @@
</div>
<div class="product">
-<a name="BSD-Google" class="title">Gentoo Package Provided Stock License BSD-Google</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Copyright 2010, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-</pre>
-<div class="license-packages">
-Used by these packages: app-i18n/input-tools-0.0.1 app-i18n/nacl-mozc-1.10.1389.104-r10 media-plugins/o3d-203170 dev-python/unittest2-0.5.1
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="BSD-bsdiff" class="title">Gentoo Package Provided Stock License BSD-bsdiff</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Copyright 2003-2005 Colin Percival
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted providing that the following conditions·
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-</pre>
-<div class="license-packages">
-Used by these packages: dev-util/bsdiff-4.3-r5
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="BSD-dhcpcd" class="title">Gentoo Package Provided Stock License BSD-dhcpcd</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Copyright (c) 2006-2010 Roy Marples <roy@marples.name>
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-</pre>
-<div class="license-packages">
-Used by these packages: net-misc/dhcpcd-5.1.4-r35
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="BSD-iputils" class="title">Gentoo Package Provided Stock License BSD-iputils</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Copyright (c) 1989 The Regents of the University of California.
-All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Mike Muuss.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. All advertising materials mentioning features or use of this software
- must display the following acknowledgement:
- This product includes software developed by the University of
- California, Berkeley and its contributors.
-4. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-</pre>
-<div class="license-packages">
-Used by these packages: net-misc/iputils-20100418-r3
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="BSD-libevent" class="title">Gentoo Package Provided Stock License BSD-libevent</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-</pre>
-<div class="license-packages">
-Used by these packages: dev-libs/libevent-1.4.13
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="BZIP2" class="title">Gentoo Package Provided Stock License BZIP2</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-<copyright notice>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
-
-3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
-4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-</pre>
-<div class="license-packages">
-Used by these packages: app-arch/bzip2-1.0.6-r3
-</div>
-</div>
-</div>
-
-<div class="product">
<a name="BitstreamVera" class="title">Gentoo Package Provided Stock License BitstreamVera</a>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<div class="licence">
@@ -12146,6 +8672,248 @@
</div>
<div class="product">
+<a name="BSD-bsdiff" class="title">Gentoo Package Provided Stock License BSD-bsdiff</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+Copyright 2003-2005 Colin Percival
+All rights reserved
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted providing that the following conditions·
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+</pre>
+<div class="license-packages">
+Used by these packages: dev-util/bsdiff-4.3-r5
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="BSD-dhcpcd" class="title">Gentoo Package Provided Stock License BSD-dhcpcd</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+Copyright (c) 2006-2010 Roy Marples <roy@marples.name>
+All rights reserved
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+</pre>
+<div class="license-packages">
+Used by these packages: net-misc/dhcpcd-5.1.4-r36
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="BSD-Google" class="title">Gentoo Package Provided Stock License BSD-Google</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+Copyright 2010, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+</pre>
+<div class="license-packages">
+Used by these packages: app-i18n/input-tools-2.4.1.0-r1 app-i18n/nacl-mozc-1.10.1389.104-r11 media-plugins/o3d-203170
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="BSD-iputils" class="title">Gentoo Package Provided Stock License BSD-iputils</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+Copyright (c) 1989 The Regents of the University of California.
+All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Mike Muuss.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ This product includes software developed by the University of
+ California, Berkeley and its contributors.
+4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+</pre>
+<div class="license-packages">
+Used by these packages: net-misc/iputils-20100418-r3
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="BSD-libevent" class="title">Gentoo Package Provided Stock License BSD-libevent</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+</pre>
+<div class="license-packages">
+Used by these packages: dev-libs/libevent-1.4.13
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="BZIP2" class="title">Gentoo Package Provided Stock License BZIP2</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+<copyright notice>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+</pre>
+<div class="license-packages">
+Used by these packages: app-arch/bzip2-1.0.6-r3
+</div>
+</div>
+</div>
+
+<div class="product">
<a name="CPL-1.0" class="title">Gentoo Package Provided Stock License CPL-1.0</a>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<div class="licence">
@@ -12309,15 +9077,16 @@
</div>
<div class="product">
-<a name="FDL-1.1" class="title">Gentoo Package Provided Stock License FDL-1.1</a>
+<a name="FDL-1.2" class="title">Gentoo Package Provided Stock License FDL-1.2</a>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<div class="licence">
<pre>
GNU Free Documentation License
- Version 1.1, March 2000
+ Version 1.2, November 2002
- Copyright (C) 2000 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -12325,12 +9094,12 @@
0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other
-written document "free" in the sense of freedom: to assure everyone
-the effective freedom to copy and redistribute it, with or without
-modifying it, either commercially or noncommercially. Secondarily,
-this License preserves for the author and publisher a way to get
-credit for their work, while not being considered responsible for
-modifications made by others.
+functional and useful document "free" in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense. It
@@ -12348,11 +9117,15 @@
1. APPLICABILITY AND DEFINITIONS
-This License applies to any manual or other work that contains a
-notice placed by the copyright holder saying it can be distributed
-under the terms of this License. The "Document", below, refers to any
-such manual or work. Any member of the public is a licensee, and is
-addressed as "you".
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License. Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein. The "Document", below,
+refers to any such manual or work. Any member of the public is a
+licensee, and is addressed as "you". You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
@@ -12362,7 +9135,7 @@
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
-within that overall subject. (For example, if the Document is in part a
+within that overall subject. (Thus, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
@@ -12371,33 +9144,40 @@
The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
-that says that the Document is released under this License.
+that says that the Document is released under this License. If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant. The Document may contain zero
+Invariant Sections. If the Document does not identify any Invariant
+Sections then there are none.
The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
-the Document is released under this License.
+the Document is released under this License. A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
-general public, whose contents can be viewed and edited directly and
+general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
-format whose markup has been designed to thwart or discourage
-subsequent modification by readers is not Transparent. A copy that is
-not "Transparent" is called "Opaque".
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
-HTML designed for human modification. Opaque formats include
-PostScript, PDF, proprietary formats that can be read and edited only
-by proprietary word processors, SGML or XML for which the DTD and/or
+HTML, PostScript or PDF designed for human modification. Examples of
+transparent image formats include PNG, XCF and JPG. Opaque formats
+include proprietary formats that can be read and edited only by
+proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
-machine-generated HTML produced by some word processors for output
-purposes only.
+machine-generated HTML, PostScript or PDF produced by some word
+processors for output purposes only.
The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
@@ -12406,6 +9186,21 @@
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
+A section "Entitled XYZ" means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language. (Here XYZ stands for a
+specific section name mentioned below, such as "Acknowledgements",
+"Dedications", "Endorsements", or "History".) To "Preserve the Title"
+of such a section when you modify the Document means that it remains a
+section "Entitled XYZ" according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document. These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
2. VERBATIM COPYING
@@ -12425,9 +9220,10 @@
3. COPYING IN QUANTITY
-If you publish printed copies of the Document numbering more than 100,
-and the Document's license notice requires Cover Texts, you must enclose
-the copies in covers that carry, clearly and legibly, all these Cover
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
you as the publisher of these copies. The front cover must present
@@ -12445,16 +9241,15 @@
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
-a publicly-accessible computer-network location containing a complete
-Transparent copy of the Document, free of added material, which the
-general network-using public has access to download anonymously at no
-charge using public-standard network protocols. If you use the latter
-option, you must take reasonably prudent steps, when you begin
-distribution of Opaque copies in quantity, to ensure that this
-Transparent copy will remain thus accessible at the stated location
-until at least one year after the last time you distribute an Opaque
-copy (directly or through your agents or retailers) of that edition to
-the public.
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to give
@@ -12478,7 +9273,8 @@
B. List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified
Version, together with at least five of the principal authors of the
- Document (all of its principal authors, if it has less than five).
+ Document (all of its principal authors, if it has fewer than five),
+ unless they release you from this requirement.
C. State on the Title page the name of the publisher of the
Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
@@ -12490,10 +9286,10 @@
G. Preserve in that license notice the full lists of Invariant Sections
and required Cover Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
-I. Preserve the section entitled "History", and its title, and add to
- it an item stating at least the title, year, new authors, and
+I. Preserve the section Entitled "History", Preserve its Title, and add
+ to it an item stating at least the title, year, new authors, and
publisher of the Modified Version as given on the Title Page. If
- there is no section entitled "History" in the Document, create one
+ there is no section Entitled "History" in the Document, create one
stating the title, year, authors, and publisher of the Document as
given on its Title Page, then add an item describing the Modified
Version as stated in the previous sentence.
@@ -12504,17 +9300,18 @@
You may omit a network location for a work that was published at
least four years before the Document itself, or if the original
publisher of the version it refers to gives permission.
-K. In any section entitled "Acknowledgements" or "Dedications",
- preserve the section's title, and preserve in the section all the
- substance and tone of each of the contributor acknowledgements
+K. For any section Entitled "Acknowledgements" or "Dedications",
+ Preserve the Title of the section, and preserve in the section all
+ the substance and tone of each of the contributor acknowledgements
and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document,
unaltered in their text and in their titles. Section numbers
or the equivalent are not considered part of the section titles.
-M. Delete any section entitled "Endorsements". Such a section
+M. Delete any section Entitled "Endorsements". Such a section
may not be included in the Modified Version.
-N. Do not retitle any existing section as "Endorsements"
+N. Do not retitle any existing section to be Entitled "Endorsements"
or to conflict in title with any Invariant Section.
+O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
@@ -12523,7 +9320,7 @@
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.
-You may add a section entitled "Endorsements", provided it contains
+You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
@@ -12551,7 +9348,7 @@
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
-license notice.
+license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
@@ -12562,11 +9359,11 @@
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.
-In the combination, you must combine any sections entitled "History"
-in the various original documents, forming one section entitled
-"History"; likewise combine any sections entitled "Acknowledgements",
-and any sections entitled "Dedications". You must delete all sections
-entitled "Endorsements."
+In the combination, you must combine any sections Entitled "History"
+in the various original documents, forming one section Entitled
+"History"; likewise combine any sections Entitled "Acknowledgements",
+and any sections Entitled "Dedications". You must delete all sections
+Entitled "Endorsements".
6. COLLECTIONS OF DOCUMENTS
@@ -12587,18 +9384,20 @@
A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
-distribution medium, does not as a whole count as a Modified Version
-of the Document, provided no compilation copyright is claimed for the
-compilation. Such a compilation is called an "aggregate", and this
-License does not apply to the other self-contained works thus compiled
-with the Document, on account of their being thus compiled, if they
-are not themselves derivative works of the Document.
+distribution medium, is called an "aggregate" if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these
-copies of the Document, then if the Document is less than one quarter
-of the entire aggregate, the Document's Cover Texts may be placed on
-covers that surround only the Document within the aggregate.
-Otherwise they must appear on covers around the whole aggregate.
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
8. TRANSLATION
@@ -12609,10 +9408,17 @@
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
-translation of this License provided that you also include the
-original English version of this License. In case of a disagreement
-between the translation and the original English version of this
-License, the original English version will prevail.
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers. In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled "Acknowledgements",
+"Dedications", or "History", the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
9. TERMINATION
@@ -12650,19 +9456,23 @@
the License in the document and put the following copyright and
license notices just after the title page:
- Copyright (c) YEAR YOUR NAME.
- Permission is granted to copy, distribute and/or modify this document
- under the terms of the GNU Free Documentation License, Version 1.1
- or any later version published by the Free Software Foundation;
- with the Invariant Sections being LIST THEIR TITLES, with the
- Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
- A copy of the license is included in the section entitled "GNU
- Free Documentation License".
+ Copyright (c) YEAR YOUR NAME.
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.2
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
+ A copy of the license is included in the section entitled "GNU
+ Free Documentation License".
-If you have no Invariant Sections, write "with no Invariant Sections"
-instead of saying which ones are invariant. If you have no
-Front-Cover Texts, write "no Front-Cover Texts" instead of
-"Front-Cover Texts being LIST"; likewise for Back-Cover Texts.
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the "with...Texts." line with this:
+
+ with the Invariant Sections being LIST THEIR TITLES, with the
+ Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
@@ -12671,58 +9481,42 @@
</pre>
<div class="license-packages">
-Used by these packages: dev-util/gtk-doc-am-1.18
+Used by these packages: sys-libs/gcc-libs-0.0.1-r1
</div>
</div>
</div>
<div class="product">
-<a name="FLEX" class="title">Gentoo Package Provided Stock License FLEX</a>
+<a name="fontconfig" class="title">Gentoo Package Provided Stock License fontconfig</a>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<div class="licence">
<pre>
-Flex carries the copyright used for BSD software, slightly modified
-because it originated at the Lawrence Berkeley (not Livermore!) Laboratory,
-which operates under a contract with the Department of Energy:
+fontconfig/COPYING
- Copyright (c) 1990 The Regents of the University of California.
- All rights reserved.
+Copyright © 2001,2003 Keith Packard
- This code is derived from software contributed to Berkeley by
- Vern Paxson.
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Keith Packard not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Keith Packard makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
- The United States Government has rights in this work pursuant
- to contract no. DE-AC03-76SF00098 between the United States
- Department of Energy and the University of California.
+THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
- Redistribution and use in source and binary forms with or without
- modification are permitted provided that: (1) source distributions
- retain this entire copyright notice and comment, and (2)
- distributions including binaries display the following
- acknowledgement: ``This product includes software developed by the
- University of California, Berkeley and its contributors'' in the
- documentation or other materials provided with the distribution and
- in all advertising materials mentioning features or use of this
- software. Neither the name of the University nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE.
-
-This basically says "do whatever you please with this software except
-remove this notice or take advantage of the University's (or the flex
-authors') name".
-
-Note that the "flex.skl" scanner skeleton carries no copyright notice.
-You are free to do whatever you please with scanners generated using flex;
-for them, you are not even bound by the above copyright.
</pre>
<div class="license-packages">
-Used by these packages: sys-devel/flex-2.5.35_p10
+Used by these packages: media-libs/fontconfig-2.7.1-r37
</div>
</div>
</div>
@@ -13246,7 +10040,7 @@
</pre>
<div class="license-packages">
-Used by these packages: sys-kernel/Linux-2.6 media-sound/adhd-0.0.1-r570 media-sound/alsa-headers-1.0.25 media-plugins/alsa-plugins-1.0.25-r1 media-sound/alsa-utils-1.0.25-r3 sys-devel/autoconf-2.13 sys-devel/autoconf-wrapper-10-r1 sys-devel/automake-1.11.1 sys-devel/automake-wrapper-5 sys-fs/avfs-1.0.1 sys-apps/baselayout-2.0.1-r230 sys-devel/binutils-config-3-r3 net-wireless/bluez-5.4-r8 sys-apps/busybox-1.21.0-r5 sys-apps/chvt-0.0.1-r1 sys-apps/dbus-1.6.8-r3 dev-libs/dbus-glib-0.100 app-misc/ddccontrol-0.4.2-r1 app-misc/ddccontrol-db-20061014 sys-apps/diffutils-3.2 sys-apps/dmidecode-2.10 sys-apps/dtc-1.3.0-r23 sys-fs/e2fsprogs-1.42 sys-libs/e2fsprogs-libs-1.42 sys-fs/ecryptfs-utils-101 sys-apps/eject-2.1.5-r2 app-admin/eselect-opengl-1.2.4 app-admin/eselect-python-20100321 sys-apps/ethtool-6 sys-apps/findutils-4.4.2-r1 sys-apps/flashrom-0.9.4-r293 media-libs/freetype-2.4.12 sys-fs/fuse-2.8.6-r3 dev-util/gtk-doc-am-1.18 net-misc/htpdate-1.0.4-r6 sys-apps/hwids-20120922 app-i18n/ibus-m17n-1.3.3-r6 dev-util/intltool-0.41.0 sys-apps/iotools-1.4 net-firewall/iptables-1.4.8-r2 sys-apps/kbd-1.15.3 sys-apps/keyutils-1.1 app-laptop/laptop-mode-tools-1.59-r17 dev-libs/libatomic_ops-7.2d sys-libs/libcap-2.17 dev-libs/libchewing-0.3.2-r1 dev-libs/libgpg-error-1.10-r1 net-libs/libnetfilter_queue-1.0.1 net-libs/libnfnetlink-1.0.1 sys-libs/libnih-1.0.3 sys-devel/libtool-2.4-r1 sys-kernel/linux-headers-3.4-r6 sys-fs/lvm2-2.02.88 dev-libs/lzo-2.06 sys-apps/mawk-1.3.4_p20100625 sys-apps/memtester-4.2.2 app-misc/mime-types-8 sys-apps/module-init-tools-3.16-r4 sys-apps/net-tools-1.60_p20110409135728 dev-libs/nspr-4.9.5-r2 dev-libs/nss-3.14.3 sys-fs/ntfs3g-2012.1.15-r2 net-misc/openvpn-2.1.12-r2 sys-libs/pam-1.1.5 sys-auth/pam_pwdfile-0.99-r1 sys-auth/pambase-20101024-r2 sys-devel/patch-2.6.1 app-misc/pax-utils-0.4 sys-apps/pciutils-3.1.10 dev-util/perf-3.4-r2417 dev-libs/pkcs11-helper-1.07 media-gfx/ply-image-0.0.1-r40 sys-apps/portage-2.1.11.50 sys-process/procps-3.3.4 app-admin/python-updater-0.10 dev-util/ragel-6.7-r2 sys-apps/sandbox-2.6-r1 media-libs/sbc-1.0 app-text/sgml-common-0.6.3-r5 sys-apps/shadow-4.1.2.2-r4 x11-misc/shared-mime-info-0.90 sys-apps/smartmontools-5.42 net-misc/strongswan-5.0.2-r5 sys-boot/syslinux-3.83-r5 sys-fs/udev-171-r3 sys-apps/upstart-1.2-r7 sys-apps/ureadahead-0.100.0-r2 sys-apps/usbutils-006 sys-apps/util-linux-2.21.2-r1 net-wireless/wpa_supplicant-0.7.2-r130 net-dialup/xl2tpd-1.3.0-r1 dev-util/xxd-1.10 app-arch/xz-utils-4.999.9_beta
+Used by these packages: media-sound/adhd-0.0.1-r613 media-plugins/alsa-plugins-1.0.25-r1 media-sound/alsa-utils-1.0.25-r3 sys-fs/avfs-1.0.1 sys-apps/baselayout-2.0.1-r230 net-wireless/bluez-5.4-r9 app-accessibility/brltty-4.5-r3 sys-apps/chvt-0.0.1-r1 sys-boot/coreboot-2013.04 sys-apps/dbus-1.6.8-r4 dev-libs/dbus-glib-0.100.2 sys-apps/dmidecode-2.11-r1 sys-apps/dtc-1.3.0-r23 sys-fs/e2fsprogs-1.42 sys-libs/e2fsprogs-libs-1.42 sys-fs/ecryptfs-utils-101 sys-apps/eject-2.1.5-r2 app-admin/eselect-python-20100321 sys-apps/ethtool-6 sys-apps/findutils-4.4.2-r1 sys-apps/flashrom-0.9.4-r297 media-libs/freetype-2.4.12 sys-fs/fuse-2.8.6-r3 sys-apps/hdparm-9.39 sys-apps/hwids-20120922 sys-apps/iotools-1.4 net-firewall/iptables-1.4.8-r2 sys-apps/keyutils-1.1 app-laptop/laptop-mode-tools-1.59-r17 sys-libs/libcap-2.17 dev-libs/libgpg-error-1.10-r1 net-libs/libnetfilter_queue-1.0.1 net-libs/libnfnetlink-1.0.1 sys-libs/libnih-1.0.3 sys-kernel/Linux-2.6 sys-kernel/linux-headers-3.4-r6 sys-fs/lvm2-2.02.88 dev-libs/lzo-2.06 sys-apps/mawk-1.3.4_p20100625 sys-apps/memtester-4.2.2 sys-apps/module-init-tools-3.16-r4 sys-apps/net-tools-1.60_p20110409135728 dev-libs/nspr-4.9.5-r2 dev-libs/nss-3.14.3 sys-fs/ntfs3g-2012.1.15-r2 net-misc/openvpn-2.1.12-r2 sys-libs/pam-1.1.5 sys-auth/pam_pwdfile-0.99-r1 sys-auth/pambase-20101024-r2 sys-apps/pciutils-3.1.10 dev-util/perf-3.4-r2454 dev-libs/pkcs11-helper-1.07 media-gfx/ply-image-0.0.1-r41 sys-process/procps-3.3.4 media-libs/sbc-1.0 sys-apps/shadow-4.1.2.2-r4 x11-misc/shared-mime-info-0.90 sys-apps/smartmontools-5.42 net-misc/strongswan-5.0.2-r5 sys-boot/syslinux-3.83-r5 sys-fs/udev-171-r4 sys-apps/upstart-1.2-r7 sys-apps/ureadahead-0.100.0-r2 sys-apps/usbutils-006 sys-apps/util-linux-2.21.2-r1 net-wireless/wpa_supplicant-0.7.2-r132 net-dialup/xl2tpd-1.3.0-r1 app-arch/xz-utils-4.999.9_beta
</div>
</div>
</div>
@@ -13261,7 +10055,7 @@
</pre>
<div class="license-packages">
-Used by these packages: dev-libs/libatomic_ops-7.2d
+Used by these packages: sys-boot/u-boot-2013.06
</div>
</div>
</div>
@@ -14314,7 +11108,54 @@
</pre>
<div class="license-packages">
-Used by these packages: sys-devel/autoconf-2.68 app-shells/bash-4.2_p20 sys-devel/binutils-2.22-r17 sys-apps/coreutils-8.20-r1 sys-fs/dosfstools-3.0.9 sys-fs/exfat-utils-0.9.8 sys-fs/fuse-exfat-0.9.8-r1 sys-libs/gdbm-1.9.1-r2 sys-apps/grep-2.14 app-arch/gzip-1.5 sys-devel/make-3.82-r1 sys-fs/mtools-4.0.15 sys-block/parted-3.1-r1 sys-libs/readline-6.2_p1 net-misc/rsync-3.0.8 app-admin/rsyslog-5.8.11 sys-apps/sed-4.2.1-r1 app-arch/sharutils-4.7 dev-lang/swig-2.0.4-r1 app-arch/tar-1.26-r1 sys-apps/util-linux-2.21.2-r1 net-misc/wget-1.12-r2 sys-apps/which-2.20
+Used by these packages: app-shells/bash-4.2_p20 sys-apps/coreutils-8.20-r1 sys-fs/dosfstools-3.0.9 sys-fs/exfat-utils-0.9.8 sys-fs/fuse-exfat-0.9.8-r1 sys-libs/gcc-libs-0.0.1-r1 sys-apps/grep-2.14 app-arch/gzip-1.5 sys-fs/mtools-4.0.15 sys-block/parted-3.1-r1 sys-libs/readline-6.2_p1 app-admin/rsyslog-5.8.11 sys-apps/sed-4.2.1-r1 app-arch/sharutils-4.7 app-arch/tar-1.26-r1 sys-apps/util-linux-2.21.2-r1 net-misc/wget-1.12-r2 sys-apps/which-2.20
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="icu" class="title">Gentoo Package Provided Stock License icu</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+ICU License - ICU 1.8.1 and later
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1995-2003 International Business Machines Corporation and others
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+--------------------------------------------------------------------------------
+All trademarks and registered trademarks mentioned herein are the property of their respective owners.
+
+</pre>
+<div class="license-packages">
+Used by these packages: media-libs/harfbuzz-0.9.18-r2
</div>
</div>
</div>
@@ -14835,7 +11676,7 @@
</pre>
<div class="license-packages">
-Used by these packages: dev-libs/atk-1.32.0-r1 dev-libs/dbus-c++-0.0.2-r41 dev-libs/glib-2.34.3-r1 x11-libs/gtk+-2.20.1 dev-libs/libaio-0.3.109-r3 dev-libs/libusb-0.1.12-r7 x11-libs/pango-1.32.5-r1
+Used by these packages: dev-libs/atk-1.32.0-r1 dev-libs/dbus-c++-0.0.2-r41 dev-libs/glib-2.34.3-r1 x11-libs/gtk+-2.20.1 dev-libs/libusb-0.1.12-r7 x11-libs/pango-1.32.5-r1
</div>
</div>
</div>
@@ -15367,7 +12208,7 @@
</pre>
<div class="license-packages">
-Used by these packages: sys-apps/acl-2.2.51 media-libs/alsa-lib-1.0.25-r1 media-plugins/alsa-plugins-1.0.25-r1 sys-apps/attr-2.4.46 net-wireless/bluez-5.4-r8 x11-libs/cairo-1.12.12 dev-libs/engine_pkcs11-0.1.8 app-i18n/ibus-1.4.99.20120314-r5 sys-apps/keyutils-1.1 media-libs/ladspa-sdk-1.13-r1 dev-libs/libgcrypt-1.4.6 dev-libs/libgpg-error-1.10-r1 app-i18n/libhangul-0.0.10 net-libs/libmnl-1.0.3-r1 media-libs/libmtp-0.0.1-r15 dev-libs/libnl-1.1-r1 dev-libs/libnl-3.2.14 dev-libs/libp11-0.2.8-r1 dev-libs/libusb-1.0.9 dev-db/m17n-contrib-1.1.10-r1 dev-db/m17n-db-1.6.1-r3 dev-libs/m17n-lib-1.6.1-r1 net-misc/modemmanager-classic-interfaces-0.0.1 net-misc/modemmanager-next-0.5.999-r156 dev-libs/nspr-4.9.5-r2 dev-libs/nss-3.14.3 media-libs/sbc-1.0 dev-util/shflags-1.0.3-r1 sys-apps/util-linux-2.21.2-r1 app-arch/xz-utils-4.999.9_beta
+Used by these packages: sys-apps/acl-2.2.51 media-libs/alsa-lib-1.0.25-r1 media-plugins/alsa-plugins-1.0.25-r1 sys-apps/attr-2.4.46 net-dns/avahi-0.6.31-r1 net-wireless/bluez-5.4-r9 app-accessibility/brltty-4.5-r3 x11-libs/cairo-1.12.12 dev-libs/engine_pkcs11-0.1.8 app-i18n/ibus-1.4.99.20120314-r5 sys-apps/keyutils-1.1 dev-libs/libdaemon-0.14-r1 dev-libs/libgcrypt-1.4.6 dev-libs/libgpg-error-1.10-r1 net-libs/libmnl-1.0.3-r1 media-libs/libmtp-0.0.1-r16 dev-libs/libnl-1.1-r1 dev-libs/libnl-3.2.14 dev-libs/libp11-0.2.8-r1 dev-libs/libusb-1.0.9 net-misc/modemmanager-classic-interfaces-0.0.1 net-misc/modemmanager-next-0.5.999-r174 dev-libs/nspr-4.9.5-r2 dev-libs/nss-3.14.3 media-libs/sbc-1.0 dev-util/shflags-1.0.3-r1 sys-apps/util-linux-2.21.2-r1 app-arch/xz-utils-4.999.9_beta
</div>
</div>
</div>
@@ -15545,33 +12386,69 @@
</pre>
<div class="license-packages">
-Used by these packages: sys-devel/binutils-2.22-r17 dev-libs/gmp-5.0.2_p1 media-libs/mesa-9.1-r9 app-admin/rsyslog-5.8.11
+Used by these packages: sys-libs/gcc-libs-0.0.1-r1 dev-libs/gmp-5.0.2_p1 media-libs/mesa-9.1-r14 app-admin/rsyslog-5.8.11
</div>
</div>
</div>
<div class="product">
-<a name="MIT-MIT" class="title">Gentoo Package Provided Stock License MIT-MIT</a>
+<a name="lsof" class="title">Gentoo Package Provided Stock License lsof</a>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<div class="licence">
<pre>
-Copyright 1998 by the Massachusetts Institute of Technology.
+ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ#1.9
-Permission to use, copy, modify, and distribute this
-software and its documentation for any purpose and without
-fee is hereby granted, provided that the above copyright
-notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of M.I.T. not be used in
-advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-M.I.T. makes no representations about the suitability of
-this software for any purpose. It is provided "as is"
-without express or implied warranty.
+Copyright 2002 Purdue Research Foundation, West Lafayette,
+Indiana 47907. All rights reserved.
+
+Written by Victor A. Abell
+
+This software is not subject to any license of the American
+Telephone and Telegraph Company or the Regents of the
+University of California.
+
+Permission is granted to anyone to use this software for
+any purpose on any computer system, and to alter it and
+redistribute it freely, subject to the following
+restrictions:
+
+1. Neither the authors nor Purdue University are responsible
+ for any consequences of the use of this software.
+
+2. The origin of this software must not be misrepresented,
+ either by explicit claim or by omission. Credit to the
+ authors and Purdue University must appear in documentation
+ and sources.
+
+3. Altered versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+4. This notice may not be removed or altered.
</pre>
<div class="license-packages">
-Used by these packages: net-dns/c-ares-1.7.5
+Used by these packages: sys-process/lsof-4.81-r2
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="Marvell" class="title">Gentoo Package Provided Stock License Marvell</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+Copyright (C) 2010, Marvell International Ltd.
+
+All Rights Reserved.
+
+This file is provided by Marvell International Ltd. "AS IS".
+Reverse engineering of this file is strictly prohibited.
+Redistribution and use in its original form are permitted.
+
+
+</pre>
+<div class="license-packages">
+Used by these packages: net-wireless/marvell_sd8787-14.64.2.47-r21
</div>
</div>
</div>
@@ -15654,7 +12531,33 @@
</pre>
<div class="license-packages">
-Used by these packages: media-libs/mesa-9.1-r9
+Used by these packages: media-libs/mesa-9.1-r14
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="MIT-MIT" class="title">Gentoo Package Provided Stock License MIT-MIT</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+Copyright 1998 by the Massachusetts Institute of Technology.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is"
+without express or implied warranty.
+
+</pre>
+<div class="license-packages">
+Used by these packages: net-dns/c-ares-1.7.5
</div>
</div>
</div>
@@ -16627,22 +13530,39 @@
</div>
<div class="product">
-<a name="Marvell" class="title">Gentoo Package Provided Stock License Marvell</a>
+<a name="ncurses" class="title">Gentoo Package Provided Stock License ncurses</a>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<div class="licence">
<pre>
-Copyright (C) 2010, Marvell International Ltd.
+Copyright (c) 1998-2000,2005 Free Software Foundation, Inc.
-All Rights Reserved.
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, distribute with modifications, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
-This file is provided by Marvell International Ltd. "AS IS".
-Reverse engineering of this file is strictly prohibited.
-Redistribution and use in its original form are permitted.
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright
+holders shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization.
</pre>
<div class="license-packages">
-Used by these packages: net-wireless/marvell_sd8787-14.64.2.47-r20
+Used by these packages: sys-libs/ncurses-5.9-r2
</div>
</div>
</div>
@@ -16858,2327 +13778,7 @@
</pre>
<div class="license-packages">
-Used by these packages: media-fonts/ko-nanumfonts-3.10.0 media-fonts/lohitfonts-cros-2.5.0-r1 media-fonts/ml-anjalioldlipi-0.740 media-fonts/my-padauk-2.50 media-fonts/tibt-jomolhari-0.0.3c
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="PSF-2" class="title">Gentoo Package Provided Stock License PSF-2</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
---------------------------------------------
-
-1. This LICENSE AGREEMENT is between the Python Software Foundation
-("PSF"), and the Individual or Organization ("Licensee") accessing and
-otherwise using this software ("Python") in source or binary form and
-its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, PSF hereby
-grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
-analyze, test, perform and/or display publicly, prepare derivative works,
-distribute, and otherwise use Python alone or in any derivative version,
-provided, however, that PSF's License Agreement and PSF's notice of copyright,
-i.e., "Copyright (c) <YEARS> Python Software Foundation; All Rights Reserved"
-are retained in Python alone or in any derivative version prepared by Licensee.
-
-3. In the event Licensee prepares a derivative work that is based on
-or incorporates Python or any part thereof, and wants to make
-the derivative work available to others as provided herein, then
-Licensee hereby agrees to include in any such work a brief summary of
-the changes made to Python.
-
-4. PSF is making Python available to Licensee on an "AS IS"
-basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
-IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
-DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
-FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
-INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
-FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
-A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
-OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material
-breach of its terms and conditions.
-
-7. Nothing in this License Agreement shall be deemed to create any
-relationship of agency, partnership, or joint venture between PSF and
-Licensee. This License Agreement does not grant permission to use PSF
-trademarks or trade name in a trademark sense to endorse or promote
-products or services of Licensee, or any third party.
-
-8. By copying, installing or otherwise using Python, Licensee
-agrees to be bound by the terms and conditions of this License
-Agreement.
-
-</pre>
-<div class="license-packages">
-Used by these packages: dev-python/argparse-1.2.1 dev-lang/python-2.7.3-r5 dev-python/setuptools-0.6.14
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="RSA" class="title">Gentoo Package Provided Stock License RSA</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-[<copyright notice>]
-
-License to copy and use this software is granted provided that it is
-identified as [the] "<copyright holder> <software>" in all material
-mentioning or referencing this software [or this function].
-
-License is also granted to make and use derivative works provided that
-such works are identified as "derived from the <copyright holder>
-<software>" in all material mentioning or referencing the derived
-work.
-
-<copyright holder> makes no representations concerning either the
-merchantability of this software or the suitability of this software
-for any particular purpose. It is provided "as is" without express or
-implied warranty of any kind.
-
-[These notices must be retained in any copies of any part of this
-documentation and/or software.]
-
-</pre>
-<div class="license-packages">
-Used by these packages: net-misc/strongswan-5.0.2-r5
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="SGI-B-2.0" class="title">Gentoo Package Provided Stock License SGI-B-2.0</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
-
-Copyright (C) [dates of first publication] Silicon Graphics, Inc. All Rights
-Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice including the dates of first publication and either
-this permission notice or a reference to http://oss.sgi.com/projects/FreeB/
-shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON
-GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Silicon Graphics, Inc. shall
-not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Silicon
-Graphics, Inc.
-
-</pre>
-<div class="license-packages">
-Used by these packages: x11-proto/glproto-1.4.14-r1 media-libs/glu-9.0.0 media-libs/mesa-9.1-r9
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="UoI-NCSA" class="title">Gentoo Package Provided Stock License UoI-NCSA</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Copyright (c) <YEAR> <OWNER ORGANIZATION NAME>. All rights reserved.
-
-Developed by: <NAME OF DEVELOPMENT GROUP>
- <NAME OF INSTITUTION>
- <URL FOR DEVELOPMENT GROUP/INSTITUTION>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal with the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimers.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimers in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the names of <NAME OF DEVELOPMENT GROUP>, <NAME OF
- INSTITUTION>, nor the names of its contributors may be used to endorse
- or promote products derived from this Software without specific prior
- written permission.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-WITH THE SOFTWARE.
-
-</pre>
-<div class="license-packages">
-Used by these packages: sys-devel/llvm-3.2-r1
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="X" class="title">Gentoo Package Provided Stock License X</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-The following is the 'standard copyright' agreed upon by most contributors,
-and is currently the canonical license preferred by the X.Org Foundation.
-This is a slight variant of the common MIT license form published by the
-Open Source Initiative at http://www.opensource.org/licenses/mit-license.php
-
-Copyright holders of new code should use this license statement where
-possible, and insert their name to this list. Please sort by surname
-for people, and by the full name for other entities (e.g. Juliusz
-Chroboczek sorts before Intel Corporation sorts before Daniel Stone).
-
-Copyright © 2000-2001 Juliusz Chroboczek
-Copyright © 1998 Egbert Eich
-Copyright © 2006-2007 Intel Corporation
-Copyright © 2006 Nokia Corporation
-Copyright © 2006-2008 Peter Hutterer
-Copyright © 2006 Adam Jackson
-Copyright © 2009 NVIDIA Corporation
-Copyright © 1999 Keith Packard
-Copyright © 2007-2009 Red Hat, Inc.
-Copyright © 2005-2008 Daniel Stone
-Copyright © 2006-2009 Simon Thum
-Copyright © 1987, 2003-2006, 2008-2009 Sun Microsystems, Inc.
-Copyright © 2006 Luc Verhaegen
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
-
-
-
-The following licenses are 'legacy': usually MIT/X11 licenses with the name
-of the copyright holder(s) in the license statement, but also some BSD-like
-licenses.
-
-
-Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
-Copyright (C) Colin Harrison 2005-2008
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
-NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the XFree86 Project shall not
-be used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from the XFree86 Project.
-
-
-Copyright 1997 by The XFree86 Project, Inc.
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of the XFree86 Project, Inc.
-not be used in advertising or publicity pertaining to distribution of
-the software without specific, written prior permission. The Xfree86
-Project, Inc. makes no representations about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
-THE XFREE86 PROJECT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE
-FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1985-1998, 2001 The Open Group
-Copyright 2002 Red Hat Inc., Durham, North Carolina.
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright (c) 1987, 1989-1990, 1992-1995 X Consortium
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from the X Consortium.
-
-
-Copyright © 1999-2000 SuSE, Inc.
-Copyright © 2007 Red Hat, Inc.
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of SuSE not be used in advertising or
-publicity pertaining to distribution of the software without specific,
-written prior permission. SuSE makes no representations about the
-suitability of this software for any purpose. It is provided "as is"
-without express or implied warranty.
-
-SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
-BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1987-1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts.
-Copyright 1991 Massachusetts Institute of Technology, Cambridge, Massachusetts.
-Copyright 1991, 1993 Olivetti Research Limited, Cambridge, England.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
-Copyright 1994 Quarterdeck Office Systems.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the names of Digital and
-Quarterdeck not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
-OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
-OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1997 Digital Equipment Corporation.
-All rights reserved.
-
-This software is furnished under license and may be used and copied only in
-accordance with the following terms and conditions. Subject to these
-conditions, you may download, copy, install, use, modify and distribute
-this software in source and/or binary form. No title or ownership is
-transferred hereby.
-
-1) Any source code used, modified or distributed must reproduce and retain
- this copyright notice and list of conditions as they appear in the
- source file.
-
-2) No right is granted to use any trade name, trademark, or logo of Digital
- Equipment Corporation. Neither the "Digital Equipment Corporation"
- name nor any trademark or logo of Digital Equipment Corporation may be
- used to endorse or promote products derived from this software without
- the prior written permission of Digital Equipment Corporation.
-
-3) This software is provided "AS-IS" and any express or implied warranties,
- including but not limited to, any implied warranties of merchantability,
- fitness for a particular purpose, or non-infringement are disclaimed.
- In no event shall DIGITAL be liable for any damages whatsoever, and in
- particular, DIGITAL shall not be liable for special, indirect,
- consequential, or incidental damages or damages for lost profits, loss
- of revenue or loss of use, whether such damages arise in contract,
- negligence, tort, under statute, in equity, at law or otherwise, even
- if advised of the possibility of such damage.
-
-
-Copyright (c) 1991, 1996-1997 Digital Equipment Corporation, Maynard, Massachusetts.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
-BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Digital Equipment Corporation
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Digital
-Equipment Corporation.
-
-
-SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
-Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice including the dates of first publication and
-either this permission notice or a reference to
-http://oss.sgi.com/projects/FreeB/
-shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
-Copyright (c) 1994, 1995 Hewlett-Packard Company
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
-THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the Hewlett-Packard
-Company shall not be used in advertising or otherwise to promote the
-sale, use or other dealings in this Software without prior written
-authorization from the Hewlett-Packard Company.
-
-
-Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Hewlett-Packard not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-
-Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
-Copyright (c) 2003 by the XFree86 Project, Inc.
-Copyright 2004-2005 Red Hat Inc., Raleigh, North Carolina.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation on the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of the Software,
-and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
-BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
-Copyright © 2008 Red Hat, Inc.
-Partly based on code Copyright © 2000 SuSE, Inc.
-
-Permission to use, copy, modify, distribute, and sell this software
-and its documentation for any purpose is hereby granted without
-fee, provided that the above copyright notice appear in all copies
-and that both that copyright notice and this permission notice
-appear in supporting documentation, and that the name of Red Hat
-not be used in advertising or publicity pertaining to distribution
-of the software without specific, written prior permission. Red
-Hat makes no representations about the suitability of this software
-for any purpose. It is provided "as is" without express or implied
-warranty.
-
-Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
-NO EVENT SHALL Red Hat BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of SuSE not be used in advertising or
-publicity pertaining to distribution of the software without specific,
-written prior permission. SuSE makes no representations about the
-suitability of this software for any purpose. It is provided "as is"
-without express or implied warranty.
-
-SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
-BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright © 2006 Red Hat, Inc.
-(C) Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sub license,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-RED HAT, INC, OR PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
-OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
-THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-Copyright (c) 1995 X Consortium
-Copyright 2004 Red Hat Inc., Durham, North Carolina.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation on the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of the Software,
-and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT, THE X CONSORTIUM,
-AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium
-shall not be used in advertising or otherwise to promote the sale,
-use or other dealings in this Software without prior written
-authorization from the X Consortium.
-
-
-Copyright 1998-2000 Precision Insight, Inc., Cedar Park, Texas.
-Copyright 2000 VA Linux Systems, Inc.
-Copyright (c) 2002, 2008, 2009 Apple Computer, Inc.
-Copyright (c) 2003-2004 Torrey T. Lyons.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-(C) Copyright IBM Corporation 2003
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-(C) Copyright IBM Corporation 2004-2005
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sub license,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-IBM,
-AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
-Copyright (c) 1997 Metro Link Incorporated
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Except as contained in this notice, the name of the Metro Link shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from Metro Link.
-
-
-Copyright 1995-1998 by Metro Link, Inc.
-Copyright (c) 1997 Matthieu Herrb
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Metro Link, Inc. not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Metro Link, Inc. makes no
-representations about the suitability of this software for any purpose.
- It is provided "as is" without express or implied warranty.
-
-METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL METRO LINK, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1998 by Metro Link Incorporated
-
-Permission to use, copy, modify, distribute, and sell this software
-and its documentation for any purpose is hereby granted without fee,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Metro Link
-Incorporated not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission. Metro Link Incorporated makes no representations
-about the suitability of this software for any purpose. It is
-provided "as is" without express or implied warranty.
-
-METRO LINK INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL METRO LINK INCORPORATED BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
-DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-
-Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Except as contained in this notice, the name of Conectiva Linux shall
-not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from
-Conectiva Linux.
-
-
-Copyright (c) 2001, Andy Ritger aritger@nvidia.com
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-o Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-o Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
- distribution.
-o Neither the name of NVIDIA nor the names of its contributors
- may be used to endorse or promote products derived from this
- software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
-NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
-THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-
-Copyright 1992 Vrije Universiteit, The Netherlands
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted, provided
-that the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of the Vrije Universiteit not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. The Vrije Universiteit makes no
-representations about the suitability of this software for any purpose.
-It is provided "as is" without express or implied warranty.
-
-The Vrije Universiteit DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL The Vrije Universiteit BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1998 by Concurrent Computer Corporation
-
-Permission to use, copy, modify, distribute, and sell this software
-and its documentation for any purpose is hereby granted without fee,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Concurrent Computer
-Corporation not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission. Concurrent Computer Corporation makes no representations
-about the suitability of this software for any purpose. It is
-provided "as is" without express or implied warranty.
-
-CONCURRENT COMPUTER CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL CONCURRENT COMPUTER CORPORATION BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
-DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-
-Copyright © 2004 Nokia
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Nokia not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Nokia makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-(c)Copyright 1988,1991 Adobe Systems Incorporated.
-All rights reserved.
-
-Permission to use, copy, modify, distribute, and sublicense this software and its
-documentation for any purpose and without fee is hereby granted, provided that
-the above copyright notices appear in all copies and that both those copyright
-notices and this permission notice appear in supporting documentation and that
-the name of Adobe Systems Incorporated not be used in advertising or publicity
-pertaining to distribution of the software without specific, written prior
-permission. No trademark license to use the Adobe trademarks is hereby
-granted. If the Adobe trademark "Display PostScript"(tm) is used to describe
-this software, its functionality or for any other purpose, such use shall be
-limited to a statement that this software works in conjunction with the Display
-PostScript system. Proper trademark attribution to reflect Adobe's ownership
-of the trademark shall be given whenever any such reference to the Display
-PostScript system is made.
-
-ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
-PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE
-DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
-OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
-DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
-LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
-SUPPORT FOR THE SOFTWARE.
-
-Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
-Incorporated which may be registered in certain jurisdictions.
-
-
-Copyright 1989 Network Computing Devices, Inc., Mountain View, California.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted, provided
-that the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of N.C.D. not be used in advertising or
-publicity pertaining to distribution of the software without specific,
-written prior permission. N.C.D. makes no representations about the
-suitability of this software for any purpose. It is provided "as is"
-without express or implied warranty.
-
-
-Copyright (c) 1987 by the Regents of the University of California
-
-Permission to use, copy, modify, and distribute this
-software and its documentation for any purpose and without
-fee is hereby granted, provided that the above copyright
-notice appear in all copies. The University of California
-makes no representations about the suitability of this
-software for any purpose. It is provided "as is" without
-express or implied warranty.
-
-
-Copyright 1992, 1993 Data General Corporation;
-Copyright 1992, 1993 OMRON Corporation
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that the
-above copyright notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting documentation, and that
-neither the name OMRON or DATA GENERAL be used in advertising or publicity
-pertaining to distribution of the software without specific, written prior
-permission of the party whose name is to be used. Neither OMRON or
-DATA GENERAL make any representation about the suitability of this software
-for any purpose. It is provided "as is" without express or implied warranty.
-
-OMRON AND DATA GENERAL EACH DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
-IN NO EVENT SHALL OMRON OR DATA GENERAL BE LIABLE FOR ANY SPECIAL, INDIRECT
-OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
-OF THIS SOFTWARE.
-
-
-Copyright © 1998-2004, 2006 Keith Packard
-Copyright © 2000-2002 Keith Packard, member of The XFree86 Project, Inc.
-Copyright (c) 2002 Apple Computer, Inc.
-Copyright (c) 2003 Torrey T. Lyons.
-All Rights Reserved.
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Keith Packard not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Keith Packard makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright © 1999 Keith Packard
-Copyright © 2000 Compaq Computer Corporation
-Copyright © 2002 MontaVista Software Inc.
-Copyright © 2005 OpenedHand Ltd.
-Copyright © 2006 Nokia Corporation
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of the authors and/or copyright holders
-not be used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission. The authors and/or
-copyright holders make no representations about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
-THE AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1993 by Davor Matic
-
-Permission to use, copy, modify, distribute, and sell this software
-and its documentation for any purpose is hereby granted without fee,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation. Davor Matic makes no representations about
-the suitability of this software for any purpose. It is provided "as
-is" without express or implied warranty.
-
-
-Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
-Copyright (C) Colin Harrison 2005-2008
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Harold L Hunt II
-shall not be used in advertising or otherwise to promote the sale, use
-or other dealings in this Software without prior written authorization
-from Harold L Hunt II.
-
-
-Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Thomas Roell not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Thomas Roell makes no representations
-about the suitability of this software for any purpose. It is provided
-"as is" without express or implied warranty.
-
-THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
-Copyright 1993 by David Wexelblat <dwex@goblin.org>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the names of Thomas Roell and David Wexelblat
-not be used in advertising or publicity pertaining to distribution of
-the software without specific, written prior permission. Thomas Roell and
-David Wexelblat makes no representations about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
-THOMAS ROELL AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID WEXELBLAT BE LIABLE FOR
-ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
-RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
-CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1990,91,92,93 by Thomas Roell, Germany.
-Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA.
-
-Permission to use, copy, modify, distribute, and sell this software
-and its documentation for any purpose is hereby granted without fee,
-provided that the above copyright notice appear in all copies and
-that both that copyright notice and this permission notice appear
-in supporting documentation, and that the name of Thomas Roell nor
-SGCS be used in advertising or publicity pertaining to distribution
-of the software without specific, written prior permission.
-Thomas Roell nor SGCS makes no representations about the suitability
-of this software for any purpose. It is provided "as is" without
-express or implied warranty.
-
-THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
-RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
-CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1998 by Alan Hourihane, Wigan, England.
-Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales.
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Alan Hourihane not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Alan Hourihane makes no representations
-about the suitability of this software for any purpose. It is provided
-"as is" without express or implied warranty.
-
-ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1995 Kaleb S. KEITHLEY
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES
-OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Kaleb S. KEITHLEY
-shall not be used in advertising or otherwise to promote the sale, use
-or other dealings in this Software without prior written authorization
-from Kaleb S. KEITHLEY
-
-
-Copyright (c) 1997 Matthieu Herrb
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Matthieu Herrb not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Matthieu Herrb makes no
-representations about the suitability of this software for any purpose.
- It is provided "as is" without express or implied warranty.
-
-MATTHIEU HERRB DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL MATTHIEU HERRB BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 2004, Egbert Eich
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-EGBERT EICH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
-NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Egbert Eich shall not
-be used in advertising or otherwise to promote the sale, use or other deal-
-ings in this Software without prior written authorization from Egbert Eich.
-
-
-Copyright 1993 by David Wexelblat <dwex@goblin.org>
-Copyright 2005 by Kean Johnston <jkj@sco.com>
-Copyright 1993 by David McCullough <davidm@stallion.oz.au>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of David Wexelblat not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. David Wexelblat makes no representations
-about the suitability of this software for any purpose. It is provided
-"as is" without express or implied warranty.
-
-DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1992 by Orest Zborowski <obz@Kodak.com>
-Copyright 1993 by David Wexelblat <dwex@goblin.org>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the names of Orest Zborowski and David Wexelblat
-not be used in advertising or publicity pertaining to distribution of
-the software without specific, written prior permission. Orest Zborowski
-and David Wexelblat make no representations about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
-OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE
-FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1992 by Orest Zborowski <obz@Kodak.com>
-Copyright 1993 by David Dawes <dawes@xfree86.org>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the names of Orest Zborowski and David Dawes
-not be used in advertising or publicity pertaining to distribution of
-the software without specific, written prior permission. Orest Zborowski
-and David Dawes make no representations about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
-OREST ZBOROWSKI AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID DAWES BE LIABLE
-FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1995-1999 by Frederic Lepied, France. <fred@sugix.frmug.fr.net>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Frederic Lepied not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Frederic Lepied makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1992 by Rich Murphey <Rich@Rice.edu>
-Copyright 1993 by David Wexelblat <dwex@goblin.org>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the names of Rich Murphey and David Wexelblat
-not be used in advertising or publicity pertaining to distribution of
-the software without specific, written prior permission. Rich Murphey and
-David Wexelblat make no representations about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
-RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT BE LIABLE FOR
-ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
-RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
-CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1992 by Rich Murphey <Rich@Rice.edu>
-Copyright 1993 by David Dawes <dawes@xfree86.org>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the names of Rich Murphey and David Dawes
-not be used in advertising or publicity pertaining to distribution of
-the software without specific, written prior permission. Rich Murphey and
-David Dawes make no representations about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
-RICH MURPHEY AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID DAWES BE LIABLE FOR
-ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
-RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
-CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright © 2003-2004 Anders Carlsson
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Anders Carlsson not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Anders Carlsson makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL ANDERS CARLSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright (C) 2003 Anders Carlsson
-Copyright © 2003-2004 Eric Anholt
-Copyright © 2004 Keith Packard
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Eric Anholt not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Eric Anholt makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright © 2004 PillowElephantBadgerBankPond
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of PillowElephantBadgerBankPond not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. PillowElephantBadgerBankPond makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-PillowElephantBadgerBankPond DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL PillowElephantBadgerBankPond BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
-FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright © 2003-2004 Philip Blundell
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Philip Blundell not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Philip Blundell makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-PHILIP BLUNDELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL PHILIP BLUNDELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-
-Copyright (c) 1994-2003 by The XFree86 Project, Inc.
-Copyright 1997 by Metro Link, Inc.
-Copyright 2003 by David H. Dawes.
-Copyright 2003 by X-Oz Technologies.
-Copyright (c) 2004, X.Org Foundation
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the copyright holder(s)
-and author(s) shall not be used in advertising or otherwise to promote
-the sale, use or other dealings in this Software without prior written
-authorization from the copyright holder(s) and author(s).
-
-
-Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
-Copyright 1993 by David Wexelblat <dwex@goblin.org>
-Copyright 1999 by David Holland <davidh@iquest.net>
-Copyright © 2000 Compaq Computer Corporation
-Copyright © 2002 Hewlett-Packard Company
-Copyright © 2004, 2005 Red Hat, Inc.
-Copyright © 2004 Nicholas Miell
-Copyright © 2005 Trolltech AS
-Copyright © 2006 Intel Corporation
-Copyright © 2006-2007 Keith Packard
-Copyright © 2008 Red Hat, Inc
-Copyright © 2008 George Sapountzis <gsap7@yahoo.gr>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting documentation, and
-that the name of the copyright holders not be used in advertising or
-publicity pertaining to distribution of the software without specific,
-written prior permission. The copyright holders make no representations
-about the suitability of this software for any purpose. It is provided "as
-is" without express or implied warranty.
-
-THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
-OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-
-Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
- 2005 Lars Knoll & Zack Rusin, Trolltech
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Keith Packard not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Keith Packard makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
-OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-
-Copyright 1987, 1998 The Open Group
-Copyright © 1998-1999, 2001 The XFree86 Project, Inc.
-Copyright © 2000 VA Linux Systems, Inc.
-Copyright (c) 2000, 2001 Nokia Home Communications
-Copyright © 2007, 2008 Red Hat, Inc.
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, and/or sell copies of the Software, and to permit persons
-to whom the Software is furnished to do so, provided that the above
-copyright notice(s) and this permission notice appear in all copies of
-the Software and that both the above copyright notice(s) and this
-permission notice appear in supporting documentation.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
-INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
-FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder
-shall not be used in advertising or otherwise to promote the sale, use
-or other dealings in this Software without prior written authorization
-of the copyright holder.
-
-
-Copyright 1996 by Thomas E. Dickey <dickey@clark.net>
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the above listed
-copyright holder(s) not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior
-permission.
-
-THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
-Copyright (c) 2001 Andreas Monitzer.
-Copyright (c) 2001-2004 Greg Parker.
-Copyright (c) 2001-2004 Torrey T. Lyons
-Copyright (c) 2002-2003 Apple Computer, Inc.
-Copyright (c) 2004-2005 Alexander Gottwald
-Copyright (c) 2002-2009 Apple Inc.
-Copyright (c) 2007 Jeremy Huddleston
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name(s) of the above copyright
-holders shall not be used in advertising or otherwise to promote the sale,
-use or other dealings in this Software without prior written authorization.
-
-
-Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
-Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
-NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Copyright (C) 2005 Bogdan D. bogdand@users.sourceforge.net
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the author shall not be used in
-advertising or otherwise to promote the sale, use or other dealings in this
-Software without prior written authorization from the author.
-
-
-Copyright © 2002 David Dawes
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Except as contained in this notice, the name of the author(s) shall
-not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from
-the author(s).
-
-
-Copyright (C) 1996-1999 SciTech Software, Inc.
-Copyright (C) David Mosberger-Tang
-Copyright (C) 1999 Egbert Eich
-Copyright (C) 2008 Bart Trojanowski, Symbio Technologies, LLC
-
-Permission to use, copy, modify, distribute, and sell this software and
-its documentation for any purpose is hereby granted without fee,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the authors not be used
-in advertising or publicity pertaining to distribution of the software
-without specific, written prior permission. The authors makes no
-representations about the suitability of this software for any purpose.
-It is provided "as is" without express or implied warranty.
-
-THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
-USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 2005-2006 Luc Verhaegen.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-
-Copyright 1995 by Robin Cutshaw <robin@XFree86.Org>
-Copyright 2000 by Egbert Eich
-Copyright 2002 by David Dawes
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the names of the above listed copyright holder(s)
-not be used in advertising or publicity pertaining to distribution of
-the software without specific, written prior permission. The above listed
-copyright holder(s) make(s) no representations about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
-THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
-DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
-OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 1997-2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting documentation, and
-that the name of Marc Aurele La France not be used in advertising or
-publicity pertaining to distribution of the software without specific,
-written prior permission. Marc Aurele La France makes no representations
-about the suitability of this software for any purpose. It is provided
-"as-is" without express or implied warranty.
-
-MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
-EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
-OF THIS SOFTWARE.
-
-
-Copyright 1990, 1991 by Thomas Roell, Dinkelscherben, Germany
-Copyright 1992 by David Dawes <dawes@XFree86.org>
-Copyright 1992 by Jim Tsillas <jtsilla@damon.ccs.northeastern.edu>
-Copyright 1992 by Rich Murphey <Rich@Rice.edu>
-Copyright 1992 by Robert Baron <Robert.Baron@ernst.mach.cs.cmu.edu>
-Copyright 1992 by Orest Zborowski <obz@eskimo.com>
-Copyright 1993 by Vrije Universiteit, The Netherlands
-Copyright 1993 by David Wexelblat <dwex@XFree86.org>
-Copyright 1994, 1996 by Holger Veit <Holger.Veit@gmd.de>
-Copyright 1997 by Takis Psarogiannakopoulos <takis@dpmms.cam.ac.uk>
-Copyright 1994-2003 by The XFree86 Project, Inc
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the names of the above listed copyright holders
-not be used in advertising or publicity pertaining to distribution of
-the software without specific, written prior permission. The above listed
-copyright holders make no representations about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
-THE ABOVE LISTED COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDERS BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
-DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
-OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright 2001-2005 by J. Kean Johnston <jkj@sco.com>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name J. Kean Johnston not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. J. Kean Johnston makes no
-representations about the suitability of this software for any purpose.
-It is provided "as is" without express or implied warranty.
-
-J. KEAN JOHNSTON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL J. KEAN JOHNSTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
-USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-Copyright 1997,1998 by UCHIYAMA Yasushi
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of UCHIYAMA Yasushi not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. UCHIYAMA Yasushi makes no representations
-about the suitability of this software for any purpose. It is provided
-"as is" without express or implied warranty.
-
-UCHIYAMA YASUSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL UCHIYAMA YASUSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright (C) 2000 Keith Packard
- 2004 Eric Anholt
- 2005 Zack Rusin
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of copyright holders not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Copyright holders make no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
-OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-
-(C) Copyright IBM Corporation 2002-2007
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-this permission notice appear in supporting documentation. This permission
-notice shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-Copyright © 2007 OpenedHand Ltd
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of OpenedHand Ltd not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. OpenedHand Ltd makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-Copyright (c) 1989, 1990, 1993, 1994
- The Regents of the University of California. All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Chris Torek.
-
-This code is derived from software contributed to Berkeley by
-Michael Rendell of Memorial University of Newfoundland.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 4. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-</pre>
-<div class="license-packages">
-Used by these packages: x11-base/X.Org-1.9.3
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="ZLIB" class="title">Gentoo Package Provided Stock License ZLIB</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Copyright (C) <year> <copyright holders>
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the author(s) be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-</pre>
-<div class="license-packages">
-Used by these packages: sys-libs/zlib-1.2.7
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="as-is" class="title">Gentoo Package Provided Stock License as-is</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Note: This license label is deprecated, so don't use it for new packages.
-Unfortunately, "as-is" has been (ab)used also for non-free software and
-you cannot rely on it. Please check the upstream license instead.
-
-"as-is" in its originally intended sense is now covered by the OSI-approved
-"HPND" (Historical Permission Notice and Disclaimer).
-
----------------------------------------------------------------------------
-
-This is a generic place holder for a class of licenses that boil down to do
-no guarantees and all you get is what you have. The language is usually
-similar to:
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted, provided
- that the above copyright notice appears in all copies and that both the
- copyright notice and this permission notice appear in supporting
- documentation, and that the same name not be used in advertising or
- publicity pertaining to distribution of the software without specific,
- written prior permission. We make no representations about the
- suitability of this software for any purpose. It is provided "as is"
- without express or implied warranty.
-
-
-You will need to check the license that came with the software for the exact
-specifics. Generally you are free to do most anything you want with "as is"
-software but you should not take this license as legal advice.
-
-Note: Most all license have an "as is" clause. For our purposes this does
-not make all software in this category. This category is for software with
-very little restrictions.
-
-The information in this license about licenses is presented "as is". :-P
-
-</pre>
-<div class="license-packages">
-Used by these packages: net-wireless/crda-1.1.1-r1 app-text/docbook-xml-dtd-4.1.2-r6 sys-apps/hdparm-9.20 net-wireless/iw-3.6-r1 media-libs/libpng-1.2.49-r1 net-misc/openssh-5.2_p1-r10 dev-db/sqlite-3.6.22-r3 dev-lang/swig-2.0.4-r1 net-wireless/wireless-regdb-20101124-r1 app-arch/xz-utils-4.999.9_beta
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="boehm-gc" class="title">Gentoo Package Provided Stock License boehm-gc</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-<copyright notice>
-
-THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
-OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
-
-Permission is hereby granted to use or copy this program
-for any purpose, provided the above notices are retained on all copies.
-Permission to modify the code and to distribute modified code is granted,
-provided the above notices are retained, and a notice that the code was
-modified is included with the above copyright notice.
-
-</pre>
-<div class="license-packages">
-Used by these packages: dev-libs/libatomic_ops-7.2d
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="fontconfig" class="title">Gentoo Package Provided Stock License fontconfig</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-fontconfig/COPYING
-
-Copyright © 2001,2003 Keith Packard
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of Keith Packard not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. Keith Packard makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-
-</pre>
-<div class="license-packages">
-Used by these packages: media-libs/fontconfig-2.7.1-r36
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="icu" class="title">Gentoo Package Provided Stock License icu</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-ICU License - ICU 1.8.1 and later
-
-COPYRIGHT AND PERMISSION NOTICE
-
-Copyright (c) 1995-2003 International Business Machines Corporation and others
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, and/or sell copies of the Software, and to permit persons
-to whom the Software is furnished to do so, provided that the above
-copyright notice(s) and this permission notice appear in all copies of
-the Software and that both the above copyright notice(s) and this
-permission notice appear in supporting documentation.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
-INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
-FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder
-shall not be used in advertising or otherwise to promote the sale, use
-or other dealings in this Software without prior written authorization
-of the copyright holder.
-
---------------------------------------------------------------------------------
-All trademarks and registered trademarks mentioned herein are the property of their respective owners.
-
-</pre>
-<div class="license-packages">
-Used by these packages: media-libs/harfbuzz-0.9.18-r2
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="lsof" class="title">Gentoo Package Provided Stock License lsof</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ#1.9
-
-Copyright 2002 Purdue Research Foundation, West Lafayette,
-Indiana 47907. All rights reserved.
-
-Written by Victor A. Abell
-
-This software is not subject to any license of the American
-Telephone and Telegraph Company or the Regents of the
-University of California.
-
-Permission is granted to anyone to use this software for
-any purpose on any computer system, and to alter it and
-redistribute it freely, subject to the following
-restrictions:
-
-1. Neither the authors nor Purdue University are responsible
- for any consequences of the use of this software.
-
-2. The origin of this software must not be misrepresented,
- either by explicit claim or by omission. Credit to the
- authors and Purdue University must appear in documentation
- and sources.
-
-3. Altered versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
-4. This notice may not be removed or altered.
-
-</pre>
-<div class="license-packages">
-Used by these packages: sys-process/lsof-4.81-r2
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="ncurses" class="title">Gentoo Package Provided Stock License ncurses</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Copyright (c) 1998-2000,2005 Free Software Foundation, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, distribute with modifications, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
-THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name(s) of the above copyright
-holders shall not be used in advertising or otherwise to promote the
-sale, use or other dealings in this Software without prior written
-authorization.
-
-</pre>
-<div class="license-packages">
-Used by these packages: sys-libs/ncurses-5.9-r2
-</div>
-</div>
-</div>
-
-<div class="product">
-<a name="netiface" class="title">Gentoo Package Provided Stock License netiface</a>
-<a class="show" href="#" onclick="return toggle(this);">show license text</a>
-<div class="licence">
-<pre>
-Copyright (c) 2007, 2008 Alastair Houghton
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-</pre>
-<div class="license-packages">
-Used by these packages: dev-python/netifaces-0.8
+Used by these packages: media-fonts/crosextrafonts-carlito-20130920 media-fonts/ko-nanumfonts-3.10.0 media-fonts/lohitfonts-cros-2.5.0-r1 media-fonts/ml-anjalioldlipi-0.740 media-fonts/my-padauk-2.50 media-fonts/tibt-jomolhari-0.0.3c
</div>
</div>
</div>
@@ -22156,7 +16756,7 @@
</pre>
<div class="license-packages">
-Used by these packages: sys-libs/timezone-data-2012j sys-apps/util-linux-2.21.2-r1 app-arch/xz-utils-4.999.9_beta
+Used by these packages: sys-libs/timezone-data-2013d sys-apps/util-linux-2.21.2-r1 app-arch/xz-utils-4.999.9_beta
</div>
</div>
</div>
@@ -22214,6 +16814,77 @@
</div>
<div class="product">
+<a name="RSA" class="title">Gentoo Package Provided Stock License RSA</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+[<copyright notice>]
+
+License to copy and use this software is granted provided that it is
+identified as [the] "<copyright holder> <software>" in all material
+mentioning or referencing this software [or this function].
+
+License is also granted to make and use derivative works provided that
+such works are identified as "derived from the <copyright holder>
+<software>" in all material mentioning or referencing the derived
+work.
+
+<copyright holder> makes no representations concerning either the
+merchantability of this software or the suitability of this software
+for any particular purpose. It is provided "as is" without express or
+implied warranty of any kind.
+
+[These notices must be retained in any copies of any part of this
+documentation and/or software.]
+
+</pre>
+<div class="license-packages">
+Used by these packages: net-misc/strongswan-5.0.2-r5
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="SGI-B-2.0" class="title">Gentoo Package Provided Stock License SGI-B-2.0</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+
+Copyright (C) [dates of first publication] Silicon Graphics, Inc. All Rights
+Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice including the dates of first publication and either
+this permission notice or a reference to http://oss.sgi.com/projects/FreeB/
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON
+GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Silicon Graphics, Inc. shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Silicon
+Graphics, Inc.
+
+</pre>
+<div class="license-packages">
+Used by these packages: media-libs/glu-9.0.0 media-libs/mesa-9.1-r14
+</div>
+</div>
+</div>
+
+<div class="product">
<a name="unRAR" class="title">Gentoo Package Provided Stock License unRAR</a>
<a class="show" href="#" onclick="return toggle(this);">show license text</a>
<div class="licence">
@@ -22570,5 +17241,1891 @@
</div>
</div>
+<div class="product">
+<a name="X" class="title">Gentoo Package Provided Stock License X</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+The following is the 'standard copyright' agreed upon by most contributors,
+and is currently the canonical license preferred by the X.Org Foundation.
+This is a slight variant of the common MIT license form published by the
+Open Source Initiative at http://www.opensource.org/licenses/mit-license.php
+
+Copyright holders of new code should use this license statement where
+possible, and insert their name to this list. Please sort by surname
+for people, and by the full name for other entities (e.g. Juliusz
+Chroboczek sorts before Intel Corporation sorts before Daniel Stone).
+
+Copyright © 2000-2001 Juliusz Chroboczek
+Copyright © 1998 Egbert Eich
+Copyright © 2006-2007 Intel Corporation
+Copyright © 2006 Nokia Corporation
+Copyright © 2006-2008 Peter Hutterer
+Copyright © 2006 Adam Jackson
+Copyright © 2009 NVIDIA Corporation
+Copyright © 1999 Keith Packard
+Copyright © 2007-2009 Red Hat, Inc.
+Copyright © 2005-2008 Daniel Stone
+Copyright © 2006-2009 Simon Thum
+Copyright © 1987, 2003-2006, 2008-2009 Sun Microsystems, Inc.
+Copyright © 2006 Luc Verhaegen
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+
+
+The following licenses are 'legacy': usually MIT/X11 licenses with the name
+of the copyright holder(s) in the license statement, but also some BSD-like
+licenses.
+
+
+Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) Colin Harrison 2005-2008
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+
+
+Copyright 1997 by The XFree86 Project, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of the XFree86 Project, Inc.
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission. The Xfree86
+Project, Inc. makes no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+THE XFREE86 PROJECT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1985-1998, 2001 The Open Group
+Copyright 2002 Red Hat Inc., Durham, North Carolina.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright (c) 1987, 1989-1990, 1992-1995 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+
+Copyright © 1999-2000 SuSE, Inc.
+Copyright © 2007 Red Hat, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of SuSE not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. SuSE makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+
+SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1987-1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts.
+Copyright 1991 Massachusetts Institute of Technology, Cambridge, Massachusetts.
+Copyright 1991, 1993 Olivetti Research Limited, Cambridge, England.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
+Copyright 1994 Quarterdeck Office Systems.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital and
+Quarterdeck not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
+OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1997 Digital Equipment Corporation.
+All rights reserved.
+
+This software is furnished under license and may be used and copied only in
+accordance with the following terms and conditions. Subject to these
+conditions, you may download, copy, install, use, modify and distribute
+this software in source and/or binary form. No title or ownership is
+transferred hereby.
+
+1) Any source code used, modified or distributed must reproduce and retain
+ this copyright notice and list of conditions as they appear in the
+ source file.
+
+2) No right is granted to use any trade name, trademark, or logo of Digital
+ Equipment Corporation. Neither the "Digital Equipment Corporation"
+ name nor any trademark or logo of Digital Equipment Corporation may be
+ used to endorse or promote products derived from this software without
+ the prior written permission of Digital Equipment Corporation.
+
+3) This software is provided "AS-IS" and any express or implied warranties,
+ including but not limited to, any implied warranties of merchantability,
+ fitness for a particular purpose, or non-infringement are disclaimed.
+ In no event shall DIGITAL be liable for any damages whatsoever, and in
+ particular, DIGITAL shall not be liable for special, indirect,
+ consequential, or incidental damages or damages for lost profits, loss
+ of revenue or loss of use, whether such damages arise in contract,
+ negligence, tort, under statute, in equity, at law or otherwise, even
+ if advised of the possibility of such damage.
+
+
+Copyright (c) 1991, 1996-1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+
+SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice including the dates of first publication and
+either this permission notice or a reference to
+http://oss.sgi.com/projects/FreeB/
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+Copyright (c) 1994, 1995 Hewlett-Packard Company
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the Hewlett-Packard
+Company shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the Hewlett-Packard Company.
+
+
+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Hewlett-Packard not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+
+Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
+Copyright (c) 2003 by the XFree86 Project, Inc.
+Copyright 2004-2005 Red Hat Inc., Raleigh, North Carolina.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation on the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+Copyright © 2008 Red Hat, Inc.
+Partly based on code Copyright © 2000 SuSE, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without
+fee, provided that the above copyright notice appear in all copies
+and that both that copyright notice and this permission notice
+appear in supporting documentation, and that the name of Red Hat
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission. Red
+Hat makes no representations about the suitability of this software
+for any purpose. It is provided "as is" without express or implied
+warranty.
+
+Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+NO EVENT SHALL Red Hat BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of SuSE not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. SuSE makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+
+SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright © 2006 Red Hat, Inc.
+(C) Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sub license,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+RED HAT, INC, OR PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright (c) 1995 X Consortium
+Copyright 2004 Red Hat Inc., Durham, North Carolina.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation on the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT, THE X CONSORTIUM,
+AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written
+authorization from the X Consortium.
+
+
+Copyright 1998-2000 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+Copyright (c) 2002, 2008, 2009 Apple Computer, Inc.
+Copyright (c) 2003-2004 Torrey T. Lyons.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+(C) Copyright IBM Corporation 2003
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+(C) Copyright IBM Corporation 2004-2005
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sub license,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+IBM,
+AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+Copyright (c) 1997 Metro Link Incorporated
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the Metro Link shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from Metro Link.
+
+
+Copyright 1995-1998 by Metro Link, Inc.
+Copyright (c) 1997 Matthieu Herrb
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Metro Link, Inc. not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Metro Link, Inc. makes no
+representations about the suitability of this software for any purpose.
+ It is provided "as is" without express or implied warranty.
+
+METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL METRO LINK, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1998 by Metro Link Incorporated
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Metro Link
+Incorporated not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission. Metro Link Incorporated makes no representations
+about the suitability of this software for any purpose. It is
+provided "as is" without express or implied warranty.
+
+METRO LINK INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL METRO LINK INCORPORATED BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+
+Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of Conectiva Linux shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from
+Conectiva Linux.
+
+
+Copyright (c) 2001, Andy Ritger aritger@nvidia.com
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+o Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+o Neither the name of NVIDIA nor the names of its contributors
+ may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
+NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+Copyright 1992 Vrije Universiteit, The Netherlands
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of the Vrije Universiteit not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. The Vrije Universiteit makes no
+representations about the suitability of this software for any purpose.
+It is provided "as is" without express or implied warranty.
+
+The Vrije Universiteit DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL The Vrije Universiteit BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1998 by Concurrent Computer Corporation
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Concurrent Computer
+Corporation not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission. Concurrent Computer Corporation makes no representations
+about the suitability of this software for any purpose. It is
+provided "as is" without express or implied warranty.
+
+CONCURRENT COMPUTER CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL CONCURRENT COMPUTER CORPORATION BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+
+Copyright © 2004 Nokia
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Nokia not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Nokia makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+(c)Copyright 1988,1991 Adobe Systems Incorporated.
+All rights reserved.
+
+Permission to use, copy, modify, distribute, and sublicense this software and its
+documentation for any purpose and without fee is hereby granted, provided that
+the above copyright notices appear in all copies and that both those copyright
+notices and this permission notice appear in supporting documentation and that
+the name of Adobe Systems Incorporated not be used in advertising or publicity
+pertaining to distribution of the software without specific, written prior
+permission. No trademark license to use the Adobe trademarks is hereby
+granted. If the Adobe trademark "Display PostScript"(tm) is used to describe
+this software, its functionality or for any other purpose, such use shall be
+limited to a statement that this software works in conjunction with the Display
+PostScript system. Proper trademark attribution to reflect Adobe's ownership
+of the trademark shall be given whenever any such reference to the Display
+PostScript system is made.
+
+ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
+PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE
+DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
+INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
+OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
+LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
+SUPPORT FOR THE SOFTWARE.
+
+Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+Incorporated which may be registered in certain jurisdictions.
+
+
+Copyright 1989 Network Computing Devices, Inc., Mountain View, California.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of N.C.D. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. N.C.D. makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+
+
+Copyright (c) 1987 by the Regents of the University of California
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies. The University of California
+makes no representations about the suitability of this
+software for any purpose. It is provided "as is" without
+express or implied warranty.
+
+
+Copyright 1992, 1993 Data General Corporation;
+Copyright 1992, 1993 OMRON Corporation
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that the
+above copyright notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting documentation, and that
+neither the name OMRON or DATA GENERAL be used in advertising or publicity
+pertaining to distribution of the software without specific, written prior
+permission of the party whose name is to be used. Neither OMRON or
+DATA GENERAL make any representation about the suitability of this software
+for any purpose. It is provided "as is" without express or implied warranty.
+
+OMRON AND DATA GENERAL EACH DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL OMRON OR DATA GENERAL BE LIABLE FOR ANY SPECIAL, INDIRECT
+OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+OF THIS SOFTWARE.
+
+
+Copyright © 1998-2004, 2006 Keith Packard
+Copyright © 2000-2002 Keith Packard, member of The XFree86 Project, Inc.
+Copyright (c) 2002 Apple Computer, Inc.
+Copyright (c) 2003 Torrey T. Lyons.
+All Rights Reserved.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Keith Packard not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Keith Packard makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright © 1999 Keith Packard
+Copyright © 2000 Compaq Computer Corporation
+Copyright © 2002 MontaVista Software Inc.
+Copyright © 2005 OpenedHand Ltd.
+Copyright © 2006 Nokia Corporation
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of the authors and/or copyright holders
+not be used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission. The authors and/or
+copyright holders make no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+THE AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1993 by Davor Matic
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+
+Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
+Copyright (C) Colin Harrison 2005-2008
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Harold L Hunt II
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+from Harold L Hunt II.
+
+
+Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Thomas Roell not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Thomas Roell makes no representations
+about the suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of Thomas Roell and David Wexelblat
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission. Thomas Roell and
+David Wexelblat makes no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+THOMAS ROELL AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID WEXELBLAT BE LIABLE FOR
+ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1990,91,92,93 by Thomas Roell, Germany.
+Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA.
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and
+that both that copyright notice and this permission notice appear
+in supporting documentation, and that the name of Thomas Roell nor
+SGCS be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+Thomas Roell nor SGCS makes no representations about the suitability
+of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+
+THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1998 by Alan Hourihane, Wigan, England.
+Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Alan Hourihane not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Alan Hourihane makes no representations
+about the suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1995 Kaleb S. KEITHLEY
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES
+OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Kaleb S. KEITHLEY
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+from Kaleb S. KEITHLEY
+
+
+Copyright (c) 1997 Matthieu Herrb
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Matthieu Herrb not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Matthieu Herrb makes no
+representations about the suitability of this software for any purpose.
+ It is provided "as is" without express or implied warranty.
+
+MATTHIEU HERRB DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL MATTHIEU HERRB BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 2004, Egbert Eich
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+EGBERT EICH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Egbert Eich shall not
+be used in advertising or otherwise to promote the sale, use or other deal-
+ings in this Software without prior written authorization from Egbert Eich.
+
+
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+Copyright 2005 by Kean Johnston <jkj@sco.com>
+Copyright 1993 by David McCullough <davidm@stallion.oz.au>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of David Wexelblat not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. David Wexelblat makes no representations
+about the suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1992 by Orest Zborowski <obz@Kodak.com>
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of Orest Zborowski and David Wexelblat
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission. Orest Zborowski
+and David Wexelblat make no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1992 by Orest Zborowski <obz@Kodak.com>
+Copyright 1993 by David Dawes <dawes@xfree86.org>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of Orest Zborowski and David Dawes
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission. Orest Zborowski
+and David Dawes make no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+OREST ZBOROWSKI AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID DAWES BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1995-1999 by Frederic Lepied, France. <fred@sugix.frmug.fr.net>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Frederic Lepied not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Frederic Lepied makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1992 by Rich Murphey <Rich@Rice.edu>
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of Rich Murphey and David Wexelblat
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission. Rich Murphey and
+David Wexelblat make no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT BE LIABLE FOR
+ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1992 by Rich Murphey <Rich@Rice.edu>
+Copyright 1993 by David Dawes <dawes@xfree86.org>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of Rich Murphey and David Dawes
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission. Rich Murphey and
+David Dawes make no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+RICH MURPHEY AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID DAWES BE LIABLE FOR
+ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright © 2003-2004 Anders Carlsson
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Anders Carlsson not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Anders Carlsson makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL ANDERS CARLSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright (C) 2003 Anders Carlsson
+Copyright © 2003-2004 Eric Anholt
+Copyright © 2004 Keith Packard
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Eric Anholt not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Eric Anholt makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright © 2004 PillowElephantBadgerBankPond
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of PillowElephantBadgerBankPond not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. PillowElephantBadgerBankPond makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+PillowElephantBadgerBankPond DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL PillowElephantBadgerBankPond BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright © 2003-2004 Philip Blundell
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Philip Blundell not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Philip Blundell makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+PHILIP BLUNDELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL PHILIP BLUNDELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+
+Copyright (c) 1994-2003 by The XFree86 Project, Inc.
+Copyright 1997 by Metro Link, Inc.
+Copyright 2003 by David H. Dawes.
+Copyright 2003 by X-Oz Technologies.
+Copyright (c) 2004, X.Org Foundation
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holder(s)
+and author(s) shall not be used in advertising or otherwise to promote
+the sale, use or other dealings in this Software without prior written
+authorization from the copyright holder(s) and author(s).
+
+
+Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
+Copyright 1993 by David Wexelblat <dwex@goblin.org>
+Copyright 1999 by David Holland <davidh@iquest.net>
+Copyright © 2000 Compaq Computer Corporation
+Copyright © 2002 Hewlett-Packard Company
+Copyright © 2004, 2005 Red Hat, Inc.
+Copyright © 2004 Nicholas Miell
+Copyright © 2005 Trolltech AS
+Copyright © 2006 Intel Corporation
+Copyright © 2006-2007 Keith Packard
+Copyright © 2008 Red Hat, Inc
+Copyright © 2008 George Sapountzis <gsap7@yahoo.gr>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting documentation, and
+that the name of the copyright holders not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. The copyright holders make no representations
+about the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+
+Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ 2005 Lars Knoll & Zack Rusin, Trolltech
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Keith Packard not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Keith Packard makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+
+Copyright 1987, 1998 The Open Group
+Copyright © 1998-1999, 2001 The XFree86 Project, Inc.
+Copyright © 2000 VA Linux Systems, Inc.
+Copyright (c) 2000, 2001 Nokia Home Communications
+Copyright © 2007, 2008 Red Hat, Inc.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+
+Copyright 1996 by Thomas E. Dickey <dickey@clark.net>
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the above listed
+copyright holder(s) not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright (c) 2001 Andreas Monitzer.
+Copyright (c) 2001-2004 Greg Parker.
+Copyright (c) 2001-2004 Torrey T. Lyons
+Copyright (c) 2002-2003 Apple Computer, Inc.
+Copyright (c) 2004-2005 Alexander Gottwald
+Copyright (c) 2002-2009 Apple Inc.
+Copyright (c) 2007 Jeremy Huddleston
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name(s) of the above copyright
+holders shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written authorization.
+
+
+Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
+Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Copyright (C) 2005 Bogdan D. bogdand@users.sourceforge.net
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall not be used in
+advertising or otherwise to promote the sale, use or other dealings in this
+Software without prior written authorization from the author.
+
+
+Copyright © 2002 David Dawes
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of the author(s) shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from
+the author(s).
+
+
+Copyright (C) 1996-1999 SciTech Software, Inc.
+Copyright (C) David Mosberger-Tang
+Copyright (C) 1999 Egbert Eich
+Copyright (C) 2008 Bart Trojanowski, Symbio Technologies, LLC
+
+Permission to use, copy, modify, distribute, and sell this software and
+its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the authors not be used
+in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. The authors makes no
+representations about the suitability of this software for any purpose.
+It is provided "as is" without express or implied warranty.
+
+THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 2005-2006 Luc Verhaegen.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright 1995 by Robin Cutshaw <robin@XFree86.Org>
+Copyright 2000 by Egbert Eich
+Copyright 2002 by David Dawes
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of the above listed copyright holder(s)
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission. The above listed
+copyright holder(s) make(s) no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1997-2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting documentation, and
+that the name of Marc Aurele La France not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. Marc Aurele La France makes no representations
+about the suitability of this software for any purpose. It is provided
+"as-is" without express or implied warranty.
+
+MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+OF THIS SOFTWARE.
+
+
+Copyright 1990, 1991 by Thomas Roell, Dinkelscherben, Germany
+Copyright 1992 by David Dawes <dawes@XFree86.org>
+Copyright 1992 by Jim Tsillas <jtsilla@damon.ccs.northeastern.edu>
+Copyright 1992 by Rich Murphey <Rich@Rice.edu>
+Copyright 1992 by Robert Baron <Robert.Baron@ernst.mach.cs.cmu.edu>
+Copyright 1992 by Orest Zborowski <obz@eskimo.com>
+Copyright 1993 by Vrije Universiteit, The Netherlands
+Copyright 1993 by David Wexelblat <dwex@XFree86.org>
+Copyright 1994, 1996 by Holger Veit <Holger.Veit@gmd.de>
+Copyright 1997 by Takis Psarogiannakopoulos <takis@dpmms.cam.ac.uk>
+Copyright 1994-2003 by The XFree86 Project, Inc
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of the above listed copyright holders
+not be used in advertising or publicity pertaining to distribution of
+the software without specific, written prior permission. The above listed
+copyright holders make no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+THE ABOVE LISTED COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDERS BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 2001-2005 by J. Kean Johnston <jkj@sco.com>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name J. Kean Johnston not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. J. Kean Johnston makes no
+representations about the suitability of this software for any purpose.
+It is provided "as is" without express or implied warranty.
+
+J. KEAN JOHNSTON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL J. KEAN JOHNSTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright 1997,1998 by UCHIYAMA Yasushi
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of UCHIYAMA Yasushi not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. UCHIYAMA Yasushi makes no representations
+about the suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+UCHIYAMA YASUSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL UCHIYAMA YASUSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright (C) 2000 Keith Packard
+ 2004 Eric Anholt
+ 2005 Zack Rusin
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of copyright holders not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Copyright holders make no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+
+(C) Copyright IBM Corporation 2002-2007
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation. This permission
+notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright © 2007 OpenedHand Ltd
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of OpenedHand Ltd not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. OpenedHand Ltd makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright (c) 1989, 1990, 1993, 1994
+ The Regents of the University of California. All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Chris Torek.
+
+This code is derived from software contributed to Berkeley by
+Michael Rendell of Memorial University of Newfoundland.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+</pre>
+<div class="license-packages">
+Used by these packages: x11-base/X.Org-1.9.3
+</div>
+</div>
+</div>
+
+<div class="product">
+<a name="ZLIB" class="title">Gentoo Package Provided Stock License ZLIB</a>
+<a class="show" href="#" onclick="return toggle(this);">show license text</a>
+<div class="licence">
+<pre>
+Copyright (C) <year> <copyright holders>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the author(s) be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+</pre>
+<div class="license-packages">
+Used by these packages: sys-libs/zlib-1.2.7
+</div>
+</div>
+</div>
+
</body>
</html>
diff --git a/chrome/browser/resources/chromeos/about_sys.css b/chrome/browser/resources/chromeos/about_sys.css
new file mode 100644
index 0000000..aca684d
--- /dev/null
+++ b/chrome/browser/resources/chromeos/about_sys.css
@@ -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.
+ */
+
+#anchor {
+ display: none;
+}
+
+body {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 84%;
+ margin: 0;
+ min-width: 45em;
+ padding: 0.75em;
+}
+
+.global-button {
+ margin: 1px 3px 0 3px;
+}
+
+h1,
+h2 {
+ font-size: 120%;
+ letter-spacing: -.5px;
+ margin: 0;
+}
+
+h1 {
+ color: rgb(74, 142, 230);
+ font-weight: bold;
+ padding: 0;
+}
+
+h2 {
+ -webkit-padding-end: 1em;
+ -webkit-padding-start: 0;
+ color: rgb(58, 117, 189);
+ display: inline-block;
+ font-weight: normal;
+ margin-top: 0;
+}
+
+#header {
+ background: rgb(82, 150, 222);
+ background-size: 100%;
+ border: 1px solid rgb(58, 117, 189);
+ border-radius: 6px;
+ color: white;
+ margin-bottom: 0.75em;
+ overflow: hidden;
+ padding: 0.6em 1em 0.75em 0;
+ position: relative;
+ text-shadow: 0 0 2px black;
+}
+
+html[dir='rtl'] #header {
+ padding: 0.6em 0 0.75em 1em;
+}
+
+#header h1 {
+ -webkit-padding-start: 3em;
+ background: url('../../../../ui/webui/resources/images/gear.png') no-repeat;
+ background-position: 12px 60%;
+ color: white;
+ display: inline;
+ margin: 0;
+}
+
+html[dir='rtl'] #header h1 {
+ background-position: right 12px top 60%;
+}
+
+#header p {
+ -webkit-padding-start: 0.4em;
+ color: white;
+ display: inline;
+ font-size: 84%;
+ font-style: italic;
+}
+
+.list {
+ border-collapse: collapse;
+ font-size: 84%;
+ line-height: 200%;
+ width: 100%;
+}
+
+.list:not(.filtered) tr:nth-child(odd) td {
+ background: rgb(239, 243, 255);
+}
+
+.list td {
+ font-family: 'Courier New', monospace;
+ line-height: 1.4em;
+ padding: 0 0.5em;
+ padding-top: 0.35em;
+ vertical-align: top;
+ white-space: pre;
+}
+
+.list tr td:nth-last-child(1),
+.list tr th:nth-last-child(1) {
+ -webkit-padding-end: 1em;
+}
+
+.list:not(.filtered) .tab .name {
+ -webkit-padding-start: 1.5em;
+}
+
+.list .name {
+ width: 20%;
+}
+
+.list .button-cell {
+ width: 7%;
+}
+
+.list .name div {
+ height: 1.6em;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.button-hidden {
+ display: none;
+}
+
+.number-expanded,
+.number-collapsed {
+ text-align: left;
+ width: 80%;
+}
+
+html[dir='rtl'] .number-expanded,
+html[dir='rtl'] .number-collapsed {
+ text-align: right;
+}
+
+tr > *:nth-child(1),
+tr > *:nth-child(2) {
+ -webkit-border-end: 1px solid rgb(181, 198, 222);
+}
+
+.name {
+ background-position: 5em center;
+ background-repeat: no-repeat;
+}
+
+html[dir='rtl'] #details .name {
+ background-position-left: auto;
+ background-position-right: 5em;
+}
+
+.number-collapsed .stat-value {
+ display: none;
+}
+
+.number-expanded .stat-value {
+ display: auto;
+}
+
+#status {
+ color: rgb(255, 0, 0);
+ margin: .5em 0;
+}
diff --git a/chrome/browser/resources/chromeos/about_sys.html b/chrome/browser/resources/chromeos/about_sys.html
index 6958c72..4626fe9 100644
--- a/chrome/browser/resources/chromeos/about_sys.html
+++ b/chrome/browser/resources/chromeos/about_sys.html
@@ -2,249 +2,10 @@
<html i18n-values="dir:textdirection;"><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title i18n-content="title"></title>
-
-<style>
-body {
- font-size: 84%;
- font-family: Arial, Helvetica, sans-serif;
- padding: 0.75em;
- margin: 0;
- min-width: 45em;
-}
-
-h1, h2 {
- font-size: 120%;
- letter-spacing: -1px;
- margin: 0;
-}
-
-h1 {
- font-weight: bold;
- color: #4a8ee6;
- padding: 0;
-}
-
-h2 {
- font-weight: normal;
- padding: 0.5em 1em;
- color: #3a75bd;
- -webkit-margin-start: -38px;
- -webkit-padding-start: 38px;
- border-top: 1px solid #3a75bd;
- padding-top: 0.5em;
-}
-
-h2:first-child {
- border-top: 0;
- padding-top: 0;
- float: left;
- vertical-align: text-bottom;
-}
-
-#header {
- padding: 0.6em 1em 0.75em 0;
- margin-bottom: 0.75em;
- position: relative;
- overflow: hidden;
- background: #5296de;
- background-size: 100%;
- border: 1px solid #3a75bd;
- border-radius: 6px;
- color: white;
- text-shadow: 0 0 2px black;
-}
-
-html[dir='rtl'] #header {
- padding: 0.6em 0 0.75em 1em;
-}
-
-#header h1 {
- -webkit-padding-start: 3em;
- margin: 0;
- display: inline;
- background: url('../../../../ui/webui/resources/images/gear.png') no-repeat;
- background-position: 12px 60%;
- color: white;
-}
-
-html[dir='rtl'] #header h1 {
- background-position-left: auto;
- backgroun-position-right: 12px;
-}
-
-#header p {
- font-size: 84%;
- font-style: italic;
- padding: 0;
- margin: 0;
- color: white;
- -webkit-padding-start: 0.4em;
- display: inline;
-}
-
-.list {
- line-height: 200%;
- border-collapse: collapse;
- font-size: 84%;
- width: 100%;
-}
-.list:not(.filtered) tr:nth-child(odd) td {
- background: #eff3ff;
-}
-
-.list td {
- padding: 0 0.5em;
- vertical-align: top;
- line-height: 1.4em;
- padding-top: 0.35em;
- font-family: 'Courier New', monospace;
- white-space: pre;
-}
-
-.list tr td:nth-last-child(1),
-.list tr th:nth-last-child(1) {
- -webkit-padding-end: 1em;
-}
-
-.list:not(.filtered) .tab .name {
- -webkit-padding-start: 1.5em;
-}
-
-.list .name {
- width: 20%;
-}
-
-.list .button_cell {
- width: 7%;
-}
-
-.list .name div {
- height: 1.6em;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-
-.button_hidden {
- display: none;
-}
-
-.number_expanded, .number_collapsed {
- text-align: left;
- width: 80%;
-}
-
-html[dir='rtl'] .number_expanded, html[dir='rtl'] .number_collapsed {
- text-align: right;
-}
-
-tr:not(.firstRow) > *:nth-child(1),
-tr:not(.firstRow) > *:nth-child(2),
-tr.firstRow th:nth-child(1),
-tr.firstRow th:nth-child(2) {
- -webkit-border-end: 1px solid #b5c6de;
-}
-
-.name {
- background-position: 5em center;
- background-repeat: no-repeat;
-}
-
-html[dir='rtl'] #details .name {
- background-position-left: auto;
- background-position-right: 5em;
-}
-
-.number_collapsed .stat_value {
- display: none;
-}
-
-.number_expanded .stat_value {
- display: auto;
-}
-
-#anchor {
- display: none;
-}
-
-.globalButton {
- float: left;
- margin: 1px 5px;
-}
-
-html[dir='rtl'] .globalButton {
- float: right;
-}
-</style>
+<link rel="stylesheet" href="about_sys.css">
+<script src="chrome://resources/js/util.js"></script>
<script src="chrome://resources/js/local_strings.js"></script>
-<script>
-var localStrings;
-
-function getValueDivForButton(button) {
- return document.getElementById(button.id.substr(0, button.id.length - 4));
-}
-
-function getButtonForValueDiv(valueDiv) {
- return document.getElementById(valueDiv.id + '-btn');
-}
-
-function changeCollapsedStatus() {
- var valueDiv = getValueDivForButton(this);
- if (valueDiv.parentNode.className == 'number_collapsed') {
- valueDiv.parentNode.className = 'number_expanded';
- this.textContent = localStrings.getString('collapse_btn');
- } else {
- valueDiv.parentNode.className = 'number_collapsed';
- this.textContent = localStrings.getString('expand_btn');
- }
-}
-
-function collapseAll() {
- var valueDivs = document.getElementsByClassName('stat_value');
- for(var i = 0; i < valueDivs.length; i++) {
- var button = getButtonForValueDiv(valueDivs[i]);
- if (button && button.className != 'button_hidden') {
- button.textContent = localStrings.getString('expand_btn');
- valueDivs[i].parentNode.className = 'number_collapsed';
- }
- }
-}
-
-function expandAll() {
- var valueDivs = document.getElementsByClassName('stat_value');
- for(var i = 0; i < valueDivs.length; i++) {
- var button = getButtonForValueDiv(valueDivs[i]);
- if (button && button.className != 'button_hidden') {
- button.textContent = localStrings.getString('collapse_btn');
- valueDivs[i].parentNode.className = 'number_expanded';
- }
- }
-}
-
-document.addEventListener('DOMContentLoaded', function() {
- localStrings = new LocalStrings();
-
- var collapseAllBtn = document.getElementById('collapseAll');
- collapseAllBtn.onclick = collapseAll;
-
- var expandAllBtn = document.getElementById('expandAll');
- expandAllBtn.onclick = expandAll;
-
- var anchorName = document.getElementById('anchor').textContent;
- var valueDivs = document.getElementsByClassName('stat_value');
- for(var i = 0; i < valueDivs.length; i++) {
- var button = getButtonForValueDiv(valueDivs[i]);
- button.onclick = changeCollapsedStatus;
- if (valueDivs[i].textContent.split('\n').length > 1) {
- button.textContent = localStrings.getString('expand_btn');
- valueDivs[i].parentNode.className = 'number_collapsed';
- } else {
- button.className = 'button_hidden';
- }
- }
-});
-</script>
-
+<script src="about_sys.js"></script>
</head>
<body id="t">
<div id="header">
@@ -252,20 +13,21 @@
<p i18n-content="description"></p>
</div>
<div id="content">
- <h2 i18n-content="table_title"></h2>
+ <h2 id="tableTitle" i18n-content="tableTitle"></h2>
<div id="anchor" jscontent="anchor"></div>
- <button id="expandAll" class="globalButton" i18n-content="expand_all_btn">
+ <button id="expandAll" class="global-button" i18n-content="expandAllBtn">
</button>
- <button id="collapseAll" class="globalButton"
- i18n-content="collapse_all_btn"></button>
+ <button id="collapseAll" class="global-button"
+ i18n-content="collapseAllBtn"></button>
+ <p id="status"></p>
<table class="list" id="details">
<tr jsselect="details">
- <td class="name"><a jsvalues="name:anchor_value"><div
- jscontent="stat_name"></div></a></td>
- <td class="button_cell"><button jsvalues="id:stat_name + '-value-btn'"
- class="expand_status"></button></td>
- <td class="number"><div class="stat_value" jscontent="stat_value"
- jsvalues="id:stat_name + '-value'"></div></td>
+ <td class="name"<div
+ jscontent="statName"></div></td>
+ <td class="button-cell"><button jsvalues="id:statName + '-value-btn'"
+ class="expand-status"></button></td>
+ <td class="number"><div class="stat-value" jscontent="statValue"
+ jsvalues="id:statName + '-value'"></div></td>
</tr>
</table>
</div>
diff --git a/chrome/browser/resources/chromeos/about_sys.js b/chrome/browser/resources/chromeos/about_sys.js
new file mode 100644
index 0000000..0bc3944
--- /dev/null
+++ b/chrome/browser/resources/chromeos/about_sys.js
@@ -0,0 +1,185 @@
+// Copyright 2013 The Chromium 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 localStrings;
+
+// Contents of lines that act as delimiters for multi-line values.
+var DELIM_START = '---------- START ----------';
+var DELIM_END = '---------- END ----------';
+
+// Limit file size to 10 MiB to prevent hanging on accidental upload.
+var MAX_FILE_SIZE = 10485760;
+
+function getValueDivForButton(button) {
+ return $(button.id.substr(0, button.id.length - 4));
+}
+
+function getButtonForValueDiv(valueDiv) {
+ return $(valueDiv.id + '-btn');
+}
+
+function handleDragOver(e) {
+ e.dataTransfer.dropEffect = 'copy';
+ e.preventDefault();
+}
+
+function showError(fileName) {
+ $('status').textContent = localStrings.getStringF('parseError', fileName);
+}
+
+/**
+ * Toggles whether an item is collapsed or expanded.
+ */
+function changeCollapsedStatus() {
+ var valueDiv = getValueDivForButton(this);
+ if (valueDiv.parentNode.className == 'number-collapsed') {
+ valueDiv.parentNode.className = 'number-expanded';
+ this.textContent = localStrings.getString('collapseBtn');
+ } else {
+ valueDiv.parentNode.className = 'number-collapsed';
+ this.textContent = localStrings.getString('expandBtn');
+ }
+}
+
+/**
+ * Collapses all log items.
+ */
+function collapseAll() {
+ var valueDivs = document.getElementsByClassName('stat-value');
+ for (var i = 0; i < valueDivs.length; i++) {
+ var button = getButtonForValueDiv(valueDivs[i]);
+ if (button && button.className != 'button-hidden') {
+ button.textContent = localStrings.getString('expandBtn');
+ valueDivs[i].parentNode.className = 'number-collapsed';
+ }
+ }
+}
+
+/**
+ * Expands all log items.
+ */
+function expandAll() {
+ var valueDivs = document.getElementsByClassName('stat-value');
+ for (var i = 0; i < valueDivs.length; i++) {
+ var button = getButtonForValueDiv(valueDivs[i]);
+ if (button && button.className != 'button-hidden') {
+ button.textContent = localStrings.getString('collapseBtn');
+ valueDivs[i].parentNode.className = 'number-expanded';
+ }
+ }
+}
+
+/**
+ * Collapse only those log items with multi-line values.
+ */
+function collapseMultiLineStrings() {
+ var valueDivs = document.getElementsByClassName('stat-value');
+ for (var i = 0; i < valueDivs.length; i++) {
+ var button = getButtonForValueDiv(valueDivs[i]);
+ button.onclick = changeCollapsedStatus;
+ if (valueDivs[i].textContent.split('\n').length > 1) {
+ button.className = '';
+ button.textContent = localStrings.getString('expandBtn');
+ valueDivs[i].parentNode.className = 'number-collapsed';
+ } else {
+ button.className = 'button-hidden';
+ valueDivs[i].parentNode.className = 'number';
+ }
+ }
+}
+
+/**
+ * Read in a log asynchronously, calling parseSystemLog if successful.
+ * @param {Event} e The drop event from dropping a file dragged onto the page.
+ */
+function importLog(e) {
+ var file = e.dataTransfer.files[0];
+ if (file && file.size <= MAX_FILE_SIZE) {
+ var reader = new FileReader();
+ reader.onload = function() {
+ if (parseSystemLog(this.result)) {
+ // Reset table title and status
+ $('tableTitle').textContent =
+ localStrings.getStringF('logFileTableTitle', file.name);
+ $('status').textContent = '';
+ } else {
+ showError(file.name);
+ }
+ };
+ reader.readAsText(file);
+ } else if (file) {
+ showError(file.name);
+ }
+ e.preventDefault();
+}
+
+/**
+ * Convert text-based log into list of name-value pairs.
+ * @param {string} text The raw text of a log.
+ * @return {boolean} True if the log was parsed successfully.
+ */
+function parseSystemLog(text) {
+ var details = [];
+ var lines = text.split('\n');
+ for (var i = 0, len = lines.length; i < len; i++) {
+ // Skip empty lines.
+ if (!lines[i])
+ continue;
+
+ var delimiter = lines[i].indexOf('=');
+ if (delimiter <= 0) {
+ if (i == lines.length - 1)
+ break;
+ // If '=' is missing here, format is wrong.
+ return false;
+ }
+
+ var name = lines[i].substring(0, delimiter);
+ var value = '';
+ // Set value if non-empty
+ if (lines[i].length > delimiter + 1)
+ value = lines[i].substring(delimiter + 1);
+
+ // Delimiters are based on kMultilineIndicatorString, kMultilineStartString,
+ // and kMultilineEndString in chrome/browser/feedback/feedback_data.cc.
+ // If these change, we should check for both the old and new versions.
+ if (value == '<multiline>') {
+ // Skip start delimiter.
+ if (i == len - 1 ||
+ lines[++i].indexOf(DELIM_START) == -1)
+ return false;
+
+ ++i;
+ value = '';
+ // Append lines between start and end delimiters.
+ while (i < len && lines[i] != DELIM_END)
+ value += lines[i++] + '\n';
+
+ // Remove trailing newline.
+ if (value)
+ value = value.substr(0, value.length - 1);
+ }
+ details.push({'statName': name, 'statValue': value});
+ }
+
+ templateData['details'] = details;
+ i18nTemplate.process(document, templateData);
+ jstProcess(new JsEvalContext(templateData), $('t'));
+
+ collapseMultiLineStrings();
+ return true;
+}
+
+document.addEventListener('DOMContentLoaded', function() {
+ localStrings = new LocalStrings();
+
+ $('collapseAll').onclick = collapseAll;
+ $('expandAll').onclick = expandAll;
+
+ var tp = $('t');
+ tp.addEventListener('dragover', handleDragOver, false);
+ tp.addEventListener('drop', importLog, false);
+
+ collapseMultiLineStrings();
+});
diff --git a/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json b/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json
index 16becc0..1da4932 100644
--- a/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json
+++ b/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json
@@ -2,7 +2,7 @@
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGJWLUb83WKoDeODlrPIZu60M8bzbvrkg3Jf/5aO3ux2FL+G+/BO4Vyt/J0t8lXBtnTOvHo6KPpA042PyE9xMdlufFnJqEkvPXNzRlBWeVQqFHbMWE6o/x8diG69dNmHyFYcUjjFFDk2X2GOLQXNUGJQ6MIikbdzoWdLGttmhAIwIDAQAB",
"manifest_version": 2,
"name": "Connectivity Diagnostics",
- "version": "0.6.1",
+ "version": "0.7.9",
"minimum_chrome_version": "27",
"offline_enabled": true,
"default_locale": "en",
@@ -20,6 +20,8 @@
]},
"clipboardWrite",
"experimental",
+ "dns",
+ "diagnostics",
"metricsPrivate",
"networkingPrivate",
"http://*.google.com/*",
diff --git a/chrome/browser/resources/chromeos/genius_app/manifest.json b/chrome/browser/resources/chromeos/genius_app/manifest.json
index 236e142..fa0302f 100644
--- a/chrome/browser/resources/chromeos/genius_app/manifest.json
+++ b/chrome/browser/resources/chromeos/genius_app/manifest.json
@@ -30,5 +30,7 @@
"https://storage.googleapis.com/*",
"https://www-googleapis-test.sandbox.google.com/*",
"https://www.googleapis.com/*"
- ]
+ ],
+ "display_in_launcher": false,
+ "display_in_new_tab_page": false
}
diff --git a/chrome/browser/resources/chromeos/login/login_common.js b/chrome/browser/resources/chromeos/login/login_common.js
index 59498d9..7fcfbbf 100644
--- a/chrome/browser/resources/chromeos/login/login_common.js
+++ b/chrome/browser/resources/chromeos/login/login_common.js
@@ -251,6 +251,15 @@
chrome.send('completeLogin', [username, password]);
};
+ /**
+ * Authenticate for autotests.
+ * @param {string} username Login username.
+ * @param {string} password Login password.
+ */
+ Oobe.authenticateForTesting = function(username, password) {
+ chrome.send('authenticateUser', [username, password]);
+ };
+
// Export
return {
Oobe: Oobe
diff --git a/chrome/browser/resources/chromeos/login/oobe.css b/chrome/browser/resources/chromeos/login/oobe.css
index 4446008..3221b4c 100644
--- a/chrome/browser/resources/chromeos/login/oobe.css
+++ b/chrome/browser/resources/chromeos/login/oobe.css
@@ -223,3 +223,23 @@
.background-initial {
opacity: 0;
}
+
+.throbber {
+ -webkit-animation: throbber-animation 1s steps(36) infinite;
+ -webkit-margin-before: 2px;
+ -webkit-margin-end: 4px;
+ background-image: url(chrome://theme/IDR_CROS_DEFAULT_THROBBER);
+ display: inline-block;
+ height: 16px;
+ width: 16px;
+}
+
+@-webkit-keyframes throbber-animation {
+ from {
+ background-position: 0;
+ }
+ to {
+ background-position: -576px;
+ }
+}
+
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_update.css b/chrome/browser/resources/chromeos/login/oobe_screen_update.css
index 42bb77e..4272f49 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_update.css
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_update.css
@@ -8,25 +8,6 @@
padding: 70px 17px 69px; /* Screen has no controls. */
}
-.throbber {
- -webkit-animation: throbber-animation 1s steps(36) infinite;
- -webkit-margin-before: 2px;
- -webkit-margin-end: 4px;
- background-image: url(chrome://theme/IDR_CROS_DEFAULT_THROBBER);
- display: inline-block;
- height: 16px;
- width: 16px;
-}
-
-@-webkit-keyframes throbber-animation {
- from {
- background-position: 0;
- }
- to {
- background-position: -576px;
- }
-}
-
#update #update-screen-curtain {
-webkit-box-align: start;
-webkit-box-pack: center;
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.css b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.css
index 9c69a8f..a82c6d5 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.css
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.css
@@ -240,3 +240,11 @@
.camera.live:not(.online) .user-image-stream-area .spinner {
display: block;
}
+
+#user-images-loading {
+ -webkit-align-items: center;
+ -webkit-justify-content: center;
+ color: #9c9c9c;
+ display: -webkit-flex;
+}
+
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.html b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.html
index 5e45a7d..a887846 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.html
@@ -33,6 +33,7 @@
</div>
<div id="user-image-controls" class="step-controls"></div>
<div id="user-images-loading" class="step-loading">
- <div class="spinner"></div>
+ <div class="throbber"></div>
+ <div i18n-content="syncingPreferences"></div>
</div>
</div>
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 9fc8982..9e4f9cb 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
@@ -493,7 +493,8 @@
var managerPassword = selectedPod.passwordElement.value;
if (managerPassword.empty)
return;
-
+ if (this.disabled)
+ return;
this.disabled = true;
this.context_.managerId = managerId;
this.context_.managerDisplayId = managerDisplayId;
@@ -517,6 +518,8 @@
loadTimeData.getString('createManagedUserPasswordMismatchError'));
return;
}
+ if (this.disabled)
+ return;
this.disabled = true;
this.context_.managedName = userName;
chrome.send('specifyLocallyManagedUserCreationFlowUserData',
@@ -577,6 +580,7 @@
12, 4);
this.setButtonDisabledStatus('next', true);
}
+ this.disabled = false;
},
/**
@@ -669,6 +673,7 @@
setVisiblePage_: function(visiblePage) {
this.disabled = false;
this.updateText_();
+ $('bubble').hide();
var pageNames = ['intro',
'manager',
'username',
@@ -703,6 +708,7 @@
this.currentPage_ = visiblePage;
if (visiblePage == 'manager' || visiblePage == 'intro') {
+ $('managed-user-creation-password').classList.remove('password-error');
this.managerList_.selectPod(null);
if (this.managerList_.pods.length == 1)
this.managerList_.selectPod(this.managerList_.pods[0]);
diff --git a/chrome/browser/resources/chromeos/login/user_pod_row.css b/chrome/browser/resources/chromeos/login/user_pod_row.css
index 1bf3e5e..cca829e 100644
--- a/chrome/browser/resources/chromeos/login/user_pod_row.css
+++ b/chrome/browser/resources/chromeos/login/user_pod_row.css
@@ -46,8 +46,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 +67,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 {
diff --git a/chrome/browser/resources/chromeos/neterror.css b/chrome/browser/resources/chromeos/neterror.css
new file mode 100644
index 0000000..4c6557e
--- /dev/null
+++ b/chrome/browser/resources/chromeos/neterror.css
@@ -0,0 +1,258 @@
+/* Copyright 2013 The Chromium 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 {
+ background-color: #E6E6E6;
+ font-family: Helvetica, Arial, sans-serif;
+ font-size: 10pt;
+ margin: 50px 40px 20px 40px;
+ text-align: center;
+}
+
+#main-frame-error {
+ margin: auto;
+ max-width: 540px;
+ min-width: 200px;
+}
+
+/* Don't use the main frame div when the error is in a subframe. */
+html[subframe] #main-frame-error {
+ display: none;
+}
+
+/* Don't use the subframe error div when the error is in a main frame. */
+html:not([subframe]) #sub-frame-error {
+ display: none;
+}
+
+#box {
+ background-color: #fbfbfb;
+ border: 1px solid #AAA;
+ border-bottom: 1px solid #888;
+ border-radius: 3px;
+ box-shadow: 0 2px 2px #AAA;
+ color: black;
+}
+
+#diagnose-button {
+ -webkit-margin-start: 0;
+ margin-bottom: 10px;
+ margin-top: 20px;
+}
+
+h1 {
+ color: #666;
+ font-size: 1.5em;
+ font-weight: normal;
+ margin: 10px 0 25px 0;
+}
+
+a {
+ color: rgb(17, 85, 204);
+ text-decoration: none;
+}
+
+.icon {
+ -webkit-user-select: none;
+}
+
+.icon-generic {
+ /**
+ * Can't access chrome://theme/IDR_ERROR_NETWORK_GENERIC from an untrusted
+ * renderer process, so embed the resource manually.
+ */
+ content: -webkit-image-set(
+ url('../../../app/theme/default_100_percent/common/error_network_generic.png') 1x,
+ url('../../../app/theme/default_200_percent/common/error_network_generic.png') 2x);
+}
+
+.icon-offline {
+ content: -webkit-image-set(
+ url('../../../app/theme/default_100_percent/common/error_network_offline.png') 1x,
+ url('../../../app/theme/default_200_percent/common/error_network_offline.png') 2x);
+}
+
+#content-top {
+ margin: 20px 20px 20px 25px;
+}
+
+#help-box-outer {
+ -webkit-transition: height ease-in 218ms;
+ overflow: hidden;
+}
+
+#help-box-inner {
+ background-color: #f9f9f9;
+ border-top: 1px solid #EEE;
+ color: #444;
+ padding: 25px 20px;
+ text-align: start;
+}
+
+#suggestions {
+ margin-top: 15px;
+}
+
+#sub-frame-error-details {
+ color: #8F8F8F;
+ text-shadow: 0 1px 0 rgba(255,255,255,0.3);
+}
+
+[jscontent=failedUrl] {
+ overflow-wrap: break-word;
+}
+
+button {
+ -webkit-user-select: none;
+ background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
+ border: 1px solid rgba(0, 0, 0, 0.25);
+ border-radius: 2px;
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),
+ inset 0 1px 2px rgba(255, 255, 255, 0.75);
+ color: #444;
+ margin: 0 5px;
+ min-height: 29px;
+ min-width: 65px;
+ padding: 8px 13px;
+ text-shadow: 0 1px 0 rgb(240, 240, 240);
+}
+
+button:hover {
+ background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);
+ border: 1px solid rgba(0, 0, 0, 0.3);
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12),
+ inset 0 1px 2px rgba(255, 255, 255, 0.95);
+ color: #000;
+}
+
+button:active {
+ background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
+ border: 1px solid rgba(0, 0, 0, 0.3);
+ box-shadow: none;
+ color: #444;
+}
+
+#reload-button {
+ background-image: -webkit-linear-gradient(rgb(93, 154, 255),
+ rgb(93, 154, 255),
+ rgb(88, 145, 240));
+ border: 1px solid rgba(45, 102, 195, 1);
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.15),
+ inset 0 1px 2px rgba(255, 255, 255, 0.2);
+ color: #fff;
+ text-shadow: 0 1px 0 rgba(0,0,0,0.5);
+}
+
+#reload-button:hover {
+ background-image: -webkit-linear-gradient(rgb(101, 158, 253),
+ rgb(101, 158, 253),
+ rgb(96, 151, 241));
+ border: 1px solid rgba(45, 102, 195, 1);
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25),
+ inset 0 1px 2px rgba(255, 255, 255, 0.2);
+}
+
+#reload-button:active {
+ background-image: -webkit-linear-gradient(rgb(96, 149, 237),
+ rgb(96, 149, 237),
+ rgb(96, 149, 237));
+ border: 1px solid rgb(38, 84, 160);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
+}
+
+.hidden {
+ display: none;
+}
+
+.suggestions {
+ margin-top: 18px;
+}
+
+.suggestion-header {
+ font-weight: bold;
+ margin-bottom: 4px;
+}
+
+.suggestion-body {
+ color: #777;
+}
+
+.error-code {
+ color: #A0A0A0;
+ margin-top: 15px;
+}
+
+/* Increase line height at higher resolutions. */
+@media (min-width: 641px) and (min-height: 641px) {
+ #help-box-inner {
+ line-height: 18px;
+ }
+}
+
+/* Decrease padding at low sizes. */
+@media (max-width: 640px),
+ (max-height: 640px) {
+ body {
+ margin: 15px;
+ }
+ h1 {
+ margin: 10px 0 15px 0;
+ }
+ #content-top {
+ margin: 15px;
+ }
+ #help-box-inner {
+ padding: 20px;
+ }
+ .suggestions {
+ margin-top: 10px;
+ }
+ .suggestion-header {
+ margin-bottom: 0;
+ }
+ .error-code {
+ margin-top: 10px;
+ }
+}
+
+/* Don't allow overflow when in a subframe. */
+html[subframe] body {
+ overflow: hidden;
+}
+
+#sub-frame-error {
+ -webkit-align-items: center;
+ -webkit-flex-flow: column;
+ -webkit-justify-content: center;
+ background-color: #DDD;
+ display: -webkit-flex;
+ height: 100%;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+
+#sub-frame-error:hover {
+ background-color: #EEE;
+}
+
+#sub-frame-error-details {
+ margin: 0 10px;
+ visibility: hidden;
+}
+
+/* Show details only when hovering. */
+#sub-frame-error:hover #sub-frame-error-details {
+ visibility: visible;
+}
+
+/* If the iframe is too small, always hide the error code. */
+/* TODO(mmenke): See if overflow: no-display works better, once supported. */
+@media (max-width: 200px),
+ (max-height: 95px) {
+ #sub-frame-error-details {
+ display: none;
+ }
+}
diff --git a/chrome/browser/resources/chromeos/neterror.js b/chrome/browser/resources/chromeos/neterror.js
new file mode 100644
index 0000000..0c8fcc0
--- /dev/null
+++ b/chrome/browser/resources/chromeos/neterror.js
@@ -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.
+
+function toggleHelpBox() {
+ var helpBoxOuter = $('help-box-outer');
+ helpBoxOuter.classList.toggle('hidden');
+ var moreLessButton = $('more-less-button');
+ if (helpBoxOuter.classList.contains('hidden')) {
+ moreLessButton.innerText = moreLessButton.moreText;
+ } else {
+ moreLessButton.innerText = moreLessButton.lessText;
+ }
+}
+
+function diagnoseErrors() {
+ var extensionId = 'idddmepepmjcgiedknnmlbadcokidhoa';
+ var diagnoseFrame = $('diagnose-frame');
+ diagnoseFrame.innerHTML =
+ '<iframe src="chrome-extension://' + extensionId +
+ '/index.html"></iframe>';
+}
+
+// Subframes use a different layout but the same html file. This is to make it
+// easier to support platforms that load the error page via different
+// mechanisms (Currently just iOS).
+if (window.top.location != window.location)
+ document.documentElement.setAttribute('subframe', '');
+
+// Re-renders the error page using |strings| as the dictionary of values.
+// Used by NetErrorTabHelper to update DNS error pages with probe results.
+function updateForDnsProbe(strings) {
+ i18nTemplate.process(document, strings);
+ var context = new JsEvalContext(strings);
+ jstProcess(context, $('t'));
+}
+
+// Given the classList property of an element, adds an icon class to the list
+// and removes the previously-
+function updateIconClass(classList, newClass) {
+ var oldClass;
+
+ if (classList.hasOwnProperty('last_icon_class')) {
+ oldClass = classList['last_icon_class'];
+ if (oldClass == newClass)
+ return;
+ }
+
+ classList.add(newClass);
+ if (oldClass !== undefined)
+ classList.remove(oldClass);
+
+ classList['last_icon_class'] = newClass;
+}
diff --git a/chrome/browser/resources/chromeos/offline_app_load.html b/chrome/browser/resources/chromeos/offline_app_load.html
new file mode 100644
index 0000000..028548a
--- /dev/null
+++ b/chrome/browser/resources/chromeos/offline_app_load.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html i18n-values="dir:textdirection">
+<head>
+<title i18n-content="title">
+</title>
+<style>
+html {
+ height: 100%;
+}
+body {
+ color: #000;
+ font-family: Helvetica, Arial, sans-serif;
+ background-image: -webkit-linear-gradient(rgb(255, 255, 255) 50%,
+ rgb(236, 244, 255));
+ height: 100%;
+ padding: 0px;
+ margin: 0px;
+}
+#error {
+ position: absolute;
+ left: 180px;
+ top: 150px;
+ font-size: 24px;
+}
+#error img {
+ margin-right: 10px;
+ vertical-align: middle;
+}
+#name {
+ font-weight: bold;
+}
+#msg {
+}
+</style>
+</head>
+
+<body id="t">
+
+<div id="error" jsvalues=".title:url">
+<img jsvalues=".src:icon" width="96" height="96">
+<div style="display:inline-block; vertical-align: middle;">
+<div id="name" jsvalues=".innerText:name"></div>
+<div id="msg" jsvalues=".innerText:msg"></div>
+<div id="suggestions" jsselect="suggestionsLearnMore">
+ <span jsvalues=".innerHTML:msg"></span>
+</div>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/chrome/browser/resources/chromeos/offline_load.html b/chrome/browser/resources/chromeos/offline_load.html
deleted file mode 100644
index bab14d9..0000000
--- a/chrome/browser/resources/chromeos/offline_load.html
+++ /dev/null
@@ -1,138 +0,0 @@
-<!DOCTYPE html>
-<html id="template_root" i18n-values="dir:textdirection">
-<head>
-<title i18n-content="title">
-</title>
-<style>
-html {
- height: 100%;
-}
-body {
- -webkit-box-pack: center;
- -webkit-user-select: none;
- background-image: -webkit-linear-gradient(white 50%, rgb(236, 244, 255));
- color: #000;
- display: -webkit-box;
- height: 100%;
- margin: 0;
- padding: 0;
- visibility: hidden;
- width: 100%;
-}
-
-#mainview {
- display: -webkit-box;
- padding-top: 100px;
-}
-
-#right {
- -webkit-margin-start: 70px;
-}
-
-.upper {
- position: relative;
- width: 100%;
- -webkit-box-flex: 0.8;
-}
-
-#logo-container {
- display: -webkit-box;
-}
-
-#product-name {
- -webkit-margin-start: 5px;
- color: grey;
- font-size: 160%;
-}
-
-#heading {
- font-size: 15px;
- padding-top: 20px;
-}
-
-#message {
- font-size: 12px;
- padding-top: 5px;
-}
-
-#button {
- padding-top: 30px;
-}
-
-.offline_message {
- position: absolute;
- width: 600px;
- height: 49%;
-}
-
-.activation_message {
- position: absolute;
- width: 500px;
- top: 0;
- margin-top: 0;
- left: 50%;
- margin-left: -250px;
- min-height: 380px;
-}
-
-#carrierPage {
- padding-top: 10px;
- width: 500px;
- height: 380px;
- overflow-x: none;
- overflow-y: none;
-}
-
-.hidden {
- display: none;
-}
-
-.splitter {
- border-top: 1px solid #DDD;
- height: 1px;
-}
-</style>
-<script src="../../../../ui/webui/resources/js/local_strings.js"></script>
-
-<script>
-var localStrings = new LocalStrings();
-
-function sendCommand(cmd) {
- window.domAutomationController.setAutomationId(1);
- window.domAutomationController.send(cmd);
-}
-
-// Show the offline page.
-function showPage() {
- document.body.style.visibility = 'visible';
-}
-
-document.addEventListener('DOMContentLoaded', function() {
- var timeToWait = localStrings.getString('time_to_wait');
- window.setTimeout(showPage, timeToWait);
-});
-</script>
-
-<body oncontextmenu="return false;"
- i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
- <div id="mainview">
- <div id="left">
- <div class="upper">
- <div id="logo-container">
- <img i18n-values=".src:icon">
- <div id="product-name" i18n-content="product_name"></div>
- </div>
- <div id="heading" i18n-content="heading"></div>
- <div id="message" i18n-content="msg"></div>
- <div id="button">
- <button onclick="sendCommand('open_network_settings')"
- i18n-content="network_settings"></button>
- </div>
- </div>
- </div>
- <div id="right">
- <img src="images/broken_robot.png">
- </div>
- </div>
-</body>
-</html>
diff --git a/chrome/browser/resources/chromeos/offline_net_load.html b/chrome/browser/resources/chromeos/offline_net_load.html
new file mode 100644
index 0000000..2ee8f9a
--- /dev/null
+++ b/chrome/browser/resources/chromeos/offline_net_load.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html i18n-values="dir:textdirection">
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0,
+ maximum-scale=1.0, user-scalable=no">
+ <title i18n-content="title"></title>
+ <link rel="stylesheet" href="neterror.css">
+ <script src="../../../../ui/webui/resources/js/util.js"></script>
+ <script src="neterror.js"></script>
+</head>
+<body id="t">
+ <div id="main-frame-error">
+ <div id="box">
+ <div id="content-top">
+ <h1>
+ <div>
+ <img class="icon"
+ jseval="updateIconClass(this.classList, iconClass)">
+ </div>
+ <span i18n-content="heading"></span>
+ </h1>
+ <button id="reload-button" onclick="location = this.url"
+ jsselect="reload" jsvalues=".url:reloadUrl"
+ jscontent="msg"></button>
+ <button id="more-less-button" onclick="toggleHelpBox()" jsdisplay="more"
+ jsvalues=".moreText:more; .lessText:less;"
+ jscontent="more"></button>
+ </div>
+ <!-- Outer and inner divs are needed both for margins and sizing. -->
+ <div id="help-box-outer" class="hidden">
+ <div id="help-box-inner">
+ <div jsselect="summary">
+ <span jsvalues=".innerHTML:msg"></span>
+ </div>
+ <div class="suggestions" jsselect="suggestions">
+ <div class="suggestion-header" jsvalues=".innerHTML:header"></div>
+ <div class="suggestion-body" jsvalues=".innerHTML:body"></div>
+ </div>
+ <button id="diagnose-button" onclick="diagnoseErrors()"
+ jscontent="diagnose" jsdisplay="diagnose"></button>
+ <div id="diagnose-frame" class="hidden"></div>
+ <div class="error-code" jscontent="errorCode"></div>
+ </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. -->
+ <img class="icon" jseval="updateIconClass(this.classList, iconClass)"
+ jsvalues=".title:errorDetails">
+ <div id="sub-frame-error-details" jsvalues=".innerHTML:errorDetails"></div>
+ </div>
+</body>
+</html>
diff --git a/chrome/browser/resources/extensions/extension_error_severity_info.png b/chrome/browser/resources/extensions/extension_error_severity_info.png
index 8de5a27..edc95f7 100644
--- a/chrome/browser/resources/extensions/extension_error_severity_info.png
+++ b/chrome/browser/resources/extensions/extension_error_severity_info.png
Binary files differ
diff --git a/chrome/browser/resources/feedback/html/default.html b/chrome/browser/resources/feedback/html/default.html
index 20ed36f..b1960cf 100644
--- a/chrome/browser/resources/feedback/html/default.html
+++ b/chrome/browser/resources/feedback/html/default.html
@@ -60,6 +60,12 @@
<a id="sysinfo-url" href="#" i18n-content="sysinfo"></a>
</span>
</div>
+ <!-- Performance Feedback -->
+ <div id="performance-info-area" hidden>
+ <input id="performance-info-checkbox" type="checkbox">
+ <label id="performance-info-label" i18n-content="performance-trace">
+ </label>
+ </div>
</if>
<!-- Privacy node -->
<div id="privacy-note" i18n-values=".innerHTML:privacy-note"></div>
diff --git a/chrome/browser/resources/feedback/images/icon32.png b/chrome/browser/resources/feedback/images/icon32.png
index 6bd5396..977a949 100644
--- a/chrome/browser/resources/feedback/images/icon32.png
+++ b/chrome/browser/resources/feedback/images/icon32.png
Binary files differ
diff --git a/chrome/browser/resources/feedback/images/icon64.png b/chrome/browser/resources/feedback/images/icon64.png
index 3c74b1e..a0c24dc 100644
--- a/chrome/browser/resources/feedback/images/icon64.png
+++ b/chrome/browser/resources/feedback/images/icon64.png
Binary files differ
diff --git a/chrome/browser/resources/feedback/js/event_handler.js b/chrome/browser/resources/feedback/js/event_handler.js
index ddfb739..a5680ec 100644
--- a/chrome/browser/resources/feedback/js/event_handler.js
+++ b/chrome/browser/resources/feedback/js/event_handler.js
@@ -12,6 +12,11 @@
* @const
*/
var FEEDBACK_HEIGHT = 610;
+/**
+ * @type {number}
+ * @const
+ */
+var TRACING_CHECKBOX_HEIGHT = 29;
var initialFeedbackInfo = null;
@@ -46,12 +51,16 @@
* @param {Object} feedbackInfo Object containing any initial feedback info.
*/
function startFeedbackUI(feedbackInfo) {
+ var windowHeight = FEEDBACK_HEIGHT;
+ if (feedbackInfo.traceId) {
+ windowHeight += TRACING_CHECKBOX_HEIGHT;
+ }
initialFeedbackInfo = feedbackInfo;
chrome.app.window.create('html/default.html', {
frame: 'none',
id: 'default_window',
width: FEEDBACK_WIDTH,
- height: FEEDBACK_HEIGHT,
+ height: windowHeight,
hidden: true,
singleton: true },
function(appWindow) {});
diff --git a/chrome/browser/resources/feedback/js/feedback.js b/chrome/browser/resources/feedback/js/feedback.js
index 2d10e9c..90c7c91 100644
--- a/chrome/browser/resources/feedback/js/feedback.js
+++ b/chrome/browser/resources/feedback/js/feedback.js
@@ -104,6 +104,10 @@
systemInfo != null) {
useSystemInfo = true;
}
+ if ($('performance-info-checkbox') == null ||
+ !($('performance-info-checkbox').checked)) {
+ feedbackInfo.traceId = null;
+ }
</if>
// On NonChromeOS, we don't have any system information gathered except the
@@ -161,6 +165,28 @@
return new Blob([new Uint8Array(dataArray)], {type: mimeString});
}
+<if expr="pp_ifdef('chromeos')">
+/**
+ * Update the page when performance feedback state is changed.
+ */
+function performanceFeedbackChanged() {
+ if ($('performance-info-checkbox').checked) {
+ $('attach-file').disabled = true;
+ $('attach-file').checked = false;
+
+ $('screenshot-checkbox').disabled = true;
+ $('screenshot-checkbox').checked = false;
+
+ $('sys-info-checkbox').disabled = true;
+ $('sys-info-checkbox').checked = false;
+ } else {
+ $('attach-file').disabled = false;
+ $('screenshot-checkbox').disabled = false;
+ $('sys-info-checkbox').disabled = false;
+ }
+}
+</if>
+
/**
* Initializes our page.
* Flow:
@@ -204,6 +230,14 @@
$('attach-file').hidden = true;
}
+<if expr="pp_ifdef('chromeos')">
+ if (feedbackInfo.traceId && ($('performance-info-area'))) {
+ $('performance-info-area').hidden = false;
+ $('performance-info-checkbox').checked = true;
+ performanceFeedbackChanged();
+ }
+</if>
+
chrome.feedbackPrivate.getStrings(function(strings) {
loadTimeData.data = strings;
i18nTemplate.process(document, loadTimeData);
@@ -220,6 +254,10 @@
$('send-report-button').onclick = sendReport;
$('cancel-button').onclick = cancel;
$('remove-attached-file').onclick = clearAttachedFile;
+<if expr="pp_ifdef('chromeos')">
+ $('performance-info-checkbox').addEventListener(
+ 'change', performanceFeedbackChanged);
+</if>
chrome.windows.onRemoved.addListener(function(windowId, removeInfo) {
if (windowId == systemInfoWindowId)
diff --git a/chrome/browser/resources/file_manager/css/gallery.css b/chrome/browser/resources/file_manager/css/gallery.css
index 30aac69..c33c919 100644
--- a/chrome/browser/resources/file_manager/css/gallery.css
+++ b/chrome/browser/resources/file_manager/css/gallery.css
@@ -813,12 +813,6 @@
url('../images/gallery/2x/icon_share_selected.png') 2x);
}
-.gallery[error] > .toolbar button.edit,
-.gallery[error] > .toolbar button.share {
- opacity: 0.7;
- pointer-events: none;
-}
-
.gallery > .toolbar > button.share[disabled] {
display: none;
}
diff --git a/chrome/browser/resources/file_manager/js/action_choice.js b/chrome/browser/resources/file_manager/js/action_choice.js
index 8361ec0..1d9f1e4 100644
--- a/chrome/browser/resources/file_manager/js/action_choice.js
+++ b/chrome/browser/resources/file_manager/js/action_choice.js
@@ -260,16 +260,18 @@
* @private
*/
ActionChoice.prototype.checkDrive_ = function(callback) {
- var onMounted = function() {
- this.importPhotosToDriveAction_.disabled = false;
+ var onVolumeManagerReady = function() {
+ this.volumeManager_.removeEventListener('ready', onVolumeManagerReady);
+ this.importPhotosToDriveAction_.disabled =
+ !this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE);
this.renderList_();
callback();
}.bind(this);
- if (this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE)) {
- onMounted();
+ if (this.volumeManager_.isReady()) {
+ onVolumeManagerReady();
} else {
- this.volumeManager_.mountDrive(onMounted, callback);
+ this.volumeManager_.addEvventListener('ready', onVolumeManagerReady);
}
};
diff --git a/chrome/browser/resources/file_manager/js/background.js b/chrome/browser/resources/file_manager/js/background.js
index dddb0ca..8cb691c 100644
--- a/chrome/browser/resources/file_manager/js/background.js
+++ b/chrome/browser/resources/file_manager/js/background.js
@@ -16,11 +16,6 @@
var queue = new AsyncUtil.Queue();
/**
- * Synchronous queue for the onExecute handler.
- */
-var executeQueue = new AsyncUtil.Queue();
-
-/**
* @return {Array.<DOMWindow>} Array of content windows for all currently open
* app windows.
*/
@@ -54,18 +49,20 @@
* 3. The app may have |unload| function to persist the app state that does not
* fit into |window.appState|.
*
- * @param {AsyncUtil.Queue} queue Queue for asynchronous window launches.
* @param {string} url App window content url.
* @param {string} id App window id.
* @param {Object|function()} options Options object or a function to create it.
* @constructor
*/
-function AppWindowWrapper(queue, url, id, options) {
- this.queue_ = queue;
+function AppWindowWrapper(url, id, options) {
this.url_ = url;
this.id_ = id;
this.options_ = options;
this.window_ = null;
+ this.appState_ = null;
+ this.openingOrOpened_ = false;
+ this.queue = new AsyncUtil.Queue();
+ Object.seal(this);
}
/**
@@ -76,13 +73,6 @@
AppWindowWrapper.SHIFT_DISTANCE = 40;
/**
- * @return {boolean} True if the window is currently open.
- */
-AppWindowWrapper.prototype.isOpen = function() {
- return this.window_ && !this.window_.contentWindow.closed;
-};
-
-/**
* Gets similar windows, it means with the same initial url.
* @return {Array.<AppWindow>} List of similar windows.
* @private
@@ -100,16 +90,22 @@
* Opens the window.
*
* @param {Object} appState App state.
- * @param {function()} callback Completion callback.
+ * @param {function()=} opt_callback Completion callback.
*/
-AppWindowWrapper.prototype.launch = function(appState, callback) {
- if (this.isOpen()) {
- console.error('The window is already open');
- callback();
+AppWindowWrapper.prototype.launch = function(appState, opt_callback) {
+ // Check if the window is opened or not.
+ if (this.openingOrOpened_) {
+ console.error('The window is already opened.');
+ if (opt_callback)
+ opt_callback();
return;
}
+ this.openingOrOpened_ = true;
+
+ // Save application state.
this.appState_ = appState;
+ // Window options.
var options = this.options_;
if (typeof options == 'function')
options = options();
@@ -120,75 +116,74 @@
// main windows of Files.app.
var similarWindows = this.getSimilarWindows_();
- // Closure creating the window, once all preprocessing tasks are finished.
- var createWindow = function() {
- chrome.app.window.onRestored.removeListener(createWindow);
- chrome.app.window.create(this.url_, options, function(appWindow) {
- this.window_ = appWindow;
-
- // If we have already another window of the same kind, then shift this
- // window to avoid overlapping with the previous one.
- if (similarWindows.length) {
- var bounds = appWindow.getBounds();
- appWindow.moveTo(bounds.left + AppWindowWrapper.SHIFT_DISTANCE,
- bounds.top + AppWindowWrapper.SHIFT_DISTANCE);
- }
-
- appWindows[this.id_] = appWindow;
- var contentWindow = appWindow.contentWindow;
- contentWindow.appID = this.id_;
- contentWindow.appState = this.appState_;
- contentWindow.appInitialURL = this.url_;
- if (window.IN_TEST)
- contentWindow.IN_TEST = true;
- appWindow.onClosed.addListener(function() {
- if (contentWindow.unload)
- contentWindow.unload();
- if (contentWindow.saveOnExit) {
- contentWindow.saveOnExit.forEach(function(entry) {
- util.AppCache.update(entry.key, entry.value);
- });
- }
- delete appWindows[this.id_];
- chrome.storage.local.remove(this.id_); // Forget the persisted state.
- this.window_ = null;
- maybeCloseBackgroundPage();
- }.bind(this));
-
- callback();
- }.bind(this));
- }.bind(this);
-
// Restore maximized windows, to avoid hiding them to tray, which can be
// confusing for users.
- for (var index = 0; index < similarWindows.length; index++) {
- if (similarWindows[index].isMaximized()) {
- var createWindowAndRemoveListener = function() {
- createWindow();
- similarWindows[index].onRestored.removeListener(
+ this.queue.run(function(nextStep) {
+ for (var index = 0; index < similarWindows.length; index++) {
+ if (similarWindows[index].isMaximized()) {
+ var createWindowAndRemoveListener = function() {
+ similarWindows[index].onRestored.removeListener(
+ createWindowAndRemoveListener);
+ nextStep();
+ };
+ similarWindows[index].onRestored.addListener(
createWindowAndRemoveListener);
- };
- similarWindows[index].onRestored.addListener(
- createWindowAndRemoveListener);
- similarWindows[index].restore();
- return;
+ similarWindows[index].restore();
+ return;
+ }
}
- }
+ // If no maximized windows, then create the window immediately.
+ nextStep();
+ });
- // If no maximized windows, then create the window immediately.
- createWindow();
-};
+ // Closure creating the window, once all preprocessing tasks are finished.
+ this.queue.run(function(nextStep) {
+ chrome.app.window.create(this.url_, options, function(appWindow) {
+ this.window_ = appWindow;
+ nextStep();
+ }.bind(this));
+ }.bind(this));
-/**
- * Enqueues opening the window.
- * @param {Object} appState App state.
- * @param {function()=} opt_callback Callback function to be called at the end
- * of launch.
- */
-AppWindowWrapper.prototype.enqueueLaunch = function(appState, opt_callback) {
- this.queue_.run(this.launch.bind(this, appState));
- if (opt_callback)
- this.queue_.run(function(nextStep) { opt_callback(); nextStep(); });
+ // After creating.
+ this.queue.run(function(nextStep) {
+ var appWindow = this.window_;
+ if (similarWindows.length) {
+ // If we have already another window of the same kind, then shift this
+ // window to avoid overlapping with the previous one.
+
+ var bounds = appWindow.getBounds();
+ appWindow.moveTo(bounds.left + AppWindowWrapper.SHIFT_DISTANCE,
+ bounds.top + AppWindowWrapper.SHIFT_DISTANCE);
+ }
+
+ appWindows[this.id_] = appWindow;
+ var contentWindow = appWindow.contentWindow;
+ contentWindow.appID = this.id_;
+ contentWindow.appState = this.appState_;
+ contentWindow.appInitialURL = this.url_;
+ if (window.IN_TEST)
+ contentWindow.IN_TEST = true;
+
+ appWindow.onClosed.addListener(function() {
+ if (contentWindow.unload)
+ contentWindow.unload();
+ if (contentWindow.saveOnExit) {
+ contentWindow.saveOnExit.forEach(function(entry) {
+ util.AppCache.update(entry.key, entry.value);
+ });
+ }
+ delete appWindows[this.id_];
+ chrome.storage.local.remove(this.id_); // Forget the persisted state.
+ this.window_ = null;
+ this.openingOrOpened_ = false;
+ maybeCloseBackgroundPage();
+ }.bind(this));
+
+ if (opt_callback)
+ opt_callback();
+
+ nextStep();
+ }.bind(this));
};
/**
@@ -198,19 +193,18 @@
* have |reload| method that re-initializes the app based on a changed
* |window.appState|.
*
- * @param {AsyncUtil.Queue} queue Queue for asynchronous window launches.
* @param {string} url App window content url.
* @param {Object|function()} options Options object or a function to return it.
* @constructor
*/
-function SingletonAppWindowWrapper(queue, url, options) {
- AppWindowWrapper.call(this, queue, url, url, options);
+function SingletonAppWindowWrapper(url, options) {
+ AppWindowWrapper.call(this, url, url, options);
}
/**
* Inherits from AppWindowWrapper.
*/
-SingletonAppWindowWrapper.prototype = { __proto__: AppWindowWrapper.prototype };
+SingletonAppWindowWrapper.prototype = {__proto__: AppWindowWrapper.prototype};
/**
* Open the window.
@@ -218,18 +212,25 @@
* Activates an existing window or creates a new one.
*
* @param {Object} appState App state.
- * @param {function()} callback Completion callback.
+ * @param {function()=} opt_callback Completion callback.
*/
-SingletonAppWindowWrapper.prototype.launch = function(appState, callback) {
- if (this.isOpen()) {
- this.window_.contentWindow.appState = appState;
- this.window_.contentWindow.reload();
- this.window_.focus();
- callback();
+SingletonAppWindowWrapper.prototype.launch = function(appState, opt_callback) {
+ // If the window is not opened yet, just call the parent method.
+ if (!this.openingOrOpened_) {
+ AppWindowWrapper.prototype.launch.call(this, appState, opt_callback);
return;
}
- AppWindowWrapper.prototype.launch.call(this, appState, callback);
+ // If the window is already opened, reload the window.
+ // The queue is used to wait until the window is opened.
+ this.queue.run(function(nextStep) {
+ this.window_.contentWindow.appState = appState;
+ this.window_.contentWindow.reload();
+ this.window_.focus();
+ if (opt_callback)
+ opt_callback();
+ nextStep();
+ }.bind(this));
};
/**
@@ -247,11 +248,10 @@
console.error('Corrupt launch data for ' + this.id_, value);
return;
}
- this.enqueueLaunch(appState);
+ this.launch(appState);
}.bind(this));
};
-
/**
* Prefix for the file manager window ID.
*/
@@ -267,7 +267,6 @@
*/
var nextFileManagerWindowID = 0;
-
/**
* @return {Object} File manager window create options.
*/
@@ -360,13 +359,14 @@
var appId = FILES_ID_PREFIX + id;
var appWindow = new AppWindowWrapper(
- queue,
'main.html',
appId,
createFileManagerOptions);
- appWindow.enqueueLaunch(opt_appState || {},
- opt_callback && opt_callback.bind(null, appId));
- onTaskCompleted();
+ appWindow.launch(opt_appState || {}, function() {
+ if (opt_callback)
+ opt_callback(appId);
+ onTaskCompleted();
+ });
});
}
@@ -412,7 +412,8 @@
default:
var launchEnable = null;
- executeQueue.run(function(nextStep) {
+ var queue = new AsyncUtil.Queue();
+ queue.run(function(nextStep) {
// If it is not auto-open (triggered by mounting external devices), we
// always launch Files.app.
if (action != 'auto-open') {
@@ -428,7 +429,7 @@
nextStep();
});
});
- executeQueue.run(function(nextStep) {
+ queue.run(function(nextStep) {
if (!launchEnable) {
nextStep();
return;
@@ -445,10 +446,7 @@
// volume will appear on the navigation list.
var type = action == 'auto-open' ? LaunchType.FOCUS_ANY_OR_CREATE :
LaunchType.FOCUS_SAME_OR_CREATE;
- launchFileManager(appState,
- undefined, // App ID.
- type,
- nextStep);
+ launchFileManager(appState, /* App ID */ undefined, type, nextStep);
});
break;
}
@@ -470,8 +468,7 @@
};
}
-var audioPlayer = new SingletonAppWindowWrapper(queue,
- 'mediaplayer.html',
+var audioPlayer = new SingletonAppWindowWrapper('mediaplayer.html',
createAudioPlayerOptions);
/**
@@ -479,11 +476,10 @@
* @param {Object} playlist Playlist.
*/
function launchAudioPlayer(playlist) {
- audioPlayer.enqueueLaunch(playlist);
+ audioPlayer.launch(playlist);
}
-var videoPlayer = new SingletonAppWindowWrapper(queue,
- 'video_player.html',
+var videoPlayer = new SingletonAppWindowWrapper('video_player.html',
{hidden: true});
/**
@@ -491,7 +487,7 @@
* @param {string} url Video url.
*/
function launchVideoPlayer(url) {
- videoPlayer.enqueueLaunch({url: url});
+ videoPlayer.launch({url: url});
}
/**
diff --git a/chrome/browser/resources/file_manager/js/butter_bar.js b/chrome/browser/resources/file_manager/js/butter_bar.js
index ea954bf..b47e801 100644
--- a/chrome/browser/resources/file_manager/js/butter_bar.js
+++ b/chrome/browser/resources/file_manager/js/butter_bar.js
@@ -223,27 +223,15 @@
};
/**
- * @return {string?} The type of operation.
+ * @return {string} The type of operation.
* @private
*/
ButterBar.prototype.transferType_ = function() {
var progress = this.progress_;
- if (!progress)
- return 'TRANSFER';
+ if (progress && progress.operationType)
+ return progress.operationType;
- var pendingTransferTypesCount =
- (progress.pendingMoves === 0 ? 0 : 1) +
- (progress.pendingCopies === 0 ? 0 : 1) +
- (progress.pendingZips === 0 ? 0 : 1);
-
- if (pendingTransferTypesCount != 1)
- return 'TRANSFER';
- else if (progress.pendingMoves > 0)
- return 'MOVE';
- else if (progress.pendingCopies > 0)
- return 'COPY';
- else
- return 'ZIP';
+ return 'TRANSFER';
};
/**
@@ -256,15 +244,15 @@
ButterBar.prototype.showProgress_ = function(progress) {
this.progress_ = progress;
var options = {
- progress: progress.completedBytes / progress.totalBytes,
+ progress: progress.processedBytes / progress.totalBytes,
actions: {},
timeout: false
};
- var pendingItems = progress.totalItems - progress.completedItems;
+ var pendingItems = progress.numRemainingItems;
var type = this.transferType_();
var progressString = (pendingItems === 1) ?
- strf(type + '_FILE_NAME', progress.filename) :
+ strf(type + '_FILE_NAME', progress.processingEntry.name) :
strf(type + '_ITEMS_REMAINING', pendingItems);
if (this.currentMode_ == ButterBar.Mode.COPY) {
diff --git a/chrome/browser/resources/file_manager/js/directory_model.js b/chrome/browser/resources/file_manager/js/directory_model.js
index e144633..a301096 100644
--- a/chrome/browser/resources/file_manager/js/directory_model.js
+++ b/chrome/browser/resources/file_manager/js/directory_model.js
@@ -872,7 +872,7 @@
}
this.resolveDirectory(path, function(directoryEntry) {
- this.changeDirectoryEntry_(false, directoryEntry);
+ this.changeDirectoryEntry_(directoryEntry);
}.bind(this), function(error) {
console.error('Error changing directory to ' + path + ': ', error);
if (opt_errorCallback)
@@ -949,24 +949,21 @@
* Dispatches the 'directory-changed' event when the directory is successfully
* changed.
*
- * @param {boolean} initial True if it comes from setupPath and
- * false if caused by an user action.
* @param {DirectoryEntry} dirEntry The absolute path to the new directory.
* @param {function()=} opt_callback Executed if the directory loads
* successfully.
* @private
*/
-DirectoryModel.prototype.changeDirectoryEntry_ = function(initial, dirEntry,
- opt_callback) {
+DirectoryModel.prototype.changeDirectoryEntry_ = function(
+ dirEntry, opt_callback) {
this.fileWatcher_.changeWatchedDirectory(dirEntry, function() {
var previous = this.currentDirContents_.getDirectoryEntry();
this.clearSearch_();
this.changeDirectoryEntrySilent_(dirEntry, opt_callback);
var e = new cr.Event('directory-changed');
- e.previousDirEntry = previous;
+ e.previousDirEntry = (previous.fullpath == '/') ? null : previous;
e.newDirEntry = dirEntry;
- e.initial = initial;
this.dispatchEvent(e);
}.bind(this));
};
@@ -982,7 +979,6 @@
dm_: this,
active_: false,
hasChanged: false,
- exceptInitialChange: false,
start: function() {
if (!this.active_) {
@@ -1002,9 +998,6 @@
},
onDirectoryChange_: function(event) {
- // this == tracker.dm_ here.
- if (tracker.exceptInitialChange && event.initial)
- return;
tracker.stop();
tracker.hasChanged = true;
}
@@ -1015,6 +1008,8 @@
/**
* Change the state of the model to reflect the specified path (either a
* file or directory).
+ * TODO(hidehiko): This logic should be merged with
+ * FileManager.setupCurrentDirectory_.
*
* @param {string} path The root path to use.
* @param {function(string, string, boolean)=} opt_pathResolveCallback Invoked
@@ -1036,20 +1031,19 @@
exists && !tracker.hasChanged);
};
- var changeDirectoryEntry = function(directoryEntry, initial, opt_callback) {
+ var changeDirectoryEntry = function(directoryEntry, opt_callback) {
tracker.stop();
if (!tracker.hasChanged)
- self.changeDirectoryEntry_(initial, directoryEntry, opt_callback);
+ self.changeDirectoryEntry_(directoryEntry, opt_callback);
};
- var INITIAL = true;
var EXISTS = true;
var changeToDefault = function(leafName) {
var def = PathUtil.DEFAULT_DIRECTORY;
self.resolveDirectory(def, function(directoryEntry) {
resolveCallback(def, leafName, !EXISTS);
- changeDirectoryEntry(directoryEntry, INITIAL);
+ changeDirectoryEntry(directoryEntry);
}, function(error) {
console.error('Failed to resolve default directory: ' + def, error);
resolveCallback('/', leafName, !EXISTS);
@@ -1068,7 +1062,7 @@
this.resolveDirectory(path, function(directoryEntry) {
resolveCallback(directoryEntry.fullPath, '', !EXISTS);
- changeDirectoryEntry(directoryEntry, INITIAL);
+ changeDirectoryEntry(directoryEntry);
}, function(error) {
// Usually, leaf does not exist, because it's just a suggested file name.
var fileExists = error.code == FileError.TYPE_MISMATCH_ERR;
@@ -1085,7 +1079,6 @@
var fileName = path.substr(nameDelimiter + 1);
resolveCallback(parentDirectoryEntry.fullPath, fileName, fileExists);
changeDirectoryEntry(parentDirectoryEntry,
- INITIAL,
function() {
self.selectEntry(fileName);
});
@@ -1219,7 +1212,7 @@
} else if (PathUtil.isDriveBasedPath(currentDirEntry.fullPath)) {
// Now, Drive file system is unmounted. Go back to the fake Drive
// entry.
- this.changeDirectoryEntry_(false, DirectoryModel.fakeDriveEntry_);
+ this.changeDirectoryEntry_(DirectoryModel.fakeDriveEntry_);
}
}
@@ -1368,7 +1361,6 @@
var e = new cr.Event('directory-changed');
e.previousDirEntry = previous;
e.newDirEntry = dirEntry;
- e.initial = false;
this.dispatchEvent(e);
}.bind(this);
diff --git a/chrome/browser/resources/file_manager/js/directory_tree.js b/chrome/browser/resources/file_manager/js/directory_tree.js
index ab2bca2..c5d1587 100644
--- a/chrome/browser/resources/file_manager/js/directory_tree.js
+++ b/chrome/browser/resources/file_manager/js/directory_tree.js
@@ -13,101 +13,6 @@
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 {DirectoryTree} tree Current directory tree, which contains this item.
- * @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, tree, 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, tree);
- 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, tree);
- 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;
- }
-};
-
-/**
- * Finds a parent directory of the {@code entry} from the {@code items}, and
- * invokes the DirectoryItem.selectByEntry() of the found directory.
- *
- * @param {Array.<DirectoryItem>} items Items to be searched.
- * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be
- * a fake.
- * @return {boolean} True if the parent item is found.
- */
-DirectoryTreeUtil.searchAndSelectByEntry = function(items, entry) {
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- if (util.isParentEntry(item.entry, entry)) {
- item.selectByEntry(entry);
- return true;
- }
- }
- return false;
-};
-
-/**
* Generate a list of the directory entries for the top level on the tree.
* @return {Array.<DirectoryEntry>} Entries for the top level on the tree.
*/
@@ -119,7 +24,7 @@
DirectoryModel.fakeDriveRecentEntry_,
];
- for (var i in entries) {
+ for (var i = 0; i < entries.length; i++) {
entries[i]['label'] = PathUtil.getRootLabel(entries[i].fullPath);
}
@@ -127,56 +32,6 @@
};
/**
- * Retrieves the file list with the latest information.
- *
- * @param {DirectoryTree|DirectoryItem} item Parent to be reloaded.
- * @param {function(Array.<Entry>)} successCallback Callback on success.
- * @param {function()=} opt_errorCallback Callback on failure.
- */
-DirectoryTreeUtil.updateSubDirectories = function(
- item, successCallback, opt_errorCallback) {
- if (util.isFakeDirectoryEntry(item.entry)) {
- if (opt_errorCallback)
- opt_errorCallback();
- return;
- }
-
- var reader = item.entry.createReader();
- var entries = [];
- var readEntry = function() {
- reader.readEntries(function(results) {
- if (!results.length) {
- 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 the given directory can be on the tree or not.
*
* @param {string} path Path to be checked.
@@ -187,6 +42,86 @@
return PathUtil.isDriveBasedPath(path);
};
+Object.freeze(DirectoryTreeUtil);
+
+////////////////////////////////////////////////////////////////////////////////
+// DirectoryTreeBase
+
+/**
+ * Implementation of methods for DirectoryTree and DirectoryItem. These classes
+ * inherits cr.ui.Tree/TreeItem so we can't make them inherit this class.
+ * Instead, we separate their implementations to this separate object and call
+ * it with setting 'this' from DirectoryTree/Item.
+ */
+var DirectoryItemTreeBaseMethods = {};
+
+/**
+ * Updates sub-elements of {@code this} reading {@code DirectoryEntry}.
+ * The list of {@code DirectoryEntry} are not updated by this method.
+ *
+ * @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.
+ */
+DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) {
+ var index = 0;
+ var tree = this.parentTree_ || this; // If no parent, 'this' itself is tree.
+ while (this.entries_[index]) {
+ var currentEntry = this.entries_[index];
+ var currentElement = this.items[index];
+
+ if (index >= this.items.length) {
+ var item = new DirectoryItem(currentEntry, this, tree);
+ this.add(item);
+ index++;
+ } else if (currentEntry.fullPath == currentElement.fullPath) {
+ if (recursive && this.expanded)
+ currentElement.updateSubDirectories(true /* recursive */);
+
+ index++;
+ } else if (currentEntry.fullPath < currentElement.fullPath) {
+ var item = new DirectoryItem(currentEntry, this, tree);
+ this.addAt(item, index);
+ index++;
+ } else if (currentEntry.fullPath > currentElement.fullPath) {
+ this.remove(currentElement);
+ }
+ }
+
+ var removedChild;
+ while (removedChild = this.items[index]) {
+ this.remove(removedChild);
+ }
+
+ if (index == 0) {
+ this.hasChildren = false;
+ this.expanded = false;
+ } else {
+ this.hasChildren = true;
+ }
+};
+
+/**
+ * Finds a parent directory of the {@code entry} in {@code this}, and
+ * invokes the DirectoryItem.selectByEntry() of the found directory.
+ *
+ * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be
+ * a fake.
+ * @return {boolean} True if the parent item is found.
+ */
+DirectoryItemTreeBaseMethods.searchAndSelectByEntry = function(entry) {
+ for (var i = 0; i < this.items.length; i++) {
+ var item = this.items[i];
+ if (util.isParentEntry(item.entry, entry)) {
+ item.selectByEntry(entry);
+ return true;
+ }
+ }
+ return false;
+};
+
+Object.freeze(DirectoryItemTreeBaseMethods);
+
////////////////////////////////////////////////////////////////////////////////
// DirectoryItem
@@ -241,6 +176,27 @@
};
/**
+ * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList().
+ *
+ * @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.
+ */
+DirectoryItem.prototype.updateSubElementsFromList = function(recursive) {
+ DirectoryItemTreeBaseMethods.updateSubElementsFromList.call(this, recursive);
+};
+
+/**
+ * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList().
+ * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be
+ * a fake.
+ * @return {boolean} True if the parent item is found.
+ */
+DirectoryItem.prototype.searchAndSelectByEntry = function(entry) {
+ return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry);
+};
+
+/**
* @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
* @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
* @param {DirectoryTree} tree Current tree, which contains this item.
@@ -353,14 +309,64 @@
*/
DirectoryItem.prototype.updateSubDirectories = function(
recursive, opt_successCallback, opt_errorCallback) {
- DirectoryTreeUtil.updateSubDirectories(
- this,
- function(entries) {
- this.entries_ = entries;
- this.redrawSubDirectoryList_(recursive);
- opt_successCallback && opt_successCallback();
- }.bind(this),
- opt_errorCallback);
+ if (util.isFakeDirectoryEntry(this.entry)) {
+ if (opt_errorCallback)
+ opt_errorCallback();
+ return;
+ }
+
+ var 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));
+ };
+
+ var onSuccess = function(entries) {
+ this.entries_ = entries;
+ this.redrawSubDirectoryList_(recursive);
+ opt_successCallback && opt_successCallback();
+ }.bind(this);
+
+ var reader = this.entry.createReader();
+ var entries = [];
+ var readEntry = function() {
+ reader.readEntries(function(results) {
+ if (!results.length) {
+ onSuccess(sortEntries(this.fileFilter_, entries));
+ return;
+ }
+
+ for (var i = 0; i < results.length; i++) {
+ var entry = results[i];
+ if (entry.isDirectory)
+ entries.push(entry);
+ }
+ readEntry();
+ }.bind(this));
+ }.bind(this);
+ readEntry();
+};
+
+/**
+ * Updates sub-elements of {@code parentElement} reading {@code DirectoryEntry}
+ * with calling {@code iterator}.
+ *
+ * @param {string} changedDirectryPath The path of the changed directory.
+ */
+DirectoryItem.prototype.updateItemByPath = function(changedDirectryPath) {
+ if (changedDirectryPath === this.entry.fullPath) {
+ this.updateSubDirectories(false /* recursive */);
+ return;
+ }
+
+ for (var i = 0; i < this.items.length; i++) {
+ var item = this.items[i];
+ if (PathUtil.isParentPath(item.entry.fullPath, changedDirectryPath)) {
+ item.updateItemByPath(changedDirectryPath);
+ break;
+ }
+ }
};
/**
@@ -370,11 +376,7 @@
* @private
*/
DirectoryItem.prototype.redrawSubDirectoryList_ = function(recursive) {
- DirectoryTreeUtil.updateSubElementsFromList(
- this,
- function(i) { return this.entries_[i]; }.bind(this),
- this.parentTree_,
- recursive);
+ this.updateSubElementsFromList(recursive);
};
/**
@@ -387,13 +389,13 @@
return;
}
- if (DirectoryTreeUtil.searchAndSelectByEntry(this.items, entry))
+ if (this.searchAndSelectByEntry(entry))
return;
// If the path doesn't exist, updates sub directories and tryes again.
this.updateSubDirectories(
false /* recursive */,
- DirectoryTreeUtil.searchAndSelectByEntry.bind(null, this.items, entry));
+ this.searchAndSelectByEntry.bind(this, entry));
};
/**
@@ -483,6 +485,27 @@
cr.defineProperty(DirectoryTree, 'contextMenuForSubitems', cr.PropertyKind.JS);
/**
+ * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList().
+ *
+ * @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.
+ */
+DirectoryTree.prototype.updateSubElementsFromList = function(recursive) {
+ DirectoryItemTreeBaseMethods.updateSubElementsFromList.call(this, recursive);
+};
+
+/**
+ * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList().
+ * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be
+ * a fake.
+ * @return {boolean} True if the parent item is found.
+ */
+DirectoryTree.prototype.searchAndSelectByEntry = function(entry) {
+ return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry);
+};
+
+/**
* Decorates an element.
* @param {DirectoryModel} directoryModel Current DirectoryModel.
* @param {VolumeManager} volumeManager VolumeManager of the system.
@@ -543,7 +566,7 @@
if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry))
return;
- if (DirectoryTreeUtil.searchAndSelectByEntry(this.items, entry))
+ if (this.searchAndSelectByEntry(entry))
return;
this.selectedItem = null;
@@ -551,7 +574,7 @@
false /* recursive */,
// Success callback, failure is not handled.
function() {
- if (!DirectoryTreeUtil.searchAndSelectByEntry(this.items, entry))
+ if (!this.searchAndSelectByEntry(entry))
this.selectedItem = null;
}.bind(this));
}.bind(this));
@@ -608,11 +631,7 @@
* only root items are updated.
*/
DirectoryTree.prototype.redraw = function(recursive) {
- DirectoryTreeUtil.updateSubElementsFromList(
- this,
- function(i) { return this.entries_[i]; }.bind(this),
- this,
- recursive);
+ this.updateSubElementsFromList(recursive);
};
/**
@@ -639,7 +658,7 @@
return;
var myDriveItem = this.items[0];
- DirectoryTreeUtil.updateChangedDirectoryItem(path, myDriveItem);
+ myDriveItem.updateItemByPath(path);
}
};
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index 8cf3d94..1d8bb57 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -488,97 +488,80 @@
this.__lookupSetter__('hidden').call(this, value);
};
- var commands = this.dialogDom_.querySelectorAll('command');
- for (var i = 0; i < commands.length; i++)
- cr.ui.Command.decorate(commands[i]);
-
var doc = this.document_;
-
- CommandUtil.registerCommand(this.dialogContainer_, 'newfolder',
- Commands.newFolderCommand, this, this.directoryModel_);
+ var handler = new CommandHandler(doc);
// Required to handle the command outside of the container, on the footer.
// TODO(mtomasz): Remove after fixing crbug.com/275235.
- CommandUtil.registerCommand(this.dialogDom_.querySelector('.dialog-footer'),
- 'newfolder', Commands.newFolderCommand, this, this.directoryModel_);
+ handler.registerCommand('newfolder', Commands.newFolderCommand, this,
+ this.directoryModel_);
- CommandUtil.registerCommand(this.dialogContainer_, 'newwindow',
- Commands.newWindowCommand, this, this.directoryModel_);
+ handler.registerCommand('newwindow', Commands.newWindowCommand, this,
+ this.directoryModel_);
- CommandUtil.registerCommand(this.dialogContainer_, 'change-default-app',
- Commands.changeDefaultAppCommand, this);
+ handler.registerCommand('change-default-app',
+ Commands.changeDefaultAppCommand, this);
- CommandUtil.registerCommand(this.navigationList_, 'unmount',
- Commands.unmountCommand, this);
+ handler.registerCommand('unmount', Commands.unmountCommand, this);
- CommandUtil.registerCommand(this.navigationList_, 'import-photos',
- Commands.importCommand, this.navigationList_);
+ handler.registerCommand('import-photos', Commands.importCommand,
+ this.navigationList_);
- CommandUtil.registerCommand(this.dialogContainer_, 'format',
- Commands.formatCommand, this,
- this.directoryModel_);
+ handler.registerCommand('format', Commands.formatCommand, this,
+ this.directoryModel_);
- CommandUtil.registerCommand(this.dialogContainer_, 'delete',
- Commands.deleteFileCommand, this);
+ handler.registerCommand('delete', Commands.deleteFileCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_, 'rename',
- Commands.renameFileCommand, this);
+ handler.registerCommand('rename', Commands.renameFileCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_, 'volume-help',
- Commands.volumeHelpCommand, this);
+ handler.registerCommand('volume-help', Commands.volumeHelpCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_, 'drive-buy-more-space',
- Commands.driveBuySpaceCommand, this);
+ handler.registerCommand('drive-buy-more-space',
+ Commands.driveBuySpaceCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_,
- 'drive-clear-local-cache', Commands.driveClearCacheCommand, this);
+ handler.registerCommand('drive-clear-local-cache',
+ Commands.driveClearCacheCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_, 'drive-go-to-drive',
- Commands.driveGoToDriveCommand, this);
+ handler.registerCommand('drive-go-to-drive',
+ Commands.driveGoToDriveCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_, 'paste',
- Commands.pasteFileCommand, doc, this.fileTransferController_);
+ handler.registerCommand('paste', Commands.pasteFileCommand, doc,
+ this.fileTransferController_);
- CommandUtil.registerCommand(this.dialogContainer_, 'open-with',
- Commands.openWithCommand, this);
+ handler.registerCommand('open-with', Commands.openWithCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_, 'toggle-pinned',
- Commands.togglePinnedCommand, this);
+ handler.registerCommand('toggle-pinned', Commands.togglePinnedCommand,
+ this);
- CommandUtil.registerCommand(this.dialogContainer_, 'zip-selection',
- Commands.zipSelectionCommand, this, this.directoryModel_);
+ handler.registerCommand('zip-selection', Commands.zipSelectionCommand, this,
+ this.directoryModel_);
- CommandUtil.registerCommand(this.dialogContainer_, 'share',
- Commands.shareCommand, this);
+ handler.registerCommand('share', Commands.shareCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_,
- 'create-folder-shortcut', Commands.createFolderShortcutCommand, this);
+ handler.registerCommand('create-folder-shortcut',
+ Commands.createFolderShortcutCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_,
- 'remove-folder-shortcut', Commands.removeFolderShortcutCommand, this);
+ handler.registerCommand('remove-folder-shortcut',
+ Commands.removeFolderShortcutCommand, this);
- CommandUtil.registerCommand(this.dialogContainer_, 'search',
- Commands.searchCommand, this,
- this.dialogDom_.querySelector('#search-box'));
+ handler.registerCommand('search', Commands.searchCommand, this,
+ this.dialogDom_.querySelector('#search-box'));
// Register commands with CTRL-1..9 shortcuts for switching between
// volumes.
for (var i = 1; i <= 9; i++) {
- CommandUtil.registerCommand(this.dialogContainer_,
- 'volume-switch-' + i,
- Commands.volumeSwitchCommand,
- this.navigationList_,
- i);
+ handler.registerCommand('volume-switch-' + i,
+ Commands.volumeSwitchCommand,
+ this.navigationList_,
+ i);
}
- CommandUtil.registerCommand(doc, 'zoom-in', Commands.zoomInCommand);
- CommandUtil.registerCommand(doc, 'zoom-out', Commands.zoomOutCommand);
- CommandUtil.registerCommand(doc, 'zoom-reset', Commands.zoomResetCommand);
+ handler.registerCommand('zoom-in', Commands.zoomInCommand);
+ handler.registerCommand('zoom-out', Commands.zoomOutCommand);
+ handler.registerCommand('zoom-reset', Commands.zoomResetCommand);
- CommandUtil.registerCommand(this.dialogContainer_, 'cut',
- Commands.defaultCommand, doc);
- CommandUtil.registerCommand(this.dialogContainer_, 'copy',
- Commands.defaultCommand, doc);
+ handler.registerCommand('cut', Commands.defaultCommand, doc);
+ handler.registerCommand('copy', Commands.defaultCommand, doc);
var inputs = this.dialogDom_.querySelectorAll(
'input[type=text], input[type=search], textarea');
@@ -616,11 +599,15 @@
});
};
+ /**
+ * Entry point of the initialization.
+ * This method is called from main.js.
+ */
FileManager.prototype.initializeCore = function() {
this.initializeQueue_.add(this.initGeneral_.bind(this), [], 'initGeneral');
this.initializeQueue_.add(this.initStrings_.bind(this), [], 'initStrings');
this.initializeQueue_.add(
- this.initPreferences_.bind(this), [], 'initPreferences');
+ this.initPreferences_.bind(this), ['initGeneral'], 'initPreferences');
this.initializeQueue_.add(
this.initVolumeManager_.bind(this),
['initPreferences'], 'initVolumeManager');
@@ -769,6 +756,9 @@
this.initDialogType_();
+ // Create the root view of FileManager.
+ this.ui_ = new FileManagerUI(this.dialogDom_);
+
// Show the window as soon as the UI pre-initialization is done.
if (this.dialogType == DialogType.FULL_PAGE &&
!util.platform.runningInBrowser()) {
@@ -784,20 +774,19 @@
* @private
*/
FileManager.prototype.initDialogs_ = function() {
- var d = cr.ui.dialogs;
- d.BaseDialog.OK_LABEL = str('OK_LABEL');
- d.BaseDialog.CANCEL_LABEL = str('CANCEL_LABEL');
- this.error = new ErrorDialog(this.dialogDom_);
- this.alert = new d.AlertDialog(this.dialogDom_);
- this.confirm = new d.ConfirmDialog(this.dialogDom_);
- this.prompt = new d.PromptDialog(this.dialogDom_);
-
+ // Initialize the dialog.
+ this.ui_.initDialogs();
FileManagerDialogBase.setFileManager(this);
- this.shareDialog_ = new ShareDialog(this.dialogDom_);
- this.defaultTaskPicker =
- new cr.filebrowser.DefaultActionDialog(this.dialogDom_);
- this.suggestAppsDialog =
- new SuggestAppsDialog(this.dialogDom_);
+
+ // Obtains the dialog instances from FileManagerUI.
+ // TODO(hirono): Remove the properties from the FileManager class.
+ this.error = this.ui_.errorDialog;
+ this.alert = this.ui_.alertDialog;
+ this.confirm = this.ui_.confirmDialog;
+ this.prompt = this.ui_.promptDialog;
+ this.shareDialog_ = this.ui_.shareDialog;
+ this.defaultTaskPicker = this.ui_.defaultTaskPicker;
+ this.suggestAppsDialog = this.ui_.suggestAppsDialog;
};
/**
@@ -850,7 +839,6 @@
this.previewPanel_.breadcrumbs.addEventListener(
'pathclick', this.onBreadcrumbClick_.bind(this));
- this.previewPanel_.breadcrumbs.setHideLast(false);
this.progressCenterPanel_ = new ProgressCenterPanel(
dom.querySelector('#progress-center'));
@@ -1563,23 +1551,22 @@
this.finishSetupCurrentDirectory_(path);
return;
}
- if (this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE)) {
- this.finishSetupCurrentDirectory_(path);
- return;
- }
var tracker = this.directoryModel_.createDirectoryChangeTracker();
- // Expected finish of setupPath to Drive.
- tracker.exceptInitialChange = true;
- tracker.start();
- // Waits until the Drive is mounted.
- this.volumeManager_.mountDrive(function() {
+ var onVolumeManagerReady = function() {
+ this.volumeManager_.removeEventListener('ready', onVolumeManagerReady);
tracker.stop();
if (!tracker.hasChanged)
this.finishSetupCurrentDirectory_(path);
- }.bind(this), function(error) {
- tracker.stop();
- });
+ }.bind(this);
+
+ tracker.start();
+ if (this.volumeManager_.isReady()) {
+ onVolumeManagerReady();
+ } else {
+ // Wait until the VolumeManager gets ready.
+ this.volumeManager_.addEventListener('ready', onVolumeManagerReady);
+ }
} else {
this.finishSetupCurrentDirectory_(path);
}
@@ -1909,7 +1896,6 @@
var isDriveEnabled = self.isDriveEnabled();
self.volumeManager_.setDriveEnabled(isDriveEnabled);
- self.navigationList_.dataModel.showShortcuts(isDriveEnabled);
if (prefs.cellularDisabled)
self.syncButton.setAttribute('checked', '');
@@ -2442,11 +2428,12 @@
this.updateSearchBoxOnDirChange_();
util.updateAppState(this.getCurrentDirectory());
- if (this.closeOnUnmount_ && !event.initial &&
+ // If the current directory is moved from the device's volume, do not
+ // automatically close the window on device removal.
+ if (event.previousDirEntry &&
PathUtil.getRootPath(event.previousDirEntry.fullPath) !=
- PathUtil.getRootPath(event.newDirEntry.fullPath)) {
+ PathUtil.getRootPath(event.newDirEntry.fullPath))
this.closeOnUnmount_ = false;
- }
this.updateCommands();
this.updateUnformattedDriveStatus_();
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 b0b268f..9bcc533 100644
--- a/chrome/browser/resources/file_manager/js/file_manager_commands.js
+++ b/chrome/browser/resources/file_manager/js/file_manager_commands.js
@@ -118,7 +118,7 @@
* @param {Node} node Node to register command handler on.
* @param {string} commandId Command id to respond to.
* @param {{execute:function, canExecute:function}} handler Handler to use.
- * @param {...Object} var_args Additional arguments to pass to handler.
+ * @param {...*} var_args Additional arguments to pass to handler.
*/
CommandUtil.registerCommand = function(node, commandId, handler, var_args) {
var args = Array.prototype.slice.call(arguments, 3);
@@ -157,10 +157,84 @@
CommandUtil.registerCommand(node, commandId, Commands.defaultCommand, doc);
};
+/**
+ * Handle of the command events.
+ * @param {HTMLDocument} doc Document of Files.app's UI.
+ * @constructor
+ */
+var CommandHandler = function(doc) {
+ // Set member variable.
+ this.commands_ = {};
+
+ // Decorate command tags in the document.
+ var commands = doc.querySelectorAll('command');
+ for (var i = 0; i < commands.length; i++) {
+ cr.ui.Command.decorate(commands[i]);
+ }
+
+ // Register events.
+ doc.addEventListener('command', this.onCommand_.bind(this));
+ doc.addEventListener('canExecute', this.onCanExecute_.bind(this));
+};
+
+/**
+ * Registers handler on specific command on specific node.
+ * @param {string} commandId Command id to respond to.
+ * @param {{execute:function, canExecute:function}} handler Handler to use.
+ * @param {...*} var_args Additional arguments to pass to handler.
+ */
+CommandHandler.prototype.registerCommand = function(commandId,
+ handler,
+ var_args) {
+ handler.args = Array.prototype.slice.call(arguments, 2);
+ this.commands_[commandId] = handler;
+};
+
+/**
+ * Handles command events.
+ * @param {Event} event Command event.
+ * @private
+ */
+CommandHandler.prototype.onCommand_ = function(event) {
+ var handler = this.commands_[event.command.id];
+ handler.execute.apply(handler, [event].concat(handler.args));
+};
+
+/**
+ * Handles canExecute events.
+ * @param {Event} event Can execute event.
+ * @private
+ */
+CommandHandler.prototype.onCanExecute_ = function(event) {
+ var handler = this.commands_[event.command.id];
+ handler.canExecute.apply(handler, [event].concat(handler.args));
+};
+
+/**
+ * A command.
+ * @interface
+ */
+var Command = function() {};
+
+/**
+ * Handles the execute event.
+ * @param {Event} event Command event.
+ * @param {...*} var_args Additional arguments.
+ */
+Command.prototype.execute = function(event, var_args) {};
+
+/**
+ * Handles the can execute event.
+ * @param {Event} event Can execute event.
+ * @param {...*} var_args Additional arguments.
+ */
+Command.prototype.canExecute = function(event, var_args) {};
+
var Commands = {};
/**
* Forwards all command events to standard document handlers.
+ * @implements {Command}
*/
Commands.defaultCommand = {
execute: function(event, document) {
@@ -173,6 +247,7 @@
/**
* Unmounts external drive.
+ * @implements {Command}
*/
Commands.unmountCommand = {
/**
@@ -201,6 +276,7 @@
/**
* Formats external drive.
+ * @implements {Command}
*/
Commands.formatCommand = {
/**
@@ -233,7 +309,8 @@
};
/**
- * Imports photos from external drive
+ * Imports photos from external drive.
+ * @implements {Command}
*/
Commands.importCommand = {
/**
@@ -259,6 +336,7 @@
/**
* Initiates new folder creation.
+ * @implements {Command}
*/
Commands.newFolderCommand = {
execute: function(event, fileManager) {
@@ -274,6 +352,7 @@
/**
* Initiates new window creation.
+ * @implements {Command}
*/
Commands.newWindowCommand = {
execute: function(event, fileManager, directoryModel) {
@@ -291,6 +370,7 @@
/**
* Changed the default app handling inserted media.
+ * @implements {Command}
*/
Commands.changeDefaultAppCommand = {
execute: function(event, fileManager) {
@@ -301,6 +381,7 @@
/**
* Deletes selected files.
+ * @implements {Command}
*/
Commands.deleteFileCommand = {
execute: function(event, fileManager) {
@@ -316,6 +397,7 @@
/**
* Pastes files from clipboard.
+ * @implements {Command}
*/
Commands.pasteFileCommand = {
execute: Commands.defaultCommand.execute,
@@ -327,6 +409,7 @@
/**
* Initiates file renaming.
+ * @implements {Command}
*/
Commands.renameFileCommand = {
execute: function(event, fileManager) {
@@ -344,6 +427,7 @@
/**
* Opens drive help.
+ * @implements {Command}
*/
Commands.volumeHelpCommand = {
execute: function() {
@@ -357,6 +441,7 @@
/**
* Opens drive buy-more-space url.
+ * @implements {Command}
*/
Commands.driveBuySpaceCommand = {
execute: function() {
@@ -367,6 +452,7 @@
/**
* Clears drive cache.
+ * @implements {Command}
*/
Commands.driveClearCacheCommand = {
execute: function() {
@@ -377,6 +463,7 @@
/**
* Opens drive.google.com.
+ * @implements {Command}
*/
Commands.driveGoToDriveCommand = {
execute: function() {
@@ -387,6 +474,7 @@
/**
* Displays open with dialog for current selection.
+ * @implements {Command}
*/
Commands.openWithCommand = {
execute: function(event, fileManager) {
@@ -408,6 +496,7 @@
/**
* Focuses search input box.
+ * @implements {Command}
*/
Commands.searchCommand = {
execute: function(event, fileManager, element) {
@@ -421,6 +510,7 @@
/**
* Activates the n-th volume.
+ * @implements {Command}
*/
Commands.volumeSwitchCommand = {
execute: function(event, navigationList, index) {
@@ -433,6 +523,7 @@
/**
* Flips 'available offline' flag on the file.
+ * @implements {Command}
*/
Commands.togglePinnedCommand = {
execute: function(event, fileManager) {
@@ -529,6 +620,7 @@
/**
* Creates zip file for current selection.
+ * @implements {Command}
*/
Commands.zipSelectionCommand = {
execute: function(event, fileManager, directoryModel) {
@@ -546,6 +638,7 @@
/**
* Shows the share dialog for the current selection (single only).
+ * @implements {Command}
*/
Commands.shareCommand = {
execute: function(event, fileManager) {
@@ -562,6 +655,7 @@
/**
* Creates a shortcut of the selected folder (single only).
+ * @implements {Command}
*/
Commands.createFolderShortcutCommand = {
/**
@@ -609,6 +703,7 @@
/**
* Removes the folder shortcut.
+ * @implements {Command}
*/
Commands.removeFolderShortcutCommand = {
/**
@@ -645,6 +740,7 @@
/**
* Zoom in to the Files.app.
+ * @implements {Command}
*/
Commands.zoomInCommand = {
execute: function(event) {
@@ -655,6 +751,7 @@
/**
* Zoom out from the Files.app.
+ * @implements {Command}
*/
Commands.zoomOutCommand = {
execute: function(event) {
@@ -665,6 +762,7 @@
/**
* Reset the zoom factor.
+ * @implements {Command}
*/
Commands.zoomResetCommand = {
execute: function(event) {
diff --git a/chrome/browser/resources/file_manager/js/file_operation_manager.js b/chrome/browser/resources/file_manager/js/file_operation_manager.js
index 21a469b..674a9d9 100644
--- a/chrome/browser/resources/file_manager/js/file_operation_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_operation_manager.js
@@ -47,6 +47,84 @@
};
/**
+ * Traverses files/subdirectories of the given entry, and returns them.
+ * In addition, this method annotate the size of each entry. The result will
+ * include the entry itself.
+ *
+ * @param {Entry} entry The root Entry for traversing.
+ * @param {function(Array.<Entry>)} successCallback Called when the traverse
+ * is successfully done with the array of the entries.
+ * @param {function(FileError)} errorCallback Called on error with the first
+ * occured error (i.e. following errors will just be discarded).
+ */
+fileOperationUtil.resolveRecursively = function(
+ entry, successCallback, errorCallback) {
+ var result = [];
+ var error = null;
+ var numRunningTasks = 0;
+
+ var maybeInvokeCallback = function() {
+ // If there still remain some running tasks, wait their finishing.
+ if (numRunningTasks > 0)
+ return;
+
+ if (error)
+ errorCallback(error);
+ else
+ successCallback(result);
+ };
+
+ // The error handling can be shared.
+ var onError = function(fileError) {
+ // If this is the first error, remember it.
+ if (!error)
+ error = fileError;
+ --numRunningTasks;
+ maybeInvokeCallback();
+ };
+
+ var process = function(entry) {
+ numRunningTasks++;
+ result.push(entry);
+ if (entry.isDirectory) {
+ // The size of a directory is 1 bytes here, so that the progress bar
+ // will work smoother.
+ // TODO(hidehiko): Remove this hack.
+ entry.size = 1;
+
+ // Recursively traverse children.
+ var reader = entry.createReader();
+ reader.readEntries(
+ function processSubEntries(subEntries) {
+ if (error || subEntries.length == 0) {
+ // If an error is found already, or this is the completion
+ // callback, then finish the process.
+ --numRunningTasks;
+ maybeInvokeCallback();
+ return;
+ }
+
+ for (var i = 0; i < subEntries.length; i++)
+ process(subEntries[i]);
+
+ // Continue to read remaining children.
+ reader.readEntries(processSubEntries, onError);
+ },
+ onError);
+ } else {
+ // For a file, annotate the file size.
+ entry.getMetadata(function(metadata) {
+ entry.size = metadata.size;
+ --numRunningTasks;
+ maybeInvokeCallback();
+ }, onError);
+ }
+ };
+
+ process(entry);
+};
+
+/**
* Sets last modified date to the entry.
* @param {Entry} entry The entry to which the last modified is set.
* @param {Date} modificationTime The last modified time.
@@ -68,13 +146,14 @@
* @param {Entry} source The entry to be copied.
* @param {DirectoryEntry} parent The entry of the destination directory.
* @param {string} newName The name of copied file.
- * @param {function(util.EntryChangedKind, Entry)} entryChangedCallback
- * Callback invoked when an entry is changed.
- * @param {function(Entry, number)} progressCallback Callback invoked
- * periodically during the copying. It takes source and the number of
- * copied bytes since the last invocation.
- * @param {function(Entry)} successCallback Callback invoked when the copy
- * is successfully done with the entry of the created entry.
+ * @param {function(string, string)} entryChangedCallback
+ * Callback invoked when an entry is created with the source url and
+ * the destination url.
+ * @param {function(string, number)} progressCallback Callback invoked
+ * periodically during the copying. It takes the source url and the
+ * processed bytes of it.
+ * @param {function(string)} successCallback Callback invoked when the copy
+ * is successfully done with the url of the created entry.
* @param {function(FileError)} errorCallback Callback invoked when an error
* is found.
* @return {function()} Callback to cancel the current file copy operation.
@@ -86,8 +165,6 @@
successCallback, errorCallback) {
var copyId = null;
var pendingCallbacks = [];
- var resolveQueue = new AsyncUtil.Queue();
- var lastProgressSize = 0;
var onCopyProgress = function(progressCopyId, status) {
if (copyId == null) {
@@ -103,59 +180,24 @@
switch (status.type) {
case 'begin_entry_copy':
- resolveQueue.run(function(callback) {
- webkitResolveFileSystemURL(status.url, function(entry) {
- // Notify progress to update the status.
- // This will be used to update the entry currently being copied.
- lastProgressSize = 0;
- progressCallback(entry, 0);
- callback();
- });
- });
break;
case 'end_entry_copy':
- resolveQueue.run(function(callback) {
- webkitResolveFileSystemURL(status.url, function(entry) {
- // The entry is created.
- entryChangedCallback(util.EntryChangedKind.CREATED, entry);
- callback();
- });
- });
+ entryChangedCallback(status.sourceUrl, status.destinationUrl);
break;
case 'progress':
- resolveQueue.run(function(callback) {
- webkitResolveFileSystemURL(status.url, function(entry) {
- // For the backword compatibility, here the reported size is the
- // diff since the last invocation.
- // TODO(hidehiko): Fix this to report the size directly.
- var updateSize = status.size - lastProgressSize;
- lastProgressSize = status.size;
- progressCallback(entry, updateSize);
- callback();
- });
- });
+ progressCallback(status.sourceUrl, status.size);
break;
case 'success':
chrome.fileBrowserPrivate.onCopyProgress.removeListener(onCopyProgress);
- resolveQueue.run(function(callback) {
- webkitResolveFileSystemURL(status.url, function(entry) {
- successCallback(entry);
- // Do not call callback here, because this is the completion
- // callback.
- });
- });
+ successCallback(status.destinationUrl);
break;
case 'error':
chrome.fileBrowserPrivate.onCopyProgress.removeListener(onCopyProgress);
- resolveQueue.run(function(callback) {
- errorCallback(util.createFileError(status.error));
- // Do not call callback here, because this is the completion
- // callback.
- });
+ errorCallback(util.createFileError(status.error));
break;
default:
@@ -163,10 +205,7 @@
console.error('Unknown progress type: ' + status.type);
chrome.fileBrowserPrivate.onCopyProgress.removeListener(onCopyProgress);
chrome.fileBrowserPrivate.cancelCopy(copyId);
- resolveQueue.run(function(callback) {
- errorCallback(util.createFileError(FileError.INVALID_STATE_ERR));
- });
-
+ errorCallback(util.createFileError(FileError.INVALID_STATE_ERR));
}
};
@@ -212,13 +251,14 @@
* @param {Entry} source The entry to be copied.
* @param {DirectoryEntry} parent The entry of the destination directory.
* @param {string} newName The name of copied file.
- * @param {function(util.EntryChangedKind, Entry)} entryChangedCallback
- * Callback invoked when an entry is changed.
- * @param {function(Entry, number)} progressCallback Callback invoked
- * periodically during the copying. It takes source and the number of
- * copied bytes since the last invocation.
- * @param {function(Entry)} successCallback Callback invoked when the copy
- * is successfully done with the entry of the created entry.
+ * @param {function(string, string)} entryChangedCallback
+ * Callback invoked when an entry is created with the source url and
+ * the destination url.
+ * @param {function(string, number)} progressCallback Callback invoked
+ * periodically during the copying. It takes the source url and the
+ * processed bytes of it.
+ * @param {function(string)} successCallback Callback invoked when the copy
+ * is successfully done with the url of the created entry.
* @param {function(FileError)} errorCallback Callback invoked when an error
* is found.
* @return {function()} Callback to cancel the current file copy operation.
@@ -236,8 +276,8 @@
return fileOperationUtil.copyFile_(
source, parent, newName, progressCallback,
function(entry) {
- entryChangedCallback(util.EntryChangedKind.CREATED, entry);
- successCallback(entry);
+ entryChangedCallback(source.toURL(), entry.toURL());
+ successCallback(entry.toURL());
},
errorCallback);
}
@@ -250,7 +290,7 @@
parent.getDirectory(
newName, {create: true, exclusive: true},
function(dirEntry) {
- entryChangedCallback(util.EntryChangedKind.CREATED, dirEntry);
+ entryChangedCallback(source.toURL(), dirEntry.toURL());
if (cancelRequested) {
errorCallback(util.createFileError(FileError.ABORT_ERR));
return;
@@ -278,7 +318,7 @@
});
},
function() {
- successCallback(dirEntry);
+ successCallback(dirEntry.toURL());
},
errorCallback);
},
@@ -301,11 +341,9 @@
* @param {FileEntry} source The file entry to be copied.
* @param {DirectoryEntry} parent The entry of the destination directory.
* @param {string} newName The name of copied file.
- * @param {function(FileEntry, number)} progressCallback Callback invoked
- * periodically during the file writing. It takes source and the number of
- * copied bytes since the last invocation. This is also called just before
- * starting the operation (with '0' bytes) and just after the finishing the
- * operation (with the total copied size).
+ * @param {function(string, number)} progressCallback Callback invoked
+ * periodically during the file writing with the source url and the
+ * number of the processed bytes.
* @param {function(FileEntry)} successCallback Callback invoked when the copy
* is successfully done with the entry of the created file.
* @param {function(FileError)} errorCallback Callback invoked when an error
@@ -346,11 +384,9 @@
* @param {FileEntry} source The file entry to be copied.
* @param {DirectoryEntry} parent The entry of the destination directory.
* @param {string} newName The name of copied file.
- * @param {function(FileEntry, number)} progressCallback Callback invoked
- * periodically during the file writing. It takes source and the number of
- * copied bytes since the last invocation. This is also called just before
- * starting the operation (with '0' bytes) and just after the finishing the
- * operation (with the total copied size).
+ * @param {function(string, number)} progressCallback Callback invoked
+ * periodically during the file writing with the source url and the
+ * number of the processed bytes.
* @param {function(FileEntry)} successCallback Callback invoked when the copy
* is successfully done with the entry of the created file.
* @param {function(FileError)} errorCallback Callback invoked when an error
@@ -389,7 +425,6 @@
writer.error);
};
- var reportedProgress = 0;
writer.onprogress = function(progress) {
if (cancelRequested) {
// If the copy was cancelled, we should abort the operation.
@@ -398,12 +433,7 @@
writer.abort();
return;
}
-
- // |progress.loaded| will contain total amount of data copied by now.
- // |progressCallback| expects data amount delta from the last progress
- // update.
- progressCallback(target, progress.loaded - reportedProgress);
- reportedProgress = progress.loaded;
+ progressCallback(source.toURL(), progress.loaded);
};
writer.onwrite = function() {
@@ -463,9 +493,9 @@
* @param {FileEntry} source The entry of the file to be copied.
* @param {DirectoryEntry} parent The entry of the destination directory.
* @param {string} newName The name of the copied file.
- * @param {function(FileEntry, number)} progressCallback Callback periodically
- * invoked during file transfer with the source and the number of
- * transferred bytes from the last call.
+ * @param {function(string, number)} progressCallback Callback invoked
+ * periodically during the file writing with the source url and the
+ * number of the processed bytes.
* @param {function(FileEntry)} successCallback Callback invoked when the
* file copy is successfully done with the entry of the copied file.
* @param {function(FileError)} errorCallback Callback invoked when an error
@@ -487,7 +517,6 @@
// Because the uploading the file from local cache to Drive server will be
// done as a part of background Drive file system sync, so for this copy
// operation, what we need to take care about is only file downloading.
- var numTransferredBytes = 0;
if (PathUtil.isDriveBasedPath(source.fullPath)) {
var sourceUrl = source.toURL();
var sourcePath = util.extractFilePath(sourceUrl);
@@ -499,11 +528,7 @@
// url encoding schemes (eg. rfc2396 vs. rfc3986).
var filePath = util.extractFilePath(status.fileUrl);
if (filePath == sourcePath) {
- var processed = status.processed;
- if (processed > numTransferredBytes) {
- progressCallback(source, processed - numTransferredBytes);
- numTransferredBytes = processed;
- }
+ progressCallback(source.toURL(), status.processed);
return;
}
}
@@ -541,11 +566,7 @@
return;
}
- entry.getMetadata(function(metadata) {
- if (metadata.size > numTransferredBytes)
- progressCallback(source, metadata.size - numTransferredBytes);
- successCallback(entry);
- }, errorCallback);
+ successCallback(entry);
},
function(error) {
if (onCopyToCompleted)
@@ -696,35 +717,36 @@
* Tasks may be added while the queue is being serviced. Though a
* cancel operation cancels everything in the queue.
*
+ * @param {util.FileOperationType} operationType The type of this operation.
* @param {Array.<Entry>} sourceEntries Array of source entries.
* @param {DirectoryEntry} targetDirEntry Target directory.
* @constructor
*/
-FileOperationManager.Task = function(sourceEntries, targetDirEntry) {
+FileOperationManager.Task = function(
+ operationType, sourceEntries, targetDirEntry) {
+ this.operationType = operationType;
this.sourceEntries = sourceEntries;
this.targetDirEntry = targetDirEntry;
- // TODO(hidehiko): When we support recursive copy, we should be able to
- // rely on originalEntries. Then remove this.
- this.entries = [];
+ /**
+ * An array of map from url to Entry being processed.
+ * @type {Array.<Object<string, Entry>>}
+ */
+ this.processingEntries = null;
/**
- * The number of entries, whose processing is completed.
+ * Total number of bytes to be processed. Filled in initialize().
* @type {number}
*/
- this.numCompletedEntries = 0;
this.totalBytes = 0;
- this.completedBytes = 0;
/**
- * The entry currently being processed.
- * @type {Entry}
+ * Total number of already processed bytes. Updated periodically.
+ * @type {number}
*/
- this.processingEntry = null;
+ this.processedBytes = 0;
this.deleteAfterCopy = false;
- this.move = false;
- this.zip = false;
/**
* Set to true when cancel is requested.
@@ -751,32 +773,6 @@
* @param {function()} callback When entries resolved.
*/
FileOperationManager.Task.prototype.initialize = function(callback) {
- // When moving directories, FileEntry.moveTo() is used if both source
- // and target are on Drive. There is no need to recurse into directories.
- util.recurseAndResolveEntries(
- this.sourceEntries, !this.move,
- function(result) {
- if (this.move) {
- // This may be moving from search results, where it fails if we
- // move parent entries earlier than child entries. We should
- // process the deepest entry first. Since move of each entry is
- // done by a single moveTo() call, we don't need to care about the
- // recursive traversal order.
- this.entries = result.dirEntries.concat(result.fileEntries).sort(
- function(entry1, entry2) {
- return entry2.fullPath.length - entry1.fullPath.length;
- });
- } else {
- // Copying tasks are recursively processed. So, directories must be
- // processed earlier than their child files. Since
- // util.recurseAndResolveEntries is already listing entries in the
- // recursive traversal order, we just keep the ordering.
- this.entries = result.dirEntries.concat(result.fileEntries);
- }
-
- this.totalBytes = result.fileBytes;
- callback();
- }.bind(this));
};
/**
@@ -789,35 +785,6 @@
};
/**
- * @param {string} fromName Old name.
- * @param {string} toName New name.
- */
-FileOperationManager.Task.prototype.registerRename = function(
- fromName, toName) {
- this.renamedDirectories_.push({from: fromName + '/', to: toName + '/'});
-};
-
-/**
- * @param {string} path A path.
- * @return {string} Path after renames.
- */
-FileOperationManager.Task.prototype.applyRenames = function(path) {
- // Directories are processed in pre-order, so we will store only the first
- // renaming point:
- // x -> x (1) -- new directory created.
- // x\y -> x (1)\y -- no more renames inside the new directory, so
- // this one will not be stored.
- // x\y\a.txt -- only one rename will be applied.
- for (var index = 0; index < this.renamedDirectories_.length; ++index) {
- var rename = this.renamedDirectories_[index];
- if (path.indexOf(rename.from) == 0) {
- path = rename.to + path.substr(rename.from.length);
- }
- }
- return path;
-};
-
-/**
* Requests cancellation of this task.
* When the cancellation is done, it is notified via callbacks of run().
*/
@@ -853,7 +820,8 @@
* @extends {FileOperationManager.Task}
*/
FileOperationManager.CopyTask = function(sourceEntries, targetDirEntry) {
- FileOperationManager.Task.call(this, sourceEntries, targetDirEntry);
+ FileOperationManager.Task.call(
+ this, util.FileOperationType.COPY, sourceEntries, targetDirEntry);
};
/**
@@ -863,6 +831,48 @@
FileOperationManager.Task.prototype;
/**
+ * Initializes the CopyTask.
+ * @param {function()} callback Called when the initialize is completed.
+ */
+FileOperationManager.CopyTask.prototype.initialize = function(callback) {
+ var group = new AsyncUtil.Group();
+ // Correct all entries to be copied for status update.
+ this.processingEntries = [];
+ for (var i = 0; i < this.sourceEntries.length; i++) {
+ group.add(function(index, callback) {
+ fileOperationUtil.resolveRecursively(
+ this.sourceEntries[index],
+ function(resolvedEntries) {
+ var resolvedEntryMap = {};
+ for (var j = 0; j < resolvedEntries.length; ++j) {
+ var entry = resolvedEntries[j];
+ entry.processedBytes = 0;
+ resolvedEntryMap[entry.toURL()] = entry;
+ }
+ this.processingEntries[index] = resolvedEntryMap;
+ callback();
+ }.bind(this),
+ function(error) {
+ console.error(
+ 'Failed to resolve for copy: %s',
+ util.getFileErrorMnemonic(error.code));
+ });
+ }.bind(this, i));
+ }
+
+ group.run(function() {
+ // Fill totalBytes.
+ this.totalBytes = 0;
+ for (var i = 0; i < this.processingEntries.length; i++) {
+ for (var url in this.processingEntries[i])
+ this.totalBytes += this.processingEntries[i][url].size;
+ }
+
+ callback();
+ }.bind(this));
+};
+
+/**
* Copies all entries to the target directory.
* Note: this method contains also the operation of "Move" due to historical
* reason.
@@ -879,7 +889,7 @@
entryChangedCallback, progressCallback, successCallback, errorCallback) {
// TODO(hidehiko): We should be able to share the code to iterate on entries
// with serviceMoveTask_().
- if (this.entries.length == 0) {
+ if (this.sourceEntries.length == 0) {
successCallback();
return;
}
@@ -920,14 +930,28 @@
progressCallback();
this.cancelCallback_ = FileOperationManager.CopyTask.processEntry_(
entry, this.targetDirEntry,
- function(type, entry) {
- this.numCompletedEntries++;
- entryChangedCallback(type, entry);
+ function(sourceUrl, destinationUrl) {
+ // Finalize the entry's progress state.
+ var entry = this.processingEntries[index][sourceUrl];
+ if (entry) {
+ this.processedBytes += entry.size - entry.processedBytes;
+ progressCallback();
+ delete this.processingEntries[index][sourceUrl];
+ }
+
+ webkitResolveLocalFileSystemURL(
+ destinationUrl, function(destinationEntry) {
+ entryChangedCallback(
+ util.EntryChangedKind.CREATED, destinationEntry);
+ });
}.bind(this),
- function(entry, size) {
- this.processingEntry = entry;
- this.updateFileCopyProgress(size);
- progressCallback();
+ function(source_url, size) {
+ var entry = this.processingEntries[index][source_url];
+ if (entry) {
+ this.processedBytes += size - entry.processedBytes;
+ entry.processedBytes = size;
+ progressCallback();
+ }
}.bind(this),
function() {
this.cancelCallback_ = null;
@@ -954,9 +978,10 @@
* @param {Entry} sourceEntry An entry to be copied.
* @param {DirectoryEntry} destinationEntry The entry which will contain the
* copied entry.
- * @param {function(util.EntryChangedKind, Entry)} entryChangedCallback
- * Callback invoked when an entry is changed.
- * @param {function(Entry, number)} progressCallback Callback invoked
+ * @param {function(string, string)} entryChangedCallback
+ * Callback invoked when an entry is created with the source url and
+ * the destination url.
+ * @param {function(string, number)} progressCallback Callback invoked
* periodically during the copying.
* @param {function()} successCallback On success.
* @param {function(FileOperationManager.Error)} errorCallback On error.
@@ -1013,9 +1038,8 @@
* @extends {FileOperationManager.Task}
*/
FileOperationManager.MoveTask = function(sourceEntries, targetDirEntry) {
- FileOperationManager.Task.call(this, sourceEntries, targetDirEntry);
- // TODO(hidehiko): We should handle dispatching copy/move/zip more nicely.
- this.move = true;
+ FileOperationManager.Task.call(
+ this, util.FileOperationType.MOVE, sourceEntries, targetDirEntry);
};
/**
@@ -1025,6 +1049,37 @@
FileOperationManager.Task.prototype;
/**
+ * Initializes the MoveTask.
+ * @param {function()} callback Called when the initialize is completed.
+ */
+FileOperationManager.MoveTask.prototype.initialize = function(callback) {
+ // This may be moving from search results, where it fails if we
+ // move parent entries earlier than child entries. We should
+ // process the deepest entry first. Since move of each entry is
+ // done by a single moveTo() call, we don't need to care about the
+ // recursive traversal order.
+ this.sourceEntries.sort(function(entry1, entry2) {
+ return entry2.fullPath.length - entry1.fullPath.length;
+ });
+
+ this.processingEntries = [];
+ for (var i = 0; i < this.sourceEntries.length; i++) {
+ var processingEntryMap = {};
+ var entry = this.sourceEntries[i];
+
+ // The move should be done with updating the metadata. So here we assume
+ // all the file size is 1 byte. (Avoiding 0, so that progress bar can
+ // move smoothly).
+ // TODO(hidehiko): Remove this hack.
+ entry.size = 1;
+ processingEntryMap[entry.toURL()] = entry;
+ this.processingEntries[i] = processingEntryMap;
+ }
+
+ callback();
+};
+
+/**
* Moves all entries in the task.
*
* @param {function(util.EntryChangedKind, Entry)} entryChangedCallback
@@ -1037,13 +1092,13 @@
*/
FileOperationManager.MoveTask.prototype.run = function(
entryChangedCallback, progressCallback, successCallback, errorCallback) {
- if (this.entries.length == 0) {
+ if (this.sourceEntries.length == 0) {
successCallback();
return;
}
AsyncUtil.forEach(
- this.entries,
+ this.sourceEntries,
function(callback, entry, index) {
if (this.cancelRequested_) {
errorCallback(new FileOperationManager.Error(
@@ -1051,12 +1106,13 @@
util.createFileError(FileError.ABORT_ERR)));
return;
}
- this.processingEntry = entry;
progressCallback();
FileOperationManager.MoveTask.processEntry_(
entry, this.targetDirEntry, entryChangedCallback,
function() {
- this.numCompletedEntries++;
+ // Erase the processing entry.
+ this.processingEntries[index] = {};
+ this.processedBytes++;
callback();
}.bind(this),
errorCallback);
@@ -1113,9 +1169,9 @@
*/
FileOperationManager.ZipTask = function(
sourceEntries, targetDirEntry, zipBaseDirEntry) {
- FileOperationManager.Task.call(this, sourceEntries, targetDirEntry);
+ FileOperationManager.Task.call(
+ this, util.FileOperationType.ZIP, sourceEntries, targetDirEntry);
this.zipBaseDirEntry = zipBaseDirEntry;
- this.zip = true;
};
/**
@@ -1124,6 +1180,39 @@
FileOperationManager.ZipTask.prototype.__proto__ =
FileOperationManager.Task.prototype;
+
+/**
+ * Initializes the ZipTask.
+ * @param {function()} callback Called when the initialize is completed.
+ */
+FileOperationManager.ZipTask.prototype.initialize = function(callback) {
+ var resolvedEntryMap = {};
+ var group = new AsyncUtil.Group();
+ for (var i = 0; i < this.sourceEntries.length; i++) {
+ group.add(function(index, callback) {
+ fileOperationUtil.resolveRecursively(
+ this.sourceEntries[index],
+ function(entries) {
+ for (var j = 0; j < entries.length; j++)
+ resolvedEntryMap[entries[j].toURL()] = entries[j];
+ callback();
+ },
+ function(error) {});
+ }.bind(this, i));
+ }
+
+ group.run(function() {
+ // For zip archiving, all the entries are processed at once.
+ this.processingEntries = [resolvedEntryMap];
+
+ this.totalBytes = 0;
+ for (var url in resolvedEntryMap)
+ this.totalBytes += resolvedEntryMap[url].size;
+
+ callback();
+ }.bind(this));
+};
+
/**
* Runs a zip file creation task.
*
@@ -1153,11 +1242,17 @@
// TODO: per-entry zip progress update with accurate byte count.
// For now just set completedBytes to same value as totalBytes so
// that the progress bar is full.
- this.completedBytes = this.totalBytes;
+ this.processedBytes = this.totalBytes;
progressCallback();
+ // The number of elements in processingEntries is 1. See also
+ // initialize().
+ var entries = [];
+ for (var url in this.processingEntries[0])
+ entries.push(this.processingEntries[0][url]);
+
fileOperationUtil.zipSelection(
- this.entries,
+ entries,
this.zipBaseDirEntry,
destPath,
function(entry) {
@@ -1206,47 +1301,51 @@
FileOperationManager.prototype.getStatus = function() {
// TODO(hidehiko): Reorganize the structure when delete queue is merged
// into copy task queue.
- var rv = {
- totalItems: 0,
- completedItems: 0,
+ var result = {
+ // Set to util.FileOperationType if all the running/pending tasks is
+ // the same kind of task.
+ operationType: null,
+ // The number of entries to be processed.
+ numRemainingItems: 0,
+
+ // The total number of bytes to be processed.
totalBytes: 0,
- completedBytes: 0,
- pendingCopies: 0,
- pendingMoves: 0,
- pendingZips: 0,
+ // The number of bytes.
+ processedBytes: 0,
- // In case the number of the incompleted entry is exactly one.
- filename: '',
+ // Available if numRemainingItems == 1. Pointing to an Entry which is
+ // begin processed.
+ processingEntry: null,
};
- var pendingEntry = null;
+ var operationType =
+ this.copyTasks_.length > 0 ? this.copyTasks_[0].operationType : null;
+ var processingEntry = null;
for (var i = 0; i < this.copyTasks_.length; i++) {
var task = this.copyTasks_[i];
- rv.totalItems += task.entries.length;
- rv.completedItems += task.numCompletedEntries;
+ if (task.operationType != operationType)
+ operationType = null;
- rv.totalBytes += task.totalBytes;
- rv.completedBytes += task.completedBytes;
-
- var numPendingEntries = task.entries.length - task.numCompletedEntries;
- if (task.zip) {
- rv.pendingZips += numPendingEntries;
- } else if (task.move || task.deleteAfterCopy) {
- rv.pendingMoves += numPendingEntries;
- } else {
- rv.pendingCopies += numPendingEntries;
+ // Assuming the number of entries is small enough, count everytime.
+ for (var j = 0; j < task.processingEntries.length; j++) {
+ for (var url in task.processingEntries[j]) {
+ ++result.numRemainingItems;
+ processingEntry = task.processingEntries[j][url];
+ }
}
- if (task.processingEntry)
- pendingEntry = task.processingEntry;
+ result.totalBytes += task.totalBytes;
+ result.processedBytes += task.processedBytes;
}
- if (rv.totalItems - rv.completedItems == 1 && pendingEntry)
- rv.filename = pendingEntry.name;
+ result.operationType = operationType;
- return rv;
+ if (result.numRemainingItems == 1)
+ result.processingEntry = processingEntry;
+
+ return result;
};
/**
diff --git a/chrome/browser/resources/file_manager/js/file_selection.js b/chrome/browser/resources/file_manager/js/file_selection.js
index b7ce79c..d2ce7ed 100644
--- a/chrome/browser/resources/file_manager/js/file_selection.js
+++ b/chrome/browser/resources/file_manager/js/file_selection.js
@@ -160,20 +160,7 @@
this.okButton_ = fileManager.okButton_;
this.filenameInput_ = fileManager.filenameInput_;
this.previewPanel_ = fileManager.previewPanel_;
- this.previewPanelElement_ =
- fileManager.dialogDom_.querySelector('.preview-panel');
- this.previewThumbnails_ = this.previewPanelElement_.
- querySelector('.preview-thumbnails');
- this.previewSummary_ =
- this.previewPanelElement_.querySelector('.preview-summary');
- this.previewText_ = this.previewSummary_.querySelector('.preview-text');
- this.calculatingSize_ = this.previewSummary_.
- querySelector('.calculating-size');
- this.calculatingSize_.textContent = str('CALCULATING_SIZE');
-
this.taskItems_ = fileManager.taskItems_;
-
- this.animationTimeout_ = null;
}
/**
diff --git a/chrome/browser/resources/file_manager/js/main_scripts.js b/chrome/browser/resources/file_manager/js/main_scripts.js
index ebe4668..494dd30 100644
--- a/chrome/browser/resources/file_manager/js/main_scripts.js
+++ b/chrome/browser/resources/file_manager/js/main_scripts.js
@@ -104,6 +104,7 @@
//<include src="text_measure.js"/>
//<include src="tree.css.js"/>
//<include src="ui/breadcrumbs_controller.js"/>
+//<include src="ui/file_manager_ui.js"/>
//<include src="ui/preview_panel.js"/>
//<include src="ui/progress_center_panel.js"/>
//<include src="url_constants.js"/>
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 889cc5d..cb7bfd7 100644
--- a/chrome/browser/resources/file_manager/js/media/video_player.js
+++ b/chrome/browser/resources/file_manager/js/media/video_player.js
@@ -217,9 +217,8 @@
}
// Detach the previous video element, if exists.
- if (video) {
+ if (video)
video.parentNode.removeChild(video);
- }
video = document.createElement('video');
document.querySelector('#video-container').appendChild(video);
@@ -269,8 +268,7 @@
selectedItemFilesystemPath = null;
webkitResolveLocalFileSystemURL(src,
function(entry) {
- var video = document.querySelector('video');
- if (video.src != src) return;
+ if (video && video.src != src) return;
selectedItemFilesystemPath = entry.fullPath;
});
});
diff --git a/chrome/browser/resources/file_manager/js/navigation_list.js b/chrome/browser/resources/file_manager/js/navigation_list.js
index e2c4607..34712b6 100644
--- a/chrome/browser/resources/file_manager/js/navigation_list.js
+++ b/chrome/browser/resources/file_manager/js/navigation_list.js
@@ -508,6 +508,9 @@
var parentSetter = cr.ui.List.prototype.__lookupSetter__('dataModel');
parentSetter.call(this, dataModel);
+ // Shows the folder shortcut if necessary.
+ this.updateFolderShortcutsStatus_();
+
// This must be placed after the parent method is called, in order to make
// it sure that the list was changed.
dataModel.addEventListener('change', this.onListContentChangedBound_);
@@ -547,6 +550,8 @@
this.directoryModel_.addEventListener('directory-changed',
this.onCurrentDirectoryChanged_.bind(this));
+ this.volumeManager_.addEventListener('drive-status-changed',
+ this.onDriveStatusChanged_.bind(this));
this.selectionModel.addEventListener(
'change', this.onSelectionChange_.bind(this));
this.selectionModel.addEventListener(
@@ -755,6 +760,27 @@
};
/**
+ * Invoked when the content in the data model is changed.
+ * @param {Event} event The event.
+ * @private
+ */
+NavigationList.prototype.onDriveStatusChanged_ = function(event) {
+ this.updateFolderShortcutsStatus_();
+};
+
+/**
+ * Updates folder shortcut status.
+ * If the drive is mounted, shows the folder shortcut. Otherwise, hide it.
+ *
+ * @private
+ */
+NavigationList.prototype.updateFolderShortcutsStatus_ = function() {
+ var driveVolume = this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE);
+ var isDriveMounted = driveVolume && !driveVolume.error;
+ this.dataModel.showShortcuts(isDriveMounted);
+};
+
+/**
* Synchronizes the volume list selection with the current directory, after
* it is changed outside of the volume list.
* @private
diff --git a/chrome/browser/resources/file_manager/js/photo/gallery.js b/chrome/browser/resources/file_manager/js/photo/gallery.js
index 9bcbfb6..ed7f480 100644
--- a/chrome/browser/resources/file_manager/js/photo/gallery.js
+++ b/chrome/browser/resources/file_manager/js/photo/gallery.js
@@ -227,10 +227,6 @@
cr.dispatchSimpleEvent(this, 'image-saved');
}.bind(this));
- this.printButton_ = this.createToolbarButton_('print', 'GALLERY_PRINT');
- this.printButton_.setAttribute('disabled', '');
- this.printButton_.addEventListener('click', this.print_.bind(this));
-
var deleteButton = this.createToolbarButton_('delete', 'GALLERY_DELETE');
deleteButton.addEventListener('click', this.delete_.bind(this));
@@ -404,21 +400,9 @@
console.error('Invalid Gallery mode');
this.currentMode_ = mode;
- if (this.modeButton_) {
- var oppositeMode =
- mode == this.slideMode_ ? this.mosaicMode_ : this.slideMode_;
- this.modeButton_.title =
- 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_();
+ this.updateButtons_();
};
/**
@@ -534,15 +518,6 @@
};
/**
- * Prints the current item.
- * @private
- */
-Gallery.prototype.print_ = function() {
- this.onUserAction_();
- window.print();
-};
-
-/**
* @return {Array.<Gallery.Item>} Current selection.
*/
Gallery.prototype.getSelectedItems = function() {
@@ -631,11 +606,6 @@
this.slideMode_.startSlideshow(SlideMode.SLIDESHOW_INTERVAL_FIRST, event);
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.delete_();
@@ -816,7 +786,7 @@
};
/**
- * Update available actions list based on the currently selected urls.
+ * Updates available actions list based on the currently selected urls.
* @private.
*/
Gallery.prototype.updateShareMenu_ = function() {
@@ -865,7 +835,7 @@
};
/**
- * Update thumbnails.
+ * Updates thumbnails.
* @private
*/
Gallery.prototype.updateThumbnails_ = function() {
@@ -878,3 +848,18 @@
mosaic.reload();
}
};
+
+/**
+ * Updates buttons.
+ * @private
+ */
+Gallery.prototype.updateButtons_ = function() {
+ if (this.modeButton_) {
+ var oppositeMode =
+ this.currentMode_ == this.slideMode_ ? this.mosaicMode_ :
+ this.slideMode_;
+ this.modeButton_.title =
+ this.displayStringFunction_(oppositeMode.getTitle());
+ }
+};
+
diff --git a/chrome/browser/resources/file_manager/js/photo/photo_import.js b/chrome/browser/resources/file_manager/js/photo/photo_import.js
index d8035a8..b289878 100644
--- a/chrome/browser/resources/file_manager/js/photo/photo_import.js
+++ b/chrome/browser/resources/file_manager/js/photo/photo_import.js
@@ -135,27 +135,27 @@
* @private
*/
PhotoImport.prototype.initMyPhotos_ = function() {
- var onError = this.onError_.bind(
- this, loadTimeData.getString('PHOTO_IMPORT_DRIVE_ERROR'));
-
- var onDirectory = function(dir) {
- // This may enable the import button, so check that.
- this.myPhotosDirectory_ = dir;
- this.onSelectionChanged_();
- }.bind(this);
-
- var onMounted = function() {
- var dir = PathUtil.join(
+ var onVolumeManagerReady = function() {
+ this.volumeManager_.removeEventListener('ready', onVolumeManagerReady);
+ var directoryPath = PathUtil.join(
RootDirectory.DRIVE,
loadTimeData.getString('PHOTO_IMPORT_MY_PHOTOS_DIRECTORY_NAME'));
- util.getOrCreateDirectory(this.filesystem_.root, dir, onDirectory, onError);
+ util.getOrCreateDirectory(
+ this.filesystem_.root, directoryPath,
+ function(entry) {
+ // This may enable the import button, so check that.
+ this.myPhotosDirectory_ = entry;
+ this.onSelectionChanged_();
+ }.bind(this),
+ function(error) {
+ this.onError_(loadTimeData.getString('PHOTO_IMPORT_DRIVE_ERROR'));
+ }.bind(this));
}.bind(this);
- if (this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE)) {
- onMounted();
- } else {
- this.volumeManager_.mountDrive(onMounted, onError);
- }
+ if (this.volumeManager_.isReady())
+ onVolumeManagerReady();
+ else
+ this.volumeManager_.addEventListener('ready', onVolumeManagerReady);
};
/**
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 06c2228..f4cf2ce 100644
--- a/chrome/browser/resources/file_manager/js/photo/slide_mode.js
+++ b/chrome/browser/resources/file_manager/js/photo/slide_mode.js
@@ -196,8 +196,14 @@
this.editButton_ = util.createChild(this.toolbar_, 'button edit', 'button');
this.editButton_.title = this.displayStringFunction_('GALLERY_EDIT');
+ this.editButton_.setAttribute('disabled', ''); // Disabled by default.
this.editButton_.addEventListener('click', this.toggleEditor.bind(this));
+ this.printButton_ = util.createChild(this.toolbar_, 'button print', 'button');
+ this.printButton_.title = this.displayStringFunction_('GALLERY_PRINT');
+ this.printButton_.setAttribute('disabled', ''); // Disabled by default.
+ this.printButton_.addEventListener('click', this.print_.bind(this));
+
this.editBarSpacer_ = util.createChild(this.toolbar_, 'edit-bar-spacer');
this.editBarMain_ = util.createChild(this.editBarSpacer_, 'edit-main');
@@ -323,6 +329,10 @@
} else {
this.commitItem_(commitDone);
}
+
+ // Disable the slide-mode only buttons when leaving.
+ this.editButton_.setAttribute('disabled', '');
+ this.printButton_.setAttribute('disabled', '');
};
@@ -660,7 +670,8 @@
// The editor toolbar does not make sense for video, hide it.
this.stopEditing_();
this.mediaControls_.attachMedia(this.imageView_.getVideo());
- //TODO(kaznacheev): Add metrics for video playback.
+
+ // TODO(kaznacheev): Add metrics for video playback.
} else {
ImageUtil.metrics.recordUserAction(ImageUtil.getMetricName('View'));
@@ -682,6 +693,15 @@
ImageUtil.getMetricName('FileType'), ext, ImageUtil.FILE_TYPES);
}
+ // Enable or disable buttons for editing and printing.
+ if (video || error) {
+ this.editButton_.setAttribute('disabled', '');
+ this.printButton_.setAttribute('disabled', '');
+ } else {
+ this.editButton_.removeAttribute('disabled');
+ this.printButton_.removeAttribute('disabled');
+ }
+
// For once edited image, disallow the 'overwrite' setting change.
ImageUtil.setAttribute(this.options_, 'saved',
!this.getSelectedItem().isOriginal());
@@ -838,13 +858,18 @@
switch (keyID) {
case 'U+0020': // Space toggles the video playback.
- if (this.isShowingVideo_()) {
+ if (this.isShowingVideo_())
this.mediaControls_.togglePlayStateWithFeedback();
- }
+ break;
+
+ case 'Ctrl-U+0050': // Ctrl+'p' prints the current image.
+ if (!this.printButton_.hasAttribute('disabled'))
+ this.print_();
break;
case 'U+0045': // 'e' toggles the editor.
- this.toggleEditor(event);
+ if (!this.editButton_.hasAttribute('disabled'))
+ this.toggleEditor(event);
break;
case 'U+001B': // Escape
@@ -1219,6 +1244,15 @@
};
/**
+ * Prints the current item.
+ * @private
+ */
+SlideMode.prototype.print_ = function() {
+ cr.dispatchSimpleEvent(this, 'useraction');
+ window.print();
+};
+
+/**
* Display the error banner.
* @param {string} message Message.
* @private
diff --git a/chrome/browser/resources/file_manager/js/suggest_apps_dialog.js b/chrome/browser/resources/file_manager/js/suggest_apps_dialog.js
index 076d189..7b75a98 100644
--- a/chrome/browser/resources/file_manager/js/suggest_apps_dialog.js
+++ b/chrome/browser/resources/file_manager/js/suggest_apps_dialog.js
@@ -110,25 +110,6 @@
this.widgetUrl_ = CWS_WIDGET_URL;
this.widgetOrigin_ = CWS_WIDGET_ORIGIN;
- // For development, we provide the feature to override the URL of the widget.
- // TODO(yoshiki): Remove this before ShareDialog launches or M31 branch cut.
- this.urlOverrided_ = false;
- chrome.storage.local.get(
- ['widgetUrlOverride'],
- function(items) {
- if (items['widgetUrlOverride']) {
- this.widgetUrl_ = items['widgetUrlOverride'];
- var match = REGEXP_EXTRACT_HOST.exec(this.widgetUrl_);
- // Overriding URL must be on either localhost or .google.com.
- if (!match ||
- (!REGEXP_GOOGLE_MATCH.test(match[0]) &&
- !REGEXP_LOCALHOST_MATCH.test(match[0])))
- throw new Error('The widget URL is invalid.');
- this.widgetOrigin_ = match[0];
- this.urlOverrided_ = true;
- }
- }.bind(this));
-
this.extension_ = null;
this.mime_ = null;
this.installingItemId_ = null;
@@ -247,10 +228,6 @@
var title = str('SUGGEST_DIALOG_TITLE');
- // TODO(yoshiki): Remove this before ShareDialog launches.
- if (this.urlOverrided_)
- title += ' [OVERRIDED]';
-
var show =
FileManagerDialogBase.prototype.showTitleOnlyDialog.call(this, title);
if (!show) {
diff --git a/chrome/browser/resources/file_manager/js/test_util.js b/chrome/browser/resources/file_manager/js/test_util.js
index a896cc8..1335ae8 100644
--- a/chrome/browser/resources/file_manager/js/test_util.js
+++ b/chrome/browser/resources/file_manager/js/test_util.js
@@ -372,6 +372,20 @@
};
/**
+ * Open the file by selectFile and fakeMouseDoubleClick.
+ *
+ * @param {Window} contentWindow Window to be tested.
+ * @param {string} filename Name of the file to be opened.
+ * @return {boolean} True if file got selected and a double click message is
+ * sent, false otherwise.
+ */
+test.util.sync.openFile = function(contentWindow, filename) {
+ var query = '#file-list li.table-row[selected] .filename-label span';
+ return test.util.sync.selectFile(contentWindow, filename) &&
+ test.util.sync.fakeMouseDoubleClick(contentWindow, query);
+};
+
+/**
* Selects a volume specified by its icon name
*
* @param {Window} contentWindow Window to be tested.
@@ -423,17 +437,28 @@
*
* @param {Window} contentWindow Window to be tested.
* @param {Array.<Array.<string>>} expected Expected contents of file list.
- * @param {boolean=} opt_orderCheck If it is true, this function also compares
- * the order of files.
+ * @param {{orderCheck:boolean=, ignoreLastModifiedTime:boolean=}=} opt_options
+ * Options of the comparision. If orderCheck is true, it also compares the
+ * order of files. If ignoreLastModifiedTime is true, it compares the file
+ * without its last modified time.
* @param {function()} callback Callback function to notify the caller that
* expected files turned up.
*/
test.util.async.waitForFiles = function(
- contentWindow, expected, opt_orderCheck, callback) {
+ contentWindow, expected, opt_options, callback) {
+ var options = opt_options || {};
test.util.repeatUntilTrue_(function() {
var files = test.util.sync.getFileList(contentWindow);
- if (!opt_orderCheck)
+ if (!options.orderCheck) {
files.sort();
+ expected.sort();
+ }
+ if (options.ignoreLastModifiedTime) {
+ for (var i = 0; i < Math.min(files.length, expected.length); i++) {
+ files[i][3] = '';
+ expected[i][3] = '';
+ }
+ }
if (chrome.test.checkDeepEq(expected, files)) {
callback(true);
return true;
diff --git a/chrome/browser/resources/file_manager/js/ui/file_manager_ui.js b/chrome/browser/resources/file_manager/js/ui/file_manager_ui.js
new file mode 100644
index 0000000..08dceb9
--- /dev/null
+++ b/chrome/browser/resources/file_manager/js/ui/file_manager_ui.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.
+
+'use strict';
+
+/**
+ * The root of the file manager's view managing the DOM of Files.app.
+ *
+ * @param {HTMLElement} element Top level element of Files.app.
+ * @constructor.
+ */
+var FileManagerUI = function(element) {
+ /**
+ * Top level element of Files.app.
+ * @type {HTMLElement}
+ * @private
+ */
+ this.element_ = element;
+
+ /**
+ * Error dialog.
+ * @type {ErrorDialog}
+ */
+ this.errorDialog = null;
+
+ /**
+ * Alert dialog.
+ * @type {cr.ui.dialogs.AlertDialog}
+ */
+ this.alertDialog = null;
+
+ /**
+ * Confirm dialog.
+ * @type {cr.ui.dialogs.ConfirmDialog}
+ */
+ this.confirmDialog = null;
+
+ /**
+ * Prompt dialog.
+ * @type {cr.ui.dialogs.PromptDialog}
+ */
+ this.promptDialog = null;
+
+ /**
+ * Share dialog.
+ * @type {ShareDialog}
+ */
+ this.shareDialog = null;
+
+ /**
+ * Default task picker.
+ * @type {DefaultActionDialog}
+ */
+ this.defaultTaskPicker = null;
+
+ /**
+ * Suggest apps dialog.
+ * @type {SuggestAppsDialog}
+ */
+ this.suggestAppsDialog = null;
+
+ Object.seal(this);
+};
+
+/**
+ * Initialize the dialogs.
+ */
+FileManagerUI.prototype.initDialogs = function() {
+ // Initialize the dialog label.
+ var dialogs = cr.ui.dialogs;
+ dialogs.BaseDialog.OK_LABEL = str('OK_LABEL');
+ dialogs.BaseDialog.CANCEL_LABEL = str('CANCEL_LABEL');
+
+ // Create the dialog instances.
+ this.errorDialog = new ErrorDialog(this.element_);
+ this.alertDialog = new dialogs.AlertDialog(this.element_);
+ this.confirmDialog = new dialogs.ConfirmDialog(this.element_);
+ this.promptDialog = new dialogs.PromptDialog(this.element_);
+ this.shareDialog = new ShareDialog(this.element_);
+ this.defaultTaskPicker =
+ new cr.filebrowser.DefaultActionDialog(this.element_);
+ this.suggestAppsDialog = new SuggestAppsDialog(this.element_);
+};
diff --git a/chrome/browser/resources/file_manager/js/util.js b/chrome/browser/resources/file_manager/js/util.js
index 856b0b3..b049d4a 100644
--- a/chrome/browser/resources/file_manager/js/util.js
+++ b/chrome/browser/resources/file_manager/js/util.js
@@ -114,89 +114,6 @@
};
/**
- * Given a list of Entries, recurse any DirectoryEntries if |recurse| is true,
- * and call back with a list of all file and directory entries encountered
- * (including the original set).
- * @param {Array.<Entry>} entries List of entries.
- * @param {boolean} recurse Whether to recurse.
- * @param {function(Object)} successCallback Object has the fields dirEntries,
- * fileEntries and fileBytes.
- */
-util.recurseAndResolveEntries = function(entries, recurse, successCallback) {
- var pendingSubdirectories = 0;
- var pendingFiles = 0;
-
- var dirEntries = [];
- var fileEntries = [];
- var fileBytes = 0;
-
- var steps = {
- // Start operations.
- start: function() {
- for (var i = 0; i < entries.length; i++) {
- var parentPath = PathUtil.getParentDirectory(entries[i].fullPath);
- steps.tallyEntry(entries[i], parentPath);
- }
- steps.areWeThereYet();
- },
-
- // Process one entry.
- tallyEntry: function(entry, originalSourcePath) {
- entry.originalSourcePath = originalSourcePath;
- if (entry.isDirectory) {
- dirEntries.push(entry);
- if (!recurse)
- return;
- pendingSubdirectories++;
- util.forEachDirEntry(
- entry,
- function(inEntry, callback) {
- steps.tallyEntry(inEntry, originalSourcePath);
- callback();
- },
- function() {
- pendingSubdirectories--;
- steps.areWeThereYet();
- },
- function(err) {
- console.error('Failed to read dir entries at ' + entry.fullPath);
- });
- } else {
- fileEntries.push(entry);
- pendingFiles++;
- entry.getMetadata(function(metadata) {
- fileBytes += metadata.size;
- pendingFiles--;
- steps.areWeThereYet();
- });
- }
- },
-
- // We invoke this after each async callback to see if we've received all
- // the expected callbacks. If so, we're done.
- areWeThereYet: function() {
- if (!successCallback || pendingSubdirectories != 0 || pendingFiles != 0)
- return;
- var pathCompare = function(a, b) {
- if (a.fullPath > b.fullPath)
- return 1;
- if (a.fullPath < b.fullPath)
- return -1;
- return 0;
- };
- var result = {
- dirEntries: dirEntries.sort(pathCompare),
- fileEntries: fileEntries.sort(pathCompare),
- fileBytes: fileBytes
- };
- successCallback(result);
- }
- };
-
- steps.start();
-};
-
-/**
* Iterates the entries contained by dirEntry, and invokes callback once for
* each entry. On completion, successCallback will be invoked.
*
@@ -1126,6 +1043,16 @@
};
/**
+ * The type of a file operation.
+ * @enum {string}
+ */
+util.FileOperationType = {
+ COPY: 'COPY',
+ MOVE: 'MOVE',
+ ZIP: 'ZIP',
+};
+
+/**
* The type of a file operation error.
* @enum {number}
*/
diff --git a/chrome/browser/resources/file_manager/js/volume_manager.js b/chrome/browser/resources/file_manager/js/volume_manager.js
index 795033e..8f8419a 100644
--- a/chrome/browser/resources/file_manager/js/volume_manager.js
+++ b/chrome/browser/resources/file_manager/js/volume_manager.js
@@ -328,6 +328,8 @@
/**
* True, if mount points have been initialized.
+ * TODO(hidehiko): Remove this by returning the VolumeManager instance
+ * after the initialization is done.
* @type {boolean}
* @private
*/
@@ -472,10 +474,6 @@
if (this.driveEnabled == enabled)
return;
this.driveEnabled = enabled;
-
- // When drive is enabled, start to mount.
- if (enabled)
- this.mountDrive(function() {}, function() {});
};
/**
@@ -640,26 +638,6 @@
return requestType + ':' + volumeType + ':' + mountOrSourcePath;
};
-
-/**
- * @param {function(string)} successCallback Success callback.
- * @param {function(VolumeManager.Error)} errorCallback Error callback.
- */
-VolumeManager.prototype.mountDrive = function(successCallback, errorCallback) {
- if (this.driveStatus_ == VolumeManager.DriveStatus.ERROR) {
- this.setDriveStatus_(VolumeManager.DriveStatus.UNMOUNTED);
- }
- var self = this;
- this.mount_(
- '', 'drive',
- successCallback,
- function(error) {
- if (self.driveStatus_ != VolumeManager.DriveStatus.MOUNTED)
- self.setDriveStatus_(VolumeManager.DriveStatus.ERROR);
- errorCallback(error);
- });
-};
-
/**
* @param {string} fileUrl File url to the archive file.
* @param {function(string)} successCallback Success callback.
@@ -698,6 +676,28 @@
};
/**
+ * Resolve the path to its entry.
+ * @param {string} path The path to be resolved.
+ * @param {function(Entry)} successCallback Called with the resolved entry on
+ * success.
+ * @param {function(FileError)} errorCallback Called on error.
+ */
+VolumeManager.prototype.resolvePath = function(
+ path, successCallback, errorCallback) {
+ // Make sure the path is in the mounted volume.
+ var mountPath = PathUtil.isDriveBasedPath(path) ?
+ RootDirectory.DRIVE : PathUtil.getRootPath(path);
+ var volumeInfo = this.getVolumeInfo(mountPath);
+ if (!volumeInfo || !volumeInfo.root) {
+ errorCallback(util.createFileError(FileError.NOT_FOUND_ERR));
+ return;
+ }
+
+ webkitResolveLocalFileSystemURL(
+ util.makeFilesystemUrl(path), successCallback, errorCallback);
+};
+
+/**
* @param {string} mountPath Volume mounted path.
* @return {VolumeInfo} The data about the volume.
*/
diff --git a/chrome/browser/resources/file_manager/main.html b/chrome/browser/resources/file_manager/main.html
index 5b43d30..33fbf1b 100644
--- a/chrome/browser/resources/file_manager/main.html
+++ b/chrome/browser/resources/file_manager/main.html
@@ -117,6 +117,7 @@
<script src="js/text_measure.js"></script>
<script src="js/tree.css.js"></script>
<script src="js/ui/breadcrumbs_controller.js"></script>
+ <script src="js/ui/file_manager_ui.js"></script>
<script src="js/ui/preview_panel.js"></script>
<script src="js/ui/progress_center_panel.js"></script>
<script src="js/url_constants.js"></script>
diff --git a/chrome/browser/resources/history/history.js b/chrome/browser/resources/history/history.js
index e3ec452..4c7566a 100644
--- a/chrome/browser/resources/history/history.js
+++ b/chrome/browser/resources/history/history.js
@@ -1560,8 +1560,8 @@
});
}
- // Move the button to the bottom of the body.
- document.body.appendChild($('clear-browsing-data'));
+ // Move the button to the bottom of the page.
+ $('history-page').appendChild($('clear-browsing-data'));
} else {
window.addEventListener('message', function(e) {
if (e.data.method == 'frameSelected')
diff --git a/chrome/browser/resources/history/history_mobile.css b/chrome/browser/resources/history/history_mobile.css
index fdb7fbf..898fa6f 100644
--- a/chrome/browser/resources/history/history_mobile.css
+++ b/chrome/browser/resources/history/history_mobile.css
@@ -12,16 +12,17 @@
color: rgb(76, 76, 76);
height: 100%;
margin: 0;
- margin-bottom: 46px;
}
.page {
+ -webkit-flex-flow: column;
+ display: -webkit-flex;
height: 100%;
}
#scrolling-container {
+ -webkit-flex: auto; /* Container should take up extra vertical space. */
-webkit-overflow-scrolling: touch;
- height: -webkit-calc(100% - 46px);
overflow-y: auto;
}
@@ -163,13 +164,12 @@
border: 0;
border-radius: 0;
border-top: 1px solid rgb(198, 198, 198);
- bottom: 0;
box-shadow: none;
font-size: 75%;
font-weight: bold;
height: 46px;
margin: 0;
- position: fixed;
+ min-height: 46px;
text-shadow: none;
text-transform: uppercase;
width: 100%;
@@ -239,6 +239,19 @@
-webkit-box-pack: center;
display: -webkit-box;
}
+
+#scrolling-container {
+ bottom: 46px;
+ left: 0;
+ position: fixed;
+ right: 0;
+ top: 0;
+}
+
+#clear-browsing-data {
+ bottom: 0;
+ position: fixed;
+}
</if>
.entry .bookmark-section {
diff --git a/chrome/browser/resources/inspect/inspect.js b/chrome/browser/resources/inspect/inspect.js
index c3637f1..1b1d53d 100644
--- a/chrome/browser/resources/inspect/inspect.js
+++ b/chrome/browser/resources/inspect/inspect.js
@@ -372,13 +372,15 @@
}
function addWebViewDescription(row, webview) {
- var viewStatus = { visibility: 'empty', position: '', size: '' };
+ var viewStatus = { visibility: '', position: '', size: '' };
if (!webview.empty) {
- if (webview.attached)
- viewStatus.visibility = webview.visible ? 'visible' : 'hidden';
- else
+ if (webview.attached && !webview.visible)
+ viewStatus.visibility = 'hidden';
+ else if (!webview.attached)
viewStatus.visibility = 'detached';
viewStatus.size = 'size ' + webview.width + ' \u00d7 ' + webview.height;
+ } else {
+ viewStatus.visibility = 'empty';
}
if (webview.attached) {
viewStatus.position =
diff --git a/chrome/browser/resources/local_discovery/local_discovery.css b/chrome/browser/resources/local_discovery/local_discovery.css
index 0ee0c93..5296fe3 100644
--- a/chrome/browser/resources/local_discovery/local_discovery.css
+++ b/chrome/browser/resources/local_discovery/local_discovery.css
@@ -2,6 +2,23 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
+body {
+ margin: 21px 10px 24px 10px;
+}
+
+h1 {
+ margin: 0 0 13px 0;
+}
+
+h2 {
+ margin: 23px 0 0 0;
+}
+
+header {
+ border-bottom: 1px solid #eee;
+ max-width: 718px;
+}
+
.device {
margin: 23px 0;
max-width: 695px;
@@ -56,7 +73,6 @@
.controls {
border-bottom: 1px solid #eee;
max-width: 711px;
- padding: 13px 3px 7px 4px;
}
html[dir='rtl'] .controls {
@@ -73,6 +89,14 @@
}
.inline-spinner {
- position: relative;
- top: 3px;
+ position: relative;
+ top: 3px;
}
+
+.cloud-print-message {
+ margin: 23px 0;
+}
+
+section {
+ margin-bottom: 23px;
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/local_discovery/local_discovery.html b/chrome/browser/resources/local_discovery/local_discovery.html
index 423057a..1f1714a 100644
--- a/chrome/browser/resources/local_discovery/local_discovery.html
+++ b/chrome/browser/resources/local_discovery/local_discovery.html
@@ -8,7 +8,6 @@
<link rel="stylesheet" href="chrome://resources/css/overlay.css">
<link rel="stylesheet" href="chrome://resources/css/spinner.css">
<link rel="stylesheet" href="local_discovery.css">
- <link rel="stylesheet" href="../uber/uber_shared.css">
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/util.js"></script>
@@ -25,23 +24,16 @@
<div id="register-overlay" class="page">
<div class="close-button"></div>
- <div id="register-page-choose" class="register-page">
+ <div id="register-page-confirm" class="register-page">
<h1 i18n-content="confirmRegistration"></h1>
- <div id="register-message"
- i18n-content="noPrintersOnNetworkExplanation">
- </div>
- <div id="register-login-promo" class="login-promo" hidden>
- <span i18n-content="registerNeedLogin"></span>
- <button class="link-button" id="register-login-button"
- i18n-content="cloudDevicesLogin"></button>
- </div>
- <div id="register-device-picker">
- <div class="devices" id="register-device-list">
- </div>
+ <div id="register-message">
</div>
<div class="button-list">
<button class="register-cancel" i18n-content="cancel"></button>
+ <button id="register-continue-button"
+ i18n-content="serviceRegister">
+ </button>
</div>
</div>
@@ -76,22 +68,48 @@
<h1 i18n-content="devicesTitle"></h1>
</header>
- <div class="controls">
- <button id="add-printers-button" i18n-content="addPrinters"></button>
- <span id="printer-num" class="subline"
- i18n-content="printersOnNetworkZero">
- </span>
+ <div class="controls" id="printers">
+ <h2 i18n-content="availableDevicesTitle"></h2>
+
+ <div id="register-login-promo" class="login-promo cloud-print-message"
+ hidden>
+ <span i18n-content="registerNeedLogin"></span>
+ <button class="link-button" id="register-login-button"
+ i18n-content="cloudDevicesLogin"></button>
+ </div>
+ <div id="no-printers-message"
+ class="cloud-print-message"
+ i18n-content="noPrintersOnNetworkExplanation">
+ </div>
+
+ <div class="devices" id="register-device-list"></div>
+
+ <if expr="not pp_ifdef('chromeos') and not is_macosx">
+ <section id="cloud-print-connector-section">
+ <h2 i18n-content="titleConnector"></h2>
+ <div>
+ <p id="cloudPrintConnectorLabel" class="settings-row"></p>
+
+ <div class="settings-row">
+ <button id="cloudPrintConnectorSetupButton"></button>
+ </div>
+ </div>
+ </section>
+ </if>
</div>
- <div id="cloud-devices-loading" hidden>
+ <h2 i18n-content="myDevicesTitle"></h2>
+ <div id="cloud-devices-loading" class="cloud-print-message" hidden>
<div class="inline-spinner"> </div> <span i18n-content="loading"></span>
</div>
- <div id="cloud-devices-login-promo" class="login-promo" hidden>
+ <div id="cloud-devices-login-promo" class="login-promo cloud-print-message"
+ hidden>
<span i18n-content="cloudDevicesNeedLogin"></span>
<button class="link-button" id="cloud-devices-login-button"
i18n-content="cloudDevicesLogin"></button>
</div>
- <div id="cloud-devices-unavailable" hidden>
+ <div id="cloud-devices-unavailable"
+ class="cloud-print-message" hidden>
<span i18n-content="cloudDevicesUnavailable"></span>
<button class="link-button" id="cloud-devices-retry-button"
i18n-content="retryLoadCloudDevices"></button>
diff --git a/chrome/browser/resources/local_discovery/local_discovery.js b/chrome/browser/resources/local_discovery/local_discovery.js
index 7427525..ecbb4b2 100644
--- a/chrome/browser/resources/local_discovery/local_discovery.js
+++ b/chrome/browser/resources/local_discovery/local_discovery.js
@@ -12,9 +12,6 @@
* registering a device on the local network.
*/
-
-<include src="../uber/uber_utils.js" />
-
cr.define('local_discovery', function() {
'use strict';
@@ -24,6 +21,21 @@
*/
var PRINTER_MANAGEMENT_PAGE_PREFIX = '#printers/';
+ // Histogram buckets for UMA tracking.
+ /** @const */ var DEVICES_PAGE_EVENTS = {
+ OPENED: 0,
+ LOG_IN_STARTED_FROM_REGISTER_PROMO: 1,
+ LOG_IN_STARTED_FROM_DEVICE_LIST_PROMO: 2,
+ ADD_PRINTER_CLICKED: 3,
+ REGISTER_CLICKED: 4,
+ REGISTER_CONFIRMED: 5,
+ REGISTER_SUCCESS: 6,
+ REGISTER_CANCEL: 7,
+ REGISTER_FAILURE: 8,
+ MANAGE_CLICKED: 9,
+ MAX_EVENT: 10,
+ };
+
/**
* Map of service names to corresponding service objects.
* @type {Object.<string,Service>}
@@ -86,7 +98,7 @@
this.info.human_readable_name,
this.info.description,
loadTimeData.getString('serviceRegister'),
- this.register.bind(this));
+ this.showRegister.bind(this));
this.setRegisterEnabled(this.registerEnabled);
},
@@ -103,11 +115,22 @@
* Register the device.
*/
register: function() {
- recordUmaAction('DevicesPage_RegisterClicked');
+ recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_CONFIRMED);
chrome.send('registerDevice', [this.info.service_name]);
setRegisterPage('register-page-adding1');
},
/**
+ * Show registrtation UI for device.
+ */
+ showRegister: function() {
+ recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_CLICKED);
+ $('register-message').textContent = loadTimeData.getStringF(
+ 'registerConfirmMessage',
+ this.info.human_readable_name);
+ $('register-continue-button').onclick = this.register.bind(this);
+ showRegisterOverlay();
+ },
+ /**
* Set registration button enabled/disabled
*/
setRegisterEnabled: function(isEnabled) {
@@ -195,15 +218,14 @@
* Show the register overlay.
*/
function showRegisterOverlay() {
- recordUmaAction('DevicesPage_AddPrintersClicked');
+ recordUmaEvent(DEVICES_PAGE_EVENTS.ADD_PRINTER_CLICKED);
var registerOverlay = $('register-overlay');
registerOverlay.classList.add('showing');
registerOverlay.focus();
$('overlay').hidden = false;
- uber.invokeMethodOnParent('beginInterceptingEvents');
- setRegisterPage('register-page-choose');
+ setRegisterPage('register-page-confirm');
}
/**
@@ -212,7 +234,6 @@
function hideRegisterOverlay() {
$('register-overlay').classList.remove('showing');
$('overlay').hidden = true;
- uber.invokeMethodOnParent('stopInterceptingEvents');
}
/**
@@ -230,7 +251,7 @@
*/
function onRegistrationFailed() {
setRegisterPage('register-page-error');
- recordUmaAction('DevicesPage_RegisterFailure');
+ recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_FAILURE);
}
/**
@@ -320,19 +341,13 @@
*/
function updateUIToReflectState() {
var numberPrinters = $('register-device-list').children.length;
- $('printer-num').textContent = generateNumberPrintersAvailableText(
- numberPrinters);
-
if (numberPrinters == 0) {
- $('register-message').textContent = loadTimeData.getString(
- 'noPrintersOnNetworkExplanation');
+ $('no-printers-message').hidden = false;
$('register-login-promo').hidden = true;
} else {
+ $('no-printers-message').hidden = true;
$('register-login-promo').hidden = isUserLoggedIn;
-
- $('register-message').textContent = loadTimeData.getString(
- 'registerConfirmMessage');
}
}
@@ -343,7 +358,7 @@
function onRegistrationSuccess() {
hideRegisterOverlay();
requestPrinterList();
- recordUmaAction('DevicesPage_RegisterSuccess');
+ recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_SUCCESS);
}
/**
@@ -385,17 +400,19 @@
* @param {string} device_id ID of device.
*/
function manageCloudDevice(device_id) {
- recordUmaAction('DevicesPage_ManageClicked');
+ recordUmaEvent(DEVICES_PAGE_EVENTS.MANAGE_CLICKED);
chrome.send('openCloudPrintURL',
[PRINTER_MANAGEMENT_PAGE_PREFIX + device_id]);
}
/**
- * Record an action in UMA.
- * @param {string} actionDesc The name of the action to be logged.
- */
- function recordUmaAction(actionDesc) {
- chrome.send('metricsHandler:recordAction', [actionDesc]);
+ * Record an event in the UMA histogram.
+ * @param {number} eventId The id of the event to be recorded.
+ * @private
+ */
+ function recordUmaEvent(eventId) {
+ chrome.send('metricsHandler:recordInHistogram',
+ ['LocalDiscovery.DevicesPage', eventId, DEVICES_PAGE_EVENTS.MAX_EVENT]);
}
/**
@@ -404,7 +421,7 @@
function cancelRegistration() {
hideRegisterOverlay();
chrome.send('cancelRegistration');
- recordUmaAction('DevicesPage_RegisterCancel');
+ recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_CANCEL);
}
/**
@@ -443,18 +460,58 @@
}
function registerLoginButtonClicked() {
- recordUmaAction('DevicesPage_LogInStartedFromRegisterPromo');
+ recordUmaEvent(DEVICES_PAGE_EVENTS.LOG_IN_STARTED_FROM_REGISTER_PROMO);
openSignInPage();
}
function cloudDevicesLoginButtonClicked() {
- recordUmaAction('DevicesPage_LogInStartedFromDeviceListPromo');
+ recordUmaEvent(DEVICES_PAGE_EVENTS.LOG_IN_STARTED_FROM_DEVICE_LIST_PROMO);
openSignInPage();
}
- document.addEventListener('DOMContentLoaded', function() {
- uber.onContentFrameLoaded();
+ /**
+ * Set the Cloud Print proxy UI to enabled, disabled, or processing.
+ * @private
+ */
+ function setupCloudPrintConnectorSection(disabled, label, allowed) {
+ if (!cr.isChromeOS && !cr.isMac) {
+ $('cloudPrintConnectorLabel').textContent = label;
+ if (disabled || !allowed) {
+ $('cloudPrintConnectorSetupButton').textContent =
+ loadTimeData.getString('cloudPrintConnectorDisabledButton');
+ } else {
+ $('cloudPrintConnectorSetupButton').textContent =
+ loadTimeData.getString('cloudPrintConnectorEnabledButton');
+ }
+ $('cloudPrintConnectorSetupButton').disabled = !allowed;
+ if (disabled) {
+ $('cloudPrintConnectorSetupButton').onclick = function(event) {
+ // Disable the button, set its text to the intermediate state.
+ $('cloudPrintConnectorSetupButton').textContent =
+ loadTimeData.getString('cloudPrintConnectorEnablingButton');
+ $('cloudPrintConnectorSetupButton').disabled = true;
+ chrome.send('showCloudPrintSetupDialog');
+ };
+ } else {
+ $('cloudPrintConnectorSetupButton').onclick = function(event) {
+ chrome.send('disableCloudPrintConnector');
+ requestPrinterList();
+ };
+ }
+ }
+ }
+
+ function removeCloudPrintConnectorSection() {
+ if (!cr.isChromeOS && !cr.isMac) {
+ var connectorSectionElm = $('cloud-print-connector-section');
+ if (connectorSectionElm)
+ connectorSectionElm.parentNode.removeChild(connectorSectionElm);
+ }
+ }
+
+
+ document.addEventListener('DOMContentLoaded', function() {
cr.ui.overlay.setupOverlay($('overlay'));
cr.ui.overlay.globalInitialization();
$('overlay').addEventListener('cancelOverlay', cancelRegistration);
@@ -468,9 +525,6 @@
$('register-error-exit').addEventListener('click', cancelRegistration);
- $('add-printers-button').addEventListener('click',
- showRegisterOverlay);
-
$('cloud-devices-retry-button').addEventListener('click',
retryLoadCloudDevices);
@@ -486,14 +540,12 @@
document.addEventListener('webkitvisibilitychange', updateVisibility,
false);
- var title = loadTimeData.getString('devicesTitle');
- uber.invokeMethodOnParent('setTitle', {title: title});
focusManager = new LocalDiscoveryFocusManager();
focusManager.initialize();
chrome.send('start');
- recordUmaAction('DevicesPage_Opened');
+ recordUmaEvent(DEVICES_PAGE_EVENTS.OPENED);
});
return {
@@ -504,6 +556,8 @@
onCloudDeviceListAvailable: onCloudDeviceListAvailable,
onCloudDeviceListUnavailable: onCloudDeviceListUnavailable,
onDeviceCacheFlushed: onDeviceCacheFlushed,
- setUserLoggedIn: setUserLoggedIn
+ setUserLoggedIn: setUserLoggedIn,
+ setupCloudPrintConnectorSection: setupCloudPrintConnectorSection,
+ removeCloudPrintConnectorSection: removeCloudPrintConnectorSection
};
});
diff --git a/chrome/browser/resources/local_discovery/printer.png b/chrome/browser/resources/local_discovery/printer.png
index 4fc6783..563da8b 100644
--- a/chrome/browser/resources/local_discovery/printer.png
+++ b/chrome/browser/resources/local_discovery/printer.png
Binary files differ
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 0c4a066..53a1e20 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/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index d8184b7..72c4c94 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -548,45 +548,72 @@
<div class="checkbox">
<label>
<input id="sslCheckRevocation" pref="ssl.rev_checking.enabled"
- type="checkbox">
+ type="checkbox">
<span i18n-content="sslCheckRevocation"></span>
</label>
</div>
</div>
- </section>
-<if expr="not pp_ifdef('chromeos')">
- <section id="cloud-print-connector-section">
- <h3 i18n-content="advancedSectionTitleCloudPrint"></h3>
- <div>
- <p id="cloudPrintConnectorLabel" class="settings-row"
- i18n-content="cloudPrintConnectorDisabledLabel"></p>
- <div class="settings-row">
- <button id="cloudPrintConnectorSetupButton"
- i18n-content="cloudPrintConnectorDisabledButton"></button>
- <button id="cloudPrintManageButton"
- i18n-content="cloudPrintConnectorEnabledManageButton"></button>
- </div>
- </div>
- </section>
-</if>
-<if expr="pp_ifdef('chromeos')">
+ </section>
<section id="cloud-print-connector-section">
<h3 i18n-content="advancedSectionTitleCloudPrint"></h3>
- <div>
- <div>
- <span i18n-content="cloudPrintChromeosOptionLabel"></span>
- <a target="_blank" i18n-content="learnMore"
- i18n-values="href:cloudPrintLearnMoreURL"></a>
- </div>
+<if expr="pp_ifdef('enable_mdns')">
+ <div id="cloudprint-options-mdns" hidden>
<div class="settings-row">
+ <span i18n-content="cloudPrintOptionLabel"></span>
+ <a target="_blank" i18n-content="learnMore"
+ i18n-values="href:cloudPrintLearnMoreURL"></a>
+ </div>
+ <button id="cloudPrintDevicesPageButton"
+ i18n-content="cloudPrintDevicesPageButton">
+ </button>
+
+ <div class="checkbox">
+ <span class="controlled-setting-with-label">
+ <input id="local-discovery-notifications-enabled"
+ pref="local_discovery.notifications_enabled"
+ type="checkbox"
+ metric="LocalDiscoveryNotificationsDisabled_Settings" />
+ <span>
+ <label for="local-discovery-notifications-enabled"
+ i18n-content="cloudPrintEnableNotificationsLabel">
+ </label>
+ <span class="controlled-setting-indicator"
+ pref="local_discovery.notifications_enabled">
+ </span>
+ </span>
+ </div>
+ </div>
+</if>
+
+ <div id="cloudprint-options-nomdns">
+<if expr="pp_ifdef('chromeos')">
+ <div>
+ <span i18n-content="cloudPrintOptionLabel"></span>
+ <a target="_blank" i18n-content="learnMore"
+ i18n-values="href:cloudPrintLearnMoreURL"></a>
+ </div>
+</if>
+
+<if expr="not pp_ifdef('chromeos')">
+ <p id="cloudPrintConnectorLabel" class="settings-row"
+ i18n-content="cloudPrintConnectorDisabledLabel"></p>
+</if>
+
+ <div class="settings-row">
+<if expr="not pp_ifdef('chromeos')">
+ <button id="cloudPrintConnectorSetupButton"
+ i18n-content="cloudPrintConnectorDisabledButton"></button>
+</if>
+
<button id="cloudPrintManageButton"
- i18n-content="cloudPrintChromeosOptionButton"></button>
+ i18n-content="cloudPrintManageButton">
+ </button>
</div>
</div>
</section>
+
<if expr="pp_ifdef('chromeos')">
<include src="startup_section.html">
-</if>
<section>
<h3 i18n-content="accessibilityTitle"></h3>
<div class="option-control-table">
@@ -606,7 +633,7 @@
</label>
<span class="controlled-setting-indicator"
pref="settings.a11y.enable_menu">
- </span>
+ </span>
</span>
</div>
</div>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 230d0e1..133720a 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -415,6 +415,14 @@
chrome.send('showCloudPrintManagePage');
};
+ if (loadTimeData.getBoolean('cloudPrintShowMDnsOptions')) {
+ $('cloudprint-options-mdns').hidden = false;
+ $('cloudprint-options-nomdns').hidden = true;
+ $('cloudPrintDevicesPageButton').onclick = function() {
+ chrome.send('showCloudPrintDevicesPage');
+ };
+ }
+
// Accessibility section (CrOS only).
if (cr.isChromeOS) {
$('accessibility-spoken-feedback-check').onchange = function(event) {
diff --git a/chrome/browser/resources/options/import_data_overlay.js b/chrome/browser/resources/options/import_data_overlay.js
index cb3ba64..c09b1d3 100644
--- a/chrome/browser/resources/options/import_data_overlay.js
+++ b/chrome/browser/resources/options/import_data_overlay.js
@@ -99,6 +99,7 @@
for (var i = 0; i < checkboxes.length; i++)
this.setUpCheckboxState_(checkboxes[i], enabled);
$('import-data-commit').disabled = !enabled;
+ $('import-choose-file').hidden = !enabled;
$('mac-password-keychain').hidden = !enabled;
},
@@ -225,17 +226,17 @@
/**
* Update the UI to reflect whether an import operation is in progress.
- * @param {boolean} state True if an import operation is in progress.
+ * @param {boolean} importing True if an import operation is in progress.
*/
- ImportDataOverlay.setImportingState = function(state) {
+ ImportDataOverlay.setImportingState = function(importing) {
var checkboxes =
document.querySelectorAll('#import-checkboxes input[type=checkbox]');
for (var i = 0; i < checkboxes.length; i++)
checkboxes[i].setDisabled('Importing', state);
- if (!state)
+ if (!importing)
ImportDataOverlay.getInstance().updateCheckboxes_();
- $('import-browsers').disabled = state;
- $('import-throbber').style.visibility = state ? 'visible' : 'hidden';
+ $('import-browsers').disabled = importing;
+ $('import-throbber').style.visibility = importing ? 'visible' : 'hidden';
ImportDataOverlay.getInstance().validateCommitButton_();
};
diff --git a/chrome/browser/resources/options/language_options.js b/chrome/browser/resources/options/language_options.js
index 440da0a..41258c5 100644
--- a/chrome/browser/resources/options/language_options.js
+++ b/chrome/browser/resources/options/language_options.js
@@ -398,10 +398,10 @@
if (cr.isWindows || cr.isChromeOS)
this.updateUiLanguageButton_(languageCode);
- if (!cr.isMac) {
- this.updateSelectedLanguageName_(languageCode);
+ this.updateSelectedLanguageName_(languageCode);
+
+ if (!cr.isMac)
this.updateSpellCheckLanguageButton_(languageCode);
- }
if (cr.isChromeOS)
this.updateInputMethodList_(languageCode);
diff --git a/chrome/browser/resources/options/manage_profile_overlay.js b/chrome/browser/resources/options/manage_profile_overlay.js
index 3a49c55..154d261 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.js
+++ b/chrome/browser/resources/options/manage_profile_overlay.js
@@ -337,7 +337,7 @@
var isManaged = $('create-profile-managed').checked;
var existingManagedUserId = '';
- // 'createProfile' is handled by the BrowserOptionsHandler.
+ // 'createProfile' is handled by the CreateProfileHandler.
chrome.send('createProfile',
[name, iconUrl, createShortcut,
isManaged, existingManagedUserId]);
diff --git a/chrome/browser/resources/options/managed_user_import.js b/chrome/browser/resources/options/managed_user_import.js
index f404ea7..fef05b9 100644
--- a/chrome/browser/resources/options/managed_user_import.js
+++ b/chrome/browser/resources/options/managed_user_import.js
@@ -58,7 +58,7 @@
OptionsPage.closeOverlay();
self.updateImportInProgress_(false);
- // 'cancelCreateProfile' is handled by BrowserOptionsHandler.
+ // 'cancelCreateProfile' is handled by CreateProfileHandler.
chrome.send('cancelCreateProfile');
};
@@ -116,7 +116,7 @@
this.updateImportInProgress_(true);
- // 'createProfile' is handled by BrowserOptionsHandler.
+ // 'createProfile' is handled by CreateProfileHandler.
chrome.send('createProfile', [managedUser.name, avatarUrl,
false, true, managedUser.id]);
},
diff --git a/chrome/browser/resources/plugin_metadata/plugins_mac.json b/chrome/browser/resources/plugin_metadata/plugins_mac.json
index 85de8e1..ed4eab0 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_mac.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_mac.json
@@ -1,5 +1,5 @@
{
- "x-version": 3,
+ "x-version": 4,
"google-talk": {
"mime_types": [
],
@@ -273,5 +273,37 @@
],
"name": "Chrome PDF Viewer",
"group_name_matcher": "*Chrome PDF Viewer*"
+ },
+ "facebook-video-calling": {
+ "mime_types": [
+ "application/skypesdk-plugin"
+ ],
+ "versions": [
+ {
+ "version": "0",
+ "status": "up_to_date",
+ "comment": "We do not track version information for the Facebook Video Calling Plugin."
+ }
+ ],
+ "lang": "en-US",
+ "name": "Facebook Video Calling",
+ "url": "https://www.facebook.com/chat/video/videocalldownload.php",
+ "group_name_matcher": "*Facebook Video*"
+ },
+ "google-earth": {
+ "mime_types": [
+ "application/geplugin"
+ ],
+ "versions": [
+ {
+ "version": "0",
+ "status": "up_to_date",
+ "comment": "We do not track version information for the Google Earth Plugin."
+ }
+ ],
+ "lang": "en-US",
+ "name": "Google Earth",
+ "url": "http://www.google.com/earth/explore/products/plugin.html",
+ "group_name_matcher": "*Google Earth*"
}
}
diff --git a/chrome/browser/resources/plugin_metadata/plugins_win.json b/chrome/browser/resources/plugin_metadata/plugins_win.json
index 0cc937d..5bdbc8d 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_win.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_win.json
@@ -1,5 +1,5 @@
{
- "x-version": 9,
+ "x-version": 10,
"google-talk": {
"mime_types": [
],
@@ -384,5 +384,37 @@
],
"name": "Google Update",
"group_name_matcher": "Google Update"
+ },
+ "facebook-video-calling": {
+ "mime_types": [
+ "application/skypesdk-plugin"
+ ],
+ "versions": [
+ {
+ "version": "0",
+ "status": "up_to_date",
+ "comment": "We do not track version information for the Facebook Video Calling Plugin."
+ }
+ ],
+ "lang": "en-US",
+ "name": "Facebook Video Calling",
+ "url": "https://www.facebook.com/chat/video/videocalldownload.php",
+ "group_name_matcher": "*Facebook Video*"
+ },
+ "google-earth": {
+ "mime_types": [
+ "application/geplugin"
+ ],
+ "versions": [
+ {
+ "version": "0",
+ "status": "up_to_date",
+ "comment": "We do not track version information for the Google Earth Plugin."
+ }
+ ],
+ "lang": "en-US",
+ "name": "Google Earth",
+ "url": "http://www.google.com/earth/explore/products/plugin.html",
+ "group_name_matcher": "*Google Earth*"
}
}
diff --git a/chrome/browser/resources/quick_office/manifest_editor.json b/chrome/browser/resources/quick_office/manifest_editor.json
index 8eaaf83..23cea37 100644
--- a/chrome/browser/resources/quick_office/manifest_editor.json
+++ b/chrome/browser/resources/quick_office/manifest_editor.json
@@ -58,6 +58,8 @@
"name": "Quickoffice (Beta)",
"offline_enabled": true,
"permissions": [
+ "clipboardRead",
+ "clipboardWrite",
"fileBrowserHandler",
"fileSystem",
"fileSystem.write",
@@ -79,7 +81,7 @@
"sub_package_path": "_platform_specific/arm/"
}
],
- "version": "31.89.1353",
+ "version": "31.90.1387.1",
"web_accessible_resources": [
"views/qowt.html"
]
diff --git a/chrome/browser/resources/quick_office/manifest_viewing.json b/chrome/browser/resources/quick_office/manifest_viewing.json
index d067c46..2759ca8 100644
--- a/chrome/browser/resources/quick_office/manifest_viewing.json
+++ b/chrome/browser/resources/quick_office/manifest_viewing.json
@@ -57,6 +57,8 @@
"name": "Chrome Office Viewer (Beta)",
"offline_enabled": true,
"permissions": [
+ "clipboardRead",
+ "clipboardWrite",
"fileBrowserHandler",
"fileSystem",
"fileSystem.write",
@@ -78,7 +80,7 @@
"sub_package_path": "_platform_specific/arm/"
}
],
- "version": "31.89.1353",
+ "version": "31.90.1387.1",
"web_accessible_resources": [
"views/qowt.html"
]
diff --git a/chrome/browser/safe_browsing/database_manager.cc b/chrome/browser/safe_browsing/database_manager.cc
index fa4c296..5e3522d 100644
--- a/chrome/browser/safe_browsing/database_manager.cc
+++ b/chrome/browser/safe_browsing/database_manager.cc
@@ -521,6 +521,14 @@
}
}
+void SafeBrowsingDatabaseManager::NotifyDatabaseUpdateFinished(
+ bool update_succeeded) {
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
+ content::Source<SafeBrowsingDatabaseManager>(this),
+ content::Details<bool>(&update_succeeded));
+}
+
SafeBrowsingDatabaseManager::QueuedCheck::QueuedCheck(
const safe_browsing_util::ListType check_type,
Client* client,
@@ -859,14 +867,6 @@
this, update_succeeded));
}
-void SafeBrowsingDatabaseManager::NotifyDatabaseUpdateFinished(
- bool update_succeeded) {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
- content::Source<SafeBrowsingDatabaseManager>(this),
- content::Details<bool>(&update_succeeded));
-}
-
void SafeBrowsingDatabaseManager::OnCloseDatabase() {
DCHECK_EQ(base::MessageLoop::current(),
safe_browsing_thread_->message_loop());
diff --git a/chrome/browser/safe_browsing/database_manager.h b/chrome/browser/safe_browsing/database_manager.h
index 25b7f5a..ed17f5a 100644
--- a/chrome/browser/safe_browsing/database_manager.h
+++ b/chrome/browser/safe_browsing/database_manager.h
@@ -210,6 +210,9 @@
protected:
virtual ~SafeBrowsingDatabaseManager();
+ // protected for tests.
+ void NotifyDatabaseUpdateFinished(bool update_succeeded);
+
private:
friend class base::RefCountedThreadSafe<SafeBrowsingDatabaseManager>;
friend class SafeBrowsingServerTest;
@@ -295,8 +298,6 @@
void DatabaseUpdateFinished(bool update_succeeded);
- void NotifyDatabaseUpdateFinished(bool update_succeeded);
-
// Called on the db thread to close the database. See CloseDatabase().
void OnCloseDatabase();
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index 241675e..2cfbd67 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -63,31 +63,23 @@
"http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=%s&client=chromium";
#endif
-const char* const kSbReportPhishingErrorUrl =
+const char kSbReportPhishingErrorUrl[] =
"http://www.google.com/safebrowsing/report_error/";
// URL for the "Learn more" link on the multi threat malware blocking page.
-const char* const kLearnMoreMalwareUrl =
+const char kLearnMoreMalwareUrl[] =
"https://www.google.com/support/bin/answer.py?answer=45449&topic=360"
"&sa=X&oi=malwarewarninglink&resnum=1&ct=help";
-const char* const kLearnMoreMalwareUrlV2 =
+const char kLearnMoreMalwareUrlV2[] =
"https://www.google.com/goodtoknow/online-safety/malware/";
-const char* const kLearnMorePhishingUrlV2 =
+const char kLearnMorePhishingUrlV2[] =
"https://www.google.com/goodtoknow/online-safety/phishing/";
// URL for the "Learn more" link on the phishing blocking page.
-const char* const kLearnMorePhishingUrl =
+const char kLearnMorePhishingUrl[] =
"https://www.google.com/support/bin/answer.py?answer=106318";
-const char* const kSbDiagnosticHtml =
- "<a href=\"\" onclick=\"sendCommand('showDiagnostic'); return false;\" "
- "onmousedown=\"return false;\">%s</a>";
-
-const char* const kPLinkHtml =
- "<a href=\"\" onclick=\"sendCommand('proceed'); return false;\" "
- "onmousedown=\"return false;\">%s</a>";
-
-const char* const kPrivacyLinkHtml =
+const char kPrivacyLinkHtml[] =
"<a id=\"privacy-link\" href=\"\" onclick=\"sendCommand('showPrivacy'); "
"return false;\" onmousedown=\"return false;\">%s</a>";
@@ -98,43 +90,37 @@
const int64 kMalwareDetailsProceedDelayMilliSeconds = 3000;
// The commands returned by the page when the user performs an action.
-const char* const kShowDiagnosticCommand = "showDiagnostic";
-const char* const kReportErrorCommand = "reportError";
-const char* const kLearnMoreCommand = "learnMore";
-const char* const kLearnMoreCommandV2 = "learnMore2";
-const char* const kShowPrivacyCommand = "showPrivacy";
-const char* const kProceedCommand = "proceed";
-const char* const kTakeMeBackCommand = "takeMeBack";
-const char* const kDoReportCommand = "doReport";
-const char* const kDontReportCommand = "dontReport";
-const char* const kDisplayCheckBox = "displaycheckbox";
-const char* const kBoxChecked = "boxchecked";
-const char* const kExpandedSeeMore = "expandedSeeMore";
+const char kShowDiagnosticCommand[] = "showDiagnostic";
+const char kReportErrorCommand[] = "reportError";
+const char kLearnMoreCommand[] = "learnMore";
+const char kLearnMoreCommandV2[] = "learnMore2";
+const char kShowPrivacyCommand[] = "showPrivacy";
+const char kProceedCommand[] = "proceed";
+const char kTakeMeBackCommand[] = "takeMeBack";
+const char kDoReportCommand[] = "doReport";
+const char kDontReportCommand[] = "dontReport";
+const char kDisplayCheckBox[] = "displaycheckbox";
+const char kBoxChecked[] = "boxchecked";
+const char kExpandedSeeMore[] = "expandedSeeMore";
// Special command that we use when the user navigated away from the
// page. E.g., closed the tab or the window. This is only used by
// RecordUserReactionTime.
-const char* const kNavigatedAwayMetaCommand = "closed";
+const char kNavigatedAwayMetaCommand[] = "closed";
base::LazyInstance<SafeBrowsingBlockingPage::UnsafeResourceMap>
g_unsafe_resource_map = LAZY_INSTANCE_INITIALIZER;
// These are the conditions for the summer 2013 Finch experiment.
-const char* const kMalwareStudyName = "InterstitialMalware310";
-const char* const kPhishingStudyName = "InterstitialPhishing564";
-const char* const kCond1MalwareControl = "cond1MalwareControl";
-const char* const kCond2MalwareNoBrand = "cond2MalwareNoBrand";
-const char* const kCond3PhishingControl = "cond3PhishingControl";
-const char* const kCond4PhishingNoBrand = "cond4PhishingNoBrand";
-const char* const kCond5MalwareOneStep = "cond5MalwareOneStep";
-const char* const kCond6PhishingOneStep = "cond6PhishingOneStep";
-const char* const kCond7MalwareFearMsg = "cond7MalwareFearMsg";
-const char* const kCond8PhishingFearMsg = "cond8PhishingFearMsg";
-const char* const kCond9MalwareCollabMsg = "cond9MalwareCollabMsg";
-const char* const kCond10PhishingCollabMsg = "cond10PhishingCollabMsg";
-const char* const kCond11MalwareQuestion = "cond11MalwareQuestion";
-const char* const kCond12PhishingQuestion = "cond12PhishingQuestion";
-const char* const kCond13MalwareGoBack = "cond13MalwareGoBack";
-const char* const kCond14PhishingGoBack = "cond14PhishingGoBack";
+const char kMalwareStudyName[] = "InterstitialMalware310";
+const char kPhishingStudyName[] = "InterstitialPhishing564";
+const char kCond7MalwareFearMsg[] = "cond7MalwareFearMsg";
+const char kCond8PhishingFearMsg[] = "cond8PhishingFearMsg";
+const char kCond9MalwareCollabMsg[] = "cond9MalwareCollabMsg";
+const char kCond10PhishingCollabMsg[] = "cond10PhishingCollabMsg";
+const char kCond11MalwareQuestion[] = "cond11MalwareQuestion";
+const char kCond12PhishingQuestion[] = "cond12PhishingQuestion";
+const char kCond13MalwareGoBack[] = "cond13MalwareGoBack";
+const char kCond14PhishingGoBack[] = "cond14PhishingGoBack";
} // namespace
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc
index b193f50..04aebf1 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -230,8 +230,11 @@
// list ids then |list_ranges| must contain two elements.
void GetChunkRanges(const std::vector<int>& chunks,
std::vector<std::string>* list_ranges) {
- DCHECK_GT(list_ranges->size(), 0U);
- DCHECK_LE(list_ranges->size(), 2U);
+ // Since there are 2 possible list ids, there must be exactly two
+ // list ranges. Even if the chunk data should only contain one
+ // line, this code has to somehow handle corruption.
+ DCHECK_EQ(2U, list_ranges->size());
+
std::vector<std::vector<int> > decoded_chunks(list_ranges->size());
for (std::vector<int>::const_iterator iter = chunks.begin();
iter != chunks.end(); ++iter) {
@@ -257,8 +260,11 @@
store->GetAddChunks(&add_chunks);
store->GetSubChunks(&sub_chunks);
- std::vector<std::string> adds(listnames.size());
- std::vector<std::string> subs(listnames.size());
+ // Always decode 2 ranges, even if only the first one is expected.
+ // The loop below will only load as many into |lists| as |listnames|
+ // indicates.
+ std::vector<std::string> adds(2);
+ std::vector<std::string> subs(2);
GetChunkRanges(add_chunks, &adds);
GetChunkRanges(sub_chunks, &subs);
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index cf455ce..1a3a5fb 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -463,7 +463,6 @@
const char kEmptyPage[] = "files/empty.html";
const char kMalwareFile[] = "files/downloads/dangerous/dangerous.exe";
-const char kMalwareIframe[] = "files/safe_browsing/malware_iframe.html";
const char kMalwarePage[] = "files/safe_browsing/malware.html";
// This test goes through DownloadResourceHandler.
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
index 3470736..48f6d28 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
@@ -13,9 +13,6 @@
namespace {
-const base::FilePath::CharType kFolderPrefix[] =
- FILE_PATH_LITERAL("SafeBrowsingTestStoreFile");
-
class SafeBrowsingStoreFileTest : public PlatformTest {
public:
virtual void SetUp() {
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.cc b/chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.cc
index 48f5e80..ce47b93 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.cc
@@ -15,7 +15,6 @@
// Disjoint chunk numbers for subs to flush out typos.
const int kSubChunk1 = 2;
const int kSubChunk2 = 4;
-const int kSubChunk3 = 6;
const SBFullHash kHash1 = SBFullHashFromString("one");
const SBFullHash kHash2 = SBFullHashFromString("two");
diff --git a/chrome/browser/screensaver_window_finder_x11.cc b/chrome/browser/screensaver_window_finder_x11.cc
index f78079f..ddd6628 100644
--- a/chrome/browser/screensaver_window_finder_x11.cc
+++ b/chrome/browser/screensaver_window_finder_x11.cc
@@ -4,12 +4,8 @@
#include "chrome/browser/screensaver_window_finder_x11.h"
-#if defined(TOOLKIT_GTK)
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#endif
-
#include "base/basictypes.h"
+#include "ui/base/x/x11_error_tracker.h"
#include "ui/base/x/x11_util.h"
ScreensaverWindowFinder::ScreensaverWindowFinder()
@@ -17,16 +13,10 @@
}
bool ScreensaverWindowFinder::ScreensaverWindowExists() {
-#if defined(TOOLKIT_GTK)
- gdk_error_trap_push();
-#endif
+ ui::X11ErrorTracker err_tracker;
ScreensaverWindowFinder finder;
ui::EnumerateTopLevelWindows(&finder);
- bool got_error = false;
-#if defined(TOOLKIT_GTK)
- got_error = gdk_error_trap_pop();
-#endif
- return finder.exists_ && !got_error;
+ return finder.exists_ && !err_tracker.FoundNewError();
}
bool ScreensaverWindowFinder::ShouldStopIterating(XID window) {
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc
index 62e8580..c50d271 100644
--- a/chrome/browser/search/instant_service.cc
+++ b/chrome/browser/search/instant_service.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/logging.h"
+#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/history_notifications.h"
@@ -19,18 +20,25 @@
#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_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/webui/favicon_source.h"
#include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
#include "chrome/browser/ui/webui/theme_source.h"
+#include "chrome/common/pref_names.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/notification_types.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/url_data_source.h"
#include "grit/theme_resources.h"
+#include "net/base/net_util.h"
#include "net/url_request/url_request.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/image/image_skia.h"
@@ -57,7 +65,7 @@
InstantService::InstantService(Profile* profile)
: profile_(profile),
- ntp_prerenderer_(profile, profile->GetPrefs()),
+ ntp_prerenderer_(profile, this, profile->GetPrefs()),
browser_instant_controller_object_count_(0),
weak_ptr_factory_(this) {
// Stub for unit tests.
@@ -90,15 +98,25 @@
content::Source<ThemeService>(
ThemeServiceFactory::GetForProfile(profile_)));
- content::URLDataSource::Add(profile, new ThemeSource(profile));
+ content::URLDataSource::Add(profile_, new ThemeSource(profile_));
#endif // defined(ENABLE_THEMES)
- content::URLDataSource::Add(profile, new ThumbnailSource(profile, false));
- content::URLDataSource::Add(profile, new ThumbnailSource(profile, true));
- content::URLDataSource::Add(profile, new FaviconSource(
- profile, FaviconSource::FAVICON));
- content::URLDataSource::Add(profile, new LocalNtpSource(profile));
- content::URLDataSource::Add(profile, new MostVisitedIframeSource());
+
+ content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, false));
+ content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, true));
+ content::URLDataSource::Add(
+ profile_, new FaviconSource(profile_, FaviconSource::FAVICON));
+ content::URLDataSource::Add(profile_, new LocalNtpSource(profile_));
+ content::URLDataSource::Add(profile_, new MostVisitedIframeSource());
+
+ profile_pref_registrar_.Init(profile_->GetPrefs());
+ profile_pref_registrar_.Add(
+ prefs::kDefaultSearchProviderID,
+ base::Bind(&InstantService::OnDefaultSearchProviderChanged,
+ base::Unretained(this)));
+
+ registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_URL_UPDATED,
+ content::Source<Profile>(profile_->GetOriginalProfile()));
registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
content::Source<Profile>(profile_));
}
@@ -195,7 +213,7 @@
++browser_instant_controller_object_count_;
if (browser_instant_controller_object_count_ == 1)
- ntp_prerenderer_.PreloadInstantNTP();
+ ntp_prerenderer_.ReloadInstantNTP();
}
void InstantService::OnBrowserInstantControllerDestroyed() {
@@ -255,6 +273,12 @@
ntp_prerenderer_.DeleteNTPContents();
break;
}
+ case chrome::NOTIFICATION_GOOGLE_URL_UPDATED: {
+ OnGoogleURLUpdated(
+ content::Source<Profile>(source).ptr(),
+ content::Details<GoogleURLTracker::UpdatedDetails>(details).ptr());
+ break;
+ }
default:
NOTREACHED() << "Unexpected notification type in InstantService.";
}
@@ -391,6 +415,44 @@
ThemeInfoChanged(*theme_info_));
}
+void InstantService::OnGoogleURLUpdated(
+ Profile* profile,
+ GoogleURLTracker::UpdatedDetails* details) {
+ GURL last_prompted_url(
+ profile->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL));
+
+ // See GoogleURLTracker::OnURLFetchComplete().
+ // last_prompted_url.is_empty() indicates very first run of Chrome. So there
+ // is no need to notify, as there won't be any old state.
+ if (last_prompted_url.is_empty())
+ return;
+
+ // Only the scheme changed. Ignore it since we do not prompt the user in this
+ // case.
+ if (net::StripWWWFromHost(details->first) ==
+ net::StripWWWFromHost(details->second))
+ return;
+
+ FOR_EACH_OBSERVER(InstantServiceObserver, observers_, GoogleURLUpdated());
+}
+
+void InstantService::OnDefaultSearchProviderChanged(
+ const std::string& pref_name) {
+ DCHECK_EQ(pref_name, std::string(prefs::kDefaultSearchProviderID));
+ const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile(
+ profile_)->GetDefaultSearchProvider();
+ if (!template_url) {
+ // A NULL |template_url| could mean either this notification is sent during
+ // the browser start up operation or the user now has no default search
+ // provider. There is no way for the user to reach this state using the
+ // Chrome settings. Only explicitly poking at the DB or bugs in the Sync
+ // could cause that, neither of which we support.
+ return;
+ }
+ FOR_EACH_OBSERVER(
+ InstantServiceObserver, observers_, DefaultSearchProviderChanged());
+}
+
InstantNTPPrerenderer* InstantService::ntp_prerenderer() {
return &ntp_prerenderer_;
}
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h
index f8c88e5..f876c4a 100644
--- a/chrome/browser/search/instant_service.h
+++ b/chrome/browser/search/instant_service.h
@@ -17,6 +17,8 @@
#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 "chrome/browser/google/google_url_tracker.h"
#include "chrome/browser/history/history_types.h"
#include "chrome/browser/ui/search/instant_ntp_prerenderer.h"
#include "chrome/common/instant_types.h"
@@ -25,10 +27,8 @@
#include "content/public/browser/notification_registrar.h"
class GURL;
-class InstantExtendedTest;
class InstantIOContext;
class InstantServiceObserver;
-class InstantTestBase;
class Profile;
class ThemeService;
@@ -104,7 +104,9 @@
private:
friend class InstantExtendedTest;
+ friend class InstantServiceTest;
friend class InstantTestBase;
+ friend class InstantUnitTestBase;
FRIEND_TEST_ALL_PREFIXES(InstantExtendedNetworkTest,
NTPReactsToNetworkChanges);
@@ -133,6 +135,11 @@
// Theme changed notification handler.
void OnThemeChanged(ThemeService* theme_service);
+ void OnGoogleURLUpdated(Profile* profile,
+ GoogleURLTracker::UpdatedDetails* details);
+
+ void OnDefaultSearchProviderChanged(const std::string& pref_name);
+
// Used by tests.
InstantNTPPrerenderer* ntp_prerenderer();
@@ -151,6 +158,8 @@
content::NotificationRegistrar registrar_;
+ PrefChangeRegistrar profile_pref_registrar_;
+
scoped_refptr<InstantIOContext> instant_io_context_;
InstantNTPPrerenderer ntp_prerenderer_;
diff --git a/chrome/browser/search/instant_service_observer.cc b/chrome/browser/search/instant_service_observer.cc
new file mode 100644
index 0000000..02e8856
--- /dev/null
+++ b/chrome/browser/search/instant_service_observer.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/browser/search/instant_service_observer.h"
+
+void InstantServiceObserver::ThemeInfoChanged(const ThemeBackgroundInfo&) {
+}
+
+void InstantServiceObserver::MostVisitedItemsChanged(
+ const std::vector<InstantMostVisitedItem>&) {
+}
+
+void InstantServiceObserver::DefaultSearchProviderChanged() {
+}
+
+void InstantServiceObserver::GoogleURLUpdated() {
+}
diff --git a/chrome/browser/search/instant_service_observer.h b/chrome/browser/search/instant_service_observer.h
index c282c93..7d88b1a 100644
--- a/chrome/browser/search/instant_service_observer.h
+++ b/chrome/browser/search/instant_service_observer.h
@@ -14,11 +14,19 @@
class InstantServiceObserver {
public:
// Indicates that the user's custom theme has changed in some way.
- virtual void ThemeInfoChanged(const ThemeBackgroundInfo&) = 0;
+ virtual void ThemeInfoChanged(const ThemeBackgroundInfo&);
// Indicates that the most visited items has changed.
virtual void MostVisitedItemsChanged(
- const std::vector<InstantMostVisitedItem>&) = 0;
+ const std::vector<InstantMostVisitedItem>&);
+
+ // Indicates that the default search provider changed.
+ virtual void DefaultSearchProviderChanged();
+
+ // Indicates that the Google URL has changed as a result of searchdomaincheck.
+ // Note that the search domain change triggers a yellow infobar at the top of
+ // the page, and the actual change is triggered after the user accepts.
+ virtual void GoogleURLUpdated();
protected:
virtual ~InstantServiceObserver() {}
diff --git a/chrome/browser/search/instant_service_unittest.cc b/chrome/browser/search/instant_service_unittest.cc
new file mode 100644
index 0000000..1ae497e
--- /dev/null
+++ b/chrome/browser/search/instant_service_unittest.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 <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/search/instant_service.h"
+#include "chrome/browser/search/instant_service_observer.h"
+#include "chrome/browser/search/instant_unittest_base.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/host_desktop.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace chrome {
+
+namespace {
+
+class MockInstantServiceObserver : public InstantServiceObserver {
+ public:
+ MOCK_METHOD0(DefaultSearchProviderChanged, void());
+ MOCK_METHOD0(GoogleURLUpdated, void());
+};
+
+class MockWebContentsObserver : public content::WebContentsObserver {
+ public:
+ MOCK_METHOD1(WebContentsDestroyed, void(content::WebContents*));
+
+ // Dumb override to make MSVC happy.
+ void Observe_(content::WebContents* contents) {
+ content::WebContentsObserver::Observe(contents);
+ }
+
+ protected:
+ friend class InstantServiceTest;
+ FRIEND_TEST_ALL_PREFIXES(InstantServiceTest,
+ DispatchDefaultSearchProviderChanged);
+ FRIEND_TEST_ALL_PREFIXES(InstantServiceTest, DispatchGoogleURLUpdated);
+};
+
+class InstantServiceTest : public InstantUnitTestBase {
+ protected:
+ virtual void SetUp() OVERRIDE {
+ InstantUnitTestBase::SetUp();
+
+ instant_service_observer_.reset(new MockInstantServiceObserver());
+ instant_service_->AddObserver(instant_service_observer_.get());
+
+ instant_ntp_contents_observer_.reset(new MockWebContentsObserver());
+ instant_ntp_contents_observer_->Observe_(
+ instant_service_->GetNTPContents());
+ }
+
+ virtual void TearDown() OVERRIDE {
+ instant_service_->RemoveObserver(instant_service_observer_.get());
+ instant_ntp_contents_observer_->Observe_(NULL);
+ InstantUnitTestBase::TearDown();
+ }
+
+ scoped_ptr<MockInstantServiceObserver> instant_service_observer_;
+ scoped_ptr<MockWebContentsObserver> instant_ntp_contents_observer_;
+};
+
+TEST_F(InstantServiceTest, DispatchDefaultSearchProviderChanged) {
+ EXPECT_CALL(*instant_service_observer_.get(), DefaultSearchProviderChanged())
+ .Times(1);
+ EXPECT_CALL(*instant_ntp_contents_observer_.get(),
+ WebContentsDestroyed(instant_service_->GetNTPContents()))
+ .Times(1);
+
+ GURL ntp_url = instant_service_->GetNTPContents()->GetURL();
+ const std::string& new_base_url = "https://bar.com/";
+ SetDefaultSearchProvider(new_base_url);
+ GURL new_ntp_url = instant_service_->GetNTPContents()->GetURL();
+ EXPECT_NE(ntp_url, new_ntp_url);
+ EXPECT_TRUE(StartsWithASCII(new_ntp_url.spec(), new_base_url, true));
+}
+
+TEST_F(InstantServiceTest, DispatchGoogleURLUpdated) {
+ EXPECT_CALL(*instant_service_observer_.get(), GoogleURLUpdated()).Times(1);
+ EXPECT_CALL(*instant_ntp_contents_observer_.get(),
+ WebContentsDestroyed(instant_service_->GetNTPContents()))
+ .Times(1);
+
+ GURL ntp_url = instant_service_->GetNTPContents()->GetURL();
+ const std::string& new_base_url = "https://www.google.es/";
+ NotifyGoogleBaseURLUpdate(new_base_url);
+ GURL new_ntp_url = instant_service_->GetNTPContents()->GetURL();
+ EXPECT_NE(ntp_url, new_ntp_url);
+ EXPECT_TRUE(StartsWithASCII(new_ntp_url.spec(), new_base_url, true));
+}
+
+} // namespace
+
+} // namespace chrome
diff --git a/chrome/browser/search/instant_unittest_base.cc b/chrome/browser/search/instant_unittest_base.cc
new file mode 100644
index 0000000..1842ac3
--- /dev/null
+++ b/chrome/browser/search/instant_unittest_base.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/search/instant_unittest_base.h"
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/google/google_url_tracker.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"
+#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"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/testing_pref_service_syncable.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+
+void InstantUnitTestBase::SetUp() {
+ chrome::EnableInstantExtendedAPIForTesting();
+ BrowserWithTestWindowTest::SetUp();
+
+ TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+ profile(), &TemplateURLServiceFactory::BuildInstanceFor);
+ template_url_service_ = TemplateURLServiceFactory::GetForProfile(profile());
+ ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service_);
+
+ UIThreadSearchTermsData::SetGoogleBaseURL("https://www.google.com/");
+ TestingPrefServiceSyncable* pref_service = profile()->GetTestingPrefService();
+ pref_service->SetUserPref(prefs::kLastPromptedGoogleURL,
+ new base::StringValue("https://www.google.com/"));
+ SetDefaultSearchProvider("{google:baseURL}");
+ instant_service_ = InstantServiceFactory::GetForProfile(profile());
+}
+
+void InstantUnitTestBase::TearDown() {
+ UIThreadSearchTermsData::SetGoogleBaseURL("");
+ BrowserWithTestWindowTest::TearDown();
+}
+
+void InstantUnitTestBase::SetDefaultSearchProvider(
+ const std::string& base_url) {
+ TemplateURLData data;
+ data.SetURL(base_url + "url?bar={searchTerms}");
+ data.instant_url = base_url + "instant?"
+ "{google:omniboxStartMarginParameter}foo=foo#foo=foo&strk";
+ data.alternate_urls.push_back(base_url + "alt#quux={searchTerms}");
+ 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);
+}
+
+void InstantUnitTestBase::NotifyGoogleBaseURLUpdate(
+ const std::string& new_google_base_url) {
+ // GoogleURLTracker is not created in tests.
+ // (See GoogleURLTrackerFactory::ServiceIsNULLWhileTesting())
+ // For determining google:baseURL for NTP, the following is used:
+ // UIThreadSearchTermsData::GoogleBaseURLValue()
+ // For simulating test behavior, this is overridden below.
+ UIThreadSearchTermsData::SetGoogleBaseURL(new_google_base_url);
+ GoogleURLTracker::UpdatedDetails details(GURL("https://www.google.com/"),
+ GURL(new_google_base_url));
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_GOOGLE_URL_UPDATED,
+ content::Source<Profile>(profile()->GetOriginalProfile()),
+ content::Details<GoogleURLTracker::UpdatedDetails>(&details));
+}
+
+
+bool InstantUnitTestBase::IsInstantServiceObserver(
+ InstantServiceObserver* observer) {
+ return instant_service_->observers_.HasObserver(observer);
+}
+
diff --git a/chrome/browser/search/instant_unittest_base.h b/chrome/browser/search/instant_unittest_base.h
new file mode 100644
index 0000000..6e46cf9
--- /dev/null
+++ b/chrome/browser/search/instant_unittest_base.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_SEARCH_INSTANT_UNITTEST_BASE_H_
+#define CHROME_BROWSER_SEARCH_INSTANT_UNITTEST_BASE_H_
+
+#include <string>
+
+#include "chrome/browser/search/instant_service.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+
+class InstantServiceObserver;
+
+// This class provides an extension on top of BrowserWithTestWindowTest, and
+// adds some utility methods which can be useful for various unit tests for
+// Embedded Search / Instant implementation classes.
+class InstantUnitTestBase : public BrowserWithTestWindowTest {
+ protected:
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ // Adds and sets the default search provider using the base_url.
+ // The base_url should have the http[s]:// prefix and a trailing / after the
+ // TLD.
+ // It will always use an instant-enabled configuration using a
+ // search_terms_replacement_key.
+ void SetDefaultSearchProvider(const std::string& base_url);
+
+ // Simulates a Google Base URL change as would happen in event of
+ // search-domain-check. Note that the GoogleURLTrackerFactory is disabled for
+ // tests, so this is required.
+ void NotifyGoogleBaseURLUpdate(const std::string& new_google_base_url);
+
+ bool IsInstantServiceObserver(InstantServiceObserver* observer);
+
+ InstantService* instant_service_;
+ TemplateURLService* template_url_service_;
+};
+
+#endif // CHROME_BROWSER_SEARCH_INSTANT_UNITTEST_BASE_H_
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index 2fda4aa..10cc1de 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -56,7 +56,6 @@
// The staleness timeout can be set (in seconds) via this config.
const char kStalePageTimeoutFlagName[] = "stale";
const int kStalePageTimeoutDefault = 3 * 3600; // 3 hours.
-const int kStalePageTimeoutDisabled = 0;
const char kHideVerbatimFlagName[] = "hide_verbatim";
const char kUseRemoteNTPOnStartupFlagName[] = "use_remote_ntp_on_startup";
@@ -465,6 +464,10 @@
}
bool ShouldUseCacheableNTP() {
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kUseCacheableNewTabPage))
+ return true;
+
FieldTrialFlags flags;
if (GetFieldTrialInfo(&flags, NULL)) {
return GetBoolValueForFlagWithDefault(kUseCacheableNTP, false, flags);
@@ -740,7 +743,7 @@
if (!ShouldUseCacheableNTP())
return GURL();
- if (!profile)
+ if (!profile || !IsSuggestPrefEnabled(profile))
return GURL();
TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc
index e3f38d9..9a1fb41 100644
--- a/chrome/browser/search/search_unittest.cc
+++ b/chrome/browser/search/search_unittest.cc
@@ -711,6 +711,14 @@
controller.GetLastCommittedEntry()));
}
+TEST_F(SearchTest, UseLocalNTPInIncognito) {
+ EnableInstantExtendedAPIForTesting();
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
+ "Group1 use_cacheable_ntp:1"));
+ EXPECT_EQ(GURL(), chrome::GetNewTabPageURL(
+ profile()->GetOffTheRecordProfile()));
+}
+
TEST_F(SearchTest, GetInstantURLExtendedEnabled) {
// Instant is disabled, so no Instant URL.
EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
@@ -832,6 +840,15 @@
EXPECT_TRUE(ShouldUseCacheableNTP());
}
+TEST_F(SearchTest, ShouldUseCacheableNTP_EnabledViaCommandLine) {
+ EnableInstantExtendedAPIForTesting();
+ CommandLine::ForCurrentProcess()->
+ AppendSwitch(switches::kUseCacheableNewTabPage);
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
+ "Group1 use_cacheable_ntp:0"));
+ EXPECT_TRUE(ShouldUseCacheableNTP());
+}
+
TEST_F(SearchTest, IsNTPURL) {
GURL invalid_url;
GURL ntp_url(chrome::kChromeUINewTabURL);
diff --git a/chrome/browser/search_engines/template_url_parser.cc b/chrome/browser/search_engines/template_url_parser.cc
index 69532d2..db22b8c 100644
--- a/chrome/browser/search_engines/template_url_parser.cc
+++ b/chrome/browser/search_engines/template_url_parser.cc
@@ -53,12 +53,6 @@
// Mime type for as you type suggestions.
const char kSuggestionType[] = "application/x-suggestions+json";
-// Namespace identifier.
-const char kOSDNS[] = "xmlns";
-
-// The namespace for documents we understand.
-const char kNameSpace[] = "http://a9.com/-/spec/opensearch/1.1/";
-
std::string XMLCharToString(const xmlChar* value) {
return std::string(reinterpret_cast<const char*>(value));
}
diff --git a/chrome/browser/search_engines/template_url_service_test_util.cc b/chrome/browser/search_engines/template_url_service_test_util.cc
index 5c5e43c..bb9c69d 100644
--- a/chrome/browser/search_engines/template_url_service_test_util.cc
+++ b/chrome/browser/search_engines/template_url_service_test_util.cc
@@ -14,7 +14,6 @@
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/webdata/web_data_service_factory.h"
#include "chrome/common/pref_names.h"
-#include "chrome/test/automation/value_conversion_util.h"
#include "chrome/test/base/testing_pref_service_syncable.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/notification_service.h"
@@ -159,9 +158,11 @@
Value::CreateStringValue(icon_url));
pref_service->SetManagedPref(prefs::kDefaultSearchProviderEncodings,
Value::CreateStringValue(encodings));
+ scoped_ptr<base::ListValue> alternate_url_list(new base::ListValue());
+ if (!alternate_url.empty())
+ alternate_url_list->Append(Value::CreateStringValue(alternate_url));
pref_service->SetManagedPref(prefs::kDefaultSearchProviderAlternateURLs,
- alternate_url.empty() ? new base::ListValue() :
- CreateListValueFrom(alternate_url));
+ alternate_url_list.release());
pref_service->SetManagedPref(
prefs::kDefaultSearchProviderSearchTermsReplacementKey,
Value::CreateStringValue(search_terms_replacement_key));
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index 27c1084..9a9d298 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -59,7 +59,7 @@
#endif
#if defined(USE_ASH)
-#include "ash/wm/window_settings.h"
+#include "ash/wm/window_state.h"
#endif
using content::NavigationController;
using content::RenderWidgetHost;
@@ -1087,12 +1087,12 @@
#if defined(USE_ASH)
// Prevent the auto window management for this window on show.
- ash::wm::GetWindowSettings(browser->window()->GetNativeWindow())->
+ ash::wm::GetWindowState(browser->window()->GetNativeWindow())->
set_bounds_changed_by_user(true);
#endif
browser->window()->Show();
#if defined(USE_ASH)
- ash::wm::GetWindowSettings(browser->window()->GetNativeWindow())->
+ ash::wm::GetWindowState(browser->window()->GetNativeWindow())->
set_bounds_changed_by_user(false);
#endif
browser->set_is_session_restore(false);
diff --git a/chrome/browser/sessions/session_types_unittest.cc b/chrome/browser/sessions/session_types_unittest.cc
index 6442fbe..edbc6b4 100644
--- a/chrome/browser/sessions/session_types_unittest.cc
+++ b/chrome/browser/sessions/session_types_unittest.cc
@@ -27,7 +27,6 @@
namespace {
-const int kIndex = 3;
const int kUniqueID = 50;
const content::Referrer kReferrer =
content::Referrer(GURL("http://www.referrer.com"),
@@ -49,8 +48,6 @@
const string16 kSearchTerms = ASCIIToUTF16("my search terms");
const GURL kFaviconURL("http://virtual-url.com/favicon.ico");
-const int kPageID = 10;
-
// Create a NavigationEntry from the constants above.
scoped_ptr<content::NavigationEntry> MakeNavigationEntryForTest() {
scoped_ptr<content::NavigationEntry> navigation_entry(
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc
index c74d7fe..186a3ea 100644
--- a/chrome/browser/shell_integration_linux.cc
+++ b/chrome/browser/shell_integration_linux.cc
@@ -372,7 +372,7 @@
ShellIntegration::DefaultWebClientState GetIsDefaultWebClient(
const std::string& protocol) {
#if defined(OS_CHROMEOS)
- return ShellIntegration::IS_DEFAULT;
+ return ShellIntegration::UNKNOWN_DEFAULT;
#else
base::ThreadRestrictions::AssertIOAllowed();
diff --git a/chrome/browser/signin/android_profile_oauth2_token_service.cc b/chrome/browser/signin/android_profile_oauth2_token_service.cc
index 42a6516..e745de0 100644
--- a/chrome/browser/signin/android_profile_oauth2_token_service.cc
+++ b/chrome/browser/signin/android_profile_oauth2_token_service.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/signin/android_profile_oauth2_token_service.h"
#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/logging.h"
@@ -15,7 +16,6 @@
#include "jni/AndroidProfileOAuth2TokenServiceHelper_jni.h"
using base::android::AttachCurrentThread;
-using base::android::CheckException;
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;
@@ -54,59 +54,45 @@
AndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() {
}
-scoped_ptr<OAuth2TokenService::Request>
- AndroidProfileOAuth2TokenService::StartRequestForUsername(
- const std::string& username,
- const OAuth2TokenService::ScopeSet& scopes,
- OAuth2TokenService::Consumer* consumer) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
- scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
- FetchOAuth2TokenWithUsername(request.get(), username, scopes);
- return request.PassAs<Request>();
-}
-
-bool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable() {
- SigninManagerBase* signin_manager =
- SigninManagerFactory::GetForProfile(profile());
- return !signin_manager->GetAuthenticatedUsername().empty();
-}
-
-void AndroidProfileOAuth2TokenService::InvalidateToken(
- const ScopeSet& scopes,
- const std::string& invalid_token) {
- OAuth2TokenService::InvalidateToken(scopes, invalid_token);
-
+bool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable(
+ const std::string& account_id) {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> j_invalid_token =
- ConvertUTF8ToJavaString(env, invalid_token);
- Java_AndroidProfileOAuth2TokenServiceHelper_invalidateOAuth2AuthToken(
- env, base::android::GetApplicationContext(),
- j_invalid_token.obj());
+ ScopedJavaLocalRef<jstring> j_account_id =
+ ConvertUTF8ToJavaString(env, account_id);
+ jboolean refresh_token_is_available =
+ Java_AndroidProfileOAuth2TokenServiceHelper_hasOAuth2RefreshToken(
+ env, base::android::GetApplicationContext(),
+ j_account_id.obj());
+ return refresh_token_is_available != JNI_FALSE;
+}
+
+std::vector<std::string> AndroidProfileOAuth2TokenService::GetAccounts() {
+ std::vector<std::string> accounts;
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobjectArray> j_accounts =
+ Java_AndroidProfileOAuth2TokenServiceHelper_getAccounts(
+ env, base::android::GetApplicationContext());
+ // TODO(fgorski): We may decide to filter out some of the accounts.
+ base::android::AppendJavaStringArrayToStringVector(env,
+ j_accounts.obj(),
+ &accounts);
+ return accounts;
}
void AndroidProfileOAuth2TokenService::FetchOAuth2Token(
RequestImpl* request,
+ const std::string& account_id,
net::URLRequestContextGetter* getter,
const std::string& client_id,
const std::string& client_secret,
const OAuth2TokenService::ScopeSet& scopes) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- std::string username = SigninManagerFactory::GetForProfile(profile())->
- GetAuthenticatedUsername();
- DCHECK(!username.empty());
- // Just ignore client_id, getter, etc since we don't use them on Android.
- FetchOAuth2TokenWithUsername(request, username, scopes);
-}
+ DCHECK(!account_id.empty());
-void AndroidProfileOAuth2TokenService::FetchOAuth2TokenWithUsername(
- RequestImpl* request,
- const std::string& username,
- const OAuth2TokenService::ScopeSet& scopes) {
JNIEnv* env = AttachCurrentThread();
std::string scope = CombineScopes(scopes);
ScopedJavaLocalRef<jstring> j_username =
- ConvertUTF8ToJavaString(env, username);
+ ConvertUTF8ToJavaString(env, account_id);
ScopedJavaLocalRef<jstring> j_scope =
ConvertUTF8ToJavaString(env, scope);
@@ -125,6 +111,24 @@
reinterpret_cast<int>(heap_callback.release()));
}
+void AndroidProfileOAuth2TokenService::InvalidateOAuth2Token(
+ const std::string& account_id,
+ const std::string& client_id,
+ const ScopeSet& scopes,
+ const std::string& access_token) {
+ OAuth2TokenService::InvalidateOAuth2Token(account_id,
+ client_id,
+ scopes,
+ access_token);
+
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> j_access_token =
+ ConvertUTF8ToJavaString(env, access_token);
+ Java_AndroidProfileOAuth2TokenServiceHelper_invalidateOAuth2AuthToken(
+ env, base::android::GetApplicationContext(),
+ j_access_token.obj());
+}
+
// Called from Java when fetching of an OAuth2 token is finished. The
// |authToken| param is only valid when |result| is true.
void OAuth2TokenFetched(JNIEnv* env, jclass clazz,
diff --git a/chrome/browser/signin/android_profile_oauth2_token_service.h b/chrome/browser/signin/android_profile_oauth2_token_service.h
index 0057540..6c44377 100644
--- a/chrome/browser/signin/android_profile_oauth2_token_service.h
+++ b/chrome/browser/signin/android_profile_oauth2_token_service.h
@@ -28,22 +28,16 @@
// request from other thread, please use ProfileOAuth2TokenServiceRequest.
class AndroidProfileOAuth2TokenService : public ProfileOAuth2TokenService {
public:
- // StartRequest() fetches a token for the currently signed-in account; this
- // version uses the account corresponding to |username|. This allows fetching
- // tokens before a user is signed-in (e.g. during the sign-in flow).
- scoped_ptr<OAuth2TokenService::Request> StartRequestForUsername(
- const std::string& username,
- const OAuth2TokenService::ScopeSet& scopes,
- OAuth2TokenService::Consumer* consumer);
-
- virtual bool RefreshTokenIsAvailable() OVERRIDE;
- virtual void InvalidateToken(const ScopeSet& scopes,
- const std::string& invalid_token) OVERRIDE;
+ virtual bool RefreshTokenIsAvailable(
+ const std::string& account_id) OVERRIDE;
// Registers the AndroidProfileOAuth2TokenService's native methods through
// JNI.
static bool Register(JNIEnv* env);
+ // Lists account IDs of all accounts with a refresh token.
+ virtual std::vector<std::string> GetAccounts() OVERRIDE;
+
protected:
friend class ProfileOAuth2TokenServiceFactory;
AndroidProfileOAuth2TokenService();
@@ -52,17 +46,18 @@
// Overridden from OAuth2TokenService to intercept token fetch requests and
// redirect them to the Account Manager.
virtual void FetchOAuth2Token(RequestImpl* request,
+ const std::string& account_id,
net::URLRequestContextGetter* getter,
const std::string& client_id,
const std::string& client_secret,
const ScopeSet& scopes) OVERRIDE;
- // Low-level helper function used by both FetchOAuth2Token and
- // StartRequestForUsername to fetch tokens. virtual to enable mocks.
- virtual void FetchOAuth2TokenWithUsername(
- RequestImpl* request,
- const std::string& username,
- const ScopeSet& scope);
+ // Overridden from OAuth2TokenService to intercept token fetch requests and
+ // redirect them to the Account Manager.
+ virtual void InvalidateOAuth2Token(const std::string& account_id,
+ const std::string& client_id,
+ const ScopeSet& scopes,
+ const std::string& access_token) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(AndroidProfileOAuth2TokenService);
diff --git a/chrome/browser/signin/fake_profile_oauth2_token_service.cc b/chrome/browser/signin/fake_profile_oauth2_token_service.cc
index 6a3c8c3..6c864b1 100644
--- a/chrome/browser/signin/fake_profile_oauth2_token_service.cc
+++ b/chrome/browser/signin/fake_profile_oauth2_token_service.cc
@@ -24,6 +24,11 @@
FakeProfileOAuth2TokenService::~FakeProfileOAuth2TokenService() {
}
+bool FakeProfileOAuth2TokenService::RefreshTokenIsAvailable(
+ const std::string& account_id) {
+ return !GetRefreshToken(account_id).empty();
+}
+
void FakeProfileOAuth2TokenService::IssueRefreshToken(
const std::string& token) {
refresh_token_ = token;
@@ -82,7 +87,8 @@
}
}
-std::string FakeProfileOAuth2TokenService::GetRefreshToken() {
+std::string FakeProfileOAuth2TokenService::GetRefreshToken(
+ const std::string& account_id) {
return refresh_token_;
}
@@ -104,11 +110,13 @@
void FakeProfileOAuth2TokenService::FetchOAuth2Token(
RequestImpl* request,
+ const std::string& account_id,
net::URLRequestContextGetter* getter,
const std::string& client_id,
const std::string& client_secret,
const ScopeSet& scopes) {
PendingRequest pending_request;
+ pending_request.account_id = account_id;
pending_request.client_id = client_id;
pending_request.client_secret = client_secret;
pending_request.scopes = scopes;
diff --git a/chrome/browser/signin/fake_profile_oauth2_token_service.h b/chrome/browser/signin/fake_profile_oauth2_token_service.h
index 336938e..e8e7dc8 100644
--- a/chrome/browser/signin/fake_profile_oauth2_token_service.h
+++ b/chrome/browser/signin/fake_profile_oauth2_token_service.h
@@ -52,6 +52,7 @@
PendingRequest();
~PendingRequest();
+ std::string account_id;
std::string client_id;
std::string client_secret;
ScopeSet scopes;
@@ -61,6 +62,10 @@
FakeProfileOAuth2TokenService();
virtual ~FakeProfileOAuth2TokenService();
+ // Overriden to make sure it works on Android.
+ virtual bool RefreshTokenIsAvailable(
+ const std::string& account_id) OVERRIDE;
+
// Sets the current refresh token. If |token| is non-empty, this will invoke
// OnRefreshTokenAvailable() on all Observers, otherwise this will invoke
// OnRefreshTokenRevoked().
@@ -71,6 +76,7 @@
std::vector<PendingRequest> GetPendingRequests();
// Helper routines to issue tokens for pending requests.
+ // TODO(fgorski): Add account IDs as parameters.
void IssueTokenForScope(const ScopeSet& scopes,
const std::string& access_token,
const base::Time& expiration);
@@ -90,12 +96,13 @@
protected:
// OAuth2TokenService overrides.
virtual void FetchOAuth2Token(RequestImpl* request,
+ const std::string& account_id,
net::URLRequestContextGetter* getter,
const std::string& client_id,
const std::string& client_secret,
const ScopeSet& scopes) OVERRIDE;
- virtual std::string GetRefreshToken() OVERRIDE;
+ virtual std::string GetRefreshToken(const std::string& account_id) OVERRIDE;
virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
diff --git a/chrome/browser/signin/profile_oauth2_token_service.cc b/chrome/browser/signin/profile_oauth2_token_service.cc
index 8722688..cc89a9d 100644
--- a/chrome/browser/signin/profile_oauth2_token_service.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service.cc
@@ -46,13 +46,6 @@
return prefixed_account_id.substr(kAccountIdPrefixLength);
}
-std::string GetAccountId(Profile* profile) {
- SigninManagerBase* signin_manager =
- SigninManagerFactory::GetForProfileIfExists(profile);
- return signin_manager ? signin_manager->GetAuthenticatedUsername() :
- std::string();
-}
-
} // namespace
ProfileOAuth2TokenService::ProfileOAuth2TokenService()
@@ -99,12 +92,13 @@
signin_global_error_.reset();
}
-std::string ProfileOAuth2TokenService::GetRefreshToken() {
- TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
- if (!token_service || !token_service->HasOAuthLoginToken()) {
- return std::string();
- }
- return token_service->GetOAuth2LoginRefreshToken();
+std::string ProfileOAuth2TokenService::GetRefreshToken(
+ const std::string& account_id) {
+ std::map<std::string, std::string>::const_iterator iter =
+ refresh_tokens_.find(account_id);
+ if (iter != refresh_tokens_.end())
+ return iter->second;
+ return std::string();
}
net::URLRequestContextGetter* ProfileOAuth2TokenService::GetRequestContext() {
@@ -112,7 +106,9 @@
}
void ProfileOAuth2TokenService::UpdateAuthError(
+ const std::string& account_id,
const GoogleServiceAuthError& error) {
+ // TODO(fgorski): SigninGlobalError needs to be made multi-login aware.
// Do not report connection errors as these are not actually auth errors.
// We also want to avoid masking a "real" auth error just because we
// subsequently get a transient network error.
@@ -129,29 +125,29 @@
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
+ const std::string& account_id = GetPrimaryAccountId();
switch (type) {
case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
TokenService::TokenAvailableDetails* tok_details =
content::Details<TokenService::TokenAvailableDetails>(details).ptr();
if (tok_details->service() ==
GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
- // TODO(fgorski): Canceling all requests will not be correct in a
- // multi-login environment. We should cancel only the requests related
- // to the token being replaced (old token for the same account_id).
- // Previous refresh token is not available at this point, but since
- // there are no other refresh tokens, we cancel all active requests.
- CancelAllRequests();
- ClearCache();
- UpdateAuthError(GoogleServiceAuthError::AuthErrorNone());
- FireRefreshTokenAvailable(GetAccountId(profile_));
+ // TODO(fgorski): Work on removing this code altogether in favor of the
+ // upgrade steps invoked by Initialize.
+ // TODO(fgorski): Refresh token received that way is not persisted in
+ // the token DB.
+ CancelRequestsForAccount(account_id);
+ ClearCacheForAccount(account_id);
+ refresh_tokens_[account_id] = tok_details->token();
+ UpdateAuthError(account_id, GoogleServiceAuthError::AuthErrorNone());
+ FireRefreshTokenAvailable(account_id);
}
break;
}
case chrome::NOTIFICATION_TOKENS_CLEARED: {
CancelAllRequests();
ClearCache();
- UpdateAuthError(GoogleServiceAuthError::AuthErrorNone());
- FireRefreshTokensCleared();
+ UpdateAuthError(account_id, GoogleServiceAuthError::AuthErrorNone());
break;
}
case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED:
@@ -160,8 +156,8 @@
// user goes on to set up sync, they will have to make two attempts:
// One to surface the OAuth2 error, and a second one after signing in.
// See crbug.com/276650.
- if (!GetAccountId(profile_).empty() && GetRefreshToken().empty()) {
- UpdateAuthError(GoogleServiceAuthError(
+ if (!account_id.empty() && GetRefreshToken(account_id).empty()) {
+ UpdateAuthError(account_id, GoogleServiceAuthError(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
}
FireRefreshTokensLoaded();
@@ -176,33 +172,22 @@
return last_auth_error_;
}
-void ProfileOAuth2TokenService::RegisterCacheEntry(
- const std::string& client_id,
- const std::string& refresh_token,
- const ScopeSet& scopes,
- const std::string& access_token,
- const base::Time& expiration_date) {
- if (ShouldCacheForRefreshToken(TokenServiceFactory::GetForProfile(profile_),
- refresh_token)) {
- OAuth2TokenService::RegisterCacheEntry(client_id,
- refresh_token,
- scopes,
- access_token,
- expiration_date);
- }
+std::string ProfileOAuth2TokenService::GetPrimaryAccountId() {
+ SigninManagerBase* signin_manager =
+ SigninManagerFactory::GetForProfileIfExists(profile_);
+ // TODO(fgorski): DCHECK(signin_manager) here - it may require update to test
+ // code and the line above (SigninManager might not exist yet).
+ return signin_manager ? signin_manager->GetAuthenticatedUsername()
+ : std::string();
}
-bool ProfileOAuth2TokenService::ShouldCacheForRefreshToken(
- TokenService *token_service,
- const std::string& refresh_token) {
- if (!token_service ||
- !token_service->HasOAuthLoginToken() ||
- token_service->GetOAuth2LoginRefreshToken().compare(refresh_token) != 0) {
- DLOG(INFO) <<
- "Received a token with a refresh token not maintained by TokenService.";
- return false;
+std::vector<std::string> ProfileOAuth2TokenService::GetAccounts() {
+ std::vector<std::string> account_ids;
+ for (std::map<std::string, std::string>::const_iterator iter =
+ refresh_tokens_.begin(); iter != refresh_tokens_.end(); ++iter) {
+ account_ids.push_back(iter->first);
}
- return true;
+ return account_ids;
}
void ProfileOAuth2TokenService::UpdateCredentials(
@@ -214,18 +199,18 @@
bool refresh_token_present = refresh_tokens_.count(account_id) > 0;
if (!refresh_token_present ||
refresh_tokens_[account_id] != refresh_token) {
- // If token present, and different from the new one, cancel its requests.
- if (refresh_token_present)
- CancelRequestsForToken(refresh_tokens_[account_id]);
+ // If token present, and different from the new one, cancel its requests,
+ // and clear the entries in cache related to that account.
+ if (refresh_token_present) {
+ CancelRequestsForAccount(account_id);
+ ClearCacheForAccount(account_id);
+ }
// Save the token in memory and in persistent store.
refresh_tokens_[account_id] = refresh_token;
- scoped_refptr<TokenWebData> token_web_data =
- TokenWebData::FromBrowserContext(profile_);
- if (token_web_data.get())
- token_web_data->SetTokenForService(ApplyAccountIdPrefix(account_id),
- refresh_token);
+ PersistCredentials(account_id, refresh_token);
+ UpdateAuthError(account_id, GoogleServiceAuthError::AuthErrorNone());
FireRefreshTokenAvailable(account_id);
// TODO(fgorski): Notify diagnostic observers.
}
@@ -236,18 +221,35 @@
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (refresh_tokens_.count(account_id) > 0) {
- CancelRequestsForToken(refresh_tokens_[account_id]);
+ CancelRequestsForAccount(account_id);
+ ClearCacheForAccount(account_id);
refresh_tokens_.erase(account_id);
- scoped_refptr<TokenWebData> token_web_data =
- TokenWebData::FromBrowserContext(profile_);
- if (token_web_data.get())
- token_web_data->RemoveTokenForService(ApplyAccountIdPrefix(account_id));
+ ClearPersistedCredentials(account_id);
FireRefreshTokenRevoked(account_id);
// TODO(fgorski): Notify diagnostic observers.
}
}
+void ProfileOAuth2TokenService::PersistCredentials(
+ const std::string& account_id,
+ const std::string& refresh_token) {
+ scoped_refptr<TokenWebData> token_web_data =
+ TokenWebData::FromBrowserContext(profile_);
+ if (token_web_data.get()) {
+ token_web_data->SetTokenForService(ApplyAccountIdPrefix(account_id),
+ refresh_token);
+ }
+}
+
+void ProfileOAuth2TokenService::ClearPersistedCredentials(
+ const std::string& account_id) {
+ scoped_refptr<TokenWebData> token_web_data =
+ TokenWebData::FromBrowserContext(profile_);
+ if (token_web_data.get())
+ token_web_data->RemoveTokenForService(ApplyAccountIdPrefix(account_id));
+}
+
void ProfileOAuth2TokenService::RevokeAllCredentials() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -264,7 +266,6 @@
TokenWebData::FromBrowserContext(profile_);
if (token_web_data.get())
token_web_data->RemoveAllTokens();
- FireRefreshTokensCleared();
// TODO(fgorski): Notify diagnostic observers.
}
@@ -326,8 +327,8 @@
}
if (!old_login_token.empty() &&
- refresh_tokens_.count(GetAccountId(profile_)) == 0) {
- UpdateCredentials(GetAccountId(profile_), old_login_token);
+ refresh_tokens_.count(GetPrimaryAccountId()) == 0) {
+ UpdateCredentials(GetPrimaryAccountId(), old_login_token);
}
FireRefreshTokensLoaded();
diff --git a/chrome/browser/signin/profile_oauth2_token_service.h b/chrome/browser/signin/profile_oauth2_token_service.h
index 311873d..62d14ab 100644
--- a/chrome/browser/signin/profile_oauth2_token_service.h
+++ b/chrome/browser/signin/profile_oauth2_token_service.h
@@ -58,9 +58,11 @@
// SigninGlobalError::AuthStatusProvider implementation.
virtual GoogleServiceAuthError GetAuthStatus() const OVERRIDE;
- // Takes injected TokenService for testing.
- bool ShouldCacheForRefreshToken(TokenService *token_service,
- const std::string& refresh_token);
+ // Gets an account id of the primary account related to the profile.
+ std::string GetPrimaryAccountId();
+
+ // Lists account IDs of all accounts with a refresh token.
+ virtual std::vector<std::string> GetAccounts() OVERRIDE;
// Updates a |refresh_token| for an |account_id|. Credentials are persisted,
// and avialable through |LoadCredentials| after service is restarted.
@@ -89,30 +91,28 @@
virtual ~ProfileOAuth2TokenService();
// OAuth2TokenService overrides.
- virtual std::string GetRefreshToken() OVERRIDE;
+ virtual std::string GetRefreshToken(const std::string& account_id) OVERRIDE;
// OAuth2TokenService implementation.
virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
// Updates the internal cache of the result from the most-recently-completed
// auth request (used for reporting errors to the user).
- virtual void UpdateAuthError(const GoogleServiceAuthError& error) OVERRIDE;
+ virtual void UpdateAuthError(
+ const std::string& account_id,
+ const GoogleServiceAuthError& error) OVERRIDE;
- // Overridden to not cache tokens if the TokenService refresh token
- // changes while a token fetch is in-flight. If the user logs out and
- // logs back in with a different account, then any in-flight token
- // fetches will be for the old account's refresh token. Therefore
- // when they come back, they shouldn't be cached.
- virtual void RegisterCacheEntry(const std::string& client_id,
- const std::string& refresh_token,
- const ScopeSet& scopes,
- const std::string& access_token,
- const base::Time& expiration_date) OVERRIDE;
+ // Persists credentials for |account_id|. Enables overriding for
+ // testing purposes, or other cases, when accessing the DB is not desired.
+ virtual void PersistCredentials(const std::string& account_id,
+ const std::string& refresh_token);
+
+ // Clears credentials persisted for |account_id|. Enables overriding for
+ // testing purposes, or other cases, when accessing the DB is not desired.
+ virtual void ClearPersistedCredentials(const std::string& account_id);
private:
FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest,
- StaleRefreshTokensNotCached);
- FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest,
TokenServiceUpdateClearsCache);
FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest,
PersistenceDBUpgrade);
diff --git a/chrome/browser/signin/profile_oauth2_token_service_request.cc b/chrome/browser/signin/profile_oauth2_token_service_request.cc
index 753c2e4..b8aa363 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_request.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service_request.cc
@@ -24,9 +24,11 @@
// the "owner thread" here. This will be the thread of |owner_task_runner_|.
Core(Profile* profile,
ProfileOAuth2TokenServiceRequest* owner);
- // Starts fetching an OAuth2 access token for |scopes|. It should be called
- // on the owner thread.
- void Start(const OAuth2TokenService::ScopeSet& scopes);
+ // Starts fetching an OAuth2 access token for |account_id| and |scopes|. It
+ // should be called on the owner thread.
+ void Start(
+ const std::string& account_id,
+ const OAuth2TokenService::ScopeSet& scopes);
// Stops the OAuth2 access token fetching. It should be called on the owner
// thread.
void Stop();
@@ -47,7 +49,9 @@
virtual ~Core();
// Starts an OAuth2TokenService::Request on the UI thread.
- void StartOnUIThread(const OAuth2TokenService::ScopeSet& scopes);
+ void StartOnUIThread(
+ const std::string& account_id,
+ const OAuth2TokenService::ScopeSet& scopes);
// Stops the OAuth2TokenService::Request on the UI thread.
void StopOnUIThread();
@@ -88,17 +92,18 @@
}
void ProfileOAuth2TokenServiceRequest::Core::Start(
+ const std::string& account_id,
const OAuth2TokenService::ScopeSet& scopes) {
DCHECK(owner_task_runner_->BelongsToCurrentThread());
if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- StartOnUIThread(scopes);
+ StartOnUIThread(account_id, scopes);
} else {
content::BrowserThread::PostTask(
content::BrowserThread::UI,
FROM_HERE,
base::Bind(&ProfileOAuth2TokenServiceRequest::Core::StartOnUIThread,
- this, scopes));
+ this, account_id, scopes));
}
}
@@ -125,13 +130,14 @@
}
void ProfileOAuth2TokenServiceRequest::Core::StartOnUIThread(
+ const std::string& account_id,
const OAuth2TokenService::ScopeSet& scopes) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
ProfileOAuth2TokenService* service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
DCHECK(service);
- request_.reset(service->StartRequest(scopes, this).release());
+ request_.reset(service->StartRequest(account_id, scopes, this).release());
}
void ProfileOAuth2TokenServiceRequest::Core::OnGetTokenSuccess(
@@ -181,18 +187,21 @@
ProfileOAuth2TokenServiceRequest*
ProfileOAuth2TokenServiceRequest::CreateAndStart(
Profile* profile,
+ const std::string& account_id,
const OAuth2TokenService::ScopeSet& scopes,
OAuth2TokenService::Consumer* consumer) {
- return new ProfileOAuth2TokenServiceRequest(profile, scopes, consumer);
+ return new ProfileOAuth2TokenServiceRequest(profile, account_id, scopes,
+ consumer);
}
ProfileOAuth2TokenServiceRequest::ProfileOAuth2TokenServiceRequest(
Profile* profile,
+ const std::string& account_id,
const OAuth2TokenService::ScopeSet& scopes,
OAuth2TokenService::Consumer* consumer)
: consumer_(consumer),
core_(new Core(profile, this)) {
- core_->Start(scopes);
+ core_->Start(account_id, scopes);
}
ProfileOAuth2TokenServiceRequest::~ProfileOAuth2TokenServiceRequest() {
diff --git a/chrome/browser/signin/profile_oauth2_token_service_request.h b/chrome/browser/signin/profile_oauth2_token_service_request.h
index 022623a..fa55aa0 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_request.h
+++ b/chrome/browser/signin/profile_oauth2_token_service_request.h
@@ -26,6 +26,7 @@
public:
static ProfileOAuth2TokenServiceRequest* CreateAndStart(
Profile* profile,
+ const std::string& account_id,
const OAuth2TokenService::ScopeSet& scopes,
OAuth2TokenService::Consumer* consumer);
@@ -36,8 +37,9 @@
friend class Core;
ProfileOAuth2TokenServiceRequest(Profile* profile,
- const OAuth2TokenService::ScopeSet& scopes,
- OAuth2TokenService::Consumer* consumer);
+ const std::string& account_id,
+ const OAuth2TokenService::ScopeSet& scopes,
+ OAuth2TokenService::Consumer* consumer);
OAuth2TokenService::Consumer* const consumer_;
scoped_refptr<Core> core_;
diff --git a/chrome/browser/signin/profile_oauth2_token_service_request_unittest.cc b/chrome/browser/signin/profile_oauth2_token_service_request_unittest.cc
index 6c1336e..6ef1036 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_request_unittest.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service_request_unittest.cc
@@ -7,9 +7,8 @@
#include <string>
#include <vector>
#include "base/threading/thread.h"
-#include "chrome/browser/signin/profile_oauth2_token_service.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/token_service_factory.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h"
#include "google_apis/gaia/google_service_auth_error.h"
@@ -18,6 +17,10 @@
namespace {
+const char kAccessToken[] = "access_token";
+const char kAccountId[] = "test_user@gmail.com";
+const char kRefreshToken[] = "refresh_token";
+
class TestingOAuth2TokenServiceConsumer : public OAuth2TokenService::Consumer {
public:
TestingOAuth2TokenServiceConsumer();
@@ -59,110 +62,6 @@
++number_of_errors_;
}
-class MockProfileOAuth2TokenService : public ProfileOAuth2TokenService {
- public:
- class Request : public OAuth2TokenService::Request,
- public base::SupportsWeakPtr<Request> {
- public:
- Request(OAuth2TokenService::Consumer* consumer,
- GoogleServiceAuthError error,
- std::string access_token);
- virtual ~Request();
-
- void InformConsumer() const;
-
- private:
- OAuth2TokenService::Consumer* consumer_;
- GoogleServiceAuthError error_;
- std::string access_token_;
- base::Time expiration_date_;
- };
-
- MockProfileOAuth2TokenService();
- virtual ~MockProfileOAuth2TokenService();
-
- virtual scoped_ptr<OAuth2TokenService::Request> StartRequest(
- const std::set<std::string>& scopes,
- OAuth2TokenService::Consumer* consumer) OVERRIDE;
-
- void SetExpectation(bool success, std::string oauth2_access_token);
-
- private:
- static void InformConsumer(
- base::WeakPtr<MockProfileOAuth2TokenService::Request> request);
-
- bool success_;
- std::string oauth2_access_token_;
-};
-
-MockProfileOAuth2TokenService::Request::Request(
- OAuth2TokenService::Consumer* consumer,
- GoogleServiceAuthError error,
- std::string access_token)
- : consumer_(consumer),
- error_(error),
- access_token_(access_token) {
-}
-
-MockProfileOAuth2TokenService::Request::~Request() {
-}
-
-void MockProfileOAuth2TokenService::Request::InformConsumer() const {
- if (error_.state() == GoogleServiceAuthError::NONE)
- consumer_->OnGetTokenSuccess(this, access_token_, expiration_date_);
- else
- consumer_->OnGetTokenFailure(this, error_);
-}
-
-MockProfileOAuth2TokenService::MockProfileOAuth2TokenService()
- : success_(true),
- oauth2_access_token_(std::string("success token")) {
-}
-
-MockProfileOAuth2TokenService::~MockProfileOAuth2TokenService() {
-}
-
-void MockProfileOAuth2TokenService::SetExpectation(bool success,
- std::string oauth2_access_token) {
- success_ = success;
- oauth2_access_token_ = oauth2_access_token;
-}
-
-// static
-void MockProfileOAuth2TokenService::InformConsumer(
- base::WeakPtr<MockProfileOAuth2TokenService::Request> request) {
- if (request.get())
- request->InformConsumer();
-}
-
-scoped_ptr<OAuth2TokenService::Request>
- MockProfileOAuth2TokenService::StartRequest(
- const std::set<std::string>& scopes,
- OAuth2TokenService::Consumer* consumer) {
- scoped_ptr<Request> request;
- if (success_) {
- request.reset(new MockProfileOAuth2TokenService::Request(
- consumer,
- GoogleServiceAuthError(GoogleServiceAuthError::NONE),
- oauth2_access_token_));
- } else {
- request.reset(new MockProfileOAuth2TokenService::Request(
- consumer,
- GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE),
- std::string()));
- }
- base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &MockProfileOAuth2TokenService::InformConsumer, request->AsWeakPtr()));
- return request.PassAs<OAuth2TokenService::Request>();
-}
-
-static BrowserContextKeyedService* CreateOAuth2TokenService(
- content::BrowserContext* profile) {
- MockProfileOAuth2TokenService* mock = new MockProfileOAuth2TokenService();
- mock->Initialize(static_cast<Profile*>(profile));
- return mock;
-}
-
class ProfileOAuth2TokenServiceRequestTest : public testing::Test {
public:
virtual void SetUp() OVERRIDE;
@@ -173,7 +72,7 @@
scoped_ptr<Profile> profile_;
TestingOAuth2TokenServiceConsumer consumer_;
- MockProfileOAuth2TokenService* oauth2_service_;
+ FakeProfileOAuth2TokenService* oauth2_service_;
scoped_ptr<ProfileOAuth2TokenServiceRequest> request_;
};
@@ -183,21 +82,23 @@
&ui_loop_));
TestingProfile::Builder builder;
builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
- &CreateOAuth2TokenService);
+ &FakeProfileOAuth2TokenService::Build);
profile_ = builder.Build();
- oauth2_service_ = (MockProfileOAuth2TokenService*)
+ oauth2_service_ = (FakeProfileOAuth2TokenService*)
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
}
TEST_F(ProfileOAuth2TokenServiceRequestTest,
Failure) {
- oauth2_service_->SetExpectation(false, std::string());
scoped_ptr<ProfileOAuth2TokenServiceRequest> request(
ProfileOAuth2TokenServiceRequest::CreateAndStart(
profile_.get(),
- std::set<std::string>(),
+ std::string(),
+ OAuth2TokenService::ScopeSet(),
&consumer_));
+ oauth2_service_->IssueErrorForAllPendingRequests(
+ GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
ui_loop_.RunUntilIdle();
EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
EXPECT_EQ(1, consumer_.number_of_errors_);
@@ -205,25 +106,33 @@
TEST_F(ProfileOAuth2TokenServiceRequestTest,
Success) {
+ oauth2_service_->IssueRefreshToken(kRefreshToken);
scoped_ptr<ProfileOAuth2TokenServiceRequest> request(
ProfileOAuth2TokenServiceRequest::CreateAndStart(
profile_.get(),
- std::set<std::string>(),
+ kAccountId,
+ OAuth2TokenService::ScopeSet(),
&consumer_));
+ oauth2_service_->IssueTokenForAllPendingRequests(kAccessToken,
+ base::Time::Max());
ui_loop_.RunUntilIdle();
EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
- EXPECT_EQ("success token", consumer_.last_token_);
+ EXPECT_EQ(kAccessToken, consumer_.last_token_);
EXPECT_EQ(0, consumer_.number_of_errors_);
}
TEST_F(ProfileOAuth2TokenServiceRequestTest,
RequestDeletionBeforeServiceComplete) {
+ oauth2_service_->IssueRefreshToken(kRefreshToken);
scoped_ptr<ProfileOAuth2TokenServiceRequest> request(
ProfileOAuth2TokenServiceRequest::CreateAndStart(
profile_.get(),
- std::set<std::string>(),
+ kAccountId,
+ OAuth2TokenService::ScopeSet(),
&consumer_));
request.reset();
+ oauth2_service_->IssueTokenForAllPendingRequests(kAccessToken,
+ base::Time::Max());
ui_loop_.RunUntilIdle();
EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
EXPECT_EQ(0, consumer_.number_of_errors_);
@@ -231,11 +140,15 @@
TEST_F(ProfileOAuth2TokenServiceRequestTest,
RequestDeletionAfterServiceComplete) {
+ oauth2_service_->IssueRefreshToken(kRefreshToken);
scoped_ptr<ProfileOAuth2TokenServiceRequest> request(
ProfileOAuth2TokenServiceRequest::CreateAndStart(
profile_.get(),
- std::set<std::string>(),
+ kAccountId,
+ OAuth2TokenService::ScopeSet(),
&consumer_));
+ oauth2_service_->IssueTokenForAllPendingRequests(kAccessToken,
+ base::Time::Max());
ui_loop_.RunUntilIdle();
request.reset();
EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
diff --git a/chrome/browser/signin/profile_oauth2_token_service_unittest.cc b/chrome/browser/signin/profile_oauth2_token_service_unittest.cc
index 50f5914..ee2cfc8 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_unittest.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service_unittest.cc
@@ -26,8 +26,7 @@
ProfileOAuth2TokenServiceTest()
: token_available_count_(0),
token_revoked_count_(0),
- tokens_loaded_count_(0),
- tokens_cleared_count_(0) {
+ tokens_loaded_count_(0) {
}
virtual void SetUp() OVERRIDE {
@@ -54,22 +53,17 @@
virtual void OnRefreshTokensLoaded() OVERRIDE {
++tokens_loaded_count_;
}
- virtual void OnRefreshTokensCleared() OVERRIDE {
- ++tokens_cleared_count_;
- }
void ResetObserverCounts() {
token_available_count_ = 0;
token_revoked_count_ = 0;
tokens_loaded_count_ = 0;
- tokens_cleared_count_ = 0;
}
void ExpectNoNotifications() {
EXPECT_EQ(0, token_available_count_);
EXPECT_EQ(0, token_revoked_count_);
EXPECT_EQ(0, tokens_loaded_count_);
- EXPECT_EQ(0, tokens_cleared_count_);
ResetObserverCounts();
}
@@ -77,7 +71,6 @@
EXPECT_EQ(1, token_available_count_);
EXPECT_EQ(0, token_revoked_count_);
EXPECT_EQ(0, tokens_loaded_count_);
- EXPECT_EQ(0, tokens_cleared_count_);
ResetObserverCounts();
}
@@ -85,7 +78,6 @@
EXPECT_EQ(0, token_available_count_);
EXPECT_EQ(1, token_revoked_count_);
EXPECT_EQ(0, tokens_loaded_count_);
- EXPECT_EQ(0, tokens_cleared_count_);
ResetObserverCounts();
}
@@ -93,15 +85,6 @@
EXPECT_EQ(0, token_available_count_);
EXPECT_EQ(0, token_revoked_count_);
EXPECT_EQ(1, tokens_loaded_count_);
- EXPECT_EQ(0, tokens_cleared_count_);
- ResetObserverCounts();
- }
-
- void ExpectOneTokensClearedNotification() {
- EXPECT_EQ(0, token_available_count_);
- EXPECT_EQ(0, token_revoked_count_);
- EXPECT_EQ(0, tokens_loaded_count_);
- EXPECT_EQ(1, tokens_cleared_count_);
ResetObserverCounts();
}
@@ -112,7 +95,6 @@
int token_available_count_;
int token_revoked_count_;
int tokens_loaded_count_;
- int tokens_cleared_count_;
};
TEST_F(ProfileOAuth2TokenServiceTest, Notifications) {
@@ -123,7 +105,6 @@
service()->EraseTokensFromDB();
service()->ResetCredentialsInMemory();
- ExpectOneTokensClearedNotification();
}
TEST_F(ProfileOAuth2TokenServiceTest, PersistenceDBUpgrade) {
@@ -148,7 +129,7 @@
// Legacy tokens get discarded, but the old refresh token is kept.
EXPECT_EQ(1, tokens_loaded_count_);
EXPECT_EQ(1, token_available_count_);
- EXPECT_TRUE(oauth2_service_->RefreshTokenIsAvailable());
+ EXPECT_TRUE(oauth2_service_->RefreshTokenIsAvailable(main_account_id));
EXPECT_EQ(1U, oauth2_service_->refresh_tokens_.size());
EXPECT_EQ(main_refresh_token,
oauth2_service_->refresh_tokens_[main_account_id]);
@@ -175,7 +156,9 @@
// token is present it is not overwritten.
EXPECT_EQ(2, token_available_count_);
EXPECT_EQ(1, tokens_loaded_count_);
- EXPECT_TRUE(oauth2_service_->RefreshTokenIsAvailable());
+ EXPECT_TRUE(oauth2_service_->RefreshTokenIsAvailable(main_account_id));
+ // TODO(fgorski): cover both using RefreshTokenIsAvailable() and then get the
+ // tokens using GetRefreshToken()
EXPECT_EQ(2U, oauth2_service_->refresh_tokens_.size());
EXPECT_EQ(main_refresh_token,
oauth2_service_->refresh_tokens_[main_account_id]);
@@ -214,14 +197,13 @@
EXPECT_EQ(0, token_available_count_);
EXPECT_EQ(1, token_revoked_count_);
EXPECT_EQ(0, tokens_loaded_count_);
- EXPECT_EQ(1, tokens_cleared_count_);
ResetObserverCounts();
}
TEST_F(ProfileOAuth2TokenServiceTest, PersistenceLoadCredentials) {
// Ensure DB is clean.
oauth2_service_->RevokeAllCredentials();
- ExpectOneTokensClearedNotification();
+ ResetObserverCounts();
// Perform a load from an empty DB.
oauth2_service_->LoadCredentials();
base::RunLoop().RunUntilIdle();
@@ -238,7 +220,6 @@
EXPECT_EQ(2, token_available_count_);
EXPECT_EQ(0, token_revoked_count_);
EXPECT_EQ(1, tokens_loaded_count_);
- EXPECT_EQ(0, tokens_cleared_count_);
ResetObserverCounts();
// TODO(fgorski): Enable below when implemented:
@@ -249,7 +230,6 @@
EXPECT_EQ(0, token_available_count_);
EXPECT_EQ(2, token_revoked_count_);
EXPECT_EQ(0, tokens_loaded_count_);
- EXPECT_EQ(1, tokens_cleared_count_);
ResetObserverCounts();
}
@@ -271,10 +251,23 @@
ExpectOneTokenAvailableNotification();
oauth2_service_->RevokeAllCredentials();
- EXPECT_EQ(1, tokens_cleared_count_);
ResetObserverCounts();
}
+TEST_F(ProfileOAuth2TokenServiceTest, GetAccounts) {
+ EXPECT_TRUE(oauth2_service_->GetAccounts().empty());
+ oauth2_service_->UpdateCredentials("account_id1", "refresh_token1");
+ oauth2_service_->UpdateCredentials("account_id2", "refresh_token2");
+ std::vector<std::string> accounts = oauth2_service_->GetAccounts();
+ EXPECT_EQ(2u, accounts.size());
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id2"));
+ oauth2_service_->RevokeCredentials("account_id2");
+ accounts = oauth2_service_->GetAccounts();
+ EXPECT_EQ(1u, oauth2_service_->GetAccounts().size());
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
+}
+
// Until the TokenService class is removed, finish token loading in TokenService
// should translate to finish token loading in ProfileOAuth2TokenService.
TEST_F(ProfileOAuth2TokenServiceTest, TokensLoaded) {
@@ -302,11 +295,12 @@
EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
std::set<std::string> scope_list;
scope_list.insert("scope");
- service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
- "refreshToken");
+ oauth2_service_->UpdateCredentials(oauth2_service_->GetPrimaryAccountId(),
+ "refreshToken");
ExpectOneTokenAvailableNotification();
+
scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
- scope_list, &consumer_));
+ oauth2_service_->GetPrimaryAccountId(), scope_list, &consumer_));
base::RunLoop().RunUntilIdle();
net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
fetcher->set_response_code(net::HTTP_OK);
@@ -318,18 +312,16 @@
EXPECT_EQ(1, oauth2_service_->cache_size_for_testing());
// Signs out and signs in
- service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
- "");
- ExpectOneTokenAvailableNotification();
- service()->EraseTokensFromDB();
- ExpectOneTokensClearedNotification();
+ oauth2_service_->RevokeCredentials(oauth2_service_->GetPrimaryAccountId());
+ ExpectOneTokenRevokedNotification();
EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
- service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
- "refreshToken");
+ oauth2_service_->UpdateCredentials(oauth2_service_->GetPrimaryAccountId(),
+ "refreshToken");
ExpectOneTokenAvailableNotification();
- request = oauth2_service_->StartRequest(scope_list, &consumer_);
+ request = oauth2_service_->StartRequest(
+ oauth2_service_->GetPrimaryAccountId(), scope_list, &consumer_);
base::RunLoop().RunUntilIdle();
fetcher = factory_.GetFetcherByID(0);
fetcher->set_response_code(net::HTTP_OK);
@@ -340,23 +332,3 @@
EXPECT_EQ("another token", consumer_.last_token_);
EXPECT_EQ(1, oauth2_service_->cache_size_for_testing());
}
-
-// Android doesn't use the current profile's TokenService login refresh token.
-#if !defined(OS_ANDROID)
-TEST_F(ProfileOAuth2TokenServiceTest, StaleRefreshTokensNotCached) {
- EXPECT_FALSE(service()->HasOAuthLoginToken());
- EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(service(), "T1"));
-
- service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
- "T1");
- ExpectOneTokenAvailableNotification();
- EXPECT_TRUE(oauth2_service_->ShouldCacheForRefreshToken(service(), "T1"));
- EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(service(), "T2"));
-
- service()->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
- "T2");
- ExpectOneTokenAvailableNotification();
- EXPECT_TRUE(oauth2_service_->ShouldCacheForRefreshToken(service(), "T2"));
- EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(NULL, "T2"));
-}
-#endif
diff --git a/chrome/browser/signin/signin_promo.cc b/chrome/browser/signin/signin_promo.cc
index cbd1611..fd64bdd 100644
--- a/chrome/browser/signin/signin_promo.cc
+++ b/chrome/browser/signin/signin_promo.cc
@@ -44,9 +44,6 @@
namespace {
-const char kStringsJsFile[] = "strings.js";
-const char kSignInPromoJsFile[] = "sync_promo.js";
-
const char kSignInPromoQueryKeyAutoClose[] = "auto_close";
const char kSignInPromoQueryKeyContinue[] = "continue";
const char kSignInPromoQueryKeySource[] = "source";
diff --git a/chrome/browser/signin/ubertoken_fetcher.cc b/chrome/browser/signin/ubertoken_fetcher.cc
index b726b70..f8ffd14 100644
--- a/chrome/browser/signin/ubertoken_fetcher.cc
+++ b/chrome/browser/signin/ubertoken_fetcher.cc
@@ -28,9 +28,10 @@
void UbertokenFetcher::StartFetchingToken() {
OAuth2TokenService::ScopeSet scopes;
scopes.insert(GaiaUrls::GetInstance()->oauth1_login_scope());
- access_token_request_ =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->
- StartRequest(scopes, this);
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
+ access_token_request_ = token_service->StartRequest(
+ token_service->GetPrimaryAccountId(), scopes, this);
}
void UbertokenFetcher::OnUberAuthTokenSuccess(const std::string& token) {
diff --git a/chrome/browser/signin/ubertoken_fetcher_unittest.cc b/chrome/browser/signin/ubertoken_fetcher_unittest.cc
index 1592d4d..58464d8 100644
--- a/chrome/browser/signin/ubertoken_fetcher_unittest.cc
+++ b/chrome/browser/signin/ubertoken_fetcher_unittest.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/signin/ubertoken_fetcher.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/signin/profile_oauth2_token_service.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/token_service_unittest.h"
#include "google_apis/gaia/gaia_constants.h"
@@ -40,24 +40,6 @@
int nb_error_;
};
-class MockOAuth2TokenService : public ProfileOAuth2TokenService {
- // OAuth2TokenService overrides:
- virtual scoped_ptr<OAuth2TokenService::Request>
- StartRequest(const OAuth2TokenService::ScopeSet& scopes,
- OAuth2TokenService::Consumer* consumer) OVERRIDE {
- // Don't actually make a request.
- scoped_ptr<OAuth2TokenService::Request> request;
- return request.Pass();
- }
-};
-
-
-BrowserContextKeyedService* Build(content::BrowserContext* profile) {
- MockOAuth2TokenService* token_service = new MockOAuth2TokenService();
- token_service->Initialize(static_cast<Profile*>(profile));
- return token_service;
-}
-
} // namespace
class UbertokenFetcherTest : public TokenServiceTestHarness {
@@ -71,7 +53,7 @@
virtual scoped_ptr<TestingProfile> CreateProfile() OVERRIDE {
TestingProfile::Builder builder;
builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
- Build);
+ &FakeProfileOAuth2TokenService::Build);
return builder.Build().Pass();
}
diff --git a/chrome/browser/speech/OWNERS b/chrome/browser/speech/OWNERS
index f49ecc4..88b7dd9 100644
--- a/chrome/browser/speech/OWNERS
+++ b/chrome/browser/speech/OWNERS
@@ -1,5 +1,6 @@
# Speech recognition
hans@chromium.org
+primiano@chromium.org
tommi@chromium.org
xians@chromium.org
diff --git a/chrome/browser/speech/speech_recognition_bubble.cc b/chrome/browser/speech/speech_recognition_bubble.cc
index e93c4ec..2b28dd9 100644
--- a/chrome/browser/speech/speech_recognition_bubble.cc
+++ b/chrome/browser/speech/speech_recognition_bubble.cc
@@ -95,7 +95,7 @@
// render properly and gets vertically squished in Linux due to a bug in
// Skia. Until that gets fixed we work around by taking a real copy of it
// below as the copied image has the correct rowBytes and renders fine.
- frame.EnsureRepsForSupportedScaleFactors();
+ frame.EnsureRepsForSupportedScales();
std::vector<gfx::ImageSkiaRep> image_reps = frame.image_reps();
gfx::ImageSkia frame_copy;
for (size_t i = 0; i < image_reps.size(); ++i) {
@@ -103,7 +103,7 @@
SkBitmap copy_dst;
copy_src.copyTo(©_dst, SkBitmap::kARGB_8888_Config);
frame_copy.AddRepresentation(gfx::ImageSkiaRep(
- copy_dst, image_reps[i].scale_factor()));
+ copy_dst, image_reps[i].scale()));
}
spinner_.push_back(frame_copy);
@@ -140,16 +140,15 @@
animation_step_(0),
display_mode_(DISPLAY_MODE_RECORDING),
web_contents_(web_contents),
- scale_factor_(ui::SCALE_FACTOR_NONE) {
+ scale_(1.0f) {
gfx::NativeView view =
web_contents_ ? web_contents_->GetView()->GetNativeView() : NULL;
gfx::Screen* screen = gfx::Screen::GetScreenFor(view);
gfx::Display display = screen->GetDisplayNearestWindow(view);
- scale_factor_ = ui::GetScaleFactorFromScale(
- display.device_scale_factor());
+ scale_ = display.device_scale_factor();
const gfx::ImageSkiaRep& rep =
- g_images.Get().mic_empty()->GetRepresentation(scale_factor_);
+ g_images.Get().mic_empty()->GetRepresentation(scale_);
mic_image_.reset(new SkBitmap());
mic_image_->setConfig(SkBitmap::kARGB_8888_Config,
rep.pixel_width(), rep.pixel_height());
@@ -235,13 +234,12 @@
(((1.0f - volume) * (width * (kVolumeSteps + 1))) - width) / kVolumeSteps;
buffer_canvas.clipRect(SkRect::MakeLTRB(0, 0,
SkIntToScalar(width) - clip_right, SkIntToScalar(height)));
- buffer_canvas.drawBitmap(
- image.GetRepresentation(scale_factor_).sk_bitmap(), 0, 0);
+ buffer_canvas.drawBitmap(image.GetRepresentation(scale_).sk_bitmap(), 0, 0);
buffer_canvas.restore();
SkPaint multiply_paint;
multiply_paint.setXfermodeMode(SkXfermode::kModulate_Mode);
buffer_canvas.drawBitmap(
- g_images.Get().mic_mask()->GetRepresentation(scale_factor_).sk_bitmap(),
+ g_images.Get().mic_mask()->GetRepresentation(scale_).sk_bitmap(),
-clip_right, 0, &multiply_paint);
canvas->drawBitmap(*buffer_image_.get(), 0, 0);
@@ -255,12 +253,12 @@
// Draw the empty volume image first and the current volume image on top,
// and then the noise volume image on top of both.
canvas.drawBitmap(
- g_images.Get().mic_empty()->GetRepresentation(scale_factor_).sk_bitmap(),
+ g_images.Get().mic_empty()->GetRepresentation(scale_).sk_bitmap(),
0, 0);
DrawVolumeOverlay(&canvas, *g_images.Get().mic_full(), volume);
DrawVolumeOverlay(&canvas, *g_images.Get().mic_noise(), noise_volume);
- gfx::ImageSkia image(gfx::ImageSkiaRep(*mic_image_.get(), scale_factor_));
+ gfx::ImageSkia image(gfx::ImageSkiaRep(*mic_image_.get(), scale_));
SetImage(image);
}
diff --git a/chrome/browser/speech/speech_recognition_bubble.h b/chrome/browser/speech/speech_recognition_bubble.h
index 2bb911f..08a741e 100644
--- a/chrome/browser/speech/speech_recognition_bubble.h
+++ b/chrome/browser/speech/speech_recognition_bubble.h
@@ -184,7 +184,7 @@
// The current image displayed in the bubble's icon widget.
gfx::ImageSkia icon_image_;
// The scale factor used for the web-contents.
- ui::ScaleFactor scale_factor_;
+ float scale_;
DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionBubbleBase);
};
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc
index 0bc9315..dba4327 100644
--- a/chrome/browser/sync/glue/bookmark_model_associator.cc
+++ b/chrome/browser/sync/glue/bookmark_model_associator.cc
@@ -51,12 +51,9 @@
//
// TODO(ncarter): Pull these tags from an external protocol specification
// rather than hardcoding them here.
-static const char kBookmarkBarTag[] = "bookmark_bar";
-static const char kMobileBookmarksTag[] = "synced_bookmarks";
-static const char kOtherBookmarksTag[] = "other_bookmarks";
-static const char kServerError[] =
- "Server did not create top-level nodes. Possibly we are running against "
- "an out-of-date server?";
+const char kBookmarkBarTag[] = "bookmark_bar";
+const char kMobileBookmarksTag[] = "synced_bookmarks";
+const char kOtherBookmarksTag[] = "other_bookmarks";
// Bookmark comparer for map of bookmark nodes.
class BookmarkComparer {
diff --git a/chrome/browser/sync/glue/chrome_report_unrecoverable_error.cc b/chrome/browser/sync/glue/chrome_report_unrecoverable_error.cc
index 66fccc0..2fe9dd4 100644
--- a/chrome/browser/sync/glue/chrome_report_unrecoverable_error.cc
+++ b/chrome/browser/sync/glue/chrome_report_unrecoverable_error.cc
@@ -15,10 +15,11 @@
namespace browser_sync {
-static const double kErrorUploadRatio = 0.15;
void ChromeReportUnrecoverableError() {
// TODO(lipalani): Add this for other platforms as well.
#if defined(OS_WIN)
+ const double kErrorUploadRatio = 0.15;
+
// We only want to upload |kErrorUploadRatio| ratio of errors.
if (kErrorUploadRatio <= 0.0)
return; // We are not allowed to upload errors.
diff --git a/chrome/browser/sync/glue/data_type_manager_impl.cc b/chrome/browser/sync/glue/data_type_manager_impl.cc
index c5cbc8e..3fe7e05 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl.cc
@@ -377,30 +377,25 @@
if (!debug_info_listener_.IsInitialized())
return;
- syncer::DataTypeConfigurationStats configuration_stats;
- configuration_stats.model_type = type;
- configuration_stats.association_stats = association_stats;
+ configuration_stats_.push_back(syncer::DataTypeConfigurationStats());
+ configuration_stats_.back().model_type = type;
+ configuration_stats_.back().association_stats = association_stats;
AssociationTypesInfo& info = association_types_queue_.front();
- configuration_stats.download_wait_time =
+ configuration_stats_.back().download_wait_time =
info.download_start_time - last_restart_time_;
if (info.first_sync_types.Has(type)) {
- configuration_stats.download_time =
+ configuration_stats_.back().download_time =
info.download_ready_time - info.download_start_time;
}
- configuration_stats.association_wait_time_for_high_priority =
+ configuration_stats_.back().association_wait_time_for_high_priority =
info.association_request_time - info.download_ready_time;
- configuration_stats.high_priority_types_configured_before =
+ configuration_stats_.back().high_priority_types_configured_before =
info.high_priority_types_before;
- configuration_stats.same_priority_types_configured_before =
+ configuration_stats_.back().same_priority_types_configured_before =
info.configured_types;
info.configured_types.Put(type);
-
- debug_info_listener_.Call(
- FROM_HERE,
- &syncer::DataTypeDebugInfoListener::OnSingleDataTypeConfigureComplete,
- configuration_stats);
}
void DataTypeManagerImpl::OnModelAssociationDone(
@@ -547,6 +542,14 @@
DVLOG(1) << "NotifyDone called with result: OK";
UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.OK",
configure_time_delta_);
+ if (debug_info_listener_.IsInitialized() &&
+ !configuration_stats_.empty()) {
+ debug_info_listener_.Call(
+ FROM_HERE,
+ &syncer::DataTypeDebugInfoListener::OnDataTypeConfigureComplete,
+ configuration_stats_);
+ }
+ configuration_stats_.clear();
break;
case DataTypeManager::ABORTED:
DVLOG(1) << "NotifyDone called with result: ABORTED";
diff --git a/chrome/browser/sync/glue/data_type_manager_impl.h b/chrome/browser/sync/glue/data_type_manager_impl.h
index 762e34e..84e3a67 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl.h
+++ b/chrome/browser/sync/glue/data_type_manager_impl.h
@@ -19,6 +19,7 @@
#include "chrome/browser/sync/glue/model_association_manager.h"
namespace syncer {
+struct DataTypeConfigurationStats;
class DataTypeDebugInfoListener;
template <typename T> class WeakHandle;
}
@@ -183,6 +184,9 @@
// datatype encryption.
const browser_sync::DataTypeEncryptionHandler* encryption_handler_;
+ // Association and time stats of data type configuration.
+ std::vector<syncer::DataTypeConfigurationStats> configuration_stats_;
+
DISALLOW_COPY_AND_ASSIGN(DataTypeManagerImpl);
};
diff --git a/chrome/browser/sync/glue/device_info.cc b/chrome/browser/sync/glue/device_info.cc
index ab17542..04836c4 100644
--- a/chrome/browser/sync/glue/device_info.cc
+++ b/chrome/browser/sync/glue/device_info.cc
@@ -41,42 +41,6 @@
};
}
-std::string DeviceTypeToString(sync_pb::SyncEnums::DeviceType device_type) {
- switch (device_type) {
- case sync_pb::SyncEnums_DeviceType_TYPE_WIN:
- case sync_pb::SyncEnums_DeviceType_TYPE_MAC:
- case sync_pb::SyncEnums_DeviceType_TYPE_LINUX:
- case sync_pb::SyncEnums_DeviceType_TYPE_CROS:
- return "desktop_or_laptop";
- case sync_pb::SyncEnums_DeviceType_TYPE_PHONE:
- return "phone";
- case sync_pb::SyncEnums_DeviceType_TYPE_TABLET:
- return "tablet";
- default:
- return "unknown";
- }
-}
-
-std::string GetOS(sync_pb::SyncEnums::DeviceType device_type) {
- switch (device_type) {
- case sync_pb::SyncEnums_DeviceType_TYPE_WIN:
- return "win";
- case sync_pb::SyncEnums_DeviceType_TYPE_MAC:
- return "mac";
- case sync_pb::SyncEnums_DeviceType_TYPE_LINUX:
- return "linux";
- case sync_pb::SyncEnums_DeviceType_TYPE_CROS:
- return "chrome_os";
- case sync_pb::SyncEnums_DeviceType_TYPE_PHONE:
- case sync_pb::SyncEnums_DeviceType_TYPE_TABLET:
- // TODO(lipalani): crbug.com/170375. Add support for ios
- // phones and tablets.
- return "android";
- default:
- return "unknown";
- }
-}
-
} // namespace
DeviceInfo::DeviceInfo(const std::string& guid,
@@ -117,6 +81,42 @@
return device_type_;
}
+std::string DeviceInfo::GetOSString() const {
+ switch (device_type_) {
+ case sync_pb::SyncEnums_DeviceType_TYPE_WIN:
+ return "win";
+ case sync_pb::SyncEnums_DeviceType_TYPE_MAC:
+ return "mac";
+ case sync_pb::SyncEnums_DeviceType_TYPE_LINUX:
+ return "linux";
+ case sync_pb::SyncEnums_DeviceType_TYPE_CROS:
+ return "chrome_os";
+ case sync_pb::SyncEnums_DeviceType_TYPE_PHONE:
+ case sync_pb::SyncEnums_DeviceType_TYPE_TABLET:
+ // TODO(lipalani): crbug.com/170375. Add support for ios
+ // phones and tablets.
+ return "android";
+ default:
+ return "unknown";
+ }
+}
+
+std::string DeviceInfo::GetDeviceTypeString() const {
+ switch (device_type_) {
+ case sync_pb::SyncEnums_DeviceType_TYPE_WIN:
+ case sync_pb::SyncEnums_DeviceType_TYPE_MAC:
+ case sync_pb::SyncEnums_DeviceType_TYPE_LINUX:
+ case sync_pb::SyncEnums_DeviceType_TYPE_CROS:
+ return "desktop_or_laptop";
+ case sync_pb::SyncEnums_DeviceType_TYPE_PHONE:
+ return "phone";
+ case sync_pb::SyncEnums_DeviceType_TYPE_TABLET:
+ return "tablet";
+ default:
+ return "unknown";
+ }
+}
+
bool DeviceInfo::Equals(const DeviceInfo& other) const {
return this->guid() == other.guid()
&& this->client_name() == other.client_name()
@@ -188,8 +188,8 @@
base::DictionaryValue* value = new base::DictionaryValue();
value->SetString("name", client_name_);
value->SetString("id", public_id_);
- value->SetString("os", GetOS(device_type_));
- value->SetString("type", DeviceTypeToString(device_type_));
+ value->SetString("os", GetOSString());
+ value->SetString("type", GetDeviceTypeString());
value->SetString("chromeVersion", chrome_version_);
return value;
}
diff --git a/chrome/browser/sync/glue/device_info.h b/chrome/browser/sync/glue/device_info.h
index 9c984a7..d94a9bc 100644
--- a/chrome/browser/sync/glue/device_info.h
+++ b/chrome/browser/sync/glue/device_info.h
@@ -54,6 +54,12 @@
// Device Type.
sync_pb::SyncEnums::DeviceType device_type() const;
+ // Gets the OS in string form.
+ std::string GetOSString() const;
+
+ // Gets the device type in string form.
+ std::string GetDeviceTypeString() const;
+
// Compares this object's fields with another's.
bool Equals(const DeviceInfo& other) const;
diff --git a/chrome/browser/sync/glue/password_change_processor.cc b/chrome/browser/sync/glue/password_change_processor.cc
index 346c6dd..c02bfc3 100644
--- a/chrome/browser/sync/glue/password_change_processor.cc
+++ b/chrome/browser/sync/glue/password_change_processor.cc
@@ -253,17 +253,26 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
base::AutoLock lock(disconnect_lock_);
disconnected_ = true;
+ password_store_ = NULL;
}
void PasswordChangeProcessor::StartImpl(Profile* profile) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
password_store_->ScheduleTask(
- base::Bind(&PasswordChangeProcessor::StartObserving,
+ base::Bind(&PasswordChangeProcessor::InitObserving,
base::Unretained(this)));
}
+void PasswordChangeProcessor::InitObserving() {
+ base::AutoLock lock(disconnect_lock_);
+ if (disconnected_)
+ return;
+ StartObserving();
+}
+
void PasswordChangeProcessor::StartObserving() {
DCHECK(expected_loop_ == base::MessageLoop::current());
+ disconnect_lock_.AssertAcquired();
notification_registrar_.Add(this,
chrome::NOTIFICATION_LOGINS_CHANGED,
content::Source<PasswordStore>(password_store_));
@@ -271,6 +280,7 @@
void PasswordChangeProcessor::StopObserving() {
DCHECK(expected_loop_ == base::MessageLoop::current());
+ disconnect_lock_.AssertAcquired();
notification_registrar_.Remove(
this,
chrome::NOTIFICATION_LOGINS_CHANGED,
diff --git a/chrome/browser/sync/glue/password_change_processor.h b/chrome/browser/sync/glue/password_change_processor.h
index 11e4372..5a5d80e 100644
--- a/chrome/browser/sync/glue/password_change_processor.h
+++ b/chrome/browser/sync/glue/password_change_processor.h
@@ -67,13 +67,16 @@
void StartObserving();
void StopObserving();
+ // Registers to observe password change for the first time.
+ void InitObserving();
+
// The two models should be associated according to this ModelAssociator.
PasswordModelAssociator* model_associator_;
// The model we are processing changes from. This is owned by the
// WebDataService which is kept alive by our data type controller
// holding a reference.
- PasswordStore* password_store_;
+ scoped_refptr<PasswordStore> password_store_;
// Buffers used between ApplyChangesFromSyncModel and
// CommitChangesFromSyncModel.
diff --git a/chrome/browser/sync/glue/password_model_associator.cc b/chrome/browser/sync/glue/password_model_associator.cc
index 80ce003..9abea43 100644
--- a/chrome/browser/sync/glue/password_model_associator.cc
+++ b/chrome/browser/sync/glue/password_model_associator.cc
@@ -54,25 +54,6 @@
syncer::SyncMergeResult* syncer_merge_result) {
DCHECK(expected_loop_ == base::MessageLoop::current());
- // We must not be holding a transaction when we interact with the password
- // store, as it can post tasks to the UI thread which can itself be blocked
- // on our transaction, resulting in deadlock. (http://crbug.com/70658)
- std::vector<autofill::PasswordForm*> passwords;
- if (!password_store_->FillAutofillableLogins(&passwords) ||
- !password_store_->FillBlacklistLogins(&passwords)) {
- STLDeleteElements(&passwords);
-
- // 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());
- }
-
PasswordVector new_passwords;
PasswordVector updated_passwords;
{
@@ -80,6 +61,27 @@
if (abort_association_requested_)
return syncer::SyncError();
+ CHECK(password_store_.get());
+
+ // We must not be holding a transaction when we interact with the password
+ // store, as it can post tasks to the UI thread which can itself be blocked
+ // on our transaction, resulting in deadlock. (http://crbug.com/70658)
+ std::vector<autofill::PasswordForm*> passwords;
+ if (!password_store_->FillAutofillableLogins(&passwords) ||
+ !password_store_->FillBlacklistLogins(&passwords)) {
+ STLDeleteElements(&passwords);
+
+ // 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;
syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
syncer::ReadNode password_root(&trans);
@@ -233,6 +235,7 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
base::AutoLock lock(association_lock_);
abort_association_requested_ = true;
+ password_store_ = NULL;
}
bool PasswordModelAssociator::CryptoReadyIfNecessary() {
@@ -292,6 +295,12 @@
const PasswordVector* new_passwords,
const PasswordVector* updated_passwords,
const PasswordVector* deleted_passwords) {
+ base::AutoLock lock(association_lock_);
+ if (abort_association_requested_)
+ return syncer::SyncError();
+
+ CHECK(password_store_.get());
+
if (new_passwords) {
for (PasswordVector::const_iterator password = new_passwords->begin();
password != new_passwords->end(); ++password) {
diff --git a/chrome/browser/sync/glue/password_model_associator.h b/chrome/browser/sync/glue/password_model_associator.h
index ea0fc4a..2c9dfab 100644
--- a/chrome/browser/sync/glue/password_model_associator.h
+++ b/chrome/browser/sync/glue/password_model_associator.h
@@ -123,7 +123,7 @@
typedef std::map<int64, std::string> SyncIdToPasswordMap;
ProfileSyncService* sync_service_;
- PasswordStore* password_store_;
+ scoped_refptr<PasswordStore> password_store_;
int64 password_node_id_;
// Set true by AbortAssociation.
diff --git a/chrome/browser/sync/glue/synced_session.h b/chrome/browser/sync/glue/synced_session.h
index 5582945..ec99bce 100644
--- a/chrome/browser/sync/glue/synced_session.h
+++ b/chrome/browser/sync/glue/synced_session.h
@@ -25,6 +25,7 @@
typedef std::map<SessionID::id_type, SessionWindow*> SyncedWindowMap;
// The type of device.
+ // Please keep in sync with ForeignSessionHelper.java
enum DeviceType {
TYPE_UNSET = 0,
TYPE_WIN = 1,
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc b/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc
index d047c69..24d52ba 100644
--- a/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc
+++ b/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc
@@ -8,6 +8,8 @@
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "chrome/browser/signin/profile_oauth2_token_service.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/sync/glue/data_type_controller.h"
#include "chrome/browser/sync/profile_sync_components_factory_impl.h"
#include "chrome/browser/sync/profile_sync_service.h"
@@ -94,6 +96,7 @@
command_line_.get()),
profile_.get(),
NULL,
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get()),
ProfileSyncService::MANUAL_START));
pss->factory()->RegisterDataTypes(pss.get());
DataTypeController::StateMap controller_states;
@@ -109,12 +112,11 @@
};
TEST_F(ProfileSyncComponentsFactoryImplTest, CreatePSSDefault) {
- scoped_ptr<ProfileSyncService> pss(
- new ProfileSyncService(
- new ProfileSyncComponentsFactoryImpl(profile_.get(),
- command_line_.get()),
+ scoped_ptr<ProfileSyncService> pss(new ProfileSyncService(
+ new ProfileSyncComponentsFactoryImpl(profile_.get(), command_line_.get()),
profile_.get(),
NULL,
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get()),
ProfileSyncService::MANUAL_START));
pss->factory()->RegisterDataTypes(pss.get());
DataTypeController::StateMap controller_states;
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 599358f..38a4fee 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -31,7 +31,6 @@
#include "chrome/browser/signin/about_signin_internals.h"
#include "chrome/browser/signin/about_signin_internals_factory.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"
@@ -109,9 +108,7 @@
const char* ProfileSyncService::kDevServerUrl =
"https://clients4.google.com/chrome-sync/dev";
-static const int kSyncClearDataTimeoutInSeconds = 60; // 1 minute.
-
-static const char* kSyncUnrecoverableErrorHistogram =
+const char kSyncUnrecoverableErrorHistogram[] =
"Sync.UnrecoverableErrors";
const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
@@ -149,10 +146,12 @@
error.action != syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT);
}
-ProfileSyncService::ProfileSyncService(ProfileSyncComponentsFactory* factory,
- Profile* profile,
- SigninManagerBase* signin_manager,
- StartBehavior start_behavior)
+ProfileSyncService::ProfileSyncService(
+ ProfileSyncComponentsFactory* factory,
+ Profile* profile,
+ SigninManagerBase* signin_manager,
+ ProfileOAuth2TokenService* oauth2_token_service,
+ StartBehavior start_behavior)
: last_auth_error_(AuthError::AuthErrorNone()),
passphrase_required_reason_(syncer::REASON_PASSPHRASE_NOT_REQUIRED),
factory_(factory),
@@ -175,6 +174,8 @@
auto_start_enabled_(start_behavior == AUTO_START),
configure_status_(DataTypeManager::UNKNOWN),
setup_in_progress_(false),
+ use_oauth2_token_(false),
+ oauth2_token_service_(oauth2_token_service),
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
@@ -211,15 +212,15 @@
// and sync token otherwise (for android).
// TODO(pavely): Remove "else" part once use_oauth2_token_ is gone.
if (use_oauth2_token_) {
- ProfileOAuth2TokenService* token_service =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
- if (!token_service)
+ if (!oauth2_token_service_)
return false;
- return token_service->RefreshTokenIsAvailable();
+ return oauth2_token_service_->RefreshTokenIsAvailable(
+ oauth2_token_service_->GetPrimaryAccountId());
} else {
TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
if (!token_service)
return false;
+
return token_service->HasTokenForService(GaiaConstants::kSyncService);
}
}
@@ -347,9 +348,7 @@
}
void ProfileSyncService::RegisterAuthNotifications() {
- ProfileOAuth2TokenService* token_service =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
- token_service->AddObserver(this);
+ oauth2_token_service_->AddObserver(this);
registrar_.Add(this,
chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
@@ -360,9 +359,7 @@
}
void ProfileSyncService::UnregisterAuthNotifications() {
- ProfileOAuth2TokenService* token_service =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
- token_service->RemoveObserver(this);
+ oauth2_token_service_->RemoveObserver(this);
registrar_.RemoveAll();
}
@@ -573,14 +570,14 @@
}
#endif
- if (!sync_global_error_) {
#if !defined(OS_ANDROID)
+ if (!sync_global_error_) {
sync_global_error_.reset(new SyncGlobalError(this, signin()));
-#endif
GlobalErrorServiceFactory::GetForProfile(profile_)->AddGlobalError(
sync_global_error_.get());
AddObserver(sync_global_error_.get());
}
+#endif
} else {
// We don't care to prevent multiple calls to StartUp in deferred mode
// because it's fast and has no side effects.
@@ -715,12 +712,14 @@
void ProfileSyncService::OnRefreshTokenAvailable(
const std::string& account_id) {
- OnRefreshTokensLoaded();
+ if (oauth2_token_service_->GetPrimaryAccountId() == account_id)
+ OnRefreshTokensLoaded();
}
void ProfileSyncService::OnRefreshTokenRevoked(
const std::string& account_id) {
if (!IsOAuthRefreshTokenAvailable()) {
+ access_token_.clear();
// The additional check around IsOAuthRefreshTokenAvailable() above
// prevents us sounding the alarm if we actually have a valid token but
// a refresh attempt by TokenService failed for any variety of reasons
@@ -745,10 +744,6 @@
}
}
-void ProfileSyncService::OnRefreshTokensCleared() {
- access_token_.clear();
-}
-
void ProfileSyncService::Shutdown() {
UnregisterAuthNotifications();
@@ -1904,14 +1899,17 @@
oauth2_scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
}
- OAuth2TokenService* token_service =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
// Invalidate previous token, otherwise token service will return the same
// token again.
- if (!access_token_.empty())
- token_service->InvalidateToken(oauth2_scopes, access_token_);
+ const std::string& account_id = oauth2_token_service_->GetPrimaryAccountId();
+ if (!access_token_.empty()) {
+ oauth2_token_service_->InvalidateToken(
+ account_id, oauth2_scopes, access_token_);
+ }
+
access_token_.clear();
- access_token_request_ = token_service->StartRequest(oauth2_scopes, this);
+ access_token_request_ =
+ oauth2_token_service_->StartRequest(account_id, oauth2_scopes, this);
}
void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase,
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 8cd9c8d..0810178 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -47,6 +47,7 @@
#include "sync/js/sync_js_controller.h"
#include "url/gurl.h"
+class ProfileOAuth2TokenService;
class Profile;
class ProfileSyncComponentsFactory;
class SigninManagerBase;
@@ -60,14 +61,16 @@
class JsController;
class SessionModelAssociator;
-namespace sessions { class SyncSessionSnapshot; }
-}
+namespace sessions {
+class SyncSessionSnapshot;
+} // namespace sessions
+} // namespace browser_sync
namespace syncer {
class BaseTransaction;
struct SyncCredentials;
struct UserShare;
-}
+} // namespace syncer
namespace sync_pb {
class EncryptedData;
@@ -234,6 +237,7 @@
ProfileSyncService(ProfileSyncComponentsFactory* factory,
Profile* profile,
SigninManagerBase* signin,
+ ProfileOAuth2TokenService* oauth2_token_service,
StartBehavior start_behavior);
virtual ~ProfileSyncService();
@@ -633,7 +637,6 @@
virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE;
virtual void OnRefreshTokensLoaded() OVERRIDE;
- virtual void OnRefreshTokensCleared() OVERRIDE;
// BrowserContextKeyedService implementation. This must be called exactly
// once (before this object is destroyed).
@@ -952,6 +955,9 @@
// TODO(pavely): Remove once android is converted to oauth2 tokens.
bool use_oauth2_token_;
+ // ProfileSyncService uses this service to get access tokens.
+ ProfileOAuth2TokenService* oauth2_token_service_;
+
// ProfileSyncService needs to remember access token in order to invalidate it
// with OAuth2TokenService.
std::string access_token_;
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index 7437aec..bcad1d4 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -472,12 +472,11 @@
public syncer::DataTypeDebugInfoListener {
public:
// DataTypeDebugInfoListener implementation.
- virtual void OnSingleDataTypeConfigureComplete(
- const syncer::DataTypeConfigurationStats& configuration_stats) OVERRIDE {
- association_stats_ = configuration_stats.association_stats;
- }
- virtual void OnConfigureComplete() OVERRIDE {
- // Do nothing.
+ virtual void OnDataTypeConfigureComplete(
+ const std::vector<syncer::DataTypeConfigurationStats>&
+ configuration_stats) OVERRIDE {
+ ASSERT_EQ(1u, configuration_stats.size());
+ association_stats_ = configuration_stats[0].association_stats;
}
protected:
@@ -588,11 +587,10 @@
EXPECT_CALL(*personal_data_manager_, IsDataLoaded()).
WillRepeatedly(Return(true));
- // We need tokens to get the tests going
- token_service_->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- token_service_->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ // We need tokens to get the tests going
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())
+ ->UpdateCredentials("test_user@gmail.com", "oauth2_login_token");
+ token_service_->IssueAuthTokenForTest(GaiaConstants::kSyncService, "token");
sync_service_->RegisterDataTypeController(data_type_controller);
sync_service_->Initialize();
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc
index a6fb984..bd23d5a 100644
--- a/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -19,6 +19,7 @@
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/sessions/tab_restore_service_factory.h"
#include "chrome/browser/signin/about_signin_internals_factory.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"
@@ -105,6 +106,7 @@
CommandLine::ForCurrentProcess()),
profile,
signin,
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
behavior);
pss->factory()->RegisterDataTypes(pss);
diff --git a/chrome/browser/sync/profile_sync_service_mock.cc b/chrome/browser/sync/profile_sync_service_mock.cc
index a3ec200..e9f9eb7 100644
--- a/chrome/browser/sync/profile_sync_service_mock.cc
+++ b/chrome/browser/sync/profile_sync_service_mock.cc
@@ -4,6 +4,8 @@
#include "base/prefs/pref_service.h"
#include "base/prefs/testing_pref_store.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_factory.h"
#include "chrome/browser/sync/profile_sync_service_mock.h"
#include "chrome/common/pref_names.h"
@@ -11,18 +13,20 @@
#include "chrome/test/base/testing_profile.h"
ProfileSyncServiceMock::ProfileSyncServiceMock()
- : ProfileSyncService(NULL,
- NULL,
- NULL,
- ProfileSyncService::MANUAL_START) {
-}
+ : ProfileSyncService(
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ProfileSyncService::MANUAL_START) {}
-ProfileSyncServiceMock::ProfileSyncServiceMock(
- Profile* profile) : ProfileSyncService(NULL,
- profile,
- NULL,
- ProfileSyncService::MANUAL_START) {
-}
+ProfileSyncServiceMock::ProfileSyncServiceMock(Profile* profile)
+ : ProfileSyncService(
+ NULL,
+ profile,
+ NULL,
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
+ ProfileSyncService::MANUAL_START) {}
ProfileSyncServiceMock::~ProfileSyncServiceMock() {
}
diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc
index fabd41e..e10844d 100644
--- a/chrome/browser/sync/profile_sync_service_password_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc
@@ -95,10 +95,12 @@
PasswordTestProfileSyncService(
ProfileSyncComponentsFactory* factory,
Profile* profile,
- SigninManagerBase* signin)
+ SigninManagerBase* signin,
+ ProfileOAuth2TokenService* oauth2_token_service)
: TestProfileSyncService(factory,
profile,
signin,
+ oauth2_token_service,
ProfileSyncService::AUTO_START,
false) {}
@@ -115,9 +117,12 @@
Profile* profile = static_cast<Profile*>(context);
SigninManagerBase* signin =
SigninManagerFactory::GetForProfile(profile);
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
ProfileSyncComponentsFactoryMock* factory =
new ProfileSyncComponentsFactoryMock();
- return new PasswordTestProfileSyncService(factory, profile, signin);
+ return new PasswordTestProfileSyncService(
+ factory, profile, signin, oauth2_token_service);
}
void set_passphrase_accept_callback(const base::Closure& callback) {
@@ -229,10 +234,10 @@
WillOnce(ReturnNewDataTypeManager());
// We need tokens to get the tests going
- token_service_->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- token_service_->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())
+ ->UpdateCredentials("test_user@gmail.com", "oauth2_login_token");
+ token_service_->IssueAuthTokenForTest(GaiaConstants::kSyncService,
+ "token");
sync_service_->RegisterDataTypeController(data_type_controller);
sync_service_->Initialize();
diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
index 03b3e5d..3c5dbe6 100644
--- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
@@ -103,12 +103,11 @@
}
// DataTypeDebugInfoListener implementation.
- virtual void OnSingleDataTypeConfigureComplete(
- const syncer::DataTypeConfigurationStats& configuration_stats) OVERRIDE {
- association_stats_ = configuration_stats.association_stats;
- }
- virtual void OnConfigureComplete() OVERRIDE {
- // Do nothing.
+ virtual void OnDataTypeConfigureComplete(
+ const std::vector<syncer::DataTypeConfigurationStats>&
+ configuration_stats) OVERRIDE {
+ ASSERT_EQ(1u, configuration_stats.size());
+ association_stats_ = configuration_stats[0].association_stats;
}
protected:
@@ -185,10 +184,10 @@
WillOnce(CreateAndSaveChangeProcessor(
&change_processor_));
sync_service_->RegisterDataTypeController(dtc_);
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())
+ ->UpdateCredentials("test", "oauth2_login_token");
+ TokenServiceFactory::GetForProfile(profile_.get())
+ ->IssueAuthTokenForTest(GaiaConstants::kSyncService, "token");
sync_service_->Initialize();
base::MessageLoop::current()->Run();
diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc
index 1b4e173..979ed40 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -83,11 +83,13 @@
ProfileSyncComponentsFactory* factory,
Profile* profile,
SigninManagerBase* signin,
+ ProfileOAuth2TokenService* oauth2_token_service,
ProfileSyncService::StartBehavior behavior,
bool synchronous_backend_initialization)
: TestProfileSyncService(factory,
profile,
signin,
+ oauth2_token_service,
behavior,
synchronous_backend_initialization) {}
virtual ~FakeProfileSyncService() {}
@@ -273,12 +275,15 @@
SigninManagerBase* signin =
SigninManagerFactory::GetForProfile(profile());
signin->SetAuthenticatedUsername("test_user");
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
ProfileSyncComponentsFactoryMock* factory =
new ProfileSyncComponentsFactoryMock();
sync_service_.reset(new FakeProfileSyncService(
factory,
profile(),
signin,
+ oauth2_token_service,
ProfileSyncService::AUTO_START,
false));
sync_service_->set_backend_init_callback(callback);
@@ -301,10 +306,10 @@
EXPECT_CALL(*factory, CreateDataTypeManager(_, _, _, _, _, _)).
WillOnce(ReturnNewDataTypeManager());
- TokenServiceFactory::GetForProfile(profile())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile())
+ ->UpdateCredentials("test_user", "oauth2_login_token");
+ TokenServiceFactory::GetForProfile(profile())
+ ->IssueAuthTokenForTest(GaiaConstants::kSyncService, "token");
sync_service_->Initialize();
base::MessageLoop::current()->Run();
return true;
diff --git a/chrome/browser/sync/profile_sync_service_startup_unittest.cc b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
index c500634..8a1b6a1 100644
--- a/chrome/browser/sync/profile_sync_service_startup_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
@@ -120,11 +120,13 @@
}
static BrowserContextKeyedService* BuildService(
- content::BrowserContext* profile) {
+ content::BrowserContext* browser_context) {
+ Profile* profile = static_cast<Profile*>(browser_context);
return new TestProfileSyncService(
new ProfileSyncComponentsFactoryMock(),
- static_cast<Profile*>(profile),
- SigninManagerFactory::GetForProfile(static_cast<Profile*>(profile)),
+ profile,
+ SigninManagerFactory::GetForProfile(profile),
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
ProfileSyncService::MANUAL_START,
true);
}
@@ -136,6 +138,13 @@
sync_->set_synchronous_sync_configuration();
}
+ void IssueTestTokens() {
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())
+ ->UpdateCredentials("test_user@gmail.com", "oauth2_login_token");
+ TokenServiceFactory::GetForProfile(profile_.get())
+ ->IssueAuthTokenForTest(GaiaConstants::kSyncService, "token");
+ }
+
protected:
DataTypeManagerMock* SetUpDataTypeManager() {
DataTypeManagerMock* data_type_manager = new DataTypeManagerMock();
@@ -169,12 +178,15 @@
SigninManagerFactory::GetForProfile(profile);
profile->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
"test_user@gmail.com");
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
signin->Initialize(profile, NULL);
EXPECT_FALSE(signin->GetAuthenticatedUsername().empty());
return new TestProfileSyncService(
new ProfileSyncComponentsFactoryMock(),
profile,
signin,
+ oauth2_token_service,
ProfileSyncService::AUTO_START,
true);
}
@@ -220,10 +232,7 @@
content::Details<const GoogleServiceSigninSuccessDetails>(&details));
// Create some tokens in the token service.
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ IssueTestTokens();
// Simulate the UI telling sync it has finished setting up.
sync_->SetSetupInProgress(false);
@@ -351,10 +360,7 @@
EXPECT_CALL(*data_type_manager, Stop()).Times(1);
EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "sync_token");
+ IssueTestTokens();
sync_->Initialize();
EXPECT_TRUE(sync_->ShouldPushChanges());
}
@@ -373,10 +379,7 @@
EXPECT_CALL(*data_type_manager, Stop()).Times(1);
EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "sync_token");
+ IssueTestTokens();
sync_->Initialize();
}
@@ -407,10 +410,7 @@
EXPECT_CALL(*data_type_manager, Stop()).Times(1);
EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "sync_token");
+ IssueTestTokens();
sync_->Initialize();
EXPECT_TRUE(profile_->GetPrefs()->GetBoolean(
@@ -436,10 +436,7 @@
WillRepeatedly(Return(DataTypeManager::CONFIGURED));
EXPECT_CALL(*data_type_manager, Stop()).Times(1);
EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "sync_token");
+ IssueTestTokens();
sync_->Initialize();
EXPECT_FALSE(profile_->GetPrefs()->GetBoolean(
@@ -474,10 +471,7 @@
DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
EXPECT_CALL(*data_type_manager, Configure(_, _));
EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ IssueTestTokens();
sync_->Initialize();
// The service should stop when switching to managed mode.
@@ -525,10 +519,7 @@
EXPECT_CALL(*data_type_manager, state()).
WillOnce(Return(DataTypeManager::STOPPED));
EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ IssueTestTokens();
sync_->Initialize();
EXPECT_TRUE(sync_->HasUnrecoverableError());
}
@@ -544,10 +535,7 @@
profile_->GetPrefs()->ClearPref(prefs::kSyncHasSetupCompleted);
EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ IssueTestTokens();
sync_->fail_initial_download();
sync_->SetSetupInProgress(true);
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 c1f2fd9..9a0abbb 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -238,10 +238,11 @@
EXPECT_CALL(*components, CreateDataTypeManager(_, _, _, _, _, _)).
WillOnce(ReturnNewDataTypeManager());
- token_service_->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- token_service_->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
+ oauth2_token_service->UpdateCredentials("test", "oauth2_login_token");
+ token_service_->IssueAuthTokenForTest(GaiaConstants::kSyncService,
+ "token");
sync_service_->RegisterDataTypeController(data_type_controller);
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index 730002f..1899863 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -50,30 +50,31 @@
done->Signal();
}
-class ProfileSyncServiceTestHarness {
- public:
- ProfileSyncServiceTestHarness()
+class ProfileSyncServiceTest : public testing::Test {
+ protected:
+ ProfileSyncServiceTest()
: thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
content::TestBrowserThreadBundle::REAL_FILE_THREAD |
content::TestBrowserThreadBundle::REAL_IO_THREAD) {
}
- void SetUp() {
+ virtual void SetUp() OVERRIDE {
TestingProfile::Builder builder;
builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
FakeOAuth2TokenService::BuildTokenService);
- profile = builder.Build().Pass();
+ profile_ = builder.Build().Pass();
invalidation::InvalidationServiceFactory::GetInstance()->
SetBuildOnlyFakeInvalidatorsForTest(true);
}
- void TearDown() {
+ virtual void TearDown() OVERRIDE {
// Kill the service before the profile.
- if (service) {
- service->Shutdown();
- }
- service.reset();
- profile.reset();
+ if (service_)
+ service_->Shutdown();
+
+ service_.reset();
+ profile_.reset();
+
// Pump messages posted by the sync thread (which may end up
// posting on the IO thread).
base::RunLoop().RunUntilIdle();
@@ -94,46 +95,51 @@
bool synchronous_sync_configuration,
bool sync_setup_completed,
syncer::StorageOption storage_option) {
- if (!service) {
- SigninManagerBase* signin =
- SigninManagerFactory::GetForProfile(profile.get());
- signin->SetAuthenticatedUsername("test");
- ProfileSyncComponentsFactoryMock* factory =
- new ProfileSyncComponentsFactoryMock();
- service.reset(new TestProfileSyncService(
- factory,
- profile.get(),
- signin,
- ProfileSyncService::AUTO_START,
- true));
- if (!set_initial_sync_ended)
- service->dont_set_initial_sync_ended_on_init();
- if (synchronous_sync_configuration)
- service->set_synchronous_sync_configuration();
- service->set_storage_option(storage_option);
- if (!sync_setup_completed)
- profile->GetPrefs()->SetBoolean(prefs::kSyncHasSetupCompleted, false);
+ if (service_)
+ return;
- // Register the bookmark data type.
- ON_CALL(*factory, CreateDataTypeManager(_, _, _, _, _, _)).
- WillByDefault(ReturnNewDataTypeManager());
+ SigninManagerBase* signin =
+ SigninManagerFactory::GetForProfile(profile_.get());
+ signin->SetAuthenticatedUsername("test");
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
+ ProfileSyncComponentsFactoryMock* factory =
+ new ProfileSyncComponentsFactoryMock();
+ service_.reset(new TestProfileSyncService(
+ factory,
+ profile_.get(),
+ signin,
+ oauth2_token_service,
+ ProfileSyncService::AUTO_START,
+ true));
+ if (!set_initial_sync_ended)
+ service_->dont_set_initial_sync_ended_on_init();
- if (issue_auth_token) {
- IssueTestTokens();
- }
- service->Initialize();
- }
+ if (synchronous_sync_configuration)
+ service_->set_synchronous_sync_configuration();
+
+ service_->set_storage_option(storage_option);
+ if (!sync_setup_completed)
+ profile_->GetPrefs()->SetBoolean(prefs::kSyncHasSetupCompleted, false);
+
+ // Register the bookmark data type.
+ ON_CALL(*factory, CreateDataTypeManager(_, _, _, _, _, _)).
+ WillByDefault(ReturnNewDataTypeManager());
+
+ if (issue_auth_token)
+ IssueTestTokens();
+
+ service_->Initialize();
}
void WaitForBackendInitDone() {
for (int i = 0; i < 5; ++i) {
base::WaitableEvent done(false, false);
- service->GetBackendForTest()->GetSyncLoopForTesting()
- ->PostTask(FROM_HERE,
- base::Bind(&SignalDone, &done));
+ service_->GetBackendForTest()->GetSyncLoopForTesting()
+ ->PostTask(FROM_HERE, base::Bind(&SignalDone, &done));
done.Wait();
base::RunLoop().RunUntilIdle();
- if (service->sync_initialized()) {
+ if (service_->sync_initialized()) {
return;
}
}
@@ -141,16 +147,14 @@
}
void IssueTestTokens() {
- TokenService* token_service =
- TokenServiceFactory::GetForProfile(profile.get());
- token_service->IssueAuthTokenForTest(
- GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
- token_service->IssueAuthTokenForTest(
- GaiaConstants::kSyncService, "token");
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())
+ ->UpdateCredentials("test", "oauth2_login_token");
+ TokenServiceFactory::GetForProfile(profile_.get())
+ ->IssueAuthTokenForTest(GaiaConstants::kSyncService, "token");
}
- scoped_ptr<TestProfileSyncService> service;
- scoped_ptr<TestingProfile> profile;
+ scoped_ptr<TestProfileSyncService> service_;
+ scoped_ptr<TestingProfile> profile_;
private:
content::TestBrowserThreadBundle thread_bundle_;
@@ -169,33 +173,23 @@
bool first_setup_in_progress_;
};
-class ProfileSyncServiceTest : public testing::Test {
- protected:
- virtual void SetUp() {
- harness_.SetUp();
- }
-
- virtual void TearDown() {
- harness_.TearDown();
- }
-
- ProfileSyncServiceTestHarness harness_;
-};
-
TEST_F(ProfileSyncServiceTest, InitialState) {
SigninManagerBase* signin =
- SigninManagerFactory::GetForProfile(harness_.profile.get());
- harness_.service.reset(new TestProfileSyncService(
+ SigninManagerFactory::GetForProfile(profile_.get());
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
+ service_.reset(new TestProfileSyncService(
new ProfileSyncComponentsFactoryMock(),
- harness_.profile.get(),
+ profile_.get(),
signin,
+ oauth2_token_service,
ProfileSyncService::MANUAL_START,
true));
- harness_.service->Initialize();
+ service_->Initialize();
EXPECT_TRUE(
- harness_.service->sync_service_url().spec() ==
+ service_->sync_service_url().spec() ==
ProfileSyncService::kSyncServerUrl ||
- harness_.service->sync_service_url().spec() ==
+ service_->sync_service_url().spec() ==
ProfileSyncService::kDevServerUrl);
}
@@ -203,7 +197,7 @@
// setup state.
TEST(ProfileSyncServiceTestBasic, SetupInProgress) {
ProfileSyncService service(
- NULL, NULL, NULL, ProfileSyncService::MANUAL_START);
+ NULL, NULL, NULL, NULL, ProfileSyncService::MANUAL_START);
TestProfileSyncServiceObserver observer(&service);
service.AddObserver(&observer);
service.SetSetupInProgress(true);
@@ -214,79 +208,88 @@
}
TEST_F(ProfileSyncServiceTest, DisabledByPolicy) {
- harness_.profile->GetTestingPrefService()->SetManagedPref(
+ profile_->GetTestingPrefService()->SetManagedPref(
prefs::kSyncManaged,
Value::CreateBooleanValue(true));
SigninManagerBase* signin =
- SigninManagerFactory::GetForProfile(harness_.profile.get());
- harness_.service.reset(new TestProfileSyncService(
+ SigninManagerFactory::GetForProfile(profile_.get());
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
+ service_.reset(new TestProfileSyncService(
new ProfileSyncComponentsFactoryMock(),
- harness_.profile.get(),
+ profile_.get(),
signin,
+ oauth2_token_service,
ProfileSyncService::MANUAL_START,
true));
- harness_.service->Initialize();
- EXPECT_TRUE(harness_.service->IsManaged());
+ service_->Initialize();
+ EXPECT_TRUE(service_->IsManaged());
}
TEST_F(ProfileSyncServiceTest, AbortedByShutdown) {
SigninManagerBase* signin =
- SigninManagerFactory::GetForProfile(harness_.profile.get());
+ SigninManagerFactory::GetForProfile(profile_.get());
signin->SetAuthenticatedUsername("test");
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
ProfileSyncComponentsFactoryMock* factory =
new ProfileSyncComponentsFactoryMock();
- harness_.service.reset(new TestProfileSyncService(
+ service_.reset(new TestProfileSyncService(
factory,
- harness_.profile.get(),
+ profile_.get(),
signin,
+ oauth2_token_service,
ProfileSyncService::AUTO_START,
true));
EXPECT_CALL(*factory, CreateDataTypeManager(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(*factory, CreateBookmarkSyncComponents(_, _)).
Times(0);
- harness_.service->RegisterDataTypeController(
- new BookmarkDataTypeController(harness_.service->factory(),
- harness_.profile.get(),
- harness_.service.get()));
+ service_->RegisterDataTypeController(
+ new BookmarkDataTypeController(service_->factory(),
+ profile_.get(),
+ service_.get()));
- harness_.service->Initialize();
- harness_.service->Shutdown();
- harness_.service.reset();
+ service_->Initialize();
+ service_->Shutdown();
+ service_.reset();
}
TEST_F(ProfileSyncServiceTest, DisableAndEnableSyncTemporarily) {
SigninManagerBase* signin =
- SigninManagerFactory::GetForProfile(harness_.profile.get());
+ SigninManagerFactory::GetForProfile(profile_.get());
signin->SetAuthenticatedUsername("test");
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
ProfileSyncComponentsFactoryMock* factory =
new ProfileSyncComponentsFactoryMock();
- harness_.service.reset(new TestProfileSyncService(
+ service_.reset(new TestProfileSyncService(
factory,
- harness_.profile.get(),
+ profile_.get(),
signin,
+ oauth2_token_service,
ProfileSyncService::AUTO_START,
true));
// Register the bookmark data type.
EXPECT_CALL(*factory, CreateDataTypeManager(_, _, _, _, _, _)).
WillRepeatedly(ReturnNewDataTypeManager());
- harness_.IssueTestTokens();
+ IssueTestTokens();
- harness_.service->Initialize();
- EXPECT_TRUE(harness_.service->sync_initialized());
- EXPECT_TRUE(harness_.service->GetBackendForTest() != NULL);
+ service_->Initialize();
+ EXPECT_TRUE(service_->sync_initialized());
+ EXPECT_TRUE(service_->GetBackendForTest() != NULL);
EXPECT_FALSE(
- harness_.profile->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
+ profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
- harness_.service->StopAndSuppress();
- EXPECT_FALSE(harness_.service->sync_initialized());
+ service_->StopAndSuppress();
+ EXPECT_FALSE(service_->sync_initialized());
EXPECT_TRUE(
- harness_.profile->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
+ profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
- harness_.service->UnsuppressAndStart();
- EXPECT_TRUE(harness_.service->sync_initialized());
+ service_->UnsuppressAndStart();
+ EXPECT_TRUE(service_->sync_initialized());
EXPECT_FALSE(
- harness_.profile->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
+ profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
}
// Certain ProfileSyncService tests don't apply to Chrome OS, for example
@@ -295,41 +298,44 @@
TEST_F(ProfileSyncServiceTest, EnableSyncAndSignOut) {
SigninManager* signin =
- SigninManagerFactory::GetForProfile(harness_.profile.get());
- signin->SetAuthenticatedUsername("test@test.com");
+ SigninManagerFactory::GetForProfile(profile_.get());
+ signin->SetAuthenticatedUsername("test");
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
ProfileSyncComponentsFactoryMock* factory =
new ProfileSyncComponentsFactoryMock();
- harness_.service.reset(new TestProfileSyncService(
+ service_.reset(new TestProfileSyncService(
factory,
- harness_.profile.get(),
+ profile_.get(),
signin,
+ oauth2_token_service,
ProfileSyncService::AUTO_START,
true));
// Register the bookmark data type.
EXPECT_CALL(*factory, CreateDataTypeManager(_, _, _, _, _, _)).
WillRepeatedly(ReturnNewDataTypeManager());
- harness_.IssueTestTokens();
+ IssueTestTokens();
- harness_.service->Initialize();
- EXPECT_TRUE(harness_.service->sync_initialized());
- EXPECT_TRUE(harness_.service->GetBackendForTest() != NULL);
+ service_->Initialize();
+ EXPECT_TRUE(service_->sync_initialized());
+ EXPECT_TRUE(service_->GetBackendForTest() != NULL);
EXPECT_FALSE(
- harness_.profile->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
+ profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
signin->SignOut();
- EXPECT_FALSE(harness_.service->sync_initialized());
+ EXPECT_FALSE(service_->sync_initialized());
}
#endif // !defined(OS_CHROMEOS)
TEST_F(ProfileSyncServiceTest, JsControllerHandlersBasic) {
- harness_.StartSyncService();
- EXPECT_TRUE(harness_.service->sync_initialized());
- EXPECT_TRUE(harness_.service->GetBackendForTest() != NULL);
+ StartSyncService();
+ EXPECT_TRUE(service_->sync_initialized());
+ EXPECT_TRUE(service_->GetBackendForTest() != NULL);
base::WeakPtr<syncer::JsController> js_controller =
- harness_.service->GetJsController();
+ service_->GetJsController();
StrictMock<syncer::MockJsEventHandler> event_handler;
js_controller->AddJsEventHandler(&event_handler);
js_controller->RemoveJsEventHandler(&event_handler);
@@ -337,28 +343,28 @@
TEST_F(ProfileSyncServiceTest,
JsControllerHandlersDelayedBackendInitialization) {
- harness_.StartSyncServiceAndSetInitialSyncEnded(true, false, false, true,
+ StartSyncServiceAndSetInitialSyncEnded(true, false, false, true,
syncer::STORAGE_IN_MEMORY);
StrictMock<syncer::MockJsEventHandler> event_handler;
EXPECT_CALL(event_handler, HandleJsEvent(_, _)).Times(AtLeast(1));
- EXPECT_EQ(NULL, harness_.service->GetBackendForTest());
- EXPECT_FALSE(harness_.service->sync_initialized());
+ EXPECT_EQ(NULL, service_->GetBackendForTest());
+ EXPECT_FALSE(service_->sync_initialized());
base::WeakPtr<syncer::JsController> js_controller =
- harness_.service->GetJsController();
+ service_->GetJsController();
js_controller->AddJsEventHandler(&event_handler);
// Since we're doing synchronous initialization, backend should be
// initialized by this call.
- harness_.IssueTestTokens();
- EXPECT_TRUE(harness_.service->sync_initialized());
+ IssueTestTokens();
+ EXPECT_TRUE(service_->sync_initialized());
js_controller->RemoveJsEventHandler(&event_handler);
}
TEST_F(ProfileSyncServiceTest, JsControllerProcessJsMessageBasic) {
- harness_.StartSyncService();
- harness_.WaitForBackendInitDone();
+ StartSyncService();
+ WaitForBackendInitDone();
StrictMock<syncer::MockJsReplyHandler> reply_handler;
@@ -370,23 +376,27 @@
{
base::WeakPtr<syncer::JsController> js_controller =
- harness_.service->GetJsController();
+ service_->GetJsController();
js_controller->ProcessJsMessage("getNotificationState", args1,
reply_handler.AsWeakHandle());
}
// This forces the sync thread to process the message and reply.
base::WaitableEvent done(false, false);
- harness_.service->GetBackendForTest()->GetSyncLoopForTesting()
+ service_->GetBackendForTest()->GetSyncLoopForTesting()
->PostTask(FROM_HERE,
base::Bind(&SignalDone, &done));
done.Wait();
- harness_.TearDown();
+
+ // Call TearDown() to flush the message loops before the mock is destroyed.
+ // TearDown() is idempotent, so it's not a problem that it gets called by the
+ // test fixture again later.
+ TearDown();
}
TEST_F(ProfileSyncServiceTest,
JsControllerProcessJsMessageBasicDelayedBackendInitialization) {
- harness_.StartSyncServiceAndSetInitialSyncEnded(true, false, false, true,
+ StartSyncServiceAndSetInitialSyncEnded(true, false, false, true,
syncer::STORAGE_IN_MEMORY);
StrictMock<syncer::MockJsReplyHandler> reply_handler;
@@ -399,20 +409,20 @@
{
base::WeakPtr<syncer::JsController> js_controller =
- harness_.service->GetJsController();
+ service_->GetJsController();
js_controller->ProcessJsMessage("getNotificationState",
args1, reply_handler.AsWeakHandle());
}
- harness_.IssueTestTokens();
- harness_.WaitForBackendInitDone();
+ IssueTestTokens();
+ WaitForBackendInitDone();
// This forces the sync thread to process the message and reply.
base::WaitableEvent done(false, false);
- harness_.service->GetBackendForTest()->GetSyncLoopForTesting()
+ service_->GetBackendForTest()->GetSyncLoopForTesting()
->PostTask(FROM_HERE,
base::Bind(&SignalDone, &done));
- done.Wait(); harness_.TearDown();
+ done.Wait();
}
// Make sure that things still work if sync is not enabled, but some old sync
@@ -422,7 +432,7 @@
const char* nonsense2 = "beartato";
const char* nonsense3 = "harrison";
base::FilePath temp_directory =
- harness_.profile->GetPath().AppendASCII("Sync Data");
+ profile_->GetPath().AppendASCII("Sync Data");
base::FilePath sync_file1 =
temp_directory.AppendASCII("BookmarkSyncSettings.sqlite3");
base::FilePath sync_file2 = temp_directory.AppendASCII("SyncData.sqlite3");
@@ -435,19 +445,19 @@
ASSERT_NE(-1,
file_util::WriteFile(sync_file3, nonsense3, strlen(nonsense3)));
- harness_.StartSyncServiceAndSetInitialSyncEnded(true, false, true, false,
+ StartSyncServiceAndSetInitialSyncEnded(true, false, true, false,
syncer::STORAGE_ON_DISK);
- EXPECT_FALSE(harness_.service->HasSyncSetupCompleted());
- EXPECT_FALSE(harness_.service->sync_initialized());
+ EXPECT_FALSE(service_->HasSyncSetupCompleted());
+ EXPECT_FALSE(service_->sync_initialized());
// Since we're doing synchronous initialization, backend should be
// initialized by this call.
- harness_.IssueTestTokens();
+ IssueTestTokens();
// Stop the service so we can read the new Sync Data files that were
// created.
- harness_.service->Shutdown();
- harness_.service.reset();
+ service_->Shutdown();
+ service_.reset();
// This file should have been deleted when the whole directory was nuked.
ASSERT_FALSE(base::PathExists(sync_file3));
@@ -464,11 +474,11 @@
// recreate it. This test is useful mainly when it is run under valgrind. Its
// expectations are not very interesting.
TEST_F(ProfileSyncServiceTest, FailToOpenDatabase) {
- harness_.StartSyncServiceAndSetInitialSyncEnded(false, true, true, true,
+ StartSyncServiceAndSetInitialSyncEnded(false, true, true, true,
syncer::STORAGE_INVALID);
// The backend is not ready. Ensure the PSS knows this.
- EXPECT_FALSE(harness_.service->sync_initialized());
+ EXPECT_FALSE(service_->sync_initialized());
}
// This setup will allow the database to exist, but leave it empty. The attempt
@@ -476,11 +486,11 @@
// these tests). The sync_backend_host will notice this and inform the profile
// sync service of the failure to initialize the backed.
TEST_F(ProfileSyncServiceTest, FailToDownloadControlTypes) {
- harness_.StartSyncServiceAndSetInitialSyncEnded(false, true, true, true,
+ StartSyncServiceAndSetInitialSyncEnded(false, true, true, true,
syncer::STORAGE_IN_MEMORY);
// The backend is not ready. Ensure the PSS knows this.
- EXPECT_FALSE(harness_.service->sync_initialized());
+ EXPECT_FALSE(service_->sync_initialized());
}
} // namespace
diff --git a/chrome/browser/sync/sessions2/tab_node_pool2.cc b/chrome/browser/sync/sessions2/tab_node_pool2.cc
index 459186b..70bc225 100644
--- a/chrome/browser/sync/sessions2/tab_node_pool2.cc
+++ b/chrome/browser/sync/sessions2/tab_node_pool2.cc
@@ -15,10 +15,6 @@
namespace browser_sync {
-static const char kNoSessionsFolderError[] =
- "Server did not create the top-level sessions node. We "
- "might be running against an out-of-date server.";
-
const size_t TabNodePool2::kFreeNodesLowWatermark = 25;
const size_t TabNodePool2::kFreeNodesHighWatermark = 100;
diff --git a/chrome/browser/sync/test/integration/bookmarks_helper.cc b/chrome/browser/sync/test/integration/bookmarks_helper.cc
index a59c28c..6340788 100644
--- a/chrome/browser/sync/test/integration/bookmarks_helper.cc
+++ b/chrome/browser/sync/test/integration/bookmarks_helper.cc
@@ -292,9 +292,9 @@
// Compare only the 1x bitmaps as only those are synced.
SkBitmap bitmap_a = image_a.AsImageSkia().GetRepresentation(
- ui::SCALE_FACTOR_100P).sk_bitmap();
+ 1.0f).sk_bitmap();
SkBitmap bitmap_b = image_b.AsImageSkia().GetRepresentation(
- ui::SCALE_FACTOR_100P).sk_bitmap();
+ 1.0f).sk_bitmap();
return FaviconBitmapsMatch(bitmap_a, bitmap_b);
}
@@ -714,14 +714,16 @@
FaviconUtil::GetFaviconScaleFactors();
gfx::ImageSkia favicon;
for (size_t i = 0; i < favicon_scale_factors.size(); ++i) {
- float scale = ui::GetScaleFactorScale(favicon_scale_factors[i]);
+ float scale = ui::GetImageScale(favicon_scale_factors[i]);
int pixel_width = dip_width * scale;
int pixel_height = dip_height * scale;
SkBitmap bmp;
bmp.setConfig(SkBitmap::kARGB_8888_Config, pixel_width, pixel_height);
bmp.allocPixels();
bmp.eraseColor(color);
- favicon.AddRepresentation(gfx::ImageSkiaRep(bmp, favicon_scale_factors[i]));
+ favicon.AddRepresentation(
+ gfx::ImageSkiaRep(bmp,
+ ui::GetImageScale(favicon_scale_factors[i])));
}
return gfx::Image(favicon);
}
diff --git a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
index 83ca050..771b1a6 100644
--- a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
@@ -163,7 +163,7 @@
std::vector<ui::ScaleFactor> supported_scale_factors;
supported_scale_factors.push_back(ui::SCALE_FACTOR_100P);
supported_scale_factors.push_back(ui::SCALE_FACTOR_200P);
- ui::test::SetSupportedScaleFactors(supported_scale_factors);
+ ui::SetSupportedScaleFactors(supported_scale_factors);
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(ModelMatchesVerifier(0));
diff --git a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
index 171f0f5..367f209 100644
--- a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
@@ -165,7 +165,7 @@
std::vector<ui::ScaleFactor> supported_scale_factors;
supported_scale_factors.push_back(ui::SCALE_FACTOR_100P);
supported_scale_factors.push_back(ui::SCALE_FACTOR_200P);
- ui::test::SetSupportedScaleFactors(supported_scale_factors);
+ ui::SetSupportedScaleFactors(supported_scale_factors);
const GURL page_url(kGenericURL);
const GURL icon_url1("http://www.google.com/favicon1.ico");
diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc
index 2edd436..92d3828 100644
--- a/chrome/browser/sync/test_profile_sync_service.cc
+++ b/chrome/browser/sync/test_profile_sync_service.cc
@@ -208,11 +208,13 @@
ProfileSyncComponentsFactory* factory,
Profile* profile,
SigninManagerBase* signin,
+ ProfileOAuth2TokenService* oauth2_token_service,
ProfileSyncService::StartBehavior behavior,
bool synchronous_backend_initialization)
: ProfileSyncService(factory,
profile,
signin,
+ oauth2_token_service,
behavior),
synchronous_backend_initialization_(
synchronous_backend_initialization),
@@ -232,10 +234,16 @@
Profile* profile = static_cast<Profile*>(context);
SigninManagerBase* signin =
SigninManagerFactory::GetForProfile(profile);
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
ProfileSyncComponentsFactoryMock* factory =
new ProfileSyncComponentsFactoryMock();
- return new TestProfileSyncService(
- factory, profile, signin, ProfileSyncService::AUTO_START, false);
+ return new TestProfileSyncService(factory,
+ profile,
+ signin,
+ oauth2_token_service,
+ ProfileSyncService::AUTO_START,
+ false);
}
ProfileSyncComponentsFactoryMock*
@@ -313,17 +321,20 @@
storage_option_));
}
-scoped_ptr<OAuth2TokenService::Request> FakeOAuth2TokenService::StartRequest(
- const OAuth2TokenService::ScopeSet& scopes,
- OAuth2TokenService::Consumer* consumer) {
- // Ensure token in question is cached and never expires. Request will succeed
- // without network IO.
- RegisterCacheEntry("test_client_id",
- GetRefreshToken(),
- scopes,
- "access_token",
- base::Time::Max());
- return ProfileOAuth2TokenService::StartRequest(scopes, consumer);
+void FakeOAuth2TokenService::FetchOAuth2Token(
+ OAuth2TokenService::RequestImpl* request,
+ const std::string& account_id,
+ net::URLRequestContextGetter* getter,
+ const std::string& client_id,
+ const std::string& client_secret,
+ const OAuth2TokenService::ScopeSet& scopes) {
+ // Request will succeed without network IO.
+ base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ &RequestImpl::InformConsumer,
+ request->AsWeakPtr(),
+ GoogleServiceAuthError(GoogleServiceAuthError::NONE),
+ "access_token",
+ base::Time::Max()));
}
BrowserContextKeyedService* FakeOAuth2TokenService::BuildTokenService(
@@ -334,3 +345,14 @@
service->Initialize(profile);
return service;
}
+
+void FakeOAuth2TokenService::PersistCredentials(
+ const std::string& account_id,
+ const std::string& refresh_token) {
+ // Disabling the token persistence.
+}
+
+void FakeOAuth2TokenService::ClearPersistedCredentials(
+ const std::string& account_id) {
+ // Disabling the token persistence.
+}
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index 3eb6317..999ea58 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -24,8 +24,6 @@
#include "testing/gmock/include/gmock/gmock.h"
class Profile;
-class Task;
-class TestProfileSyncService;
ACTION(ReturnNewDataTypeManager) {
return new browser_sync::DataTypeManagerImpl(arg0,
@@ -121,6 +119,7 @@
ProfileSyncComponentsFactory* factory,
Profile* profile,
SigninManagerBase* signin,
+ ProfileOAuth2TokenService* oauth2_token_service,
ProfileSyncService::StartBehavior behavior,
bool synchronous_backend_initialization);
@@ -199,12 +198,23 @@
class FakeOAuth2TokenService : public ProfileOAuth2TokenService {
public:
- virtual scoped_ptr<OAuth2TokenService::Request> StartRequest(
- const OAuth2TokenService::ScopeSet& scopes,
- OAuth2TokenService::Consumer* consumer) OVERRIDE;
-
static BrowserContextKeyedService* BuildTokenService(
content::BrowserContext* context);
+
+ protected:
+ virtual void FetchOAuth2Token(
+ OAuth2TokenService::RequestImpl* request,
+ const std::string& account_id,
+ net::URLRequestContextGetter* getter,
+ const std::string& client_id,
+ const std::string& client_secret,
+ const OAuth2TokenService::ScopeSet& scopes) OVERRIDE;
+
+ virtual void PersistCredentials(const std::string& account_id,
+ const std::string& refresh_token) OVERRIDE;
+
+ virtual void ClearPersistedCredentials(
+ const std::string& account_id) OVERRIDE;
};
#endif // CHROME_BROWSER_SYNC_TEST_PROFILE_SYNC_SERVICE_H_
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_constants.cc b/chrome/browser/sync_file_system/drive_backend/drive_backend_constants.cc
new file mode 100644
index 0000000..7b3e653
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_constants.cc
@@ -0,0 +1,15 @@
+// Copyright 2013 The Chromium 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/drive_backend_constants.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+const char kSyncRootFolderTitle[] = "Chrome Syncable FileSystem";
+const base::FilePath::CharType kDatabaseName[] =
+ FILE_PATH_LITERAL("DriveMetadata");
+
+} // namespace drive_backend
+} // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h b/chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h
new file mode 100644
index 0000000..d6c363d
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h
@@ -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.
+
+#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_DRIVE_BACKEND_CONSTANTS_H_
+#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_DRIVE_BACKEND_CONSTANTS_H_
+
+#include "base/files/file_path.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+extern const char kSyncRootFolderTitle[];
+extern const base::FilePath::CharType kDatabaseName[];
+
+} // namespace drive_backend
+} // namespace sync_file_system
+
+#endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_DRIVE_BACKEND_CONSTANTS_H_
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.cc b/chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.cc
index 47a4019..895ecbd 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.cc
@@ -86,7 +86,6 @@
}
EXPECT_EQ(resource.md5_checksum(), details.md5());
- EXPECT_EQ(resource.etag(), details.etag());
EXPECT_EQ(resource.created_date(),
base::Time::FromInternalValue(details.creation_time()));
EXPECT_EQ(resource.modified_date(),
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.h b/chrome/browser/sync_file_system/drive_backend/metadata_database.h
index e956e8f..fa6ccc6 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database.h
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.h
@@ -216,6 +216,8 @@
const SyncStatusCallback& callback);
private:
+ friend class SyncEngineInitializerTest;
+
struct DirtyTrackerComparator {
bool operator()(const FileTracker* left,
const FileTracker* right) const;
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
index 09e3486..26ab638 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/drive/drive_api_service.h"
+#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
#include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
#include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h"
@@ -16,12 +17,6 @@
namespace sync_file_system {
namespace drive_backend {
-namespace {
-// TODO(tzik): Move this to separate file and consolidate with
-// DriveMetadataStore::kDatabaseName.
-base::FilePath::CharType kDatabaseName[] = FILE_PATH_LITERAL("DriveMetadata");
-} // namespace
-
SyncEngine::SyncEngine(
const base::FilePath& base_dir,
base::SequencedTaskRunner* task_runner,
@@ -94,11 +89,12 @@
void SyncEngine::UninstallOrigin(
const GURL& origin,
+ UninstallFlag flag,
const SyncStatusCallback& callback) {
task_manager_.ScheduleTask(
base::Bind(&SyncEngine::DoUninstallApp,
weak_ptr_factory_.GetWeakPtr(),
- origin.host()),
+ origin.host(), flag),
callback);
}
@@ -217,6 +213,7 @@
}
void SyncEngine::DoUninstallApp(const std::string& app_id,
+ UninstallFlag flag,
const SyncStatusCallback& callback) {
NOTIMPLEMENTED();
}
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.h b/chrome/browser/sync_file_system/drive_backend/sync_engine.h
index f37e643..7dded38 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine.h
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.h
@@ -62,6 +62,7 @@
const SyncStatusCallback& callback) OVERRIDE;
virtual void UninstallOrigin(
const GURL& origin,
+ UninstallFlag flag,
const SyncStatusCallback& callback) OVERRIDE;
virtual void ProcessRemoteChange(const SyncFileCallback& callback) OVERRIDE;
virtual void SetRemoteChangeProcessor(
@@ -107,6 +108,7 @@
void DoEnableApp(const std::string& app_id,
const SyncStatusCallback& callback);
void DoUninstallApp(const std::string& app_id,
+ UninstallFlag flag,
const SyncStatusCallback& callback);
void DidInitialize(SyncEngineInitializer* initializer,
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc
index 34f8d13..a634306 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/drive/drive_api_util.h"
#include "chrome/browser/google_apis/drive_api_parser.h"
#include "chrome/browser/google_apis/gdata_wapi_parser.h"
+#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
#include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_util.h"
@@ -19,9 +20,6 @@
namespace {
-// TODO(tzik): Move them to separate file.
-const char kSyncRootFolderTitle[] = "Chrome Syncable FileSystem";
-
////////////////////////////////////////////////////////////////////////////////
// Functions below are for wrapping the access to legacy GData WAPI classes.
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer_unittest.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer_unittest.cc
index 127284e..b4ba140 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer_unittest.cc
@@ -11,8 +11,11 @@
#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/sync_file_system/drive_backend/drive_backend_constants.h"
+#include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
+#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,24 +24,7 @@
namespace {
-void SyncStatusResultCallback(SyncStatusCode* status_out,
- SyncStatusCode status) {
- ASSERT_TRUE(status_out);
- EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out);
- *status_out = status;
-}
-
-void ResourceEntryResultCallback(
- google_apis::GDataErrorCode* error_out,
- scoped_ptr<google_apis::ResourceEntry>* entry_out,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- ASSERT_TRUE(error_out);
- ASSERT_TRUE(entry_out);
- EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, *error_out);
- *error_out = error;
- *entry_out = entry.Pass();
-}
+const int64 kInitialLargestChangeID = 1234;
} // namespace
@@ -62,6 +48,9 @@
}
virtual void TearDown() OVERRIDE {
+ initializer_.reset();
+ metadata_database_.reset();
+ base::MessageLoop::current()->RunUntilIdle();
}
base::FilePath database_path() {
@@ -75,7 +64,7 @@
database_path()));
SyncStatusCode status = SYNC_STATUS_UNKNOWN;
- initializer_->Run(base::Bind(&SyncStatusResultCallback, &status));
+ initializer_->Run(CreateResultReceiver(&status));
base::MessageLoop::current()->RunUntilIdle();
metadata_database_ = initializer_->PassMetadataDatabase();
@@ -95,10 +84,8 @@
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::ResourceEntry> entry;
- fake_drive_service_.GetResourceEntry(
- file->metadata.file_id(),
- base::Bind(&ResourceEntryResultCallback,
- &error, &entry));
+ fake_drive_service_.GetResourceEntry(file->metadata.file_id(),
+ CreateResultReceiver(&error, &entry));
base::MessageLoop::current()->RunUntilIdle();
if (entry) {
@@ -111,11 +98,121 @@
return error;
}
- google_apis::GDataErrorCode GetSyncRoot(
- scoped_ptr<TrackedFile>* sync_root_out) {
- return FillTrackedFileByTrackerID(
- metadata_database_->GetSyncRootTrackerID(),
- sync_root_out);
+ SyncStatusCode PopulateDatabase(
+ const google_apis::FileResource& sync_root,
+ const google_apis::FileResource** app_roots,
+ size_t app_roots_count) {
+ SyncStatusCode status = SYNC_STATUS_UNKNOWN;
+ scoped_ptr<MetadataDatabase> database;
+ MetadataDatabase::Create(
+ base::MessageLoopProxy::current(),
+ database_path(),
+ CreateResultReceiver(&status, &database));
+ base::MessageLoop::current()->RunUntilIdle();
+ if (status != SYNC_STATUS_OK)
+ return status;
+
+ // |app_root_list| must not own the resources here. Be sure to call
+ // weak_clear later.
+ ScopedVector<google_apis::FileResource> app_root_list;
+ for (size_t i = 0; i < app_roots_count; ++i) {
+ app_root_list.push_back(
+ const_cast<google_apis::FileResource*>(app_roots[i]));
+ }
+
+ status = SYNC_STATUS_UNKNOWN;
+ database->PopulateInitialData(kInitialLargestChangeID,
+ sync_root,
+ app_root_list,
+ CreateResultReceiver(&status));
+ base::MessageLoop::current()->RunUntilIdle();
+
+ app_root_list.weak_clear();
+
+ return SYNC_STATUS_OK;
+ }
+
+ scoped_ptr<google_apis::FileResource> CreateRemoteFolder(
+ const std::string& parent_folder_id,
+ const std::string& title) {
+ google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+ scoped_ptr<google_apis::ResourceEntry> entry;
+ fake_drive_service_.AddNewDirectory(
+ parent_folder_id, title,
+ CreateResultReceiver(&error, &entry));
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(google_apis::HTTP_CREATED, error);
+ if (!entry)
+ scoped_ptr<google_apis::FileResource>();
+ return drive::util::ConvertResourceEntryToFileResource(*entry);
+ }
+
+ scoped_ptr<google_apis::FileResource> CreateRemoteSyncRoot() {
+ scoped_ptr<google_apis::FileResource> sync_root(
+ CreateRemoteFolder(std::string(), kSyncRootFolderTitle));
+
+ for (size_t i = 0; i < sync_root->parents().size(); ++i) {
+ google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+ fake_drive_service_.RemoveResourceFromDirectory(
+ sync_root->parents()[i]->file_id(),
+ sync_root->file_id(),
+ CreateResultReceiver(&error));
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+ }
+
+ return sync_root.Pass();
+ }
+
+ std::string GetSyncRootFolderID() {
+ int64 sync_root_tracker_id = metadata_database_->GetSyncRootTrackerID();
+ FileTracker sync_root_tracker;
+ EXPECT_TRUE(metadata_database_->FindTrackerByTrackerID(
+ sync_root_tracker_id, &sync_root_tracker));
+ return sync_root_tracker.file_id();
+ }
+
+ size_t CountTrackersForFile(const std::string& file_id) {
+ TrackerSet trackers;
+ metadata_database_->FindTrackersByFileID(file_id, &trackers);
+ return trackers.tracker_set().size();
+ }
+
+ bool HasActiveTracker(const std::string& file_id) {
+ TrackerSet trackers;
+ return metadata_database_->FindTrackersByFileID(file_id, &trackers) &&
+ trackers.has_active();
+ }
+
+ bool HasNoParent(const std::string& file_id) {
+ google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+ scoped_ptr<google_apis::ResourceEntry> entry;
+ fake_drive_service_.GetResourceEntry(
+ file_id,
+ CreateResultReceiver(&error, &entry));
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
+ return !entry->GetLinkByType(google_apis::Link::LINK_PARENT);
+ }
+
+ size_t NumberOfMetadata() {
+ return metadata_database_->file_by_id_.size();
+ }
+
+ size_t NumberOfTrackers() {
+ return metadata_database_->tracker_by_id_.size();
+ }
+
+ google_apis::GDataErrorCode AddParentFolder(
+ const std::string& new_parent_folder_id,
+ const std::string& file_id) {
+ google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+ fake_drive_service_.AddResourceToDirectory(
+ new_parent_folder_id, file_id,
+ CreateResultReceiver(&error));
+ base::MessageLoop::current()->RunUntilIdle();
+ return error;
}
private:
@@ -132,9 +229,125 @@
TEST_F(SyncEngineInitializerTest, EmptyDatabase_NoRemoteSyncRoot) {
EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
- scoped_ptr<TrackedFile> sync_root;
- ASSERT_EQ(google_apis::HTTP_SUCCESS, GetSyncRoot(&sync_root));
- EXPECT_EQ("Chrome Syncable FileSystem", sync_root->resource->title());
+ std::string sync_root_folder_id = GetSyncRootFolderID();
+ EXPECT_EQ(1u, CountTrackersForFile(sync_root_folder_id));
+
+ EXPECT_TRUE(HasActiveTracker(sync_root_folder_id));
+
+ EXPECT_EQ(1u, NumberOfMetadata());
+ EXPECT_EQ(1u, NumberOfTrackers());
+}
+
+TEST_F(SyncEngineInitializerTest, EmptyDatabase_RemoteSyncRootExists) {
+ scoped_ptr<google_apis::FileResource> sync_root(
+ CreateRemoteSyncRoot());
+ scoped_ptr<google_apis::FileResource> app_root_1(
+ CreateRemoteFolder(sync_root->file_id(), "app-root 1"));
+ scoped_ptr<google_apis::FileResource> app_root_2(
+ CreateRemoteFolder(sync_root->file_id(), "app-root 2"));
+
+ EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
+
+ EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
+ EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id()));
+ EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id()));
+
+ EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
+ EXPECT_FALSE(HasActiveTracker(app_root_1->file_id()));
+ EXPECT_FALSE(HasActiveTracker(app_root_2->file_id()));
+
+ EXPECT_EQ(3u, NumberOfMetadata());
+ EXPECT_EQ(3u, NumberOfTrackers());
+}
+
+TEST_F(SyncEngineInitializerTest, DatabaseAlreadyInitialized) {
+ scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteSyncRoot());
+ scoped_ptr<google_apis::FileResource> app_root_1(
+ CreateRemoteFolder(sync_root->file_id(), "app-root 1"));
+ scoped_ptr<google_apis::FileResource> app_root_2(
+ CreateRemoteFolder(sync_root->file_id(), "app-root 2"));
+
+ const google_apis::FileResource* app_roots[] = {
+ app_root_1.get(), app_root_2.get()
+ };
+ EXPECT_EQ(SYNC_STATUS_OK,
+ PopulateDatabase(*sync_root, app_roots, arraysize(app_roots)));
+
+ EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
+
+ EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
+ EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id()));
+ EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id()));
+
+ EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
+ EXPECT_FALSE(HasActiveTracker(app_root_1->file_id()));
+ EXPECT_FALSE(HasActiveTracker(app_root_2->file_id()));
+
+ EXPECT_EQ(3u, NumberOfMetadata());
+ EXPECT_EQ(3u, NumberOfTrackers());
+}
+
+TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiCandidate) {
+ scoped_ptr<google_apis::FileResource> sync_root_1(CreateRemoteSyncRoot());
+ scoped_ptr<google_apis::FileResource> sync_root_2(CreateRemoteSyncRoot());
+
+ EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
+
+ EXPECT_EQ(1u, CountTrackersForFile(sync_root_1->file_id()));
+ EXPECT_EQ(0u, CountTrackersForFile(sync_root_2->file_id()));
+
+ EXPECT_TRUE(HasActiveTracker(sync_root_1->file_id()));
+ EXPECT_FALSE(HasActiveTracker(sync_root_2->file_id()));
+
+ EXPECT_EQ(1u, NumberOfMetadata());
+ EXPECT_EQ(1u, NumberOfTrackers());
+}
+
+TEST_F(SyncEngineInitializerTest, EmptyDatabase_UndetachedRemoteSyncRoot) {
+ scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
+ std::string(), kSyncRootFolderTitle));
+ EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
+
+ EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
+ EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
+
+ EXPECT_TRUE(HasNoParent(sync_root->file_id()));
+
+ EXPECT_EQ(1u, NumberOfMetadata());
+ EXPECT_EQ(1u, NumberOfTrackers());
+}
+
+TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiparentSyncRoot) {
+ scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder(
+ std::string(), "folder"));
+ scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
+ std::string(), kSyncRootFolderTitle));
+ AddParentFolder(sync_root->file_id(), folder->file_id());
+
+ EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
+
+ EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
+ EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
+
+ EXPECT_TRUE(HasNoParent(sync_root->file_id()));
+
+ EXPECT_EQ(1u, NumberOfMetadata());
+ EXPECT_EQ(1u, NumberOfTrackers());
+}
+
+TEST_F(SyncEngineInitializerTest, EmptyDatabase_FakeRemoteSyncRoot) {
+ scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder(
+ std::string(), "folder"));
+ scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
+ folder->file_id(), kSyncRootFolderTitle));
+
+ EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
+
+ EXPECT_EQ(0u, CountTrackersForFile(sync_root->file_id()));
+ EXPECT_FALSE(HasNoParent(sync_root->file_id()));
+
+ EXPECT_EQ(1u, NumberOfMetadata());
+ EXPECT_EQ(1u, NumberOfTrackers());
}
} // namespace drive_backend
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/api_util.cc b/chrome/browser/sync_file_system/drive_backend_v1/api_util.cc
index a5b08df..7086db9 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/api_util.cc
+++ b/chrome/browser/sync_file_system/drive_backend_v1/api_util.cc
@@ -44,6 +44,7 @@
const char kSyncRootDirectoryNameDev[] = "Chrome Syncable FileSystem Dev";
const char kMimeTypeOctetStream[] = "application/octet-stream";
+const char kFakeAccountId[] = "test_user@gmail.com";
const char kFakeServerBaseUrl[] = "https://fake_server/";
const char kFakeDownloadServerBaseUrl[] = "https://fake_download_server/";
@@ -168,7 +169,7 @@
kBaseDownloadUrlForProduction)),
upload_next_key_(0),
temp_dir_path_(temp_dir_path) {
- OAuth2TokenService* oauth_service =
+ ProfileOAuth2TokenService* oauth_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
if (IsDriveAPIDisabled()) {
drive_service_.reset(new drive::GDataWapiService(
@@ -189,7 +190,7 @@
std::string() /* custom_user_agent */));
}
- drive_service_->Initialize();
+ drive_service_->Initialize(oauth_service->GetPrimaryAccountId());
drive_service_->AddObserver(this);
net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
@@ -206,20 +207,22 @@
GURL(kFakeServerBaseUrl),
GURL(kFakeDownloadServerBaseUrl),
drive_service.Pass(),
- drive_uploader.Pass()));
+ drive_uploader.Pass(),
+ kFakeAccountId));
}
APIUtil::APIUtil(const base::FilePath& temp_dir_path,
const GURL& base_url,
const GURL& base_download_url,
scoped_ptr<drive::DriveServiceInterface> drive_service,
- scoped_ptr<drive::DriveUploaderInterface> drive_uploader)
+ scoped_ptr<drive::DriveUploaderInterface> drive_uploader,
+ const std::string& account_id)
: wapi_url_generator_(base_url, base_download_url),
drive_api_url_generator_(base_url, base_download_url),
upload_next_key_(0),
temp_dir_path_(temp_dir_path) {
drive_service_ = drive_service.Pass();
- drive_service_->Initialize();
+ drive_service_->Initialize(account_id);
drive_service_->AddObserver(this);
net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/api_util.h b/chrome/browser/sync_file_system/drive_backend_v1/api_util.h
index 009ba00..4208f72 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/api_util.h
+++ b/chrome/browser/sync_file_system/drive_backend_v1/api_util.h
@@ -118,7 +118,8 @@
const GURL& base_url,
const GURL& base_download_url,
scoped_ptr<drive::DriveServiceInterface> drive_service,
- scoped_ptr<drive::DriveUploaderInterface> drive_uploader);
+ scoped_ptr<drive::DriveUploaderInterface> drive_uploader,
+ const std::string& account_id);
void GetDriveRootResourceId(const GDataErrorCallback& callback);
void DidGetDriveRootResourceId(
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.cc b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.cc
index 39f2db2..bb5fbe0 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.cc
@@ -172,10 +172,12 @@
void DriveFileSyncService::UninstallOrigin(
const GURL& origin,
+ UninstallFlag flag,
const SyncStatusCallback& callback) {
pending_origin_operations_.Push(origin, OriginOperation::UNINSTALLING);
task_manager_->ScheduleTaskAtPriority(
- base::Bind(&DriveFileSyncService::DoUninstallOrigin, AsWeakPtr(), origin),
+ base::Bind(&DriveFileSyncService::DoUninstallOrigin, AsWeakPtr(),
+ origin, flag),
SyncTaskManager::PRIORITY_HIGH,
callback);
}
@@ -559,6 +561,7 @@
void DriveFileSyncService::DoUninstallOrigin(
const GURL& origin,
+ UninstallFlag flag,
const SyncStatusCallback& callback) {
OriginOperation op = pending_origin_operations_.Pop();
DCHECK_EQ(origin, op.origin);
@@ -585,6 +588,11 @@
return;
}
+ if (flag == UNINSTALL_AND_KEEP_REMOTE) {
+ DidUninstallOrigin(origin, callback, google_apis::HTTP_SUCCESS);
+ return;
+ }
+
// Convert origin's directory GURL to ResourceID and delete it. Expected MD5
// is empty to force delete (i.e. skip conflict resolution).
api_util_->DeleteFile(resource_id,
@@ -754,7 +762,11 @@
if (!extension_service->GetInstalledExtension(extension_id)) {
// Extension has been uninstalled.
- UninstallOrigin(origin, base::Bind(&EmptyStatusCallback));
+ // (At this stage we can't know if it was unpacked extension or not,
+ // so just purge the remote folder.)
+ UninstallOrigin(origin,
+ RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
+ base::Bind(&EmptyStatusCallback));
} else if (metadata_store_->IsIncrementalSyncOrigin(origin) &&
!extension_service->IsExtensionEnabled(extension_id)) {
// Incremental Extension has been disabled.
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h
index 4f57fb5..d7c0de6 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h
+++ b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h
@@ -95,6 +95,7 @@
virtual void DisableOrigin(const GURL& origin,
const SyncStatusCallback& callback) OVERRIDE;
virtual void UninstallOrigin(const GURL& origin,
+ UninstallFlag flag,
const SyncStatusCallback& callback) OVERRIDE;
virtual void ProcessRemoteChange(const SyncFileCallback& callback) OVERRIDE;
virtual void SetRemoteChangeProcessor(
@@ -196,6 +197,7 @@
const SyncStatusCallback& callback);
void DoUninstallOrigin(
const GURL& origin,
+ UninstallFlag flag,
const SyncStatusCallback& callback);
void DoProcessRemoteChange(
const SyncFileCallback& sync_callback,
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_fake_unittest.cc b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_fake_unittest.cc
index a48ddac..8c4fe62 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_fake_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_fake_unittest.cc
@@ -561,6 +561,7 @@
bool done = false;
sync_service()->UninstallOrigin(
ExtensionNameToGURL(kExtensionName1),
+ RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(done);
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_sync_unittest.cc b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_sync_unittest.cc
index 5d9f34d..b57d88d 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_sync_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_sync_unittest.cc
@@ -92,7 +92,7 @@
local_sync_service_.reset(new LocalFileSyncService(&profile_));
fake_drive_service_ = new drive::FakeDriveService();
- fake_drive_service_->Initialize();
+ fake_drive_service_->Initialize("test_user@gmail.com");
ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
"sync_file_system/account_metadata.json"));
ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_unittest.cc b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_unittest.cc
index 01f4d6e..9931fe1 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service_unittest.cc
@@ -171,6 +171,7 @@
bool done = false;
sync_service()->UninstallOrigin(
origin_gurl,
+ RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(done);
@@ -180,6 +181,36 @@
origin_dir_resource_id)->second.deleted);
}
+TEST_F(DriveFileSyncServiceTest, UninstallUnpackedOrigin) {
+ // Add fake app origin directory using fake drive_sync_client.
+ std::string origin_dir_resource_id = "uninstalledappresourceid";
+ fake_api_util()->PushRemoteChange("parent_id",
+ "parent_title",
+ "uninstall_me_folder",
+ origin_dir_resource_id,
+ "resource_md5",
+ SYNC_FILE_TYPE_FILE,
+ false);
+
+ // Add meta_data entry so GURL->resourse_id mapping is there.
+ const GURL origin_gurl("chrome-extension://uninstallme");
+ metadata_store()->AddIncrementalSyncOrigin(origin_gurl,
+ origin_dir_resource_id);
+
+ // Uninstall the origin.
+ bool done = false;
+ sync_service()->UninstallOrigin(
+ origin_gurl,
+ RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE,
+ base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(done);
+
+ // Assert the App's origin folder has not been deleted.
+ EXPECT_FALSE(fake_api_util()->remote_resources().find(
+ origin_dir_resource_id)->second.deleted);
+}
+
TEST_F(DriveFileSyncServiceTest, UninstallOriginWithoutOriginDirectory) {
// Not add fake app origin directory.
std::string origin_dir_resource_id = "uninstalledappresourceid";
@@ -193,6 +224,7 @@
bool done = false;
sync_service()->UninstallOrigin(
origin_gurl,
+ RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(done);
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.cc b/chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.cc
index a3da574..26862a8 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.cc
+++ b/chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.cc
@@ -71,7 +71,6 @@
const char kMetadataKeySeparator = ' ';
const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
const char kDriveDisabledOriginKeyPrefix[] = "DISABLED_ORIGIN: ";
-const size_t kDriveMetadataKeyPrefixLength = arraysize(kDriveMetadataKeyPrefix);
enum OriginSyncType {
INCREMENTAL_SYNC_ORIGIN,
diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
index d17f159..f70e734 100644
--- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
+++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
@@ -568,6 +568,7 @@
EXPECT_TRUE(is_filesystem_opened_);
operation_runner()->Copy(
src_url, dest_url,
+ fileapi::FileSystemOperation::OPTION_NONE,
fileapi::FileSystemOperationRunner::CopyProgressCallback(), callback);
}
@@ -576,7 +577,8 @@
const FileSystemURL& dest_url,
const StatusCallback& callback) {
EXPECT_TRUE(is_filesystem_opened_);
- operation_runner()->Move(src_url, dest_url, callback);
+ operation_runner()->Move(
+ src_url, dest_url, fileapi::FileSystemOperation::OPTION_NONE, callback);
}
void CannedSyncableFileSystem::DoTruncateFile(
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context.cc b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
index 8e45cf2..b4f3a03 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
@@ -507,8 +507,6 @@
SyncFileSystemBackend::GetBackend(file_system_context);
DCHECK(backend);
if (!backend->change_tracker()) {
- // First registers the service name.
- RegisterSyncableFileSystem();
// Create and initialize LocalFileChangeTracker and call back this method
// later again.
std::set<GURL>* origins_with_changes = new std::set<GURL>;
diff --git a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc
index 1c9eef5..199c233 100644
--- a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc
+++ b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc
@@ -66,9 +66,15 @@
DCHECK(CalledOnUIThread());
if (profile)
profile_holder_.reset(new ProfileHolder(profile));
+
+ // Register the service name here to enable to crack an URL on SyncFileSystem
+ // even if SyncFileSystemService has not started yet.
+ RegisterSyncableFileSystem();
}
SyncFileSystemBackend::~SyncFileSystemBackend() {
+ RevokeSyncableFileSystem();
+
if (change_tracker_) {
GetDelegate()->file_task_runner()->DeleteSoon(
FROM_HERE, change_tracker_.release());
diff --git a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
index 112ad95..7e7693f 100644
--- a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
+++ b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
@@ -241,10 +241,12 @@
ResetCallbackStatus();
file_system_.operation_runner()->Copy(
URL(kDir), URL("dest-copy"),
+ fileapi::FileSystemOperation::OPTION_NONE,
fileapi::FileSystemOperationRunner::CopyProgressCallback(),
ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
file_system_.operation_runner()->Move(
URL(kDir), URL("dest-move"),
+ fileapi::FileSystemOperation::OPTION_NONE,
ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, callback_count_);
@@ -262,6 +264,7 @@
ResetCallbackStatus();
file_system_.operation_runner()->Copy(
URL(kDir), URL("dest-copy2"),
+ fileapi::FileSystemOperation::OPTION_NONE,
fileapi::FileSystemOperationRunner::CopyProgressCallback(),
ExpectStatus(FROM_HERE, base::PLATFORM_FILE_OK));
base::MessageLoop::current()->RunUntilIdle();
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc b/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc
index 24579d1..49499bd 100644
--- a/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc
+++ b/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc
@@ -123,6 +123,7 @@
void SyncableFileSystemOperation::Copy(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback) {
DCHECK(CalledOnValidThread());
@@ -137,7 +138,7 @@
weak_factory_.GetWeakPtr(),
base::Bind(&FileSystemOperation::Copy,
base::Unretained(impl_.get()),
- src_url, dest_url, progress_callback,
+ src_url, dest_url, option, progress_callback,
base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
operation_runner_->PostOperationTask(task.Pass());
}
@@ -145,6 +146,7 @@
void SyncableFileSystemOperation::Move(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
DCHECK(CalledOnValidThread());
if (!operation_runner_.get()) {
@@ -159,7 +161,7 @@
weak_factory_.GetWeakPtr(),
base::Bind(&FileSystemOperation::Move,
base::Unretained(impl_.get()),
- src_url, dest_url,
+ src_url, dest_url, option,
base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
operation_runner_->PostOperationTask(task.Pass());
}
@@ -328,18 +330,20 @@
void SyncableFileSystemOperation::CopyFileLocal(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) {
DCHECK(CalledOnValidThread());
- impl_->CopyFileLocal(src_url, dest_url, progress_callback, callback);
+ impl_->CopyFileLocal(src_url, dest_url, option, progress_callback, callback);
}
void SyncableFileSystemOperation::MoveFileLocal(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
DCHECK(CalledOnValidThread());
- impl_->MoveFileLocal(src_url, dest_url, callback);
+ impl_->MoveFileLocal(src_url, dest_url, option, callback);
}
base::PlatformFileError SyncableFileSystemOperation::SyncGetPlatformPath(
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_operation.h b/chrome/browser/sync_file_system/local/syncable_file_system_operation.h
index f3aad05..d9f89aa 100644
--- a/chrome/browser/sync_file_system/local/syncable_file_system_operation.h
+++ b/chrome/browser/sync_file_system/local/syncable_file_system_operation.h
@@ -41,10 +41,12 @@
const StatusCallback& callback) OVERRIDE;
virtual void Copy(const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback) OVERRIDE;
virtual void Move(const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) OVERRIDE;
virtual void DirectoryExists(const fileapi::FileSystemURL& url,
const StatusCallback& callback) OVERRIDE;
@@ -83,10 +85,12 @@
const StatusCallback& callback) OVERRIDE;
virtual void CopyFileLocal(const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) OVERRIDE;
virtual void MoveFileLocal(const fileapi::FileSystemURL& src_url,
const fileapi::FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) OVERRIDE;
virtual base::PlatformFileError SyncGetPlatformPath(
const fileapi::FileSystemURL& url,
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 2eb4b1a..a0a69d9 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
@@ -28,7 +28,7 @@
.WillByDefault(Invoke(this, &self::AddFileStatusObserverStub));
ON_CALL(*this, RegisterOrigin(_, _))
.WillByDefault(Invoke(this, &self::RegisterOriginStub));
- ON_CALL(*this, UninstallOrigin(_, _))
+ ON_CALL(*this, UninstallOrigin(_, _, _))
.WillByDefault(
Invoke(this, &self::DeleteOriginDirectoryStub));
ON_CALL(*this, ProcessRemoteChange(_))
@@ -99,6 +99,7 @@
void MockRemoteFileSyncService::DeleteOriginDirectoryStub(
const GURL& origin,
+ UninstallFlag flag,
const SyncStatusCallback& callback) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
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 78a1b4b..7ffa0d8 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
@@ -38,8 +38,10 @@
void(const GURL& origin, const SyncStatusCallback& callback));
MOCK_METHOD2(DisableOrigin,
void(const GURL& origin, const SyncStatusCallback& callback));
- MOCK_METHOD2(UninstallOrigin,
- void(const GURL& origin, const SyncStatusCallback& callback));
+ MOCK_METHOD3(UninstallOrigin,
+ void(const GURL& origin,
+ UninstallFlag flag,
+ const SyncStatusCallback& callback));
MOCK_METHOD1(ProcessRemoteChange,
void(const SyncFileCallback& callback));
MOCK_METHOD1(SetRemoteChangeProcessor,
@@ -85,7 +87,8 @@
void RegisterOriginStub(
const GURL& origin, const SyncStatusCallback& callback);
void DeleteOriginDirectoryStub(
- const GURL& origin, const SyncStatusCallback& callback);
+ const GURL& origin, UninstallFlag flag,
+ const SyncStatusCallback& callback);
void ProcessRemoteChangeStub(const SyncFileCallback& callback);
SyncStatusCode SetConflictResolutionPolicyStub(
ConflictResolutionPolicy policy);
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 b1e3cb6..9376c1b 100644
--- a/chrome/browser/sync_file_system/remote_file_sync_service.h
+++ b/chrome/browser/sync_file_system/remote_file_sync_service.h
@@ -91,6 +91,11 @@
SyncFileMetadata metadata;
};
+ enum UninstallFlag {
+ UNINSTALL_AND_PURGE_REMOTE,
+ UNINSTALL_AND_KEEP_REMOTE,
+ };
+
// For GetOriginStatusMap.
typedef std::map<GURL, std::string> OriginStatusMap;
@@ -132,6 +137,7 @@
// the origin from the metadata store.
virtual void UninstallOrigin(
const GURL& origin,
+ UninstallFlag flag,
const SyncStatusCallback& callback) = 0;
// Called by the sync engine to process one remote change.
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 ff38834..86ad792 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_service.cc
@@ -32,6 +32,7 @@
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/storage_partition.h"
+#include "extensions/common/manifest_constants.h"
#include "url/gurl.h"
#include "webkit/browser/fileapi/file_system_context.h"
@@ -45,9 +46,20 @@
namespace {
-const int64 kSyncDelayInSeconds = 1;
-const int64 kSyncDelaySlowInSeconds = 30; // Start with 30 sec + exp backoff.
-const int64 kSyncDelayMaxInSeconds = 30 * 60; // 30 min.
+// Default delay when more changes are available.
+const int64 kSyncDelayInMilliseconds = 1 * base::Time::kMillisecondsPerSecond;
+
+// Default delay when there're more than 10 pending changes.
+const int64 kSyncDelayFastInMilliseconds = 100;
+const int kPendingChangeThresholdForFastSync = 10;
+
+// Default delay when remote service is temporarily unavailable.
+const int64 kSyncDelaySlowInMilliseconds =
+ 30 * base::Time::kMillisecondsPerSecond; // Start with 30 sec + exp backoff
+
+// Default delay when there're no changes.
+const int64 kSyncDelayMaxInMilliseconds =
+ 30 * 60 * base::Time::kMillisecondsPerSecond; // 30 min
SyncServiceState RemoteStateToSyncServiceState(
RemoteServiceState state) {
@@ -150,26 +162,29 @@
~SyncRunner() {}
void Schedule() {
- int64 delay = kSyncDelayInSeconds;
+ int64 delay = kSyncDelayInMilliseconds;
if (pending_changes_ == 0) {
- ScheduleInternal(kSyncDelayMaxInSeconds);
+ ScheduleInternal(kSyncDelayMaxInMilliseconds);
return;
}
switch (remote_service_->GetCurrentState()) {
case REMOTE_SERVICE_OK:
- delay = kSyncDelayInSeconds;
+ if (pending_changes_ > kPendingChangeThresholdForFastSync)
+ delay = kSyncDelayFastInMilliseconds;
+ else
+ delay = kSyncDelayInMilliseconds;
break;
case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE:
- delay = kSyncDelaySlowInSeconds;
- if (last_delay_ >= kSyncDelaySlowInSeconds &&
- last_delay_ < kSyncDelayMaxInSeconds)
+ delay = kSyncDelaySlowInMilliseconds;
+ if (last_delay_ >= kSyncDelaySlowInMilliseconds &&
+ last_delay_ < kSyncDelayMaxInMilliseconds)
delay = last_delay_ * 2;
break;
case REMOTE_SERVICE_AUTHENTICATION_REQUIRED:
case REMOTE_SERVICE_DISABLED:
- delay = kSyncDelayMaxInSeconds;
+ delay = kSyncDelayMaxInMilliseconds;
break;
}
ScheduleInternal(delay);
@@ -203,7 +218,7 @@
(base::Time::Now() - last_scheduled_).InSeconds());
if (status == SYNC_STATUS_NO_CHANGE_TO_SYNC ||
status == SYNC_STATUS_FILE_BUSY)
- ScheduleInternal(kSyncDelayMaxInSeconds);
+ ScheduleInternal(kSyncDelayMaxInMilliseconds);
else
Schedule();
}
@@ -222,17 +237,19 @@
}
void ScheduleInternal(int64 delay) {
- base::TimeDelta time_to_next = base::TimeDelta::FromSeconds(delay);
+ base::TimeDelta time_to_next = base::TimeDelta::FromMilliseconds(delay);
if (timer_.IsRunning()) {
if (current_delay_ == delay)
return;
base::TimeDelta elapsed = base::Time::Now() - last_scheduled_;
- if (elapsed < time_to_next)
+ if (elapsed < time_to_next) {
time_to_next = time_to_next - elapsed;
- else
- time_to_next = base::TimeDelta::FromSeconds(kSyncDelayInSeconds);
+ } else {
+ time_to_next = base::TimeDelta::FromMilliseconds(
+ kSyncDelayFastInMilliseconds);
+ }
timer_.Stop();
}
@@ -678,12 +695,24 @@
void SyncFileSystemService::HandleExtensionUninstalled(
int type,
const content::NotificationDetails& details) {
- std::string extension_id = content::Details<const Extension>(details)->id();
- GURL app_origin = Extension::GetBaseURLFromExtensionId(extension_id);
+ const Extension* extension = content::Details<const Extension>(details).ptr();
+ DCHECK(extension);
+
+ RemoteFileSyncService::UninstallFlag flag =
+ RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE;
+ // If it's loaded from an unpacked package and with key: field,
+ // the uninstall will not be sync'ed and the user might be using the
+ // same app key in other installs, so avoid purging the remote folder.
+ if (extensions::Manifest::IsUnpackedLocation(extension->location()) &&
+ extension->manifest()->HasKey(extensions::manifest_keys::kKey)) {
+ flag = RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE;
+ }
+
+ GURL app_origin = Extension::GetBaseURLFromExtensionId(extension->id());
DVLOG(1) << "Handle extension notification for UNINSTALLED: "
<< app_origin;
remote_file_service_->UninstallOrigin(
- app_origin,
+ app_origin, flag,
base::Bind(&DidHandleOriginForExtensionUnloadedEvent,
type, app_origin));
local_file_service_->SetOriginEnabled(app_origin, false);
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 8c9112e..a49355a 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
@@ -71,8 +71,6 @@
remote_file_service = mock_remote_file_service_.Pass();
} else if (CommandLine::ForCurrentProcess()->HasSwitch(
kEnableSyncFileSystemV2)) {
- RegisterSyncableFileSystem();
-
GURL base_drive_url(
google_apis::DriveApiUrlGenerator::kBaseUrlForProduction);
GURL base_download_url(
@@ -83,9 +81,11 @@
scoped_refptr<base::SequencedWorkerPool> worker_pool(
content::BrowserThread::GetBlockingPool());
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
scoped_ptr<drive::DriveAPIService> drive_api_service(
new drive::DriveAPIService(
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
+ token_service,
context->GetRequestContext(),
worker_pool.get(),
base_drive_url, base_download_url, wapi_base_url,
@@ -103,7 +103,7 @@
scoped_ptr<drive_backend::SyncEngine> sync_engine(
new drive_backend::SyncEngine(
- context->GetPath(),
+ GetSyncFileSystemDir(context->GetPath()),
task_runner.get(),
drive_api_service.Pass(),
notification_manager,
@@ -112,9 +112,6 @@
sync_engine->Initialize();
remote_file_service = sync_engine.PassAs<RemoteFileSyncService>();
} else {
- // FileSystem needs to be registered before DriveFileSyncService runs
- // its initialization code.
- RegisterSyncableFileSystem();
remote_file_service =
DriveFileSyncService::Create(profile).PassAs<RemoteFileSyncService>();
}
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 b5b0974..ea5fb78 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
@@ -166,6 +166,12 @@
EXPECT_CALL(*mock_remote_service(),
RegisterOrigin(GURL(kOrigin), _)).Times(1);
+ // GetCurrentState may be called when a remote or local sync is scheduled
+ // by change notifications or by a timer.
+ EXPECT_CALL(*mock_remote_service(), GetCurrentState())
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(REMOTE_SERVICE_OK));
+
sync_service_->InitializeForApp(
file_system_->file_system_context(),
GURL(kOrigin),
@@ -185,8 +191,6 @@
// 1. The SyncEventObserver of the service is called with
// |expected_states| service state values.
// 2. InitializeForApp's callback is called with |expected_status|
- // 3. GetCurrentState() is called at least |expected_current_state_calls|
- // times (which means that the sync service tried to start sync).
void InitializeAppForObserverTest(
RemoteServiceState state_to_notify,
SyncStatusCode status_to_return,
@@ -197,6 +201,10 @@
EnableSync();
+ EXPECT_CALL(*mock_remote_service(), GetCurrentState())
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(state_to_notify));
+
EXPECT_CALL(*mock_remote_service(),
RegisterOrigin(GURL(kOrigin), _))
.WillOnce(NotifyStateAndCallback(mock_remote_service(),
@@ -219,6 +227,8 @@
ASSERT_EQ(expected_states.size(), actual_states.size());
for (size_t i = 0; i < actual_states.size(); ++i)
EXPECT_EQ(expected_states[i], actual_states[i]);
+
+ sync_service_->RemoveSyncEventObserver(&event_observer);
}
FileSystemURL URL(const std::string& path) const {
@@ -317,11 +327,6 @@
EXPECT_CALL(status_observer, OnWriteEnabled(kFile))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
- // We expect a set of method calls for starting a local sync.
- EXPECT_CALL(*mock_remote_service(), GetCurrentState())
- .Times(AtLeast(2))
- .WillRepeatedly(Return(REMOTE_SERVICE_OK));
-
// The local_change_processor's ApplyLocalChange should be called once
// with ADD_OR_UPDATE change for TYPE_FILE.
const FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
@@ -333,6 +338,8 @@
EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->CreateFile(kFile));
run_loop.Run();
+
+ file_system_->RemoveSyncStatusObserver(&status_observer);
}
TEST_F(SyncFileSystemServiceTest, SimpleRemoteSyncFlow) {
@@ -343,9 +350,6 @@
base::RunLoop run_loop;
// We expect a set of method calls for starting a remote sync.
- EXPECT_CALL(*mock_remote_service(), GetCurrentState())
- .Times(AtLeast(1))
- .WillRepeatedly(Return(REMOTE_SERVICE_OK));
EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
@@ -366,11 +370,6 @@
base::RunLoop run_loop;
- // We expect a set of method calls for starting a remote sync.
- EXPECT_CALL(*mock_remote_service(), GetCurrentState())
- .Times(AtLeast(3))
- .WillRepeatedly(Return(REMOTE_SERVICE_OK));
-
{
InSequence sequence;
@@ -411,7 +410,14 @@
verify_file_error_run_loop.Run();
}
-TEST_F(SyncFileSystemServiceTest, GetFileSyncStatus) {
+#if defined(THREAD_SANITIZER)
+// SyncFileSystemServiceTest.GetFileSyncStatus fails under ThreadSanitizer,
+// see http://crbug.com/294904.
+#define MAYBE_GetFileSyncStatus DISABLED_GetFileSyncStatus
+#else
+#define MAYBE_GetFileSyncStatus GetFileSyncStatus
+#endif
+TEST_F(SyncFileSystemServiceTest, MAYBE_GetFileSyncStatus) {
InitializeApp();
const FileSystemURL kFile(file_system_->URL("foo"));
diff --git a/chrome/browser/sync_file_system/sync_file_system_test_util.cc b/chrome/browser/sync_file_system/sync_file_system_test_util.cc
index 4c05f1b..407b362 100644
--- a/chrome/browser/sync_file_system/sync_file_system_test_util.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_test_util.cc
@@ -10,6 +10,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "chrome/browser/google_apis/gdata_errorcode.h"
+#include "chrome/browser/google_apis/gdata_wapi_parser.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
#include "chrome/browser/sync_file_system/sync_status_code.h"
#include "content/public/browser/browser_thread.h"
@@ -84,6 +85,7 @@
template base::Callback<void(type1, scoped_ptr<type2>)> \
CreateResultReceiver(type1*, scoped_ptr<type2>*)
INSTANTIATE_RECEIVER(SyncStatusCode, drive_backend::MetadataDatabase);
+INSTANTIATE_RECEIVER(google_apis::GDataErrorCode, google_apis::ResourceEntry);
#undef INSTANTIATE_RECEIVER
} // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/syncable_file_system_util_unittest.cc b/chrome/browser/sync_file_system/syncable_file_system_util_unittest.cc
index b3804b4..31bc00d 100644
--- a/chrome/browser/sync_file_system/syncable_file_system_util_unittest.cc
+++ b/chrome/browser/sync_file_system/syncable_file_system_util_unittest.cc
@@ -112,44 +112,6 @@
RevokeSyncableFileSystem();
}
-TEST(SyncableFileSystemUtilTest, SerializeBeforeOpenFileSystem) {
- ScopedEnableSyncFSDirectoryOperation enable_directory_operation_;
- const std::string serialized = kSyncableFileSystemRootURI +
- CreateNormalizedFilePath(kPath).AsUTF8Unsafe();
- FileSystemURL deserialized;
- base::MessageLoop message_loop;
-
- // Setting up a full syncable filesystem environment.
- CannedSyncableFileSystem file_system(GURL(kOrigin),
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get());
- file_system.SetUp();
- scoped_refptr<LocalFileSyncContext> sync_context =
- new LocalFileSyncContext(base::FilePath(),
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get());
-
- // Before calling initialization we would not be able to get a valid
- // deserialized URL.
- EXPECT_FALSE(DeserializeSyncableFileSystemURL(serialized, &deserialized));
- EXPECT_FALSE(deserialized.is_valid());
-
- ASSERT_EQ(sync_file_system::SYNC_STATUS_OK,
- file_system.MaybeInitializeFileSystemContext(sync_context.get()));
-
- // After initialization this should be ok (even before opening the file
- // system).
- EXPECT_TRUE(DeserializeSyncableFileSystemURL(serialized, &deserialized));
- EXPECT_TRUE(deserialized.is_valid());
-
- // Shutting down.
- file_system.TearDown();
- RevokeSyncableFileSystem();
- sync_context->ShutdownOnUIThread();
- sync_context = NULL;
- base::MessageLoop::current()->RunUntilIdle();
-}
-
TEST(SyncableFileSystemUtilTest, SyncableFileSystemURL_IsParent) {
RegisterSyncableFileSystem();
diff --git a/chrome/browser/task_manager/browser_process_resource_provider.cc b/chrome/browser/task_manager/browser_process_resource_provider.cc
index 21cec0b..6d898b7 100644
--- a/chrome/browser/task_manager/browser_process_resource_provider.cc
+++ b/chrome/browser/task_manager/browser_process_resource_provider.cc
@@ -40,8 +40,7 @@
HICON icon = GetAppIcon();
if (icon) {
scoped_ptr<SkBitmap> bitmap(IconUtil::CreateSkBitmapFromHICON(icon));
- default_icon_ = new gfx::ImageSkia(
- gfx::ImageSkiaRep(*bitmap, ui::SCALE_FACTOR_100P));
+ default_icon_ = new gfx::ImageSkia(gfx::ImageSkiaRep(*bitmap, 1.0f));
}
}
#elif defined(OS_POSIX) && !defined(OS_MACOSX)
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 988450e..6f163af 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -245,7 +245,7 @@
// Do a memcpy to avoid misaligned memory access.
memcpy(scales.get(), input.data(), input.size());
for (size_t index = 0; index < scales_size; ++index) {
- if (scales[index] != ui::GetScaleFactorScale(expected[index]))
+ if (scales[index] != ui::GetImageScale(expected[index]))
return false;
}
return true;
@@ -256,7 +256,7 @@
const std::vector<ui::ScaleFactor>& scale_factors) {
scoped_ptr<float[]> scales(new float[scale_factors.size()]);
for (size_t i = 0; i < scale_factors.size(); ++i)
- scales[i] = ui::GetScaleFactorScale(scale_factors[i]);
+ scales[i] = ui::GetImageScale(scale_factors[i]);
std::string out_string = std::string(
reinterpret_cast<const char*>(scales.get()),
scale_factors.size() * sizeof(float));
@@ -452,8 +452,8 @@
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)));
+ ui::GetImageScale(desired_scale_factor) /
+ ui::GetImageScale(source_scale_factor)));
SkBitmap scaled_bitmap;
scaled_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
scaled_size.width(),
@@ -477,17 +477,15 @@
}
virtual ~ThemeImageSource() {}
- virtual gfx::ImageSkiaRep GetImageForScale(
- ui::ScaleFactor scale_factor) OVERRIDE {
- if (source_.HasRepresentation(scale_factor))
- return source_.GetRepresentation(scale_factor);
- const gfx::ImageSkiaRep& rep_100p =
- source_.GetRepresentation(ui::SCALE_FACTOR_100P);
+ virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ if (source_.HasRepresentation(scale))
+ return source_.GetRepresentation(scale);
+ const gfx::ImageSkiaRep& rep_100p = source_.GetRepresentation(1.0f);
SkBitmap scaled_bitmap = CreateLowQualityResizedBitmap(
rep_100p.sk_bitmap(),
ui::SCALE_FACTOR_100P,
- scale_factor);
- return gfx::ImageSkiaRep(scaled_bitmap, scale_factor);
+ ui::GetSupportedScaleFactor(scale));
+ return gfx::ImageSkiaRep(scaled_bitmap, scale);
}
private:
@@ -509,13 +507,13 @@
virtual ~ThemeImagePngSource() {}
private:
- virtual gfx::ImageSkiaRep GetImageForScale(
- ui::ScaleFactor scale_factor) OVERRIDE {
+ virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactor(scale);
// 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);
+ return gfx::ImageSkiaRep(exact_bitmap_it->second, scale);
// 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.
@@ -529,7 +527,7 @@
return gfx::ImageSkiaRep();
}
bitmap_map_[scale_factor] = bitmap;
- return gfx::ImageSkiaRep(bitmap, scale_factor);
+ return gfx::ImageSkiaRep(bitmap, scale);
}
// Find an available PNG for another scale factor. We want to use the
@@ -538,8 +536,8 @@
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)) {
+ ui::GetImageScale(png_it->first) >
+ ui::GetImageScale(available_png_it->first)) {
available_png_it = png_it;
}
}
@@ -571,7 +569,7 @@
available_scale_factor,
scale_factor);
bitmap_map_[scale_factor] = scaled_bitmap;
- return gfx::ImageSkiaRep(scaled_bitmap, scale_factor);
+ return gfx::ImageSkiaRep(scaled_bitmap, scale);
}
PngMap png_map_;
@@ -1285,7 +1283,8 @@
if (gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(),
&bitmap)) {
image_skia.AddRepresentation(
- gfx::ImageSkiaRep(bitmap, scale_factor));
+ gfx::ImageSkiaRep(bitmap,
+ ui::GetImageScale(scale_factor)));
} else {
NOTREACHED() << "Unable to decode theme image resource "
<< it->first;
@@ -1473,7 +1472,9 @@
NOTREACHED() << "Image file for resource " << it->first
<< " could not be encoded.";
}
- int raw_id = GetRawIDByPersistentID(it->first, rep_it->scale_factor());
+ int raw_id = GetRawIDByPersistentID(
+ it->first,
+ ui::GetSupportedScaleFactor(rep_it->scale()));
(*reencoded_images)[raw_id] =
base::RefCountedBytes::TakeVector(&bitmap_data);
}
@@ -1533,7 +1534,7 @@
if (base::StringToInt(key, &percent)) {
float scale = static_cast<float>(percent) / 100.0f;
for (size_t i = 0; i < scale_factors_.size(); ++i) {
- if (fabs(ui::GetScaleFactorScale(scale_factors_[i]) - scale) < 0.001) {
+ if (fabs(ui::GetImageScale(scale_factors_[i]) - scale) < 0.001) {
*scale_factor = scale_factors_[i];
return true;
}
@@ -1570,8 +1571,8 @@
for (size_t i = 0; i < scale_factors_.size(); ++i) {
int raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]);
if ((available_scale_factor == ui::SCALE_FACTOR_NONE ||
- (ui::GetScaleFactorScale(scale_factors_[i]) >
- ui::GetScaleFactorScale(available_scale_factor))) &&
+ (ui::GetImageScale(scale_factors_[i]) >
+ ui::GetImageScale(available_scale_factor))) &&
image_memory_.find(raw_id) != image_memory_.end()) {
available_scale_factor = scale_factors_[i];
}
diff --git a/chrome/browser/themes/browser_theme_pack_unittest.cc b/chrome/browser/themes/browser_theme_pack_unittest.cc
index b2fd658..7d41e55 100644
--- a/chrome/browser/themes/browser_theme_pack_unittest.cc
+++ b/chrome/browser/themes/browser_theme_pack_unittest.cc
@@ -36,8 +36,13 @@
BrowserThemePackTest()
: message_loop(),
fake_ui_thread(BrowserThread::UI, &message_loop),
- fake_file_thread(BrowserThread::FILE, &message_loop),
- theme_pack_(new BrowserThemePack) {
+ fake_file_thread(BrowserThread::FILE, &message_loop) {
+ std::vector<ui::ScaleFactor> scale_factors;
+ scale_factors.push_back(ui::SCALE_FACTOR_100P);
+ scale_factors.push_back(ui::SCALE_FACTOR_200P);
+ scoped_set_supported_scale_factors_.reset(
+ new ui::test::ScopedSetSupportedScaleFactors(scale_factors));
+ theme_pack_ = new BrowserThemePack();
}
// Transformation for link underline colors.
@@ -270,8 +275,7 @@
const gfx::ImageSkia* image_skia = image.ToImageSkia();
ASSERT_TRUE(image_skia);
// Scale 100%.
- const gfx::ImageSkiaRep& rep1 = image_skia->GetRepresentation(
- ui::SCALE_FACTOR_100P);
+ const gfx::ImageSkiaRep& rep1 = image_skia->GetRepresentation(1.0f);
ASSERT_FALSE(rep1.is_null());
EXPECT_EQ(80, rep1.sk_bitmap().width());
EXPECT_EQ(80, rep1.sk_bitmap().height());
@@ -283,8 +287,7 @@
EXPECT_EQ(SkColorSetRGB( 0, 241, 237), rep1.sk_bitmap().getColor(32, 32));
rep1.sk_bitmap().unlockPixels();
// Scale 200%.
- const gfx::ImageSkiaRep& rep2 = image_skia->GetRepresentation(
- ui::SCALE_FACTOR_200P);
+ const gfx::ImageSkiaRep& rep2 = image_skia->GetRepresentation(2.0f);
ASSERT_FALSE(rep2.is_null());
EXPECT_EQ(160, rep2.sk_bitmap().width());
EXPECT_EQ(160, rep2.sk_bitmap().height());
@@ -312,8 +315,7 @@
image_skia = image.ToImageSkia();
ASSERT_TRUE(image_skia);
// Scale 100%.
- const gfx::ImageSkiaRep& rep3 = image_skia->GetRepresentation(
- ui::SCALE_FACTOR_100P);
+ const gfx::ImageSkiaRep& rep3 = image_skia->GetRepresentation(1.0f);
ASSERT_FALSE(rep3.is_null());
EXPECT_EQ(80, rep3.sk_bitmap().width());
EXPECT_EQ(80, rep3.sk_bitmap().height());
@@ -335,8 +337,7 @@
EXPECT_EQ(static_cast<size_t>(9), normal.size());
rep3.sk_bitmap().unlockPixels();
// Scale 200%.
- const gfx::ImageSkiaRep& rep4 = image_skia->GetRepresentation(
- ui::SCALE_FACTOR_200P);
+ const gfx::ImageSkiaRep& rep4 = image_skia->GetRepresentation(2.0f);
ASSERT_FALSE(rep4.is_null());
EXPECT_EQ(160, rep4.sk_bitmap().width());
EXPECT_EQ(160, rep4.sk_bitmap().height());
@@ -355,6 +356,9 @@
content::TestBrowserThread fake_ui_thread;
content::TestBrowserThread fake_file_thread;
+ typedef scoped_ptr<ui::test::ScopedSetSupportedScaleFactors>
+ ScopedSetSupportedScaleFactors;
+ ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_;
scoped_refptr<BrowserThemePack> theme_pack_;
};
@@ -584,10 +588,6 @@
}
TEST_F(BrowserThemePackTest, HiDpiThemeTest) {
- std::vector<ui::ScaleFactor> scale_factors;
- scale_factors.push_back(ui::SCALE_FACTOR_100P);
- scale_factors.push_back(ui::SCALE_FACTOR_200P);
- ui::test::ScopedSetSupportedScaleFactors test_scale_factors(scale_factors);
base::ScopedTempDir dir;
ASSERT_TRUE(dir.CreateUniqueTempDir());
base::FilePath file = dir.path().AppendASCII("theme_data.pak");
diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc
index e91a160..930dcf6 100644
--- a/chrome/browser/themes/theme_service_factory.cc
+++ b/chrome/browser/themes/theme_service_factory.cc
@@ -18,7 +18,7 @@
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#endif
-#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#if defined(USE_AURA) && defined(USE_X11) && !defined(OS_CHROMEOS)
#include "chrome/browser/themes/theme_service_aurax11.h"
#include "ui/views/linux_ui/linux_ui.h"
#endif
@@ -56,7 +56,7 @@
ThemeService* provider = NULL;
#if defined(TOOLKIT_GTK)
provider = new GtkThemeService;
-#elif defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#elif defined(USE_AURA) && defined(USE_X11) && !defined(OS_CHROMEOS)
provider = new ThemeServiceAuraX11;
#else
provider = new ThemeService;
@@ -68,12 +68,12 @@
void ThemeServiceFactory::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#if defined(USE_X11) && !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)
+#elif defined(USE_AURA) && defined(USE_X11) && !defined(OS_CHROMEOS)
const views::LinuxUI* linux_ui = views::LinuxUI::instance();
if (linux_ui)
default_uses_system_theme = linux_ui->GetDefaultUsesSystemTheme();
diff --git a/chrome/browser/thumbnails/content_analysis_unittest.cc b/chrome/browser/thumbnails/content_analysis_unittest.cc
index dc8f2c8..a45708d 100644
--- a/chrome/browser/thumbnails/content_analysis_unittest.cc
+++ b/chrome/browser/thumbnails/content_analysis_unittest.cc
@@ -78,7 +78,7 @@
};
TEST_F(ThumbnailContentAnalysisTest, ApplyGradientMagnitudeOnImpulse) {
- gfx::Canvas canvas(gfx::Size(800, 600), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true);
// The image consists of vertical non-overlapping stripes 100 pixels wide.
canvas.FillRect(gfx::Rect(0, 0, 800, 600), SkColorSetARGB(0, 10, 10, 10));
@@ -129,7 +129,7 @@
#define MAYBE_ApplyGradientMagnitudeOnFrame ApplyGradientMagnitudeOnFrame
#endif
TEST_F(ThumbnailContentAnalysisTest, MAYBE_ApplyGradientMagnitudeOnFrame) {
- gfx::Canvas canvas(gfx::Size(800, 600), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true);
// The image consists of a single white block in the centre.
gfx::Rect draw_rect(300, 200, 200, 200);
@@ -168,7 +168,7 @@
}
TEST_F(ThumbnailContentAnalysisTest, ExtractImageProfileInformation) {
- gfx::Canvas canvas(gfx::Size(800, 600), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true);
// The image consists of a white frame drawn in the centre.
gfx::Rect draw_rect(100, 100, 200, 100);
@@ -240,7 +240,7 @@
#endif
TEST_F(ThumbnailContentAnalysisTest,
MAYBE_ExtractImageProfileInformationWithClosing) {
- gfx::Canvas canvas(gfx::Size(800, 600), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true);
// The image consists of a two white frames drawn side by side, with a
// single-pixel vertical gap in between.
@@ -575,7 +575,7 @@
TEST_F(ThumbnailContentAnalysisTest, ComputeDecimatedImage) {
gfx::Size image_size(1600, 1200);
- gfx::Canvas canvas(image_size, ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(image_size, 1.0f, true);
// Make some content we will later want to keep.
canvas.FillRect(gfx::Rect(100, 200, 100, 100), SkColorSetARGB(0, 125, 0, 0));
@@ -625,7 +625,7 @@
TEST_F(ThumbnailContentAnalysisTest, CreateRetargetedThumbnailImage) {
gfx::Size image_size(1200, 1300);
- gfx::Canvas canvas(image_size, ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(image_size, 1.0f, true);
// The following will create a 'fake image' consisting of color blocks placed
// on a neutral background. The entire layout is supposed to mimic a
diff --git a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc b/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc
index 07e033f..1e8eae7 100644
--- a/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc
+++ b/chrome/browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc
@@ -134,7 +134,7 @@
// This tests the invocation of the main thumbnail-making apparatus.
// The actual content is not really of concern here, just check the plumbing.
const gfx::Size image_size(1200, 800);
- gfx::Canvas canvas(image_size, ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(image_size, 1.0f, true);
// The image consists of vertical non-overlapping stripes 150 pixels wide.
canvas.FillRect(gfx::Rect(200, 200, 800, 400), SkColorSetRGB(255, 255, 255));
diff --git a/chrome/browser/thumbnails/render_widget_snapshot_taker.cc b/chrome/browser/thumbnails/render_widget_snapshot_taker.cc
index da2606c..f9e2263 100644
--- a/chrome/browser/thumbnails/render_widget_snapshot_taker.cc
+++ b/chrome/browser/thumbnails/render_widget_snapshot_taker.cc
@@ -45,7 +45,7 @@
// this callback for later lookup when the rendering is done.
static int sequence_num = 0;
sequence_num++;
- float scale_factor = ui::GetScaleFactorScale(ui::GetScaleFactorForNativeView(
+ float scale_factor = ui::GetImageScale(ui::GetScaleFactorForNativeView(
renderer->GetView()->GetNativeView()));
gfx::Size desired_size_in_pixel = gfx::ToFlooredSize(
gfx::ScaleSize(desired_size, scale_factor));
diff --git a/chrome/browser/thumbnails/render_widget_snapshot_taker_unittest.cc b/chrome/browser/thumbnails/render_widget_snapshot_taker_unittest.cc
index 5a33ed1..d44a69b 100644
--- a/chrome/browser/thumbnails/render_widget_snapshot_taker_unittest.cc
+++ b/chrome/browser/thumbnails/render_widget_snapshot_taker_unittest.cc
@@ -75,7 +75,8 @@
size);
EXPECT_EQ(1U, snapshot_taker.callback_map_.size());
const int sequence_num = 1;
- const gfx::Size size2(200, 200);
+ // Ensure this is bigger than the max scale factor X the size.
+ const gfx::Size size2(300, 300);
snapshot_taker.WidgetDidReceivePaintAtSizeAck(
content::RenderViewHostTestHarness::rvh(),
sequence_num,
diff --git a/chrome/browser/thumbnails/simple_thumbnail_crop.cc b/chrome/browser/thumbnails/simple_thumbnail_crop.cc
index c427b90..b2128ef 100644
--- a/chrome/browser/thumbnails/simple_thumbnail_crop.cc
+++ b/chrome/browser/thumbnails/simple_thumbnail_crop.cc
@@ -8,6 +8,7 @@
#include "content/public/browser/browser_thread.h"
#include "skia/ext/platform_canvas.h"
#include "ui/gfx/color_utils.h"
+#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/scrollbar_size.h"
#include "ui/gfx/size_conversions.h"
@@ -121,7 +122,7 @@
switch (scale_factor) {
case ui::SCALE_FACTOR_100P:
copy_size = gfx::ToFlooredSize(gfx::ScaleSize(
- copy_size, ui::GetScaleFactorScale(ui::SCALE_FACTOR_200P)));
+ copy_size, ui::GetImageScale(ui::SCALE_FACTOR_200P)));
break;
case ui::SCALE_FACTOR_200P:
// Use the size as-is.
@@ -130,7 +131,7 @@
DLOG(WARNING) << "Unsupported scale factor. Use the same copy size as "
<< "ui::SCALE_FACTOR_100P";
copy_size = gfx::ToFlooredSize(gfx::ScaleSize(
- copy_size, ui::GetMaxScaleFactor()));
+ copy_size, gfx::ImageSkia::GetMaxSupportedScale()));
break;
}
return copy_size;
@@ -183,8 +184,7 @@
const gfx::Size& given_size) {
// TODO(mazda|oshima): Update thumbnail when the max scale factor changes.
// crbug.com/159157.
- float max_scale_factor =
- ui::GetScaleFactorScale(ui::GetMaxScaleFactor());
+ float max_scale_factor = gfx::ImageSkia::GetMaxSupportedScale();
return gfx::ToFlooredSize(gfx::ScaleSize(given_size, max_scale_factor));
}
diff --git a/chrome/browser/thumbnails/simple_thumbnail_crop_unittest.cc b/chrome/browser/thumbnails/simple_thumbnail_crop_unittest.cc
index b0324a4..c00abb2 100644
--- a/chrome/browser/thumbnails/simple_thumbnail_crop_unittest.cc
+++ b/chrome/browser/thumbnails/simple_thumbnail_crop_unittest.cc
@@ -30,7 +30,7 @@
TEST_F(SimpleThumbnailCropTest, CalculateBoringScore_SingleColor) {
const gfx::Size kSize(20, 10);
- gfx::Canvas canvas(kSize, ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(kSize, 1.0f, true);
// Fill all pixels in black.
canvas.FillRect(gfx::Rect(kSize), SK_ColorBLACK);
@@ -43,7 +43,7 @@
TEST_F(SimpleThumbnailCropTest, CalculateBoringScore_TwoColors) {
const gfx::Size kSize(20, 10);
- gfx::Canvas canvas(kSize, ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(kSize, 1.0f, true);
// Fill all pixels in black.
canvas.FillRect(gfx::Rect(kSize), SK_ColorBLACK);
// Fill the left half pixels in white.
@@ -60,7 +60,7 @@
TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_TallerThanWide) {
// The input bitmap is vertically long.
- gfx::Canvas canvas(gfx::Size(40, 90), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(40, 90), 1.0f, true);
SkBitmap bitmap =
skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false);
@@ -77,7 +77,7 @@
TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_WiderThanTall) {
// The input bitmap is horizontally long.
- gfx::Canvas canvas(gfx::Size(70, 40), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(70, 40), 1.0f, true);
SkBitmap bitmap =
skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false);
@@ -94,7 +94,7 @@
TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_TooWiderThanTall) {
// The input bitmap is horizontally very long.
- gfx::Canvas canvas(gfx::Size(90, 40), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(90, 40), 1.0f, true);
SkBitmap bitmap =
skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false);
@@ -111,7 +111,7 @@
TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_NotClipped) {
// The input bitmap is square.
- gfx::Canvas canvas(gfx::Size(40, 40), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(40, 40), 1.0f, true);
SkBitmap bitmap =
skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false);
@@ -128,7 +128,7 @@
TEST_F(SimpleThumbnailCropTest, GetClippedBitmap_NonSquareOutput) {
// The input bitmap is square.
- gfx::Canvas canvas(gfx::Size(40, 40), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(40, 40), 1.0f, true);
SkBitmap bitmap =
skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false);
diff --git a/chrome/browser/translate/translate_manager.cc b/chrome/browser/translate/translate_manager.cc
index c5d22ac..c3f7829 100644
--- a/chrome/browser/translate/translate_manager.cc
+++ b/chrome/browser/translate/translate_manager.cc
@@ -61,8 +61,6 @@
using content::NavigationEntry;
using content::WebContents;
-namespace {
-
const char kReportLanguageDetectionErrorURL[] =
"https://translate.google.com/translate_error?client=cr&action=langidc";
@@ -73,16 +71,10 @@
// Used in kReportLanguageDetectionErrorURL to specify the page URL.
const char kUrlQueryName[] = "u";
-// The delay in ms that we'll wait to check if a page has finished loading
-// before attempting a translation.
-const int kTranslateLoadCheckDelayMs = 150;
-
// The maximum number of attempts we'll do to see if the page has finshed
// loading before giving up the translation
const int kMaxTranslateLoadCheckAttempts = 20;
-} // namespace
-
TranslateManager::~TranslateManager() {
weak_method_factory_.InvalidateWeakPtrs();
}
diff --git a/chrome/browser/ui/OWNERS b/chrome/browser/ui/OWNERS
index d7a02c7..dfe6fff 100644
--- a/chrome/browser/ui/OWNERS
+++ b/chrome/browser/ui/OWNERS
@@ -9,6 +9,6 @@
per-file browser_tab_contents.*=avi@chromium.org
# Instant/Search files.
-per-file browser_instant_controller.*=brettw@chromium.org
-per-file browser_instant_controller.*=jered@chromium.org
-per-file browser_instant_controller.*=samarth@chromium.org
+per-file browser_instant_controller*=brettw@chromium.org
+per-file browser_instant_controller*=jered@chromium.org
+per-file browser_instant_controller*=samarth@chromium.org
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc
index 5495fd6..7b01063 100644
--- a/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc
@@ -182,17 +182,40 @@
}
AutofillDialogControllerAndroid::~AutofillDialogControllerAndroid() {
+ if (java_object_.is_null())
+ return;
+
JNIEnv* env = base::android::AttachCurrentThread();
Java_AutofillDialogControllerAndroid_onDestroy(env, java_object_.obj());
}
void AutofillDialogControllerAndroid::Show() {
+ JNIEnv* env = base::android::AttachCurrentThread();
dialog_shown_timestamp_ = base::Time::Now();
content::NavigationEntry* entry = contents_->GetController().GetActiveEntry();
const GURL& active_url = entry ? entry->GetURL() : contents_->GetURL();
invoked_from_same_origin_ = active_url.GetOrigin() == source_url_.GetOrigin();
+ // Determine what field types should be included in the dialog.
+ bool has_types = false;
+ bool has_sections = false;
+ form_structure_.ParseFieldTypesFromAutocompleteAttributes(
+ &has_types, &has_sections);
+
+ // Fail if the author didn't specify autocomplete types, or
+ // if the dialog shouldn't be shown in a given circumstances.
+ if (!has_types ||
+ !Java_AutofillDialogControllerAndroid_isDialogAllowed(
+ env,
+ RequestingCreditCardInfo(),
+ TransmissionWillBeSecure(),
+ invoked_from_same_origin_)) {
+ callback_.Run(NULL);
+ delete this;
+ return;
+ }
+
// Log any relevant UI metrics and security exceptions.
GetMetricLogger().LogDialogUiEvent(AutofillMetrics::DIALOG_UI_SHOWN);
@@ -209,19 +232,6 @@
AutofillMetrics::SECURITY_METRIC_CROSS_ORIGIN_FRAME);
}
- // Determine what field types should be included in the dialog.
- bool has_types = false;
- bool has_sections = false;
- form_structure_.ParseFieldTypesFromAutocompleteAttributes(
- &has_types, &has_sections);
-
- // Fail if the author didn't specify autocomplete types.
- if (!has_types) {
- callback_.Run(NULL);
- delete this;
- return;
- }
-
const ServerFieldType full_billing_is_necessary_if[] = {
ADDRESS_BILLING_LINE1,
ADDRESS_BILLING_LINE2,
@@ -281,7 +291,6 @@
if (contents_->GetBrowserContext()->IsOffTheRecord())
last_used_choice_is_autofill = true;
- JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> jlast_used_account_name =
base::android::ConvertUTF16ToJavaString(
env, last_used_account_name);
diff --git a/chrome/browser/ui/android/infobar/confirm_infobar.cc b/chrome/browser/ui/android/infobar/confirm_infobar.cc
deleted file mode 100644
index a1dec50..0000000
--- a/chrome/browser/ui/android/infobar/confirm_infobar.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/android/infobar/confirm_infobar.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/logging.h"
-#include "chrome/browser/android/resource_mapper.h"
-#include "chrome/browser/infobars/confirm_infobar_delegate.h"
-#include "jni/ConfirmInfoBarDelegate_jni.h"
-
-using base::android::ConvertUTF16ToJavaString;
-using base::android::ScopedJavaLocalRef;
-
-// static
-InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
- return new ConfirmInfoBar(owner, this);
-}
-
-ConfirmInfoBar::ConfirmInfoBar(InfoBarService* owner, InfoBarDelegate* delegate)
- : InfoBarAndroid(owner, delegate),
- delegate_(delegate->AsConfirmInfoBarDelegate()),
- java_confirm_delegate_() {}
-
-ConfirmInfoBar::~ConfirmInfoBar() {}
-
-ScopedJavaLocalRef<jobject> ConfirmInfoBar::CreateRenderInfoBar(JNIEnv* env) {
- java_confirm_delegate_.Reset(Java_ConfirmInfoBarDelegate_create(env));
- ScopedJavaLocalRef<jstring> ok_button_text =
- ConvertUTF16ToJavaString(env, GetTextFor(InfoBarAndroid::ACTION_OK));
- ScopedJavaLocalRef<jstring> cancel_button_text =
- ConvertUTF16ToJavaString(env, GetTextFor(InfoBarAndroid::ACTION_CANCEL));
- ScopedJavaLocalRef<jstring> message_text =
- ConvertUTF16ToJavaString(env, GetMessage());
-
- return Java_ConfirmInfoBarDelegate_showConfirmInfoBar(
- env,
- java_confirm_delegate_.obj(),
- reinterpret_cast<jint>(this),
- GetEnumeratedIconId(),
- message_text.obj(),
- ok_button_text.obj(),
- cancel_button_text.obj());
-}
-
-void ConfirmInfoBar::ProcessButton(int action,
- const std::string& action_value) {
- DCHECK(action == InfoBarAndroid::ACTION_OK ||
- action == InfoBarAndroid::ACTION_CANCEL);
- if ((action == InfoBarAndroid::ACTION_OK) ? delegate_->Accept()
- : delegate_->Cancel())
- CloseInfoBar();
-}
-
-string16 ConfirmInfoBar::GetTextFor(ActionType action) {
- int buttons = delegate_->GetButtons();
- switch (action) {
- case InfoBarAndroid::ACTION_OK:
- if (buttons & ConfirmInfoBarDelegate::BUTTON_OK)
- return delegate_->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK);
- break;
- case InfoBarAndroid::ACTION_CANCEL:
- if (buttons & ConfirmInfoBarDelegate::BUTTON_CANCEL)
- return delegate_->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL);
- break;
- default:
- break;
- }
- return string16();
-}
-
-string16 ConfirmInfoBar::GetMessage() {
- return delegate_->GetMessageText();
-}
-
-// -----------------------------------------------------------------------------
-// Native JNI methods for confirm delegate.
-// -----------------------------------------------------------------------------
-bool RegisterConfirmInfoBarDelegate(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
diff --git a/chrome/browser/ui/android/infobar/OWNERS b/chrome/browser/ui/android/infobars/OWNERS
similarity index 100%
rename from chrome/browser/ui/android/infobar/OWNERS
rename to chrome/browser/ui/android/infobars/OWNERS
diff --git a/chrome/browser/ui/android/infobar/auto_login_infobar_delegate_android.cc b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.cc
similarity index 71%
rename from chrome/browser/ui/android/infobar/auto_login_infobar_delegate_android.cc
rename to chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.cc
index 168224b..82a9fc8 100644
--- a/chrome/browser/ui/android/infobar/auto_login_infobar_delegate_android.cc
+++ b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.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 "chrome/browser/ui/auto_login_infobar_delegate_android.h"
+#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_helper.h"
@@ -16,38 +16,38 @@
#include "jni/AutoLoginDelegate_jni.h"
#include "ui/base/l10n/l10n_util.h"
-using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString;
-using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
AutoLoginInfoBarDelegateAndroid::AutoLoginInfoBarDelegateAndroid(
InfoBarService* owner,
const Params& params)
- : AutoLoginInfoBarDelegate(owner, params), params_(params) {}
+ : AutoLoginInfoBarDelegate(owner, params),
+ params_(params) {
+}
-AutoLoginInfoBarDelegateAndroid::~AutoLoginInfoBarDelegateAndroid() {}
+AutoLoginInfoBarDelegateAndroid::~AutoLoginInfoBarDelegateAndroid() {
+}
bool AutoLoginInfoBarDelegateAndroid::AttachAccount(
JavaObjectWeakGlobalRef weak_java_auto_login_delegate) {
weak_java_auto_login_delegate_ = weak_java_auto_login_delegate;
- JNIEnv* env = AttachCurrentThread();
+ JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm());
ScopedJavaLocalRef<jstring> jaccount =
ConvertUTF8ToJavaString(env, account());
ScopedJavaLocalRef<jstring> jargs = ConvertUTF8ToJavaString(env, args());
- DCHECK(!jrealm.is_null() && !jaccount.is_null() && !jargs.is_null());
+ DCHECK(!jrealm.is_null());
+ DCHECK(!jaccount.is_null());
+ DCHECK(!jargs.is_null());
ScopedJavaLocalRef<jobject> delegate =
weak_java_auto_login_delegate_.get(env);
DCHECK(delegate.obj());
- user_ = ConvertJavaStringToUTF8(
- Java_AutoLoginDelegate_initializeAccount(env,
- delegate.obj(),
- reinterpret_cast<jint>(this),
- jrealm.obj(),
- jaccount.obj(),
- jargs.obj()));
+ user_ = base::android::ConvertJavaStringToUTF8(
+ Java_AutoLoginDelegate_initializeAccount(
+ env, delegate.obj(), reinterpret_cast<jint>(this), jrealm.obj(),
+ jaccount.obj(), jargs.obj()));
return !user_.empty();
}
@@ -57,13 +57,13 @@
}
bool AutoLoginInfoBarDelegateAndroid::Accept() {
- JNIEnv* env = AttachCurrentThread();
+ JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> delegate =
weak_java_auto_login_delegate_.get(env);
DCHECK(delegate.obj());
- Java_AutoLoginDelegate_logIn(
- env, delegate.obj(), reinterpret_cast<jint>(this));
+ Java_AutoLoginDelegate_logIn(env, delegate.obj(),
+ reinterpret_cast<jint>(this));
// Do not close the infobar on accept, it will be closed as part
// of the log in callback.
@@ -71,12 +71,12 @@
}
bool AutoLoginInfoBarDelegateAndroid::Cancel() {
- JNIEnv* env = AttachCurrentThread();
+ JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> delegate =
weak_java_auto_login_delegate_.get(env);
DCHECK(delegate.obj());
- Java_AutoLoginDelegate_cancelLogIn(
- env, delegate.obj(), reinterpret_cast<jint>(this));
+ Java_AutoLoginDelegate_cancelLogIn(env, delegate.obj(),
+ reinterpret_cast<jint>(this));
return true;
}
@@ -89,10 +89,8 @@
web_contents->Stop();
web_contents->OpenURL(content::OpenURLParams(
GURL(base::android::ConvertJavaStringToUTF8(env, result)),
- content::Referrer(),
- CURRENT_TAB,
- content::PAGE_TRANSITION_AUTO_BOOKMARK,
- false));
+ content::Referrer(), CURRENT_TAB,
+ content::PAGE_TRANSITION_AUTO_BOOKMARK, false));
}
owner()->RemoveInfoBar(this);
}
@@ -104,10 +102,8 @@
DCHECK(delegate.obj());
if (owner()) {
SimpleAlertInfoBarDelegate::Create(
- owner(),
- IDR_INFOBAR_WARNING,
- l10n_util::GetStringUTF16(IDS_AUTO_LOGIN_FAILED),
- false);
+ owner(), IDR_INFOBAR_WARNING,
+ l10n_util::GetStringUTF16(IDS_AUTO_LOGIN_FAILED), false);
owner()->RemoveInfoBar(this);
}
}
@@ -117,7 +113,6 @@
owner()->RemoveInfoBar(this);
}
-// Register Android JNI bindings.
bool AutoLoginInfoBarDelegateAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/chrome/browser/ui/auto_login_infobar_delegate_android.h b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h
similarity index 82%
rename from chrome/browser/ui/auto_login_infobar_delegate_android.h
rename to chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h
index 3f69e0f..c78352f 100644
--- a/chrome/browser/ui/auto_login_infobar_delegate_android.h
+++ b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h
@@ -1,8 +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.
-#ifndef CHROME_BROWSER_UI_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
-#define CHROME_BROWSER_UI_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
+
+#ifndef CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
+#define CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
#include "base/android/jni_helper.h"
#include "base/android/scoped_java_ref.h"
@@ -13,7 +14,7 @@
AutoLoginInfoBarDelegateAndroid(InfoBarService* owner, const Params& params);
virtual ~AutoLoginInfoBarDelegateAndroid();
- // ConfirmInfoBarDelegate:
+ // AutoLoginInfoBarDelegate:
virtual bool Accept() OVERRIDE;
virtual bool Cancel() OVERRIDE;
virtual string16 GetMessageText() const OVERRIDE;
@@ -39,6 +40,5 @@
DISALLOW_COPY_AND_ASSIGN(AutoLoginInfoBarDelegateAndroid);
};
-
-#endif // CHROME_BROWSER_UI_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
+#endif // CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
diff --git a/chrome/browser/ui/android/infobars/confirm_infobar.cc b/chrome/browser/ui/android/infobars/confirm_infobar.cc
new file mode 100644
index 0000000..dab34c0
--- /dev/null
+++ b/chrome/browser/ui/android/infobars/confirm_infobar.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/browser/ui/android/infobars/confirm_infobar.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/logging.h"
+#include "chrome/browser/android/resource_mapper.h"
+#include "chrome/browser/infobars/confirm_infobar_delegate.h"
+#include "jni/ConfirmInfoBarDelegate_jni.h"
+
+
+// ConfirmInfoBarDelegate -----------------------------------------------------
+
+// static
+InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
+ return new ConfirmInfoBar(owner, this);
+}
+
+
+// ConfirmInfoBar -------------------------------------------------------------
+
+ConfirmInfoBar::ConfirmInfoBar(InfoBarService* owner, InfoBarDelegate* delegate)
+ : InfoBarAndroid(owner, delegate),
+ delegate_(delegate->AsConfirmInfoBarDelegate()),
+ java_confirm_delegate_() {
+}
+
+ConfirmInfoBar::~ConfirmInfoBar() {
+}
+
+base::android::ScopedJavaLocalRef<jobject> ConfirmInfoBar::CreateRenderInfoBar(
+ JNIEnv* env) {
+ java_confirm_delegate_.Reset(Java_ConfirmInfoBarDelegate_create(env));
+ base::android::ScopedJavaLocalRef<jstring> ok_button_text =
+ base::android::ConvertUTF16ToJavaString(
+ env, GetTextFor(ConfirmInfoBarDelegate::BUTTON_OK));
+ base::android::ScopedJavaLocalRef<jstring> cancel_button_text =
+ base::android::ConvertUTF16ToJavaString(
+ env, GetTextFor(ConfirmInfoBarDelegate::BUTTON_CANCEL));
+ base::android::ScopedJavaLocalRef<jstring> message_text =
+ base::android::ConvertUTF16ToJavaString(
+ env, delegate_->GetMessageText());
+
+ return Java_ConfirmInfoBarDelegate_showConfirmInfoBar(
+ env, java_confirm_delegate_.obj(), reinterpret_cast<jint>(this),
+ GetEnumeratedIconId(), message_text.obj(), ok_button_text.obj(),
+ cancel_button_text.obj());
+}
+
+void ConfirmInfoBar::ProcessButton(int action,
+ const std::string& action_value) {
+ DCHECK((action == InfoBarAndroid::ACTION_OK) ||
+ (action == InfoBarAndroid::ACTION_CANCEL));
+ if ((action == InfoBarAndroid::ACTION_OK) ?
+ delegate_->Accept() : delegate_->Cancel())
+ CloseInfoBar();
+}
+
+string16 ConfirmInfoBar::GetTextFor(
+ ConfirmInfoBarDelegate::InfoBarButton button) {
+ return (delegate_->GetButtons() & button) ?
+ delegate_->GetButtonLabel(button) : string16();
+}
+
+
+// Native JNI methods ---------------------------------------------------------
+
+bool RegisterConfirmInfoBarDelegate(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
diff --git a/chrome/browser/ui/android/infobar/confirm_infobar.h b/chrome/browser/ui/android/infobars/confirm_infobar.h
similarity index 60%
rename from chrome/browser/ui/android/infobar/confirm_infobar.h
rename to chrome/browser/ui/android/infobars/confirm_infobar.h
index a3182b8..47a5b68 100644
--- a/chrome/browser/ui/android/infobar/confirm_infobar.h
+++ b/chrome/browser/ui/android/infobars/confirm_infobar.h
@@ -2,35 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_UI_ANDROID_INFOBAR_CONFIRM_INFOBAR_H_
-#define CHROME_BROWSER_UI_ANDROID_INFOBAR_CONFIRM_INFOBAR_H_
+#ifndef CHROME_BROWSER_UI_ANDROID_INFOBARS_CONFIRM_INFOBAR_H_
+#define CHROME_BROWSER_UI_ANDROID_INFOBARS_CONFIRM_INFOBAR_H_
#include "base/basictypes.h"
#include "base/strings/string16.h"
-#include "chrome/browser/ui/android/infobar/infobar_android.h"
+#include "chrome/browser/infobars/confirm_infobar_delegate.h"
+#include "chrome/browser/ui/android/infobars/infobar_android.h"
-class ConfirmInfoBarDelegate;
-
-namespace gfx {
-class Image;
-}
-
-// Implementation of InfoBar for confirm infobars, this currently
-// includes, geolocation, popups..
class ConfirmInfoBar : public InfoBarAndroid {
public:
ConfirmInfoBar(InfoBarService* owner, InfoBarDelegate* delegate);
virtual ~ConfirmInfoBar();
private:
- // InfoBar overrides.
+ // InfoBarAndroid:
virtual base::android::ScopedJavaLocalRef<jobject> CreateRenderInfoBar(
JNIEnv* env) OVERRIDE;
virtual void ProcessButton(int action,
const std::string& action_value) OVERRIDE;
- string16 GetTextFor(ActionType action);
- string16 GetMessage();
+ string16 GetTextFor(ConfirmInfoBarDelegate::InfoBarButton button);
ConfirmInfoBarDelegate* delegate_;
base::android::ScopedJavaGlobalRef<jobject> java_confirm_delegate_;
@@ -38,7 +30,7 @@
DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBar);
};
-// Registers native methods
+// Registers native methods.
bool RegisterConfirmInfoBarDelegate(JNIEnv* env);
-#endif // CHROME_BROWSER_UI_ANDROID_INFOBAR_CONFIRM_INFOBAR_H_
+#endif // CHROME_BROWSER_UI_ANDROID_INFOBARS_CONFIRM_INFOBAR_H_
diff --git a/chrome/browser/ui/android/infobar/infobar_android.cc b/chrome/browser/ui/android/infobars/infobar_android.cc
similarity index 72%
rename from chrome/browser/ui/android/infobar/infobar_android.cc
rename to chrome/browser/ui/android/infobars/infobar_android.cc
index df839b8..aad90c3 100644
--- a/chrome/browser/ui/android/infobar/infobar_android.cc
+++ b/chrome/browser/ui/android/infobars/infobar_android.cc
@@ -1,7 +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.
-#include "chrome/browser/ui/android/infobar/infobar_android.h"
+
+#include "chrome/browser/ui/android/infobars/infobar_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
@@ -12,16 +13,11 @@
#include "chrome/browser/infobars/infobar_service.h"
#include "jni/InfoBar_jni.h"
-namespace gfx {
- class Image;
-}
-using base::android::AttachCurrentThread;
-using base::android::JavaRef;
+// InfoBar --------------------------------------------------------------------
-
-// static constants defined in infobar.h we don't really use them for anything
-// but they are required. The values are copied from the GTK implementation.
+// Static constants defined in infobar.h. We don't really use them for anything
+// but they are required. The values are copied from the GTK implementation.
const int InfoBar::kSeparatorLineHeight = 1;
const int InfoBar::kDefaultArrowTargetHeight = 9;
const int InfoBar::kMaximumArrowTargetHeight = 24;
@@ -29,6 +25,9 @@
const int InfoBar::kMaximumArrowTargetHalfWidth = 14;
const int InfoBar::kDefaultBarTargetHeight = 36;
+
+// InfoBarAndroid -------------------------------------------------------------
+
InfoBarAndroid::InfoBarAndroid(InfoBarService* owner, InfoBarDelegate* delegate)
: InfoBar(owner, delegate),
delegate_(delegate) {
@@ -36,7 +35,8 @@
DCHECK(delegate_->owner());
}
-InfoBarAndroid::~InfoBarAndroid() {}
+InfoBarAndroid::~InfoBarAndroid() {
+}
void InfoBarAndroid::ReassignJavaInfoBar(InfoBarAndroid* replacement) {
DCHECK(replacement);
@@ -46,7 +46,8 @@
}
}
-void InfoBarAndroid::set_java_infobar(const JavaRef<jobject>& java_info_bar) {
+void InfoBarAndroid::set_java_infobar(
+ const base::android::JavaRef<jobject>& java_info_bar) {
DCHECK(java_info_bar_.is_null());
java_info_bar_.Reset(java_info_bar);
}
@@ -55,8 +56,10 @@
return !java_info_bar_.is_null();
}
-void InfoBarAndroid::OnButtonClicked(
- JNIEnv* env, jobject obj, jint action, jstring action_value) {
+void InfoBarAndroid::OnButtonClicked(JNIEnv* env,
+ jobject obj,
+ jint action,
+ jstring action_value) {
DCHECK(delegate_);
std::string value = base::android::ConvertJavaStringToUTF8(env, action_value);
ProcessButton(action, value);
@@ -72,15 +75,9 @@
RemoveSelf();
}
-void InfoBarAndroid::CloseInfoBar() {
- CloseJavaInfoBar();
- if (owner())
- RemoveSelf();
-}
-
void InfoBarAndroid::CloseJavaInfoBar() {
if (!java_info_bar_.is_null()) {
- JNIEnv* env = AttachCurrentThread();
+ JNIEnv* env = base::android::AttachCurrentThread();
Java_InfoBar_closeInfoBar(env, java_info_bar_.obj());
}
}
@@ -90,11 +87,15 @@
return ResourceMapper::MapFromChromiumId(delegate_->GetIconID());
}
-// -----------------------------------------------------------------------------
-// Native JNI methods
-// -----------------------------------------------------------------------------
+void InfoBarAndroid::CloseInfoBar() {
+ CloseJavaInfoBar();
+ if (owner())
+ RemoveSelf();
+}
-// Register native methods
+
+// Native JNI methods ---------------------------------------------------------
+
bool RegisterNativeInfoBar(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/chrome/browser/ui/android/infobar/infobar_android.h b/chrome/browser/ui/android/infobars/infobar_android.h
similarity index 71%
rename from chrome/browser/ui/android/infobar/infobar_android.h
rename to chrome/browser/ui/android/infobars/infobar_android.h
index 7556819..d4285ff 100644
--- a/chrome/browser/ui/android/infobar/infobar_android.h
+++ b/chrome/browser/ui/android/infobars/infobar_android.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_UI_ANDROID_INFOBAR_INFOBAR_ANDROID_H_
-#define CHROME_BROWSER_UI_ANDROID_INFOBAR_INFOBAR_ANDROID_H_
+#ifndef CHROME_BROWSER_UI_ANDROID_INFOBARS_INFOBAR_ANDROID_H_
+#define CHROME_BROWSER_UI_ANDROID_INFOBARS_INFOBAR_ANDROID_H_
#include <string>
@@ -16,15 +16,11 @@
class InfoBarDelegate;
class InfoBarService;
-namespace gfx {
- class Image;
-}
-
class InfoBarAndroid : public InfoBar {
public:
// Make sure this set of values is aligned with the java constants defined in
- // InfoBar.java
+ // InfoBar.java!
enum ActionType {
ACTION_NONE = 0,
// Confirm infobar
@@ -38,20 +34,21 @@
InfoBarAndroid(InfoBarService* owner, InfoBarDelegate* delegate);
virtual ~InfoBarAndroid();
- // InfoBar
+ // InfoBar:
virtual base::android::ScopedJavaLocalRef<jobject> CreateRenderInfoBar(
JNIEnv* env) = 0;
void set_java_infobar(const base::android::JavaRef<jobject>& java_info_bar);
-
bool HasSetJavaInfoBar() const;
// Tells the Java-side counterpart of this InfoBar to point to the replacement
// InfoBar instead of this one.
void ReassignJavaInfoBar(InfoBarAndroid* replacement);
- void OnButtonClicked(JNIEnv* env, jobject obj,
- jint action, jstring action_value);
+ void OnButtonClicked(JNIEnv* env,
+ jobject obj,
+ jint action,
+ jstring action_value);
void OnCloseButtonClicked(JNIEnv* env, jobject obj);
void OnInfoBarClosed(JNIEnv* env, jobject obj);
@@ -62,15 +59,15 @@
// translate into a Drawable ID using the ResourceId class.
int GetEnumeratedIconId();
- // Acquire the java infobar from a different one.
- // This is used to do in place replacements.
+ // Acquire the java infobar from a different one. This is used to do in-place
+ // replacements.
virtual void PassJavaInfoBar(InfoBarAndroid* source) {}
protected:
- // Derived classes must implement this method to process the
- // corresponding action.
- virtual void ProcessButton(
- int action, const std::string& action_value) = 0;
+ // Derived classes must implement this method to process the corresponding
+ // action.
+ virtual void ProcessButton(int action,
+ const std::string& action_value) = 0;
void CloseInfoBar();
private:
@@ -81,7 +78,7 @@
DISALLOW_COPY_AND_ASSIGN(InfoBarAndroid);
};
-// Register the NativeInfoBar's native methods through jni
+// Registers the NativeInfoBar's native methods through JNI.
bool RegisterNativeInfoBar(JNIEnv* env);
-#endif // CHROME_BROWSER_UI_ANDROID_INFOBAR_INFOBAR_ANDROID_H_
+#endif // CHROME_BROWSER_UI_ANDROID_INFOBARS_INFOBAR_ANDROID_H_
diff --git a/chrome/browser/ui/android/infobar/infobar_container_android.cc b/chrome/browser/ui/android/infobars/infobar_container_android.cc
similarity index 69%
rename from chrome/browser/ui/android/infobar/infobar_container_android.cc
rename to chrome/browser/ui/android/infobars/infobar_container_android.cc
index 2b77450..80b8c29 100644
--- a/chrome/browser/ui/android/infobar/infobar_container_android.cc
+++ b/chrome/browser/ui/android/infobars/infobar_container_android.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 "chrome/browser/ui/android/infobar/infobar_container_android.h"
+#include "chrome/browser/ui/android/infobars/infobar_container_android.h"
#include "base/android/jni_android.h"
#include "base/logging.h"
@@ -10,23 +10,21 @@
#include "chrome/browser/infobars/infobar.h"
#include "chrome/browser/infobars/infobar_delegate.h"
#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/ui/android/infobar/infobar_android.h"
-#include "chrome/browser/ui/auto_login_infobar_delegate_android.h"
+#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h"
+#include "chrome/browser/ui/android/infobars/infobar_android.h"
#include "content/public/browser/web_contents.h"
#include "jni/InfoBarContainer_jni.h"
-using base::android::AttachCurrentThread;
-using base::android::JavaRef;
-using base::android::ScopedJavaLocalRef;
-using content::WebContents;
-// InfoBarContainerAndroid
+// InfoBarContainerAndroid ----------------------------------------------------
+
InfoBarContainerAndroid::InfoBarContainerAndroid(JNIEnv* env,
jobject obj,
jobject auto_login_delegate)
: InfoBarContainer(NULL),
weak_java_infobar_container_(env, obj),
- weak_java_auto_login_delegate_(env, auto_login_delegate) {}
+ weak_java_auto_login_delegate_(env, auto_login_delegate) {
+}
InfoBarContainerAndroid::~InfoBarContainerAndroid() {
RemoveAllInfoBarsForDestruction();
@@ -36,21 +34,15 @@
delete this;
}
-// TODO(miguelg) Move this out of infobar container.
void InfoBarContainerAndroid::OnWebContentsReplaced(
- WebContents* old_web_contents,
- WebContents* new_web_contents) {
-
- InfoBarService* new_infobar_service = NULL;
- if (new_web_contents)
- new_infobar_service = InfoBarService::FromWebContents(new_web_contents);
- if (!new_infobar_service)
- return;
-
- ChangeInfoBarService(new_infobar_service);
+ content::WebContents* old_web_contents,
+ content::WebContents* new_web_contents) {
+ InfoBarService* new_infobar_service = new_web_contents ?
+ InfoBarService::FromWebContents(new_web_contents) : NULL;
+ if (new_infobar_service)
+ ChangeInfoBarService(new_infobar_service);
}
-// InfobarContainer
void InfoBarContainerAndroid::PlatformSpecificAddInfoBar(InfoBar* infobar,
size_t position) {
DCHECK(infobar);
@@ -68,20 +60,18 @@
AutoLoginInfoBarDelegateAndroid* auto_login_delegate =
static_cast<AutoLoginInfoBarDelegateAndroid*>(
infobar->delegate()->AsAutoLoginInfoBarDelegate());
- if (!auto_login_delegate->AttachAccount(weak_java_auto_login_delegate_)) {
+ if (!auto_login_delegate->AttachAccount(weak_java_auto_login_delegate_))
return;
- }
}
AttachJavaInfoBar(android_bar);
}
void InfoBarContainerAndroid::AttachJavaInfoBar(InfoBarAndroid* android_bar) {
- // Java infobar already set on the new bar, nothing to do.
if (android_bar->HasSetJavaInfoBar())
return;
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> java_infobar =
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> java_infobar =
android_bar->CreateRenderInfoBar(env);
Java_InfoBarContainer_addInfoBar(
env, weak_java_infobar_container_.get(env).obj(), java_infobar.obj());
@@ -89,10 +79,11 @@
}
void InfoBarContainerAndroid::PlatformSpecificReplaceInfoBar(
- InfoBar* old_infobar, InfoBar* new_infobar) {
+ InfoBar* old_infobar,
+ InfoBar* new_infobar) {
InfoBarAndroid* new_android_bar = static_cast<InfoBarAndroid*>(new_infobar);
- InfoBarAndroid* old_android_bar =
- old_infobar != NULL ? static_cast<InfoBarAndroid*>(old_infobar) : NULL;
+ InfoBarAndroid* old_android_bar = (old_infobar == NULL) ?
+ NULL : static_cast<InfoBarAndroid*>(old_infobar);
new_android_bar->PassJavaInfoBar(old_android_bar);
}
@@ -102,23 +93,20 @@
base::MessageLoop::current()->DeleteSoon(FROM_HERE, infobar);
}
-// -----------------------------------------------------------------------------
-// Native JNI methods
-// -----------------------------------------------------------------------------
+
+// Native JNI methods ---------------------------------------------------------
+
static int Init(JNIEnv* env,
jobject obj,
jint native_web_contents,
jobject auto_login_delegate) {
- InfoBarService* infobar_service = InfoBarService::FromWebContents(
- reinterpret_cast<content::WebContents*>(native_web_contents));
-
InfoBarContainerAndroid* infobar_container =
new InfoBarContainerAndroid(env, obj, auto_login_delegate);
- infobar_container->ChangeInfoBarService(infobar_service);
+ infobar_container->ChangeInfoBarService(InfoBarService::FromWebContents(
+ reinterpret_cast<content::WebContents*>(native_web_contents)));
return reinterpret_cast<int>(infobar_container);
}
-// Register native methods
bool RegisterInfoBarContainer(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/chrome/browser/ui/android/infobar/infobar_container_android.h b/chrome/browser/ui/android/infobars/infobar_container_android.h
similarity index 78%
rename from chrome/browser/ui/android/infobar/infobar_container_android.h
rename to chrome/browser/ui/android/infobars/infobar_container_android.h
index 5d49b86..7624c34 100644
--- a/chrome/browser/ui/android/infobar/infobar_container_android.h
+++ b/chrome/browser/ui/android/infobars/infobar_container_android.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_UI_ANDROID_INFOBAR_INFOBAR_CONTAINER_ANDROID_H_
-#define CHROME_BROWSER_UI_ANDROID_INFOBAR_INFOBAR_CONTAINER_ANDROID_H_
+#ifndef CHROME_BROWSER_UI_ANDROID_INFOBARS_INFOBAR_CONTAINER_ANDROID_H_
+#define CHROME_BROWSER_UI_ANDROID_INFOBARS_INFOBAR_CONTAINER_ANDROID_H_
#include <map>
#include <string>
@@ -15,8 +15,6 @@
#include "chrome/browser/infobars/infobar_container.h"
class InfoBarAndroid;
-class InfoBarDelegate;
-class InfoBarService;
namespace content {
class WebContents;
@@ -38,21 +36,22 @@
}
// The prerender is swapping the web contents.
+// TODO(miguelg) Move this out of infobar container.
void OnWebContentsReplaced(content::WebContents* old_web_contents,
content::WebContents* new_web_contents);
private:
virtual ~InfoBarContainerAndroid() OVERRIDE;
- // InfobarContainer
- virtual void PlatformSpecificAddInfoBar(InfoBar* infobar, size_t position)
- OVERRIDE;
+ // InfobarContainer:
+ virtual void PlatformSpecificAddInfoBar(InfoBar* infobar,
+ size_t position) OVERRIDE;
virtual void PlatformSpecificRemoveInfoBar(InfoBar* infobar) OVERRIDE;
virtual void PlatformSpecificReplaceInfoBar(InfoBar* old_infobar,
InfoBar* new_infobar) OVERRIDE;
// Create the Java equivalent of |android_bar| and add it to the java
- // container
+ // container.
void AttachJavaInfoBar(InfoBarAndroid* android_bar);
// We're owned by the java infobar, need to use a weak ref so it can destroy
@@ -63,7 +62,7 @@
DISALLOW_COPY_AND_ASSIGN(InfoBarContainerAndroid);
};
-// Register the InfoBarContainer's native methods through jni
+// Registers the InfoBarContainer's native methods through JNI.
bool RegisterInfoBarContainer(JNIEnv* env);
-#endif // CHROME_BROWSER_UI_ANDROID_INFOBAR_INFOBAR_CONTAINER_ANDROID_H_
+#endif // CHROME_BROWSER_UI_ANDROID_INFOBARS_INFOBAR_CONTAINER_ANDROID_H_
diff --git a/chrome/browser/ui/app_list/app_context_menu.cc b/chrome/browser/ui/app_list/app_context_menu.cc
index 9f3431d..d5f3e4b 100644
--- a/chrome/browser/ui/app_list/app_context_menu.cc
+++ b/chrome/browser/ui/app_list/app_context_menu.cc
@@ -19,6 +19,7 @@
#include "content/public/common/context_menu_params.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
+#include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(USE_ASH)
@@ -135,12 +136,14 @@
Profile* profile,
const std::string& app_id,
AppListControllerDelegate* controller,
- bool is_platform_app)
+ bool is_platform_app,
+ bool is_search_result)
: delegate_(delegate),
profile_(profile),
app_id_(app_id),
controller_(controller),
- is_platform_app_(is_platform_app) {
+ is_platform_app_(is_platform_app),
+ is_search_result_(is_search_result) {
}
AppContextMenu::~AppContextMenu() {}
@@ -256,9 +259,18 @@
if (!extension)
return;
+ const GURL url = extensions::ManifestURL::GetDetailsURL(extension);
+ DCHECK_NE(url, GURL::EmptyGURL());
+
+ const std::string source = AppListControllerDelegate::AppListSourceToString(
+ is_search_result_ ?
+ AppListControllerDelegate::LAUNCH_FROM_APP_LIST_SEARCH :
+ AppListControllerDelegate::LAUNCH_FROM_APP_LIST);
chrome::NavigateParams params(
profile_,
- extensions::ManifestURL::GetDetailsURL(extension),
+ net::AppendQueryParameter(url,
+ extension_urls::kWebstoreSourceField,
+ source),
content::PAGE_TRANSITION_LINK);
chrome::Navigate(¶ms);
}
diff --git a/chrome/browser/ui/app_list/app_context_menu.h b/chrome/browser/ui/app_list/app_context_menu.h
index c4c6227..7f6631a 100644
--- a/chrome/browser/ui/app_list/app_context_menu.h
+++ b/chrome/browser/ui/app_list/app_context_menu.h
@@ -29,7 +29,8 @@
Profile* profile,
const std::string& app_id,
AppListControllerDelegate* controller,
- bool is_platform_app);
+ bool is_platform_app,
+ bool is_search_result_);
virtual ~AppContextMenu();
// Note this could return NULL if corresponding extension is gone.
@@ -56,6 +57,7 @@
const std::string app_id_;
AppListControllerDelegate* controller_;
bool is_platform_app_;
+ bool is_search_result_;
scoped_ptr<ui::SimpleMenuModel> menu_model_;
scoped_ptr<extensions::ContextMenuMatcher> extension_menu_items_;
diff --git a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc
index ce2d5b1..ef0e746 100644
--- a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc
+++ b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "base/files/scoped_temp_dir.h"
+#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
@@ -39,6 +39,18 @@
AppListControllerBrowserTest()
: profile2_(NULL) {}
+ void InitSecondProfile() {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ base::FilePath temp_profile_dir =
+ profile_manager->user_data_dir().AppendASCII("Profile 1");
+ profile_manager->CreateProfileAsync(
+ temp_profile_dir,
+ base::Bind(&AppListControllerBrowserTest::OnProfileCreated,
+ this),
+ string16(), string16(), std::string());
+ content::RunMessageLoop(); // Will stop in OnProfileCreated().
+ }
+
void OnProfileCreated(Profile* profile, Profile::CreateStatus status) {
if (status == Profile::CREATE_STATUS_INITIALIZED) {
profile2_ = profile;
@@ -47,7 +59,6 @@
}
protected:
- base::ScopedTempDir temp_profile_dir_;
Profile* profile2_;
private:
@@ -86,24 +97,76 @@
}
IN_PROC_BROWSER_TEST_F(AppListControllerBrowserTest, SwitchAppListProfiles) {
- ProfileManager* profile_manager = g_browser_process->profile_manager();
- ASSERT_TRUE(temp_profile_dir_.CreateUniqueTempDir());
- profile_manager->CreateProfileAsync(
- temp_profile_dir_.path(),
- base::Bind(&AppListControllerBrowserTest::OnProfileCreated,
- this),
- string16(), string16(), std::string());
- content::RunMessageLoop(); // Will stop in OnProfileCreated().
+ InitSecondProfile();
AppListService* service = AppListService::Get();
+ scoped_ptr<test::AppListServiceTestApi> test_api(
+ test::AppListServiceTestApi::Create(chrome::HOST_DESKTOP_TYPE_NATIVE));
+ ASSERT_TRUE(service);
+ ASSERT_TRUE(test_api);
+
+ scoped_ptr<AppListControllerDelegate> controller(
+ service->CreateControllerDelegate());
+ ASSERT_TRUE(controller);
+
+ // Open the app list with the browser's profile.
ASSERT_FALSE(service->IsAppListVisible());
- service->ShowForProfile(browser()->profile());
+ controller->ShowForProfileByPath(browser()->profile()->GetPath());
+ app_list::AppListModel* model = test_api->GetAppListModel();
+ ASSERT_TRUE(model);
+ model->SetSignedIn(true);
+ base::RunLoop().RunUntilIdle();
+
ASSERT_TRUE(service->IsAppListVisible());
ASSERT_EQ(browser()->profile(), service->GetCurrentAppListProfile());
- service->ShowForProfile(profile2_);
+
+ // Open the app list with the second profile.
+ controller->ShowForProfileByPath(profile2_->GetPath());
+ model = test_api->GetAppListModel();
+ ASSERT_TRUE(model);
+ model->SetSignedIn(true);
+ base::RunLoop().RunUntilIdle();
+
ASSERT_TRUE(service->IsAppListVisible());
ASSERT_EQ(profile2_, service->GetCurrentAppListProfile());
- service->DismissAppList();
+
+ controller->DismissView();
+}
+
+IN_PROC_BROWSER_TEST_F(AppListControllerBrowserTest,
+ SwitchAppListProfilesDuringSearch) {
+ InitSecondProfile();
+
+ AppListService* service = AppListService::Get();
+ scoped_ptr<test::AppListServiceTestApi> test_api(
+ test::AppListServiceTestApi::Create(chrome::HOST_DESKTOP_TYPE_NATIVE));
+ ASSERT_TRUE(service);
+ ASSERT_TRUE(test_api);
+
+ scoped_ptr<AppListControllerDelegate> controller(
+ service->CreateControllerDelegate());
+ ASSERT_TRUE(controller);
+
+ // Set a search with original profile.
+ controller->ShowForProfileByPath(browser()->profile()->GetPath());
+ app_list::AppListModel* model = test_api->GetAppListModel();
+ ASSERT_TRUE(model);
+ model->SetSignedIn(true);
+ model->search_box()->SetText(ASCIIToUTF16("minimal"));
+ base::RunLoop().RunUntilIdle();
+
+ // Switch to the second profile.
+ controller->ShowForProfileByPath(profile2_->GetPath());
+ model = test_api->GetAppListModel();
+ ASSERT_TRUE(model);
+ model->SetSignedIn(true);
+ base::RunLoop().RunUntilIdle();
+
+ // Ensure the search box is empty.
+ ASSERT_TRUE(model->search_box()->text().empty());
+ ASSERT_EQ(profile2_, service->GetCurrentAppListProfile());
+
+ controller->DismissView();
ASSERT_FALSE(service->IsAppListVisible());
}
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 abb59af..ec1332d 100644
--- a/chrome/browser/ui/app_list/app_list_controller_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_controller_delegate.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/extensions/extension_constants.h"
#include "ui/gfx/image/image_skia.h"
AppListControllerDelegate::~AppListControllerDelegate() {}
@@ -37,3 +38,14 @@
bool AppListControllerDelegate::ShouldShowUserIcon() {
return g_browser_process->profile_manager()->GetNumberOfProfiles() > 1;
}
+
+std::string AppListControllerDelegate::AppListSourceToString(
+ AppListSource source) {
+ switch (source) {
+ case LAUNCH_FROM_APP_LIST:
+ return extension_urls::kLaunchSourceAppList;
+ case LAUNCH_FROM_APP_LIST_SEARCH:
+ return extension_urls::kLaunchSourceAppListSearch;
+ default: return std::string();
+ }
+}
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 b0859f4..ed49525 100644
--- a/chrome/browser/ui/app_list/app_list_controller_delegate.h
+++ b/chrome/browser/ui/app_list/app_list_controller_delegate.h
@@ -11,6 +11,10 @@
class Profile;
+namespace base {
+class FilePath;
+}
+
namespace extensions {
class Extension;
}
@@ -24,6 +28,13 @@
// platforms.
class AppListControllerDelegate {
public:
+ // Indicates the source of an app list activation, for tracking purposes.
+ enum AppListSource {
+ LAUNCH_FROM_UNKNOWN,
+ LAUNCH_FROM_APP_LIST,
+ LAUNCH_FROM_APP_LIST_SEARCH
+ };
+
virtual ~AppListControllerDelegate();
// Dismisses the view.
@@ -60,16 +71,23 @@
// Show the app's most recent window, or launch it if it is not running.
virtual void ActivateApp(Profile* profile,
const extensions::Extension* extension,
+ AppListSource source,
int event_flags) = 0;
// Launch the app.
virtual void LaunchApp(Profile* profile,
const extensions::Extension* extension,
+ AppListSource source,
int event_flags) = 0;
+ // Show the app list for the profile specified by |profile_path|.
+ virtual void ShowForProfileByPath(const base::FilePath& profile_path) = 0;
+
// Whether or not the icon indicating which user is logged in should be
// visible.
virtual bool ShouldShowUserIcon();
+
+ static std::string AppListSourceToString(AppListSource source);
};
#endif // CHROME_BROWSER_UI_APP_LIST_APP_LIST_CONTROLLER_DELEGATE_H_
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 d6ec6d2..3090c6b 100644
--- a/chrome/browser/ui/app_list/app_list_service_impl.cc
+++ b/chrome/browser/ui/app_list/app_list_service_impl.cc
@@ -148,6 +148,13 @@
}
void AppListServiceImpl::SetProfilePath(const base::FilePath& profile_path) {
+ // Ensure we don't set the pref to a managed user's profile path.
+ ProfileInfoCache& profile_info =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ size_t profile_index = profile_info.GetIndexOfProfileWithPath(profile_path);
+ if (profile_info.ProfileIsManagedAtIndex(profile_index))
+ return;
+
g_browser_process->local_state()->SetString(
prefs::kAppListProfile,
profile_path.BaseName().MaybeAsASCII());
@@ -203,4 +210,11 @@
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableAppList))
SetAppListEnabledPreference(false);
+
+ // Send app list usage stats after a delay.
+ const int kSendUsageStatsDelay = 5;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&AppListServiceImpl::SendAppListStats),
+ base::TimeDelta::FromSeconds(kSendUsageStatsDelay));
}
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 8118547..878b5ea 100644
--- a/chrome/browser/ui/app_list/app_list_service_impl.h
+++ b/chrome/browser/ui/app_list/app_list_service_impl.h
@@ -26,7 +26,6 @@
public:
static void RecordAppListLaunch();
static void RecordAppListAppLaunch();
- static void SendAppListStats();
protected:
AppListServiceImpl();
@@ -59,6 +58,8 @@
virtual void EnableAppList(Profile* initial_profile) OVERRIDE;
private:
+ static void SendAppListStats();
+
// Loads a profile asynchronously and calls OnProfileLoaded() when done.
void LoadProfileAsync(const base::FilePath& profile_file_path);
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 e3e4010..4877191 100644
--- a/chrome/browser/ui/app_list/app_list_service_mac.mm
+++ b/chrome/browser/ui/app_list/app_list_service_mac.mm
@@ -30,12 +30,15 @@
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_mac.h"
#include "chrome/common/chrome_version_info.h"
+#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/mac/app_mode_common.h"
#include "content/public/browser/browser_thread.h"
#include "grit/chrome_unscaled_resources.h"
#include "grit/google_chrome_strings.h"
+#include "net/base/url_util.h"
#import "ui/app_list/cocoa/app_list_view_controller.h"
#import "ui/app_list/cocoa/app_list_window_controller.h"
+#include "ui/app_list/search_box_model.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/display.h"
@@ -92,10 +95,14 @@
const std::string& extension_id) OVERRIDE;
virtual void ActivateApp(Profile* profile,
const extensions::Extension* extension,
+ AppListSource source,
int event_flags) OVERRIDE;
virtual void LaunchApp(Profile* profile,
const extensions::Extension* extension,
+ AppListSource source,
int event_flags) OVERRIDE;
+ virtual void ShowForProfileByPath(
+ const base::FilePath& profile_path) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(AppListControllerDelegateCocoa);
};
@@ -234,14 +241,41 @@
}
void AppListControllerDelegateCocoa::ActivateApp(
- Profile* profile, const extensions::Extension* extension, int event_flags) {
- LaunchApp(profile, extension, event_flags);
+ Profile* profile,
+ const extensions::Extension* extension,
+ AppListSource source,
+ int event_flags) {
+ LaunchApp(profile, extension, source, event_flags);
}
void AppListControllerDelegateCocoa::LaunchApp(
- Profile* profile, const extensions::Extension* extension, int event_flags) {
- chrome::OpenApplication(chrome::AppLaunchParams(
- profile, extension, NEW_FOREGROUND_TAB));
+ Profile* profile,
+ const extensions::Extension* extension,
+ AppListSource source,
+ int event_flags) {
+ AppListServiceImpl::RecordAppListAppLaunch();
+
+ chrome::AppLaunchParams params(
+ profile, extension, NEW_FOREGROUND_TAB);
+
+ if (source != LAUNCH_FROM_UNKNOWN &&
+ extension->id() == extension_misc::kWebStoreAppId) {
+ // Set an override URL to include the source.
+ GURL extension_url = extensions::AppLaunchInfo::GetFullLaunchURL(extension);
+ params.override_url = net::AppendQueryParameter(
+ extension_url,
+ extension_urls::kWebstoreSourceField,
+ AppListSourceToString(source));
+ }
+
+ chrome::OpenApplication(params);
+}
+
+void AppListControllerDelegateCocoa::ShowForProfileByPath(
+ const base::FilePath& profile_path) {
+ AppListService* service = AppListServiceMac::GetInstance();
+ service->SetProfilePath(profile_path);
+ service->Show();
}
enum DockLocation {
@@ -409,15 +443,18 @@
if (profile() == requested_profile)
return;
- // 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>()];
-
SetProfile(requested_profile);
+
+ if (window_controller_) {
+ // Clear the search box.
+ [[window_controller_ appListViewController] searchBoxModel]
+ ->SetText(base::string16());
+ } else {
+ window_controller_.reset([[AppListWindowController alloc] init]);
+ }
+
scoped_ptr<app_list::AppListViewDelegate> delegate(
new AppListViewDelegate(new AppListControllerDelegateCocoa(), profile()));
- window_controller_.reset([[AppListWindowController alloc] init]);
[[window_controller_ appListViewController] setDelegate:delegate.Pass()];
}
@@ -427,14 +464,12 @@
InvalidatePendingProfileLoads();
- if (IsAppListVisible() && (requested_profile == profile())) {
+ if (requested_profile == profile()) {
ShowWindowNearDock();
return;
}
SetProfilePath(requested_profile->GetPath());
-
- DismissAppList();
CreateForProfile(requested_profile);
ShowWindowNearDock();
}
@@ -506,6 +541,9 @@
void AppListServiceMac::OnShimQuit(apps::AppShimHandler::Host* host) {}
void AppListServiceMac::ShowWindowNearDock() {
+ if (IsAppListVisible())
+ return;
+
NSWindow* window = GetAppListWindow();
DCHECK(window);
NSPoint target_origin;
@@ -521,6 +559,7 @@
closing:NO];
[window makeKeyAndOrderFront:nil];
[NSApp activateIgnoringOtherApps:YES];
+ RecordAppListLaunch();
}
// static
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 e53fa9b..57b0253 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -4,17 +4,20 @@
#include "chrome/browser/ui/app_list/app_list_view_delegate.h"
+#include <vector>
+
#include "base/callback.h"
#include "base/files/file_path.h"
+#include "base/stl_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/feedback/feedback_util.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
#include "chrome/browser/ui/app_list/apps_model_builder.h"
#include "chrome/browser/ui/app_list/chrome_app_list_item.h"
-#include "chrome/browser/ui/app_list/chrome_signin_delegate.h"
#include "chrome/browser/ui/app_list/search/search_controller.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/chrome_pages.h"
@@ -27,6 +30,7 @@
#include "content/public/browser/notification_source.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/user_metrics.h"
+#include "ui/app_list/search_box_model.h"
#if defined(USE_ASH)
#include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h"
@@ -51,6 +55,24 @@
}
#endif
+void PopulateUsers(const ProfileInfoCache& profile_info,
+ const base::FilePath& active_profile_path,
+ app_list::AppListModel::Users* users) {
+ const size_t count = profile_info.GetNumberOfProfiles();
+ for (size_t i = 0; i < count; ++i) {
+ // Don't display managed users.
+ if (profile_info.ProfileIsManagedAtIndex(i))
+ continue;
+
+ app_list::AppListModel::User user;
+ user.name = profile_info.GetNameOfProfileAtIndex(i);
+ user.email = profile_info.GetUserNameOfProfileAtIndex(i);
+ user.profile_path = profile_info.GetPathOfProfileAtIndex(i);
+ user.active = active_profile_path == user.profile_path;
+ users->push_back(user);
+ }
+}
+
} // namespace
AppListViewDelegate::AppListViewDelegate(AppListControllerDelegate* controller,
@@ -58,13 +80,7 @@
: controller_(controller),
profile_(profile),
model_(NULL) {
- DCHECK(profile_);
- registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
- content::Source<Profile>(profile_));
- registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
- content::Source<Profile>(profile_));
- registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
- content::Source<Profile>(profile_));
+ RegisterForNotifications();
g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver(this);
}
@@ -73,52 +89,78 @@
profile_manager()->GetProfileInfoCache().RemoveObserver(this);
}
-void AppListViewDelegate::OnProfileChanged() {
- model_->SetSignedIn(!signin_delegate_->NeedSignin());
- ProfileInfoCache& cache =
- g_browser_process->profile_manager()->GetProfileInfoCache();
- // Populate the current user details.
- size_t profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
- // The profile won't exist in the cache if the current app list profile is
- // being deleted.
- if (profile_index == std::string::npos)
- return;
+void AppListViewDelegate::RegisterForNotifications() {
+ registrar_.RemoveAll();
+ DCHECK(profile_);
- model_->SetCurrentUser(cache.GetNameOfProfileAtIndex(profile_index),
- cache.GetUserNameOfProfileAtIndex(profile_index));
+ registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
+ content::Source<Profile>(profile_));
+ registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
+ content::Source<Profile>(profile_));
+ registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
+ content::Source<Profile>(profile_));
}
-void AppListViewDelegate::SetModel(app_list::AppListModel* model) {
- if (model) {
- model_ = model;
- apps_builder_.reset(new AppsModelBuilder(profile_,
- model->apps(),
- controller_.get()));
- apps_builder_->Build();
+void AppListViewDelegate::OnProfileChanged() {
+ search_controller_.reset(new app_list::SearchController(
+ profile_, model_->search_box(), model_->results(), controller_.get()));
- search_controller_.reset(new app_list::SearchController(
- profile_, model->search_box(), model->results(), controller_.get()));
-
- signin_delegate_.reset(new ChromeSigninDelegate(profile_));
+ signin_delegate_.SetProfile(profile_);
#if defined(USE_ASH)
- app_sync_ui_state_watcher_.reset(new AppSyncUIStateWatcher(profile_,
- model));
+ app_sync_ui_state_watcher_.reset(new AppSyncUIStateWatcher(profile_,
+ model_));
#endif
- OnProfileChanged();
- } else {
- model_ = NULL;
- apps_builder_.reset();
- search_controller_.reset();
- signin_delegate_.reset();
-#if defined(USE_ASH)
- app_sync_ui_state_watcher_.reset();
-#endif
- }
+
+ model_->SetSignedIn(!GetSigninDelegate()->NeedSignin());
+
+ // Don't populate the app list users if we are on the ash desktop.
+ chrome::HostDesktopType desktop = chrome::GetHostDesktopTypeForNativeWindow(
+ controller_->GetAppListWindow());
+ if (desktop == chrome::HOST_DESKTOP_TYPE_ASH)
+ return;
+
+ // Populate the app list users.
+ app_list::AppListModel::Users users;
+ PopulateUsers(g_browser_process->profile_manager()->GetProfileInfoCache(),
+ profile_->GetPath(), &users);
+ model_->SetUsers(users);
+}
+
+void AppListViewDelegate::SetProfileByPath(const base::FilePath& profile_path) {
+ DCHECK(model_);
+
+ // The profile must be loaded before this is called.
+ profile_ =
+ g_browser_process->profile_manager()->GetProfileByPath(profile_path);
+ DCHECK(profile_);
+
+ RegisterForNotifications();
+
+ apps_builder_->SwitchProfile(profile_);
+
+ OnProfileChanged();
+
+ // Clear search query.
+ model_->search_box()->SetText(base::string16());
+}
+
+void AppListViewDelegate::InitModel(app_list::AppListModel* model) {
+ DCHECK(!model_);
+ DCHECK(model);
+ model_ = model;
+
+ // Initialize apps model.
+ apps_builder_.reset(new AppsModelBuilder(profile_,
+ model->apps(),
+ controller_.get()));
+
+ // Initialize the profile information in the app list menu.
+ OnProfileChanged();
}
app_list::SigninDelegate* AppListViewDelegate::GetSigninDelegate() {
- return signin_delegate_.get();
+ return &signin_delegate_;
}
void AppListViewDelegate::ActivateAppListItem(
@@ -196,7 +238,10 @@
const extensions::Extension* extension = service->GetInstalledExtension(
extension_misc::kSettingsAppId);
DCHECK(extension);
- controller_->ActivateApp(profile_, extension, 0);
+ controller_->ActivateApp(profile_,
+ extension,
+ AppListControllerDelegate::LAUNCH_FROM_UNKNOWN,
+ 0);
}
void AppListViewDelegate::OpenHelp() {
@@ -220,6 +265,11 @@
chrome::kAppLauncherCategoryTag);
}
+void AppListViewDelegate::ShowForProfileByPath(
+ const base::FilePath& profile_path) {
+ controller_->ShowForProfileByPath(profile_path);
+}
+
void AppListViewDelegate::Observe(
int type,
const content::NotificationSource& source,
@@ -227,11 +277,17 @@
OnProfileChanged();
}
+void AppListViewDelegate::OnProfileAdded(const base::FilePath& profile_path) {
+ OnProfileChanged();
+}
+
+void AppListViewDelegate::OnProfileWasRemoved(
+ const base::FilePath& profile_path, const base::string16& profile_name) {
+ OnProfileChanged();
+}
+
void AppListViewDelegate::OnProfileNameChanged(
const base::FilePath& profile_path,
const base::string16& old_profile_name) {
- if (profile_->GetPath() != profile_path)
- return;
-
OnProfileChanged();
}
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 c2576aa..c1f3a95 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.h
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/profiles/profile_info_cache_observer.h"
+#include "chrome/browser/ui/app_list/chrome_signin_delegate.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "ui/app_list/app_list_view_delegate.h"
@@ -50,10 +51,14 @@
virtual ~AppListViewDelegate();
private:
+ // Registers the current profile for notifications.
+ void RegisterForNotifications();
+ // Updates the app list's current profile and ProfileMenuItems.
void OnProfileChanged();
// Overridden from app_list::AppListViewDelegate:
- virtual void SetModel(app_list::AppListModel* model) OVERRIDE;
+ virtual void SetProfileByPath(const base::FilePath& profile_path) OVERRIDE;
+ virtual void InitModel(app_list::AppListModel* model) OVERRIDE;
virtual app_list::SigninDelegate* GetSigninDelegate() OVERRIDE;
virtual void GetShortcutPathForApp(
const std::string& app_id,
@@ -73,6 +78,8 @@
virtual void OpenSettings() OVERRIDE;
virtual void OpenHelp() OVERRIDE;
virtual void OpenFeedback() OVERRIDE;
+ virtual void ShowForProfileByPath(
+ const base::FilePath& profile_path) OVERRIDE;
// Overridden from content::NotificationObserver:
virtual void Observe(int type,
@@ -80,11 +87,13 @@
const content::NotificationDetails& details) OVERRIDE;
// Overridden from ProfileInfoCacheObserver:
+ virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE;
+ virtual void OnProfileWasRemoved(const base::FilePath& profile_path,
+ const base::string16& profile_name) OVERRIDE;
virtual void OnProfileNameChanged(
const base::FilePath& profile_path,
const base::string16& old_profile_name) OVERRIDE;
- scoped_ptr<app_list::SigninDelegate> signin_delegate_;
scoped_ptr<AppsModelBuilder> apps_builder_;
scoped_ptr<app_list::SearchController> search_controller_;
scoped_ptr<AppListControllerDelegate> controller_;
@@ -92,6 +101,7 @@
app_list::AppListModel* model_; // Weak. Owned by AppListView.
content::NotificationRegistrar registrar_;
+ ChromeSigninDelegate signin_delegate_;
#if defined(USE_ASH)
scoped_ptr<AppSyncUIStateWatcher> app_sync_ui_state_watcher_;
#endif
diff --git a/chrome/browser/ui/app_list/apps_model_builder.cc b/chrome/browser/ui/app_list/apps_model_builder.cc
index b662b45..30022cd 100644
--- a/chrome/browser/ui/app_list/apps_model_builder.cc
+++ b/chrome/browser/ui/app_list/apps_model_builder.cc
@@ -54,13 +54,15 @@
AppsModelBuilder::AppsModelBuilder(Profile* profile,
app_list::AppListModel::Apps* model,
AppListControllerDelegate* controller)
- : profile_(profile),
+ : profile_(NULL),
controller_(controller),
model_(model),
highlighted_app_pending_(false),
ignore_changes_(false),
- tracker_(extensions::InstallTrackerFactory::GetForProfile(profile_)) {
+ tracker_(NULL) {
model_->AddObserver(this);
+ // Build the model.
+ SwitchProfile(profile);
}
AppsModelBuilder::~AppsModelBuilder() {
@@ -68,16 +70,6 @@
model_->RemoveObserver(this);
}
-void AppsModelBuilder::Build() {
- DCHECK(model_ && model_->item_count() == 0);
-
- PopulateApps();
- UpdateHighlight();
-
- // Start observing after model is built.
- tracker_->AddObserver(this);
-}
-
void AppsModelBuilder::OnBeginExtensionInstall(
const std::string& extension_id,
const std::string& extension_name,
@@ -172,6 +164,26 @@
}
}
+void AppsModelBuilder::SwitchProfile(Profile* profile) {
+ if (profile_ == profile)
+ return;
+
+ profile_ = profile;
+ model_->DeleteAll();
+ if (tracker_)
+ tracker_->RemoveObserver(this);
+
+ tracker_ = extensions::InstallTrackerFactory::GetForProfile(profile_);
+
+ DCHECK(model_ && model_->item_count() == 0);
+
+ PopulateApps();
+ UpdateHighlight();
+
+ // Start observing after model is built.
+ tracker_->AddObserver(this);
+}
+
void AppsModelBuilder::PopulateApps() {
ExtensionService* service =
extensions::ExtensionSystem::Get(profile_)->extension_service();
diff --git a/chrome/browser/ui/app_list/apps_model_builder.h b/chrome/browser/ui/app_list/apps_model_builder.h
index 0898dd9..4862896 100644
--- a/chrome/browser/ui/app_list/apps_model_builder.h
+++ b/chrome/browser/ui/app_list/apps_model_builder.h
@@ -27,6 +27,8 @@
class ImageSkia;
}
+// This class populates and maintains the given |model| with information from
+// |profile|.
class AppsModelBuilder : public ui::ListModelObserver,
public extensions::InstallObserver {
public:
@@ -35,12 +37,12 @@
AppListControllerDelegate* controller);
virtual ~AppsModelBuilder();
- // Populates the model.
- void Build();
-
// Returns app instance with id |extension_id|.
ExtensionAppItem* GetApp(const std::string& extension_id);
+ // Rebuilds the model with the given profile.
+ void SwitchProfile(Profile* profile);
+
private:
typedef std::vector<ExtensionAppItem*> Apps;
diff --git a/chrome/browser/ui/app_list/apps_model_builder_unittest.cc b/chrome/browser/ui/app_list/apps_model_builder_unittest.cc
index c1554e5..a19062e 100644
--- a/chrome/browser/ui/app_list/apps_model_builder_unittest.cc
+++ b/chrome/browser/ui/app_list/apps_model_builder_unittest.cc
@@ -91,7 +91,6 @@
scoped_ptr<app_list::AppListModel::Apps> model(
new app_list::AppListModel::Apps);
AppsModelBuilder builder(profile_.get(), model.get(), NULL);
- builder.Build();
// The apps list would have 3 extension apps in the profile.
EXPECT_EQ(std::string("Packaged App 1,Packaged App 2,Hosted App"),
@@ -118,7 +117,6 @@
// Web stores should be present in the AppListModel.
app_list::AppListModel::Apps model1;
AppsModelBuilder builder1(profile_.get(), &model1, NULL);
- builder1.Build();
std::string content = GetModelContent(&model1);
EXPECT_NE(std::string::npos, content.find("webstore"));
EXPECT_NE(std::string::npos, content.find("enterprise_webstore"));
@@ -129,7 +127,6 @@
// Web stores should NOT be in the AppListModel.
app_list::AppListModel::Apps model2;
AppsModelBuilder builder2(profile_.get(), &model2, NULL);
- builder2.Build();
content = GetModelContent(&model2);
EXPECT_EQ(std::string::npos, content.find("webstore"));
EXPECT_EQ(std::string::npos, content.find("enterprise_webstore"));
@@ -139,7 +136,6 @@
scoped_ptr<app_list::AppListModel::Apps> model(
new app_list::AppListModel::Apps);
AppsModelBuilder builder(profile_.get(), model.get(), NULL);
- builder.Build();
service_->DisableExtension(kHostedAppId,
extensions::Extension::DISABLE_NONE);
@@ -155,7 +151,6 @@
scoped_ptr<app_list::AppListModel::Apps> model(
new app_list::AppListModel::Apps);
AppsModelBuilder builder(profile_.get(), model.get(), NULL);
- builder.Build();
service_->UninstallExtension(kPackagedApp2Id, false, NULL);
EXPECT_EQ(std::string("Packaged App 1,Hosted App"),
@@ -168,7 +163,6 @@
scoped_ptr<app_list::AppListModel::Apps> model(
new app_list::AppListModel::Apps);
AppsModelBuilder builder(profile_.get(), model.get(), NULL);
- builder.Build();
const extensions::Extension* app =
service_->GetInstalledExtension(kPackagedApp2Id);
@@ -188,7 +182,6 @@
scoped_ptr<app_list::AppListModel::Apps> model(
new app_list::AppListModel::Apps);
AppsModelBuilder builder(profile_.get(), model.get(), NULL);
- builder.Build();
ExtensionSorting* sorting = service_->extension_prefs()->extension_sorting();
@@ -213,7 +206,6 @@
scoped_ptr<app_list::AppListModel::Apps> model(
new app_list::AppListModel::Apps);
AppsModelBuilder builder(profile_.get(), model.get(), NULL);
- builder.Build();
ExtensionSorting* sorting = service_->extension_prefs()->extension_sorting();
sorting->SetPageOrdinal(kHostedAppId,
@@ -246,10 +238,9 @@
scoped_ptr<app_list::AppListModel::Apps> model(
new app_list::AppListModel::Apps);
- AppsModelBuilder builder(profile_.get(), model.get(), NULL);
// This should not assert or crash.
- builder.Build();
+ AppsModelBuilder builder(profile_.get(), model.get(), NULL);
}
TEST_F(AppsModelBuilderTest, OrdinalConfilicts) {
@@ -270,7 +261,6 @@
scoped_ptr<app_list::AppListModel::Apps> model(
new app_list::AppListModel::Apps);
AppsModelBuilder builder(profile_.get(), model.get(), NULL);
- builder.Build();
// By default, conflicted items are sorted by their app ids.
EXPECT_EQ(std::string("Hosted App,Packaged App 1,Packaged App 2"),
diff --git a/chrome/browser/ui/app_list/chrome_signin_delegate.cc b/chrome/browser/ui/app_list/chrome_signin_delegate.cc
index e7d0aa4..c50ad0c 100644
--- a/chrome/browser/ui/app_list/chrome_signin_delegate.cc
+++ b/chrome/browser/ui/app_list/chrome_signin_delegate.cc
@@ -28,8 +28,13 @@
} // namespace
-ChromeSigninDelegate::ChromeSigninDelegate(Profile* profile)
- : profile_(profile) {}
+ChromeSigninDelegate::ChromeSigninDelegate() {}
+
+ChromeSigninDelegate::~ChromeSigninDelegate() {}
+
+void ChromeSigninDelegate::SetProfile(Profile* profile) {
+ profile_ = profile;
+}
bool ChromeSigninDelegate::NeedSignin() {
#if defined(OS_CHROMEOS)
@@ -96,5 +101,3 @@
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
return rb.GetLocalizedString(IDS_APP_LIST_SIGNIN_SETTINGS_TEXT);
}
-
-ChromeSigninDelegate::~ChromeSigninDelegate() {}
diff --git a/chrome/browser/ui/app_list/chrome_signin_delegate.h b/chrome/browser/ui/app_list/chrome_signin_delegate.h
index 17e9b5a..71e9a62 100644
--- a/chrome/browser/ui/app_list/chrome_signin_delegate.h
+++ b/chrome/browser/ui/app_list/chrome_signin_delegate.h
@@ -13,14 +13,11 @@
class ChromeSigninDelegate : public app_list::SigninDelegate {
public:
- explicit ChromeSigninDelegate(Profile* profile);
+ ChromeSigninDelegate();
+ virtual ~ChromeSigninDelegate();
+ void SetProfile(Profile* profile);
private:
- virtual ~ChromeSigninDelegate();
-
- bool IsActiveSignin();
- void FinishSignin();
-
// Overridden from app_list::SigninDelegate:
virtual bool NeedSignin() OVERRIDE;
virtual void ShowSignin() OVERRIDE;
diff --git a/chrome/browser/ui/app_list/extension_app_item.cc b/chrome/browser/ui/app_list/extension_app_item.cc
index 1cf2b44..6050cb7 100644
--- a/chrome/browser/ui/app_list/extension_app_item.cc
+++ b/chrome/browser/ui/app_list/extension_app_item.cc
@@ -227,7 +227,10 @@
if (RunExtensionEnableFlow())
return;
- controller_->LaunchApp(profile_, extension, event_flags);
+ controller_->LaunchApp(profile_,
+ extension,
+ AppListControllerDelegate::LAUNCH_FROM_APP_LIST,
+ event_flags);
}
void ExtensionAppItem::OnExtensionIconImageChanged(
@@ -259,13 +262,16 @@
return;
CoreAppLauncherHandler::RecordAppListMainLaunch(extension);
- controller_->ActivateApp(profile_, extension, event_flags);
+ controller_->ActivateApp(profile_,
+ extension,
+ AppListControllerDelegate::LAUNCH_FROM_APP_LIST,
+ event_flags);
}
ui::MenuModel* ExtensionAppItem::GetContextMenuModel() {
if (!context_menu_) {
context_menu_.reset(new app_list::AppContextMenu(
- this, profile_, extension_id_, controller_, is_platform_app_));
+ this, profile_, extension_id_, controller_, is_platform_app_, false));
}
return context_menu_->GetMenuModel();
diff --git a/chrome/browser/ui/app_list/fast_show_pickler.cc b/chrome/browser/ui/app_list/fast_show_pickler.cc
new file mode 100644
index 0000000..d282aab
--- /dev/null
+++ b/chrome/browser/ui/app_list/fast_show_pickler.cc
@@ -0,0 +1,259 @@
+// Copyright 2013 The Chromium 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/fast_show_pickler.h"
+
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/app_list/app_list_item_model.h"
+#include "ui/base/layout.h"
+#include "ui/gfx/image/image_skia_rep.h"
+
+namespace {
+
+using app_list::AppListItemModel;
+using app_list::AppListModel;
+
+// These have the same meaning as SkBitmap::Config. Reproduced here to insure
+// against their value changing in Skia. If the order of these changes kVersion
+// should be incremented.
+enum ImageFormat {
+ NONE,
+ A1,
+ A8,
+ INDEX_8,
+ RGB_565,
+ ARGB_4444,
+ ARGB_8888,
+};
+
+bool FormatToConfig(ImageFormat format, SkBitmap::Config* out) {
+ switch (format) {
+ case NONE:
+ *out = SkBitmap::kNo_Config;
+ break;
+ case A1:
+ *out = SkBitmap::kA1_Config;
+ break;
+ case A8:
+ *out = SkBitmap::kA8_Config;
+ break;
+ case INDEX_8:
+ *out = SkBitmap::kIndex8_Config;
+ break;
+ case RGB_565:
+ *out = SkBitmap::kRGB_565_Config;
+ break;
+ case ARGB_4444:
+ *out = SkBitmap::kARGB_4444_Config;
+ break;
+ case ARGB_8888:
+ *out = SkBitmap::kARGB_8888_Config;
+ break;
+ default: return false;
+ }
+ return true;
+}
+
+bool ConfigToFormat(SkBitmap::Config config, ImageFormat* out) {
+ switch (config) {
+ case SkBitmap::kNo_Config:
+ *out = NONE;
+ break;
+ case SkBitmap::kA1_Config:
+ *out = A1;
+ break;
+ case SkBitmap::kA8_Config:
+ *out = A8;
+ break;
+ case SkBitmap::kIndex8_Config:
+ *out = INDEX_8;
+ break;
+ case SkBitmap::kRGB_565_Config:
+ *out = RGB_565;
+ break;
+ case SkBitmap::kARGB_4444_Config:
+ *out = ARGB_4444;
+ break;
+ case SkBitmap::kARGB_8888_Config:
+ *out = ARGB_8888;
+ break;
+ default: return false;
+ }
+ return true;
+}
+
+bool PickleImage(Pickle* pickle, const gfx::ImageSkia& image) {
+ std::vector<gfx::ImageSkiaRep> reps(image.image_reps());
+ pickle->WriteInt(static_cast<int>(reps.size()));
+ for (std::vector<gfx::ImageSkiaRep>::const_iterator it = reps.begin();
+ it != reps.end(); ++it) {
+ pickle->WriteInt(static_cast<int>(ui::GetSupportedScaleFactor(it->scale())));
+ pickle->WriteInt(it->pixel_width());
+ pickle->WriteInt(it->pixel_height());
+ ImageFormat format = NONE;
+ if (!ConfigToFormat(it->sk_bitmap().getConfig(), &format))
+ return false;
+ pickle->WriteInt(static_cast<int>(format));
+ int size = static_cast<int>(it->sk_bitmap().getSafeSize());
+ pickle->WriteInt(size);
+ SkBitmap bitmap = it->sk_bitmap();
+ SkAutoLockPixels lock(bitmap);
+ pickle->WriteBytes(bitmap.getPixels(), size);
+ }
+ return true;
+}
+
+bool UnpickleImage(PickleIterator* it, gfx::ImageSkia* out) {
+ int rep_count = 0;
+ if (!it->ReadInt(&rep_count))
+ return false;
+
+ gfx::ImageSkia result;
+ for (int i = 0; i < rep_count; ++i) {
+ int scale_factor = 0;
+ if (!it->ReadInt(&scale_factor))
+ return false;
+
+ int width = 0;
+ if (!it->ReadInt(&width))
+ return false;
+
+ int height = 0;
+ if (!it->ReadInt(&height))
+ return false;
+
+ int format_int = 0;
+ if (!it->ReadInt(&format_int))
+ return false;
+ ImageFormat format = static_cast<ImageFormat>(format_int);
+ SkBitmap::Config config = SkBitmap::kNo_Config;
+ if (!FormatToConfig(format, &config))
+ return false;
+
+ int size = 0;
+ if (!it->ReadInt(&size))
+ return false;
+
+ const char* pixels = NULL;
+ if (!it->ReadBytes(&pixels, size))
+ return false;
+
+ SkBitmap bitmap;
+ bitmap.setConfig(static_cast<SkBitmap::Config>(config), width, height);
+ if (!bitmap.allocPixels())
+ return false;
+ {
+ SkAutoLockPixels lock(bitmap);
+ memcpy(bitmap.getPixels(), pixels, bitmap.getSize());
+ }
+ float scale = ui::GetImageScale(static_cast<ui::ScaleFactor>(scale_factor));
+ result.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
+ }
+
+ *out = result;
+ return true;
+}
+
+scoped_ptr<AppListItemModel> UnpickleAppListItemModel(PickleIterator* it) {
+ scoped_ptr<AppListItemModel> result(new AppListItemModel);
+ std::string id;
+ if (!it->ReadString(&id))
+ return scoped_ptr<AppListItemModel>();
+ result->set_app_id(id);
+ std::string title;
+ if (!it->ReadString(&title))
+ return scoped_ptr<AppListItemModel>();
+ std::string full_name;
+ if (!it->ReadString(&full_name))
+ return scoped_ptr<AppListItemModel>();
+ result->SetTitleAndFullName(title, full_name);
+ bool has_shadow = false;
+ if (!it->ReadBool(&has_shadow))
+ return scoped_ptr<AppListItemModel>();
+ gfx::ImageSkia icon;
+ if (!UnpickleImage(it, &icon))
+ return scoped_ptr<AppListItemModel>();
+ result->SetIcon(icon, has_shadow);
+ return result.Pass();
+}
+
+bool PickleAppListItemModel(Pickle* pickle, AppListItemModel* item) {
+ if (!pickle->WriteString(item->app_id()))
+ return false;
+ if (!pickle->WriteString(item->title()))
+ return false;
+ if (!pickle->WriteString(item->full_name()))
+ return false;
+ if (!pickle->WriteBool(item->has_shadow()))
+ return false;
+ if (!PickleImage(pickle, item->icon()))
+ return false;
+ return true;
+}
+
+void CopyOverItem(AppListItemModel* src_item, AppListItemModel* dest_item) {
+ dest_item->set_app_id(src_item->app_id());
+ dest_item->SetTitleAndFullName(src_item->title(), src_item->full_name());
+ dest_item->SetIcon(src_item->icon(), src_item->has_shadow());
+}
+
+} // namespace
+
+// The version of the pickle format defined here. This needs to be incremented
+// whenever this format is changed so new clients can invalidate old versions.
+const int FastShowPickler::kVersion = 1;
+
+scoped_ptr<Pickle> FastShowPickler::PickleAppListModelForFastShow(
+ AppListModel* model) {
+ scoped_ptr<Pickle> result(new Pickle);
+ if (!result->WriteInt(kVersion))
+ return scoped_ptr<Pickle>();
+ if (!result->WriteBool(model->signed_in()))
+ return scoped_ptr<Pickle>();
+ if (!result->WriteInt((int) model->apps()->item_count()))
+ return scoped_ptr<Pickle>();
+ for (size_t i = 0; i < model->apps()->item_count(); ++i) {
+ if (!PickleAppListItemModel(result.get(), model->apps()->GetItemAt(i)))
+ return scoped_ptr<Pickle>();
+ }
+ return result.Pass();
+}
+
+void FastShowPickler::CopyOver(AppListModel* src, AppListModel* dest) {
+ dest->apps()->DeleteAll();
+ dest->SetSignedIn(src->signed_in());
+ for (size_t i = 0; i < src->apps()->item_count(); i++) {
+ AppListItemModel* src_item = src->apps()->GetItemAt(i);
+ AppListItemModel* dest_item = new AppListItemModel;
+ CopyOverItem(src_item, dest_item);
+ dest->apps()->Add(dest_item);
+ }
+}
+
+scoped_ptr<AppListModel>
+FastShowPickler::UnpickleAppListModelForFastShow(Pickle* pickle) {
+ PickleIterator it(*pickle);
+ int read_version = 0;
+ if (!it.ReadInt(&read_version))
+ return scoped_ptr<AppListModel>();
+ if (read_version != kVersion)
+ return scoped_ptr<AppListModel>();
+ int app_count = 0;
+ bool signed_in = false;
+ if (!it.ReadBool(&signed_in))
+ return scoped_ptr<AppListModel>();
+ if (!it.ReadInt(&app_count))
+ return scoped_ptr<AppListModel>();
+
+ scoped_ptr<AppListModel> model(new AppListModel);
+ model->SetSignedIn(signed_in);
+ for (int i = 0; i < app_count; ++i) {
+ scoped_ptr<AppListItemModel> item(UnpickleAppListItemModel(&it).Pass());
+ if (!item)
+ return scoped_ptr<AppListModel>();
+ model->apps()->Add(item.release());
+ }
+
+ return model.Pass();
+}
diff --git a/chrome/browser/ui/app_list/fast_show_pickler.h b/chrome/browser/ui/app_list/fast_show_pickler.h
new file mode 100644
index 0000000..c0cc168
--- /dev/null
+++ b/chrome/browser/ui/app_list/fast_show_pickler.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_BROWSER_UI_APP_LIST_FAST_SHOW_PICKLER_H_
+#define CHROME_BROWSER_UI_APP_LIST_FAST_SHOW_PICKLER_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/pickle.h"
+#include "ui/app_list/app_list_model.h"
+
+// Functions for pickling/unpickling AppListModel for fast show. Fast show is
+// where the app list is put on the screen using data retrieved from a cache
+// before the extension system has loaded.
+class FastShowPickler {
+ public:
+ // The version that this pickler understands.
+ static const int kVersion;
+
+ // Pickles a subset of the data in |model| that is useful for doing a fast
+ // show of the app list.
+ static scoped_ptr<Pickle> PickleAppListModelForFastShow(
+ app_list::AppListModel* model);
+
+ // Given a Pickle created by PickleAppListModelForFastShow(), this creates an
+ // AppListModel that represents it.
+ static scoped_ptr<app_list::AppListModel> UnpickleAppListModelForFastShow(
+ Pickle* pickle);
+
+ // Copies parts that are needed to show the app list quickly on startup from
+ // |src| to |dest|.
+ static void CopyOver(
+ app_list::AppListModel* src, app_list::AppListModel* dest);
+};
+
+#endif // CHROME_BROWSER_UI_APP_LIST_FAST_SHOW_PICKLER_H_
diff --git a/chrome/browser/ui/app_list/search/app_result.cc b/chrome/browser/ui/app_list/search/app_result.cc
index 1c49dd3..d537c6b 100644
--- a/chrome/browser/ui/app_list/search/app_result.cc
+++ b/chrome/browser/ui/app_list/search/app_result.cc
@@ -84,7 +84,11 @@
content::RecordAction(
content::UserMetricsAction("AppList_ClickOnAppFromSearch"));
- controller_->ActivateApp(profile_, extension, event_flags);
+ controller_->ActivateApp(
+ profile_,
+ extension,
+ AppListControllerDelegate::LAUNCH_FROM_APP_LIST_SEARCH,
+ event_flags);
}
void AppResult::InvokeAction(int action_index, int event_flags) {}
@@ -105,7 +109,7 @@
ui::MenuModel* AppResult::GetContextMenuModel() {
if (!context_menu_) {
context_menu_.reset(new AppContextMenu(
- this, profile_, app_id_, controller_, is_platform_app_));
+ this, profile_, app_id_, controller_, is_platform_app_, true));
}
return context_menu_->GetMenuModel();
diff --git a/chrome/browser/ui/app_list/search/common/url_icon_source.cc b/chrome/browser/ui/app_list/search/common/url_icon_source.cc
index 443da12..acb2d28 100644
--- a/chrome/browser/ui/app_list/search/common/url_icon_source.cc
+++ b/chrome/browser/ui/app_list/search/common/url_icon_source.cc
@@ -47,17 +47,15 @@
icon_fetcher_->Start();
}
-gfx::ImageSkiaRep UrlIconSource::GetImageForScale(
- ui::ScaleFactor scale_factor) {
+gfx::ImageSkiaRep UrlIconSource::GetImageForScale(float scale) {
if (!icon_fetch_attempted_)
StartIconFetch();
if (!icon_.isNull())
- return icon_.GetRepresentation(scale_factor);
+ return icon_.GetRepresentation(scale);
return ui::ResourceBundle::GetSharedInstance()
- .GetImageSkiaNamed(default_icon_resource_id_)->GetRepresentation(
- scale_factor);
+ .GetImageSkiaNamed(default_icon_resource_id_)->GetRepresentation(scale);
}
void UrlIconSource::OnURLFetchComplete(
diff --git a/chrome/browser/ui/app_list/search/common/url_icon_source.h b/chrome/browser/ui/app_list/search/common/url_icon_source.h
index de94f28..32465e8 100644
--- a/chrome/browser/ui/app_list/search/common/url_icon_source.h
+++ b/chrome/browser/ui/app_list/search/common/url_icon_source.h
@@ -45,8 +45,7 @@
void StartIconFetch();
// gfx::ImageSkiaSource overrides:
- virtual gfx::ImageSkiaRep GetImageForScale(
- ui::ScaleFactor scale_factor) OVERRIDE;
+ virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE;
// net::URLFetcherDelegate overrides:
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
diff --git a/chrome/browser/ui/app_list/search/people/people_provider.cc b/chrome/browser/ui/app_list/search/people/people_provider.cc
index cb94679..b82f52e 100644
--- a/chrome/browser/ui/app_list/search/people/people_provider.cc
+++ b/chrome/browser/ui/app_list/search/people/people_provider.cc
@@ -31,6 +31,8 @@
const char kKeyId[] = "person.id";
const char kKeyNames[] = "person.names";
const char kKeyDisplayName[] = "displayName";
+const char kKeyEmails[] = "person.emails";
+const char kKeyEmailValue[] = "value";
const char kKeySortKeys[] = "person.sortKeys";
const char kKeyInteractionRank[] = "interactionRank";
const char kKeyImages[] = "person.images";
@@ -128,9 +130,10 @@
if (access_token_request_ != NULL)
return;
- OAuth2TokenService* token_service =
+ ProfileOAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
- access_token_request_ = token_service->StartRequest(oauth2_scope_, this);
+ access_token_request_ = token_service->StartRequest(
+ token_service->GetPrimaryAccountId(), oauth2_scope_, this);
}
GURL PeopleProvider::GetQueryUrl(const std::string& query) {
@@ -203,6 +206,13 @@
std::string display_name;
display_name = GetFirstValue(*names, kKeyDisplayName);
+ // Get the email.
+ const base::ListValue* emails;
+ if (!dict.GetList(kKeyEmails, &emails))
+ return result.Pass();
+ std::string email;
+ email = GetFirstValue(*emails, kKeyEmailValue);
+
// Get the interaction rank.
const base::DictionaryValue* sort_keys;
if (!dict.GetDictionary(kKeySortKeys, &sort_keys))
@@ -229,6 +239,7 @@
if (id.empty() ||
display_name.empty() ||
+ email.empty() ||
interaction_rank_string.empty() ||
image_url_string.empty()) {
return result.Pass();
@@ -239,7 +250,7 @@
return result.Pass();
result.reset(new PeopleResult(
- profile_, id, display_name, interaction_rank, image_url));
+ profile_, id, display_name, email, interaction_rank, image_url));
return result.Pass();
}
diff --git a/chrome/browser/ui/app_list/search/people/people_provider_browsertest.cc b/chrome/browser/ui/app_list/search/people/people_provider_browsertest.cc
index 8234b21..e4eeeb9 100644
--- a/chrome/browser/ui/app_list/search/people/people_provider_browsertest.cc
+++ b/chrome/browser/ui/app_list/search/people/people_provider_browsertest.cc
@@ -39,6 +39,9 @@
"\"names\" : [{"
"\"displayName\": \"first person\""
"}],"
+ "\"emails\" : [{"
+ "\"value\": \"first@person.com\""
+ "}],"
"\"images\" : [{"
"\"url\": \"http://host/icon\""
"}],"
@@ -57,6 +60,9 @@
"\"names\" : [{"
"\"displayName\": \"first person\""
"}],"
+ "\"emails\" : [{"
+ "\"value\": \"first@person.com\""
+ "}],"
"\"images\" : [{"
"\"url\": \"http://host/icon\""
"}],"
@@ -71,6 +77,9 @@
"\"names\" : [{"
"\"displayName\": \"second person\""
"}],"
+ "\"emails\" : [{"
+ "\"value\": \"second@person.com\""
+ "}],"
"\"images\" : [{"
"\"url\": \"http://host/icon\""
"}],"
@@ -85,6 +94,9 @@
"\"names\" : [{"
"\"displayName\": \"third person\""
"}],"
+ "\"emails\" : [{"
+ "\"value\": \"third@person.com\""
+ "}],"
"\"images\" : [{"
"\"url\": \"http://host/icon\""
"}],"
@@ -99,6 +111,9 @@
"\"names\" : [{"
"\"displayName\": \"fourth person\""
"}],"
+ "\"emails\" : [{"
+ "\"value\": \"fourth@person.com\""
+ "}],"
"\"images\" : [{"
"\"url\": \"http://host/icon\""
"}],"
@@ -113,6 +128,9 @@
"\"names\" : [{"
"\"displayName\": \"fifth person\""
"}],"
+ "\"emails\" : [{"
+ "\"value\": \"fifth@person.com\""
+ "}],"
// Images field is missing on purpose.
"\"sortKeys\" : {"
"\"interactionRank\": \"0.98\""
diff --git a/chrome/browser/ui/app_list/search/people/people_result.cc b/chrome/browser/ui/app_list/search/people/people_result.cc
index 6d0990e..01e54cf 100644
--- a/chrome/browser/ui/app_list/search/people/people_result.cc
+++ b/chrome/browser/ui/app_list/search/people/people_result.cc
@@ -11,13 +11,17 @@
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/search/common/url_icon_source.h"
+#include "chrome/browser/ui/browser_navigator.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"
namespace {
const int kIconSize = 32;
const char kImageSizePath[] = "s32-p/";
+const char kEmailUrlPrefix[] = "mailto:";
// Add a query parameter to specify the size to fetch the image in. The
// original profile image can be of an arbitrary size, we ask the server to
@@ -37,17 +41,22 @@
PeopleResult::PeopleResult(Profile* profile,
const std::string& id,
const std::string& display_name,
+ const std::string& email,
double interaction_rank,
const GURL& image_url)
: profile_(profile),
id_(id),
display_name_(display_name),
+ email_(email),
interaction_rank_(interaction_rank),
image_url_(image_url),
weak_factory_(this) {
set_id(id_);
set_title(UTF8ToUTF16(display_name_));
set_relevance(interaction_rank_);
+ set_details(UTF8ToUTF16(email_));
+
+ SetDefaultActions();
image_ = gfx::ImageSkia(
new UrlIconSource(base::Bind(&PeopleResult::OnIconLoaded,
@@ -64,17 +73,19 @@
}
void PeopleResult::Open(int event_flags) {
- // TODO(rkc): Navigate to the person's profile?
+ InvokeAction(0, event_flags);
}
void PeopleResult::InvokeAction(int action_index, int event_flags) {
DCHECK_EQ(0, action_index);
- // TODO(rkc): Decide what to do here.
+ // Currently we support only one action, sending mail.
+ SendEmail();
}
scoped_ptr<ChromeSearchResult> PeopleResult::Duplicate() {
return scoped_ptr<ChromeSearchResult>(new PeopleResult(profile_, id_,
display_name_,
+ email_,
interaction_rank_,
image_url_)).Pass();
}
@@ -84,11 +95,32 @@
// need to be re-created.
const std::vector<gfx::ImageSkiaRep>& image_reps = image_.image_reps();
for (size_t i = 0; i < image_reps.size(); ++i)
- image_.RemoveRepresentation(image_reps[i].scale_factor());
+ image_.RemoveRepresentation(image_reps[i].scale());
SetIcon(image_);
}
+void PeopleResult::SetDefaultActions() {
+ Actions actions;
+
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ actions.push_back(Action(
+ *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL),
+ *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_HOVER),
+ *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_PRESSED),
+ l10n_util::GetStringUTF16(IDS_PEOPLE_SEARCH_ACTION_EMAIL_TOOLTIP)));
+ SetActions(actions);
+}
+
+void PeopleResult::SendEmail() {
+ chrome::NavigateParams params(profile_,
+ GURL(kEmailUrlPrefix + email_),
+ content::PAGE_TRANSITION_LINK);
+ // If no window exists, this will open a new window this one tab.
+ params.disposition = NEW_FOREGROUND_TAB;
+ chrome::Navigate(¶ms);
+}
+
ChromeSearchResultType PeopleResult::GetType() {
return SEARCH_PEOPLE_SEARCH_RESULT;
}
diff --git a/chrome/browser/ui/app_list/search/people/people_result.h b/chrome/browser/ui/app_list/search/people/people_result.h
index 6303e28..d689019 100644
--- a/chrome/browser/ui/app_list/search/people/people_result.h
+++ b/chrome/browser/ui/app_list/search/people/people_result.h
@@ -21,6 +21,7 @@
PeopleResult(Profile* profile,
const std::string& id,
const std::string& display_name,
+ const std::string& email,
double interaction_rank,
const GURL& image_url);
virtual ~PeopleResult();
@@ -32,12 +33,14 @@
virtual ChromeSearchResultType GetType() OVERRIDE;
private:
- void SetDefaultDetails();
void OnIconLoaded();
+ void SetDefaultActions();
+ void SendEmail();
Profile* profile_;
const std::string id_;
const std::string display_name_;
+ const std::string email_;
const double interaction_rank_;
const GURL image_url_;
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 9940a13..e544523 100644
--- a/chrome/browser/ui/app_list/search/search_webstore_result.cc
+++ b/chrome/browser/ui/app_list/search/search_webstore_result.cc
@@ -10,6 +10,7 @@
#include "chrome/common/extensions/extension_constants.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
@@ -40,8 +41,13 @@
SearchWebstoreResult::~SearchWebstoreResult() {}
void SearchWebstoreResult::Open(int event_flags) {
+ const GURL store_url = net::AppendQueryParameter(
+ launch_url_,
+ extension_urls::kWebstoreSourceField,
+ extension_urls::kLaunchSourceAppListSearch);
+
chrome::NavigateParams params(profile_,
- launch_url_,
+ store_url,
content::PAGE_TRANSITION_LINK);
params.disposition = ui::DispositionFromEventFlags(event_flags);
chrome::Navigate(¶ms);
diff --git a/chrome/browser/ui/app_list/search/webstore/webstore_installer.cc b/chrome/browser/ui/app_list/search/webstore/webstore_installer.cc
index 48dc537..bda5665 100644
--- a/chrome/browser/ui/app_list/search/webstore/webstore_installer.cc
+++ b/chrome/browser/ui/app_list/search/webstore/webstore_installer.cc
@@ -15,7 +15,10 @@
const Callback& callback)
: WebstoreStartupInstaller(webstore_item_id, profile, true, callback),
profile_(profile),
- parent_window_(parent_window) {}
+ parent_window_(parent_window) {
+ set_install_source(
+ extensions::WebstoreInstaller::INSTALL_SOURCE_APP_LAUNCHER);
+}
WebstoreInstaller::~WebstoreInstaller() {}
diff --git a/chrome/browser/ui/app_list/search/webstore/webstore_provider.cc b/chrome/browser/ui/app_list/search/webstore/webstore_provider.cc
index db20a46..973fc2e 100644
--- a/chrome/browser/ui/app_list/search/webstore/webstore_provider.cc
+++ b/chrome/browser/ui/app_list/search/webstore/webstore_provider.cc
@@ -28,7 +28,6 @@
const char kKeyId[] = "id";
const char kKeyLocalizedName[] = "localized_name";
const char kKeyIconUrl[] = "icon_url";
-const size_t kMinimumQueryLength = 3u;
// Returns true if the launcher should send queries to the web store server.
bool UseWebstoreSearch() {
diff --git a/chrome/browser/ui/app_list/search/webstore/webstore_result.cc b/chrome/browser/ui/app_list/search/webstore/webstore_result.cc
index 27310c2..7148365 100644
--- a/chrome/browser/ui/app_list/search/webstore/webstore_result.cc
+++ b/chrome/browser/ui/app_list/search/webstore/webstore_result.cc
@@ -23,6 +23,7 @@
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
@@ -97,8 +98,11 @@
}
void WebstoreResult::Open(int event_flags) {
- const GURL store_url(extension_urls::GetWebstoreItemDetailURLPrefix() +
- app_id_);
+ const GURL store_url = net::AppendQueryParameter(
+ GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + app_id_),
+ extension_urls::kWebstoreSourceField,
+ extension_urls::kLaunchSourceAppListSearch);
+
chrome::NavigateParams params(profile_,
store_url,
content::PAGE_TRANSITION_LINK);
@@ -147,7 +151,7 @@
// need to be re-created.
const std::vector<gfx::ImageSkiaRep>& image_reps = icon_.image_reps();
for (size_t i = 0; i < image_reps.size(); ++i)
- icon_.RemoveRepresentation(image_reps[i].scale_factor());
+ icon_.RemoveRepresentation(image_reps[i].scale());
icon_ = gfx::ImageSkia(new BadgedIconSource(icon_),
gfx::Size(kIconSize, kIconSize));
diff --git a/chrome/browser/ui/app_list/test/fast_show_pickler_unittest.cc b/chrome/browser/ui/app_list/test/fast_show_pickler_unittest.cc
new file mode 100644
index 0000000..6f2d8da
--- /dev/null
+++ b/chrome/browser/ui/app_list/test/fast_show_pickler_unittest.cc
@@ -0,0 +1,142 @@
+// Copyright 2013 The Chromium 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/fast_show_pickler.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
+#include "ui/app_list/app_list_item_model.h"
+#include "ui/app_list/app_list_model.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/skia_util.h"
+
+using app_list::AppListItemModel;
+using app_list::AppListModel;
+
+class AppListModelPicklerUnitTest : public testing::Test {
+ protected:
+ void CheckIsSame(AppListModel* m1, AppListModel* m2) {
+ ASSERT_EQ(m1->apps()->item_count(), m2->apps()->item_count());
+ ASSERT_EQ(m1->signed_in(), m2->signed_in());
+ for (size_t i = 0; i < m1->apps()->item_count(); i++) {
+ ASSERT_EQ(m1->apps()->GetItemAt(i)->app_id(),
+ m2->apps()->GetItemAt(i)->app_id());
+ ASSERT_EQ(m1->apps()->GetItemAt(i)->title(),
+ m2->apps()->GetItemAt(i)->title());
+ ASSERT_EQ(m1->apps()->GetItemAt(i)->full_name(),
+ m2->apps()->GetItemAt(i)->full_name());
+ CompareImages(m1->apps()->GetItemAt(i)->icon(),
+ m2->apps()->GetItemAt(i)->icon());
+ }
+ }
+
+ void CompareImages(const gfx::ImageSkia& image1,
+ const gfx::ImageSkia& image2) {
+ std::vector<gfx::ImageSkiaRep> reps1(image1.image_reps());
+ std::vector<gfx::ImageSkiaRep> reps2(image2.image_reps());
+ ASSERT_EQ(reps1.size(), reps2.size());
+ for (size_t i = 0; i < reps1.size(); ++i) {
+ ASSERT_TRUE(
+ gfx::BitmapsAreEqual(reps1[i].sk_bitmap(), reps2[i].sk_bitmap()));
+ ASSERT_EQ(reps1[i].scale(), reps2[i].scale());
+ }
+ }
+
+ scoped_ptr<AppListModel> CopyViaPickle(AppListModel* model) {
+ scoped_ptr<Pickle> pickle(
+ FastShowPickler::PickleAppListModelForFastShow(model));
+ return FastShowPickler::UnpickleAppListModelForFastShow(pickle.get());
+ }
+
+ void DoConsistencyChecks(AppListModel* model) {
+ scoped_ptr<AppListModel> model2(CopyViaPickle(model));
+ AppListModel dest_model;
+ FastShowPickler::CopyOver(model2.get(), &dest_model);
+
+ CheckIsSame(model, model2.get());
+ CheckIsSame(model, &dest_model);
+ CheckIsSame(model2.get(), &dest_model);
+ }
+
+ gfx::ImageSkia MakeImage() {
+ const int kWidth = 10;
+ const int kHeight = 10;
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, kWidth, kHeight);
+ bitmap.allocPixels();
+ bitmap.eraseARGB(255, 1, 2, 3);
+ return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
+ }
+};
+
+TEST_F(AppListModelPicklerUnitTest, EmptyModel) {
+ AppListModel model;
+ DoConsistencyChecks(&model);
+}
+
+TEST_F(AppListModelPicklerUnitTest, OneItem) {
+ AppListModel model;
+ AppListItemModel* app1 = new AppListItemModel;
+ app1->set_app_id("abc");
+ app1->SetTitleAndFullName("ht", "hello, there");
+ model.apps()->Add(app1);
+
+ DoConsistencyChecks(&model);
+}
+
+TEST_F(AppListModelPicklerUnitTest, TwoItems) {
+ AppListModel model;
+ AppListItemModel* app1 = new AppListItemModel;
+ app1->set_app_id("abc");
+ app1->SetTitleAndFullName("ht", "hello, there");
+ model.apps()->Add(app1);
+
+ AppListItemModel* app2 = new AppListItemModel;
+ app2->set_app_id("abc2");
+ app2->SetTitleAndFullName("ht2", "hello, there 2");
+ model.apps()->Add(app2);
+
+ DoConsistencyChecks(&model);
+}
+
+TEST_F(AppListModelPicklerUnitTest, Images) {
+ AppListModel model;
+ AppListItemModel* app1 = new AppListItemModel;
+ app1->set_app_id("abc");
+ app1->SetTitleAndFullName("ht", "hello, there");
+ app1->SetIcon(MakeImage(), true);
+ model.apps()->Add(app1);
+
+ AppListItemModel* app2 = new AppListItemModel;
+ app2->set_app_id("abc2");
+ app2->SetTitleAndFullName("ht2", "hello, there 2");
+ model.apps()->Add(app2);
+
+ DoConsistencyChecks(&model);
+}
+
+TEST_F(AppListModelPicklerUnitTest, EmptyImage) {
+ AppListModel model;
+ AppListItemModel* app1 = new AppListItemModel;
+ app1->set_app_id("abc");
+ app1->SetTitleAndFullName("ht", "hello, there");
+ app1->SetIcon(gfx::ImageSkia(), true);
+ model.apps()->Add(app1);
+
+ DoConsistencyChecks(&model);
+}
+
+TEST_F(AppListModelPicklerUnitTest, SignedIn) {
+ AppListModel model;
+ model.SetSignedIn(true);
+
+ DoConsistencyChecks(&model);
+}
+
+TEST_F(AppListModelPicklerUnitTest, SignedOut) {
+ AppListModel model;
+ model.SetSignedIn(false);
+
+ DoConsistencyChecks(&model);
+}
diff --git a/chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.cc b/chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.cc
index c65a732..758d79e 100644
--- a/chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.cc
+++ b/chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.cc
@@ -108,7 +108,10 @@
return;
AppModalDialog::Invalidate();
- callback_.Reset();
+ if (!callback_.is_null()) {
+ callback_.Run(false, string16());
+ callback_.Reset();
+ }
if (native_dialog())
CloseModalDialog();
}
@@ -161,7 +164,10 @@
if (!IsValid())
return;
- callback_.Run(success, user_input);
+ if (!callback_.is_null()) {
+ callback_.Run(success, user_input);
+ callback_.Reset();
+ }
// The callback_ above may delete web_contents_, thus removing the extra
// data from the map owned by ChromeJavaScriptDialogManager. Make sure
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 0beb95f..03fea0f 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
@@ -53,19 +53,48 @@
}
void AppListControllerDelegateAsh::ActivateApp(
- Profile* profile, const extensions::Extension* extension, int event_flags) {
- ChromeLauncherController::instance()->ActivateApp(extension->id(),
- event_flags);
+ Profile* profile,
+ const extensions::Extension* extension,
+ AppListSource source,
+ int event_flags) {
+ ChromeLauncherController::instance()->ActivateApp(
+ extension->id(),
+ AppListSourceToLaunchSource(source),
+ event_flags);
+
DismissView();
}
void AppListControllerDelegateAsh::LaunchApp(
- Profile* profile, const extensions::Extension* extension, int event_flags) {
- ChromeLauncherController::instance()->LaunchApp(extension->id(),
- event_flags);
+ Profile* profile,
+ const extensions::Extension* extension,
+ AppListSource source,
+ int event_flags) {
+ ChromeLauncherController::instance()->LaunchApp(
+ extension->id(),
+ AppListSourceToLaunchSource(source),
+ event_flags);
DismissView();
}
+void AppListControllerDelegateAsh::ShowForProfileByPath(
+ const base::FilePath& profile_path) {
+ // Ash doesn't have profile switching.
+ NOTREACHED();
+}
+
bool AppListControllerDelegateAsh::ShouldShowUserIcon() {
return false;
}
+
+ash::LaunchSource AppListControllerDelegateAsh::AppListSourceToLaunchSource(
+ AppListSource source) {
+ switch (source) {
+ case LAUNCH_FROM_APP_LIST:
+ return ash::LAUNCH_FROM_APP_LIST;
+ case LAUNCH_FROM_APP_LIST_SEARCH:
+ return ash::LAUNCH_FROM_APP_LIST_SEARCH;
+ default:
+ return ash::LAUNCH_FROM_UNKNOWN;
+ }
+}
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 8df10a0..3ff048b 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
@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
+#include "chrome/browser/ui/ash/launcher/chrome_launcher_types.h"
class AppListControllerDelegateAsh : public AppListControllerDelegate {
public:
@@ -26,12 +27,18 @@
virtual void CreateNewWindow(Profile* profile, bool incognito) OVERRIDE;
virtual void ActivateApp(Profile* profile,
const extensions::Extension* extension,
+ AppListSource source,
int event_flags) OVERRIDE;
virtual void LaunchApp(Profile* profile,
const extensions::Extension* extension,
+ AppListSource source,
int event_flags) OVERRIDE;
+ virtual void ShowForProfileByPath(
+ const base::FilePath& profile_path) OVERRIDE;
virtual bool ShouldShowUserIcon() OVERRIDE;
+ ash::LaunchSource AppListSourceToLaunchSource(AppListSource source);
+
DISALLOW_COPY_AND_ASSIGN(AppListControllerDelegateAsh);
};
diff --git a/chrome/browser/ui/ash/ash_keyboard_controller_proxy.cc b/chrome/browser/ui/ash/ash_keyboard_controller_proxy.cc
index 9431a60..dfa012a 100644
--- a/chrome/browser/ui/ash/ash_keyboard_controller_proxy.cc
+++ b/chrome/browser/ui/ash/ash_keyboard_controller_proxy.cc
@@ -9,9 +9,12 @@
#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/event_names.h"
+#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/extensions/api/virtual_keyboard_private.h"
#include "chrome/common/extensions/extension_messages.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
@@ -26,6 +29,47 @@
#include "ui/base/ime/text_input_client.h"
#include "ui/keyboard/keyboard_controller.h"
+namespace virtual_keyboard_private = extensions::api::virtual_keyboard_private;
+typedef virtual_keyboard_private::OnTextInputBoxFocused::Context Context;
+
+namespace {
+
+const char* kVirtualKeyboardExtensionID = "mppnpdlheglhdfmldimlhpnegondlapf";
+
+Context::Type TextInputTypeToGeneratedInputTypeEnum(ui::TextInputType type) {
+ switch (type) {
+ case ui::TEXT_INPUT_TYPE_NONE:
+ return Context::TYPE_NONE;
+ case ui::TEXT_INPUT_TYPE_PASSWORD:
+ return Context::TYPE_PASSWORD;
+ case ui::TEXT_INPUT_TYPE_EMAIL:
+ return Context::TYPE_EMAIL;
+ case ui::TEXT_INPUT_TYPE_NUMBER:
+ return Context::TYPE_NUMBER;
+ case ui::TEXT_INPUT_TYPE_TELEPHONE:
+ return Context::TYPE_TEL;
+ case ui::TEXT_INPUT_TYPE_URL:
+ return Context::TYPE_URL;
+ case ui::TEXT_INPUT_TYPE_DATE:
+ return Context::TYPE_DATE;
+ case ui::TEXT_INPUT_TYPE_TEXT:
+ case ui::TEXT_INPUT_TYPE_SEARCH:
+ case ui::TEXT_INPUT_TYPE_DATE_TIME:
+ case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL:
+ case ui::TEXT_INPUT_TYPE_MONTH:
+ case ui::TEXT_INPUT_TYPE_TIME:
+ case ui::TEXT_INPUT_TYPE_WEEK:
+ case ui::TEXT_INPUT_TYPE_TEXT_AREA:
+ case ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE:
+ case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD:
+ return Context::TYPE_TEXT;
+ }
+ NOTREACHED();
+ return Context::TYPE_NONE;
+}
+
+} // namespace
+
AshKeyboardControllerProxy::AshKeyboardControllerProxy() {}
AshKeyboardControllerProxy::~AshKeyboardControllerProxy() {}
@@ -101,3 +145,28 @@
ash::DisplayController::GetPrimaryDisplay().work_area();
GetInputMethod()->GetTextInputClient()->EnsureCaretInRect(showing_area);
}
+
+void AshKeyboardControllerProxy::SetUpdateInputType(ui::TextInputType type) {
+ // TODO(bshe): Need to check the affected window's profile once multi-profile
+ // is supported.
+ Profile* profile = ProfileManager::GetDefaultProfile();
+ extensions::EventRouter* router =
+ extensions::ExtensionSystem::Get(profile)->event_router();
+
+ if (!router->HasEventListener(
+ virtual_keyboard_private::OnTextInputBoxFocused::kEventName)) {
+ return;
+ }
+
+ scoped_ptr<base::ListValue> event_args(new base::ListValue());
+ scoped_ptr<base::DictionaryValue> input_context(new base::DictionaryValue());
+ input_context->SetString("type",
+ Context::ToString(TextInputTypeToGeneratedInputTypeEnum(type)));
+ event_args->Append(input_context.release());
+
+ scoped_ptr<extensions::Event> event(new extensions::Event(
+ virtual_keyboard_private::OnTextInputBoxFocused::kEventName,
+ event_args.Pass()));
+ event->restrict_to_profile = profile;
+ router->DispatchEventToExtension(kVirtualKeyboardExtensionID, event.Pass());
+}
diff --git a/chrome/browser/ui/ash/ash_keyboard_controller_proxy.h b/chrome/browser/ui/ash/ash_keyboard_controller_proxy.h
index e6fabba..1cba369 100644
--- a/chrome/browser/ui/ash/ash_keyboard_controller_proxy.h
+++ b/chrome/browser/ui/ash/ash_keyboard_controller_proxy.h
@@ -46,6 +46,15 @@
virtual void SetupWebContents(content::WebContents* contents) OVERRIDE;
virtual void ShowKeyboardContainer(aura::Window* container) OVERRIDE;
+ // The overridden implementation dispatches
+ // chrome.virtualKeyboardPrivate.onTextInputBoxFocused event to extension to
+ // provide the input type information. Naturally, when the virtual keyboard
+ // extension is used as an IME then chrome.input.ime.onFocus provides the
+ // information, but not when the virtual keyboard is used in conjunction with
+ // another IME. virtualKeyboardPrivate.onTextInputBoxFocused is the remedy in
+ // that case.
+ virtual void SetUpdateInputType(ui::TextInputType type) OVERRIDE;
+
// ExtensionFunctionDispatcher::Delegate overrides
virtual extensions::WindowController* GetExtensionWindowController() const
OVERRIDE;
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 116aee8..ab32955 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -11,6 +11,7 @@
#include "ash/magnifier/magnifier_constants.h"
#include "ash/session_state_delegate.h"
#include "ash/system/tray/system_tray_delegate.h"
+#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
#include "base/prefs/pref_service.h"
@@ -158,11 +159,12 @@
aura::Window* window = ash::wm::GetActiveWindow();
if (!window)
return;
+ ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
- bool is_fullscreen = ash::wm::IsWindowFullscreen(window);
+ bool is_fullscreen = window_state->IsFullscreen();
// Windows which cannot be maximized should not be fullscreened.
- if (!is_fullscreen && !ash::wm::CanMaximizeWindow(window))
+ if (!is_fullscreen && !window_state->CanMaximize())
return;
Browser* browser = chrome::FindBrowserWithWindow(window);
@@ -184,7 +186,7 @@
}
#endif // OS_WIN
if (browser->is_app() && browser->app_type() != Browser::APP_TYPE_CHILD)
- ash::wm::ToggleMaximizedWindow(window);
+ window_state->ToggleMaximized();
else
chrome::ToggleFullscreenMode(browser);
return;
@@ -207,12 +209,13 @@
if (!window)
return;
+ ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
// Get out of fullscreen when in fullscreen mode.
- if (ash::wm::IsWindowFullscreen(window)) {
+ if (window_state->IsFullscreen()) {
ToggleFullscreen();
return;
}
- ash::wm::ToggleMaximizedWindow(window);
+ window_state->ToggleMaximized();
}
void ChromeShellDelegate::RestoreTab() {
@@ -275,7 +278,7 @@
}
void ChromeShellDelegate::OpenFeedbackPage() {
- chrome::OpenFeedbackDialog(GetTargetBrowser());
+ chrome::OpenFeedbackDialog(GetTargetBrowserIfAvailable());
}
void ChromeShellDelegate::RecordUserMetricsAction(
@@ -417,6 +420,14 @@
case ash::UMA_WINDOW_MAXIMIZE_BUTTON_SHOW_BUBBLE:
content::RecordAction(content::UserMetricsAction("MaxButton_ShowBubble"));
break;
+ case ash::UMA_WINDOW_OVERVIEW:
+ content::RecordAction(
+ content::UserMetricsAction("WindowSelector_Overview"));
+ break;
+ case ash::UMA_WINDOW_SELECTION:
+ content::RecordAction(
+ content::UserMetricsAction("WindowSelector_Selection"));
+ break;
}
}
@@ -438,7 +449,7 @@
}
Browser* ChromeShellDelegate::GetTargetBrowser() {
- Browser* browser = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow());
+ Browser* browser = GetTargetBrowserIfAvailable();
if (browser)
return browser;
return chrome::FindOrCreateTabbedBrowser(
@@ -446,6 +457,10 @@
chrome::HOST_DESKTOP_TYPE_ASH);
}
+Browser* ChromeShellDelegate::GetTargetBrowserIfAvailable() {
+ return chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow());
+}
+
keyboard::KeyboardControllerProxy*
ChromeShellDelegate::CreateKeyboardControllerProxy() {
return new AshKeyboardControllerProxy();
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index ef8ea0f..70b75e4 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -108,6 +108,11 @@
// for a browser or create one for default profile and returns it.
Browser* GetTargetBrowser();
+ // This returns the active ash window if any. Unlike the method above, it
+ // does not create a window if one isn't available, instead it returns NULL
+ // in that case.
+ Browser* GetTargetBrowserIfAvailable();
+
static ChromeShellDelegate* instance_;
content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_browsertest.cc b/chrome/browser/ui/ash/chrome_shell_delegate_browsertest.cc
index c7dee54..b06b048 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_browsertest.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_browsertest.cc
@@ -10,7 +10,7 @@
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/wm/window_properties.h"
-#include "ash/wm/window_util.h"
+#include "ash/wm/window_state.h"
#include "base/command_line.h"
#include "chrome/browser/apps/app_browsertest_util.h"
#include "chrome/browser/ui/browser.h"
@@ -43,28 +43,28 @@
IN_PROC_BROWSER_TEST_F(ChromeShellDelegateBrowserTest, ToggleMaximized) {
ash::ShellDelegate* shell_delegate = ash::Shell::GetInstance()->delegate();
ASSERT_TRUE(shell_delegate);
- aura::Window* window = ash::wm::GetActiveWindow();
- ASSERT_TRUE(window);
+ ash::wm::WindowState* window_state = ash::wm::GetActiveWindowState();
+ ASSERT_TRUE(window_state);
// When not in fullscreen, ShellDelegate::ToggleMaximized toggles Maximized.
- EXPECT_FALSE(ash::wm::IsWindowMaximized(window));
+ EXPECT_FALSE(window_state->IsMaximized());
shell_delegate->ToggleMaximized();
- EXPECT_TRUE(ash::wm::IsWindowMaximized(window));
+ EXPECT_TRUE(window_state->IsMaximized());
shell_delegate->ToggleMaximized();
- EXPECT_FALSE(ash::wm::IsWindowMaximized(window));
+ EXPECT_FALSE(window_state->IsMaximized());
// When in fullscreen ShellDelegate::ToggleMaximized gets out of fullscreen.
- EXPECT_FALSE(ash::wm::IsWindowFullscreen(window));
- Browser* browser = chrome::FindBrowserWithWindow(window);
+ EXPECT_FALSE(window_state->IsFullscreen());
+ Browser* browser = chrome::FindBrowserWithWindow(window_state->window());
ASSERT_TRUE(browser);
chrome::ToggleFullscreenMode(browser);
- EXPECT_TRUE(ash::wm::IsWindowFullscreen(window));
+ EXPECT_TRUE(window_state->IsFullscreen());
shell_delegate->ToggleMaximized();
- EXPECT_FALSE(ash::wm::IsWindowFullscreen(window));
- EXPECT_FALSE(ash::wm::IsWindowMaximized(window));
+ EXPECT_FALSE(window_state->IsFullscreen());
+ EXPECT_FALSE(window_state->IsMaximized());
shell_delegate->ToggleMaximized();
- EXPECT_FALSE(ash::wm::IsWindowFullscreen(window));
- EXPECT_TRUE(ash::wm::IsWindowMaximized(window));
+ EXPECT_FALSE(window_state->IsFullscreen());
+ EXPECT_TRUE(window_state->IsMaximized());
}
// Confirm that toggling window fullscren works properly.
diff --git a/chrome/browser/ui/ash/event_rewriter.cc b/chrome/browser/ui/ash/event_rewriter.cc
index cc3633a..f80b08d 100644
--- a/chrome/browser/ui/ash/event_rewriter.cc
+++ b/chrome/browser/ui/ash/event_rewriter.cc
@@ -237,7 +237,7 @@
}
int ndevices_return = 0;
- XIDeviceInfo* device_info = XIQueryDevice(ui::GetXDisplay(),
+ XIDeviceInfo* device_info = XIQueryDevice(gfx::GetXDisplay(),
device_id,
&ndevices_return);
@@ -282,7 +282,7 @@
if (keysym_to_keycode_map_.count(keysym))
return keysym_to_keycode_map_[keysym];
- Display* display = ui::GetXDisplay();
+ XDisplay* display = gfx::GetXDisplay();
KeyCode keycode = XKeysymToKeycode(display, keysym);
keysym_to_keycode_map_[keysym] = keycode;
return keycode;
diff --git a/chrome/browser/ui/ash/event_rewriter_unittest.cc b/chrome/browser/ui/ash/event_rewriter_unittest.cc
index dc2dd86..15ab9c2 100644
--- a/chrome/browser/ui/ash/event_rewriter_unittest.cc
+++ b/chrome/browser/ui/ash/event_rewriter_unittest.cc
@@ -25,7 +25,8 @@
#include "chrome/browser/chromeos/preferences.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/ime/mock_xkeyboard.h"
-#include "ui/base/x/x11_util.h"
+#include "ui/events/x/events_x_utils.h"
+#include "ui/gfx/x/x11_types.h"
namespace {
@@ -73,7 +74,7 @@
class EventRewriterTest : public testing::Test {
public:
EventRewriterTest()
- : display_(ui::GetXDisplay()),
+ : display_(gfx::GetXDisplay()),
keycode_a_(XKeysymToKeycode(display_, XK_a)),
keycode_alt_l_(XKeysymToKeycode(display_, XK_Alt_L)),
keycode_alt_r_(XKeysymToKeycode(display_, XK_Alt_R)),
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 edd1c1b..97f62bd 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
@@ -92,11 +92,12 @@
return false;
}
-void AppShortcutLauncherItemController::Launch(int event_flags) {
- launcher_controller()->LaunchApp(app_id(), event_flags);
+void AppShortcutLauncherItemController::Launch(ash::LaunchSource source,
+ int event_flags) {
+ launcher_controller()->LaunchApp(app_id(), source, event_flags);
}
-void AppShortcutLauncherItemController::Activate() {
+void AppShortcutLauncherItemController::Activate(ash::LaunchSource source) {
content::WebContents* content = GetLRUApplication();
if (!content) {
if (IsV2App()) {
@@ -109,7 +110,7 @@
if (!AllowNextLaunchAttempt())
return;
}
- Launch(ui::EF_NONE);
+ Launch(source, ui::EF_NONE);
return;
}
ActivateContent(content);
@@ -137,7 +138,7 @@
if (AdvanceToNextApp())
return;
}
- Activate();
+ Activate(ash::LAUNCH_FROM_UNKNOWN);
}
void AppShortcutLauncherItemController::OnRemoved() {
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 8d9ca94..2ba1c24 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
@@ -38,8 +38,8 @@
virtual bool IsCurrentlyShownInWindow(aura::Window* window) const OVERRIDE;
virtual bool IsOpen() const OVERRIDE;
virtual bool IsVisible() const OVERRIDE;
- virtual void Launch(int event_flags) OVERRIDE;
- virtual void Activate() OVERRIDE;
+ virtual void Launch(ash::LaunchSource source, int event_flags) OVERRIDE;
+ virtual void Activate(ash::LaunchSource source) OVERRIDE;
virtual void Close() OVERRIDE;
virtual void Clicked(const ui::Event& event) OVERRIDE;
virtual void OnRemoved() OVERRIDE;
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
index ae6d444..eeb59a8 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -8,7 +8,7 @@
#include "ash/launcher/launcher.h"
#include "ash/launcher/launcher_model.h"
-#include "ash/launcher/launcher_util.h"
+#include "ash/shelf/shelf_util.h"
#include "ash/shell.h"
#include "ash/wm/window_util.h"
#include "chrome/browser/profiles/profile.h"
@@ -60,7 +60,7 @@
ash::LauncherModel* model = launcher_controller()->model();
// Determine the new browser's active state and change if necessary.
- size_t browser_index = ash::launcher::GetBrowserItemIndex(*model);
+ size_t browser_index = ash::GetBrowserItemIndex(*model);
DCHECK_GE(browser_index, 0u);
ash::LauncherItem browser_item = model->items()[browser_index];
ash::LauncherItemStatus browser_status = ash::STATUS_CLOSED;
@@ -137,10 +137,11 @@
return ash::wm::IsActiveWindow(window);
}
-void BrowserShortcutLauncherItemController::Launch(int event_flags) {
+void BrowserShortcutLauncherItemController::Launch(ash::LaunchSource source,
+ int event_flags) {
}
-void BrowserShortcutLauncherItemController::Activate() {
+void BrowserShortcutLauncherItemController::Activate(ash::LaunchSource source) {
Browser* last_browser = chrome::FindTabbedBrowser(
profile_,
true,
@@ -176,7 +177,7 @@
return;
}
- Activate();
+ Activate(ash::LAUNCH_FROM_UNKNOWN);
}
void BrowserShortcutLauncherItemController::OnRemoved() {
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
index 0565dd6..a4bad3a 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
@@ -35,8 +35,8 @@
virtual bool IsCurrentlyShownInWindow(aura::Window* window) const OVERRIDE;
virtual bool IsOpen() const OVERRIDE;
virtual bool IsVisible() const OVERRIDE;
- virtual void Launch(int event_flags) OVERRIDE;
- virtual void Activate() OVERRIDE;
+ virtual void Launch(ash::LaunchSource source, int event_flags) OVERRIDE;
+ virtual void Activate(ash::LaunchSource source) OVERRIDE;
virtual void Close() OVERRIDE;
virtual void Clicked(const ui::Event& event) OVERRIDE;
virtual void OnRemoved() OVERRIDE;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index 56aeb37..36a8977 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -11,9 +11,9 @@
#include "ash/launcher/launcher.h"
#include "ash/launcher/launcher_item_delegate_manager.h"
#include "ash/launcher/launcher_model.h"
-#include "ash/launcher/launcher_util.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_util.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/wm/window_util.h"
@@ -41,6 +41,7 @@
#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h"
#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.h"
#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_tab.h"
+#include "chrome/browser/ui/ash/launcher/chrome_launcher_types.h"
#include "chrome/browser/ui/ash/launcher/launcher_app_tab_helper.h"
#include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
#include "chrome/browser/ui/ash/launcher/launcher_context_menu.h"
@@ -60,6 +61,7 @@
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
@@ -74,6 +76,7 @@
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "grit/ui_resources.h"
+#include "net/base/url_util.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
@@ -95,6 +98,11 @@
namespace {
+// This will be used as placeholder in the list of the pinned applciatons.
+// Note that this is NOT a valid extension identifier so that pre M31 versions
+// will ignore it.
+const char kAppLauncherIdPlaceholder[] = "AppLauncherIDPlaceholder--------";
+
std::string GetPrefKeyForRootWindow(aura::RootWindow* root_window) {
gfx::Display display = gfx::Screen::GetScreenFor(
root_window)->GetDisplayNearestWindow(root_window);
@@ -194,6 +202,16 @@
}
}
+std::string GetSourceFromAppListSource(ash::LaunchSource source) {
+ switch (source) {
+ case ash::LAUNCH_FROM_APP_LIST:
+ return std::string(extension_urls::kLaunchSourceAppList);
+ case ash::LAUNCH_FROM_APP_LIST_SEARCH:
+ return std::string(extension_urls::kLaunchSourceAppListSearch);
+ default: return std::string();
+ }
+}
+
} // namespace
#if defined(OS_CHROMEOS)
@@ -333,8 +351,8 @@
}
void ChromeLauncherController::Init() {
- UpdateAppLaunchersFromPref();
CreateBrowserShortcutLauncherItem();
+ UpdateAppLaunchersFromPref();
// TODO(sky): update unit test so that this test isn't necessary.
if (ash::Shell::HasInstance()) {
@@ -359,12 +377,8 @@
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) {
+ 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,
@@ -436,24 +450,11 @@
DCHECK(HasItemController(id));
LauncherItemController* controller = id_to_item_controller_map_[id];
- if (controller->type() == LauncherItemController::TYPE_APP) {
- int index = model_->ItemIndexByID(id);
- DCHECK_GE(index, 0);
- ash::LauncherItem item = model_->items()[index];
- item.type = ash::TYPE_PLATFORM_APP;
- model_->Set(index, item);
+ if (controller->type() == LauncherItemController::TYPE_APP ||
+ controller->locked()) {
+ UnpinRunningAppInternal(model_->ItemIndexByID(id));
} else {
- // Prevent the removal of items upon unpin if it is locked by a running
- // windowed V1 app.
- if (!controller->locked()) {
- LauncherItemClosed(id);
- } else {
- int index = model_->ItemIndexByID(id);
- DCHECK_GE(index, 0);
- ash::LauncherItem item = model_->items()[index];
- item.type = ash::TYPE_WINDOWED_APP;
- model_->Set(index, item);
- }
+ LauncherItemClosed(id);
}
if (CanPin())
PersistPinnedState();
@@ -514,10 +515,10 @@
}
void ChromeLauncherController::Launch(ash::LauncherID id,
- int event_flags) {
+ int event_flags) {
if (!HasItemController(id))
return; // In case invoked from menu and item closed while menu up.
- id_to_item_controller_map_[id]->Launch(event_flags);
+ id_to_item_controller_map_[id]->Launch(ash::LAUNCH_FROM_UNKNOWN, event_flags);
}
void ChromeLauncherController::Close(ash::LauncherID id) {
@@ -544,7 +545,8 @@
}
void ChromeLauncherController::LaunchApp(const std::string& app_id,
- int event_flags) {
+ ash::LaunchSource source,
+ int event_flags) {
// |extension| could be NULL when it is being unloaded for updating.
const Extension* extension = GetExtensionForAppID(app_id);
if (!extension)
@@ -563,18 +565,31 @@
return;
}
- chrome::OpenApplication(chrome::AppLaunchParams(GetProfileForNewWindows(),
- extension,
- event_flags));
+ chrome::AppLaunchParams params(GetProfileForNewWindows(),
+ extension,
+ event_flags);
+ if (source != ash::LAUNCH_FROM_UNKNOWN &&
+ app_id == extension_misc::kWebStoreAppId) {
+ // Get the corresponding source string.
+ std::string source_value = GetSourceFromAppListSource(source);
+
+ // Set an override URL to include the source.
+ GURL extension_url = extensions::AppLaunchInfo::GetFullLaunchURL(extension);
+ params.override_url = net::AppendQueryParameter(
+ extension_url, extension_urls::kWebstoreSourceField, source_value);
+ }
+
+ chrome::OpenApplication(params);
}
void ChromeLauncherController::ActivateApp(const std::string& app_id,
- int event_flags) {
+ ash::LaunchSource source,
+ int event_flags) {
// If there is an existing non-shortcut controller for this app, open it.
ash::LauncherID id = GetLauncherIDForAppID(app_id);
if (id) {
LauncherItemController* controller = id_to_item_controller_map_[id];
- controller->Activate();
+ controller->Activate(source);
return;
}
@@ -583,9 +598,9 @@
scoped_ptr<AppShortcutLauncherItemController> app_controller(
new AppShortcutLauncherItemController(app_id, this));
if (!app_controller->GetRunningApplications().empty())
- app_controller->Activate();
+ app_controller->Activate(source);
else
- LaunchApp(app_id, event_flags);
+ LaunchApp(app_id, source, event_flags);
}
extensions::ExtensionPrefs::LaunchType
@@ -739,7 +754,6 @@
NOTREACHED() << "Can't pin but pinned state being updated";
return;
}
-
// Mutating kPinnedLauncherApps is going to notify us and trigger us to
// process the change. We don't want that to happen so remove ourselves as a
// listener.
@@ -758,6 +772,11 @@
}
} else if (model_->items()[i].type == ash::TYPE_BROWSER_SHORTCUT) {
PersistChromeItemIndex(i);
+ } else if (model_->items()[i].type == ash::TYPE_APP_LIST) {
+ base::DictionaryValue* app_value = ash::CreateAppDict(
+ kAppLauncherIdPlaceholder);
+ if (app_value)
+ updater->Append(app_value);
}
}
}
@@ -957,7 +976,7 @@
}
ash::LauncherID ChromeLauncherController::GetIDByWindow(aura::Window* window) {
- int browser_index = ash::launcher::GetBrowserItemIndex(*model_);
+ int browser_index = ash::GetBrowserItemIndex(*model_);
DCHECK_GE(browser_index, 0);
ash::LauncherID browser_id = model_->items()[browser_index].id;
@@ -1002,6 +1021,12 @@
}
void ChromeLauncherController::LauncherItemAdded(int index) {
+ // The app list launcher can get added to the shelf after we applied the
+ // preferences. In that case the item might be at the wrong spot. As such we
+ // call the function again.
+ if (model_->items()[index].type == ash::TYPE_APP_LIST &&
+ ash::switches::UseAlternateShelfLayout())
+ UpdateAppLaunchersFromPref();
}
void ChromeLauncherController::LauncherItemRemoved(int index,
@@ -1010,8 +1035,12 @@
void ChromeLauncherController::LauncherItemMoved(int start_index,
int target_index) {
- ash::LauncherID id = model_->items()[target_index].id;
- if (HasItemController(id) && IsPinned(id))
+ const ash::LauncherItem& item = model_->items()[target_index];
+ // We remember the moved item position if it is either pinnable or
+ // it is the app list with the alternate shelf layout.
+ if ((HasItemController(item.id) && IsPinned(item.id)) ||
+ (ash::switches::UseAlternateShelfLayout() &&
+ item.type == ash::TYPE_APP_LIST))
PersistPinnedState();
}
@@ -1132,7 +1161,9 @@
}
void ChromeLauncherController::ExtensionEnableFlowFinished() {
- LaunchApp(extension_enable_flow_->extension_id(), ui::EF_NONE);
+ LaunchApp(extension_enable_flow_->extension_id(),
+ ash::LAUNCH_FROM_UNKNOWN,
+ ui::EF_NONE);
extension_enable_flow_.reset();
}
@@ -1309,77 +1340,112 @@
Unpin(launcher_id);
}
+int ChromeLauncherController::PinRunningAppInternal(
+ int index,
+ ash::LauncherID launcher_id) {
+ int running_index = model_->ItemIndexByID(launcher_id);
+ ash::LauncherItem item = model_->items()[running_index];
+ DCHECK(item.type == ash::TYPE_WINDOWED_APP ||
+ item.type == ash::TYPE_PLATFORM_APP);
+ item.type = ash::TYPE_APP_SHORTCUT;
+ model_->Set(running_index, item);
+ // The |LauncherModel|'s weight system might reposition the item to a
+ // new index, so we get the index again.
+ running_index = model_->ItemIndexByID(launcher_id);
+ if (running_index < index)
+ --index;
+ if (running_index != index)
+ model_->Move(running_index, index);
+ return index;
+}
+
+void ChromeLauncherController::UnpinRunningAppInternal(int index) {
+ DCHECK_GE(index, 0);
+ ash::LauncherItem item = model_->items()[index];
+ DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT);
+ item.type = ash::TYPE_WINDOWED_APP;
+ // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such
+ // we have to check here what this was before it got a shortcut.
+ if (HasItemController(item.id) &&
+ id_to_item_controller_map_[item.id]->type() ==
+ LauncherItemController::TYPE_APP)
+ item.type = ash::TYPE_PLATFORM_APP;
+ model_->Set(index, item);
+}
+
void ChromeLauncherController::UpdateAppLaunchersFromPref() {
- // Construct a vector representation of to-be-pinned apps from the pref.
- std::vector<std::string> pinned_apps;
- int chrome_icon_index = GetChromeIconIndexFromPref();
+ // There are various functions which will trigger a |PersistPinnedState| call
+ // like a direct call to |DoPinAppWithID|, or an indirect call to the menu
+ // model which will use weights to re-arrange the icons to new positions.
+ // Since this function is meant to synchronize the "is state" with the
+ // "sync state", it makes no sense to store any changes by this function back
+ // into the pref state. Therefore we tell |persistPinnedState| to ignore any
+ // invocations while we are running.
+ base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true);
+ std::vector<std::string> pinned_apps = GetListOfPinnedAppsAndBrowser();
+
int index = 0;
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;
- // The alternate shelf layout's icon position will always include the
- // AppLauncher which needs to be subtracted here.
- if (chrome_icon_index > 0)
- --chrome_icon_index;
- }
- const base::ListValue* pinned_apps_pref =
- profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps);
- for (base::ListValue::const_iterator it(pinned_apps_pref->begin());
- it != pinned_apps_pref->end(); ++it) {
- // To preserve the Chrome icon position, we insert a dummy slot for it - if
- // the model has a Chrome item. While initializing we can come here with no
- // item in which case the count would be 1 or below.
- if (it - pinned_apps_pref->begin() == chrome_icon_index &&
- model_->item_count() > 1) {
- pinned_apps.push_back(extension_misc::kChromeAppId);
- }
- DictionaryValue* app = NULL;
- std::string app_id;
- if ((*it)->GetAsDictionary(&app) &&
- app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id) &&
- std::find(pinned_apps.begin(), pinned_apps.end(), app_id) ==
- pinned_apps.end() &&
- app_tab_helper_->IsValidID(app_id)) {
- pinned_apps.push_back(app_id);
- }
- }
+ // When one of the two special items cannot be moved (and we do not know where
+ // yet), we remember the current location in one of these variables.
+ int chrome_index = -1;
+ int app_list_index = -1;
// Walk the model and |pinned_apps| from the pref lockstep, adding and
// removing items as necessary. NB: This code uses plain old indexing instead
// of iterators because of model mutations as part of the loop.
std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin());
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.
+ // Check if we have an item which we need to handle.
if (*pref_app_id == extension_misc::kChromeAppId ||
+ *pref_app_id == kAppLauncherIdPlaceholder ||
IsAppPinned(*pref_app_id)) {
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)
+ bool is_app_list = item.type == ash::TYPE_APP_LIST;
+ bool is_chrome = item.type == ash::TYPE_BROWSER_SHORTCUT;
+ if (item.type != ash::TYPE_APP_SHORTCUT && !is_app_list && !is_chrome)
continue;
-
IDToItemControllerMap::const_iterator entry =
id_to_item_controller_map_.find(item.id);
- if ((extension_misc::kChromeAppId == *pref_app_id &&
- item.type == ash::TYPE_BROWSER_SHORTCUT) ||
+ if ((kAppLauncherIdPlaceholder == *pref_app_id && is_app_list) ||
+ (extension_misc::kChromeAppId == *pref_app_id && is_chrome) ||
(entry != id_to_item_controller_map_.end() &&
entry->second->app_id() == *pref_app_id)) {
+ // Check if an item needs to be moved here.
+ MoveChromeOrApplistToFinalPosition(
+ is_chrome, is_app_list, index, &chrome_index, &app_list_index);
++pref_app_id;
break;
} else {
- if (item.type == ash::TYPE_BROWSER_SHORTCUT) {
- // We cannot delete the browser shortcut. As such we move it up by
- // one. To avoid any side effects from our pinned state observer, we
- // do not call the model directly.
- MoveItemWithoutPinnedStateChangeNotification(index, index + 1);
+ if (is_chrome || is_app_list) {
+ // We cannot delete any of these shortcuts. As such we remember
+ // their positions and move them later where they belong.
+ if (is_chrome)
+ chrome_index = index;
+ else
+ app_list_index = index;
+ // And skip the item - or exit the loop if end is reached (note that
+ // in that case we will reduce the index again by one and this only
+ // compensates for it).
+ if (index >= max_index - 1)
+ break;
+ ++index;
} else {
- LauncherItemClosed(item.id);
- --max_index;
+ // Check if this is a platform or a windowed app.
+ if (item.type == ash::TYPE_APP_SHORTCUT &&
+ (id_to_item_controller_map_[item.id]->locked() ||
+ id_to_item_controller_map_[item.id]->type() ==
+ LauncherItemController::TYPE_APP)) {
+ // Note: This will not change the amount of items (|max_index|).
+ // Even changes to the actual |index| due to item weighting
+ // changes should be fine.
+ UnpinRunningAppInternal(index);
+ } else {
+ LauncherItemClosed(item.id);
+ --max_index;
+ }
}
--index;
}
@@ -1388,9 +1454,17 @@
// is out of sync.
DCHECK(index <= max_index);
} else {
- // This app wasn't pinned before, insert a new entry.
- ash::LauncherID id = CreateAppShortcutLauncherItem(*pref_app_id, index);
- index = model_->ItemIndexByID(id);
+ // Check if the item was already running but not yet pinned.
+ ash::LauncherID launcher_id = GetLauncherIDForAppID(*pref_app_id);
+ if (launcher_id) {
+ // This app is running but not yet pinned. So pin and move it.
+ index = PinRunningAppInternal(index, launcher_id);
+ } else {
+ // This app wasn't pinned before, insert a new entry.
+ launcher_id = CreateAppShortcutLauncherItem(*pref_app_id, index);
+ ++max_index;
+ index = model_->ItemIndexByID(launcher_id);
+ }
++pref_app_id;
}
}
@@ -1398,19 +1472,49 @@
// Remove any trailing existing items.
while (index < model_->item_count()) {
const ash::LauncherItem& item(model_->items()[index]);
- if (item.type == ash::TYPE_APP_SHORTCUT)
- LauncherItemClosed(item.id);
- else
+ if (item.type == ash::TYPE_APP_SHORTCUT) {
+ if (id_to_item_controller_map_[item.id]->locked() ||
+ id_to_item_controller_map_[item.id]->type() ==
+ LauncherItemController::TYPE_APP)
+ UnpinRunningAppInternal(index);
+ else
+ LauncherItemClosed(item.id);
+ } else {
+ if (item.type == ash::TYPE_BROWSER_SHORTCUT)
+ chrome_index = index;
+ else if (item.type == ash::TYPE_APP_LIST)
+ app_list_index = index;
++index;
+ }
}
// Append unprocessed items from the pref to the end of the model.
for (; pref_app_id != pinned_apps.end(); ++pref_app_id) {
- // Ignore the chrome icon.
- if (*pref_app_id != extension_misc::kChromeAppId)
+ // All items but the chrome and / or app list shortcut needs to be added.
+ bool is_chrome = *pref_app_id == extension_misc::kChromeAppId;
+ bool is_app_list = *pref_app_id == kAppLauncherIdPlaceholder;
+ // Coming here we know the next item which can be finalized, either the
+ // chrome item or the app launcher. The final position is the end of the
+ // list. The menu model will make sure that the item is grouped according
+ // to its weight (which we do not know here).
+ if (!is_chrome && !is_app_list) {
DoPinAppWithID(*pref_app_id);
- }
+ int target_index = FindInsertionPoint(false);
+ ash::LauncherID id = GetLauncherIDForAppID(*pref_app_id);
+ int source_index = model_->ItemIndexByID(id);
+ if (source_index != target_index)
+ model_->Move(source_index, target_index);
+ // Needed for the old layout - the weight might force it to be lower in
+ // rank.
+ if (app_list_index != -1 && target_index <= app_list_index)
+ ++app_list_index;
+ } else {
+ int target_index = FindInsertionPoint(is_app_list);
+ MoveChromeOrApplistToFinalPosition(
+ is_chrome, is_app_list, target_index, &chrome_index, &app_list_index);
+ }
+ }
}
void ChromeLauncherController::SetShelfAutoHideBehaviorPrefs(
@@ -1562,7 +1666,7 @@
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32);
ash::LauncherID id = model_->next_id();
- size_t index = GetChromeIconIndexFromPref();
+ size_t index = GetChromeIconIndexForCreation();
model_->AddAt(index, browser_shortcut);
browser_item_controller_.reset(
new BrowserShortcutLauncherItemController(this, profile_));
@@ -1579,15 +1683,135 @@
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() + 1, index));
return std::max(static_cast<size_t>(0),
std::min(pinned_apps_pref->GetSize(), index));
}
+void ChromeLauncherController::MoveChromeOrApplistToFinalPosition(
+ bool is_chrome,
+ bool is_app_list,
+ int target_index,
+ int* chrome_index,
+ int* app_list_index) {
+ if (is_chrome && *chrome_index != -1) {
+ model_->Move(*chrome_index, target_index);
+ if (*app_list_index != -1 &&
+ *chrome_index < *app_list_index &&
+ target_index > *app_list_index)
+ --(*app_list_index);
+ *chrome_index = -1;
+ } else if (is_app_list && *app_list_index != -1) {
+ model_->Move(*app_list_index, target_index);
+ if (*chrome_index != -1 &&
+ *app_list_index < *chrome_index &&
+ target_index > *chrome_index)
+ --(*chrome_index);
+ *app_list_index = -1;
+ }
+}
+
+int ChromeLauncherController::FindInsertionPoint(bool is_app_list) {
+ bool alternate = ash::switches::UseAlternateShelfLayout();
+ for (int i = model_->item_count() - 1; i > 0; --i) {
+ ash::LauncherItemType type = model_->items()[i].type;
+ if (type == ash::TYPE_APP_SHORTCUT ||
+ ((is_app_list || alternate) && type == ash::TYPE_APP_LIST) ||
+ type == ash::TYPE_BROWSER_SHORTCUT ||
+ type == ash::TYPE_WINDOWED_APP)
+ return i;
+ }
+ return 0;
+}
+
+int ChromeLauncherController::GetChromeIconIndexForCreation() {
+ // We get the list of pinned apps as they currently would get pinned.
+ // Within this list the chrome icon will be the correct location.
+ std::vector<std::string> pinned_apps = GetListOfPinnedAppsAndBrowser();
+
+ std::vector<std::string>::iterator it =
+ std::find(pinned_apps.begin(),
+ pinned_apps.end(),
+ std::string(extension_misc::kChromeAppId));
+ DCHECK(it != pinned_apps.end());
+ int index = it - pinned_apps.begin();
+
+ // We should do here a comparison between the is state and the "want to be"
+ // state since some apps might be able to pin but are not yet. Instead - for
+ // the time being we clamp against the amount of known items and wait for the
+ // next |UpdateAppLaunchersFromPref()| call to correct it - it will come since
+ // the pinning will be done then.
+ return std::min(model_->item_count(), index);
+}
+
+std::vector<std::string>
+ChromeLauncherController::GetListOfPinnedAppsAndBrowser() {
+ // Adding the app list item to the list of items requires that the ID is not
+ // a valid and known ID for the extension system. The ID was constructed that
+ // way - but just to make sure...
+ DCHECK(!app_tab_helper_->IsValidID(kAppLauncherIdPlaceholder));
+
+ std::vector<std::string> pinned_apps;
+
+ // Get the new incarnation of the list.
+ const base::ListValue* pinned_apps_pref =
+ profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps);
+
+ // Keep track of the addition of the chrome and the app list icon.
+ bool chrome_icon_added = false;
+ bool app_list_icon_added = false;
+ size_t chrome_icon_index = GetChromeIconIndexFromPref();
+
+ // See if the chrome string is already in the pinned list and remove it if
+ // needed.
+ base::Value* chrome_app = ash::CreateAppDict(extension_misc::kChromeAppId);
+ if (chrome_app) {
+ chrome_icon_added = pinned_apps_pref->Find(*chrome_app) !=
+ pinned_apps_pref->end();
+ delete chrome_app;
+ }
+
+ for (size_t index = 0; index < pinned_apps_pref->GetSize(); ++index) {
+ // We need to position the chrome icon relative to it's place in the pinned
+ // preference list - even if an item of that list isn't shown yet.
+ if (index == chrome_icon_index && !chrome_icon_added) {
+ pinned_apps.push_back(extension_misc::kChromeAppId);
+ chrome_icon_added = true;
+ }
+ const DictionaryValue* app = NULL;
+ std::string app_id;
+ if (pinned_apps_pref->GetDictionary(index, &app) &&
+ app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id) &&
+ (std::find(pinned_apps.begin(), pinned_apps.end(), app_id) ==
+ pinned_apps.end())) {
+ if (app_id == extension_misc::kChromeAppId) {
+ chrome_icon_added = true;
+ pinned_apps.push_back(extension_misc::kChromeAppId);
+ } else if (app_id == kAppLauncherIdPlaceholder) {
+ app_list_icon_added = true;
+ pinned_apps.push_back(kAppLauncherIdPlaceholder);
+ } else if (app_tab_helper_->IsValidID(app_id)) {
+ pinned_apps.push_back(app_id);
+ }
+ }
+ }
+
+ // If not added yet, the chrome item will be the last item in the list.
+ if (!chrome_icon_added)
+ pinned_apps.push_back(extension_misc::kChromeAppId);
+
+ // If not added yet, add the app list item either at the end or at the
+ // beginning - depending on the shelf layout.
+ if (!app_list_icon_added) {
+ if (ash::switches::UseAlternateShelfLayout())
+ pinned_apps.insert(pinned_apps.begin(), kAppLauncherIdPlaceholder);
+ else
+ pinned_apps.push_back(kAppLauncherIdPlaceholder);
+ }
+ return pinned_apps;
+}
+
bool ChromeLauncherController::IsIncognito(
- content::WebContents* web_contents) const {
+ const content::WebContents* web_contents) const {
const Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
return profile->IsOffTheRecord() && !profile->IsGuestSession();
@@ -1619,13 +1843,6 @@
}
}
-void
-ChromeLauncherController::MoveItemWithoutPinnedStateChangeNotification(
- int source_index, int target_index) {
- base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true);
- model_->Move(source_index, target_index);
-}
-
void ChromeLauncherController::RegisterLauncherItemDelegate() {
// TODO(simon.hong81): Register LauncherItemDelegate when LauncherItemDelegate
// is created.
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
index f8a6711..52d7f51 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -29,6 +29,7 @@
#include "chrome/browser/prefs/pref_service_syncable_observer.h"
#include "chrome/browser/ui/ash/app_sync_ui_state_observer.h"
#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h"
+#include "chrome/browser/ui/ash/launcher/chrome_launcher_types.h"
#include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
#include "content/public/browser/notification_observer.h"
#include "ui/aura/window_observer.h"
@@ -86,18 +87,17 @@
// * Shortcuts have no LauncherItemController.
// TODO(simon.hong81): Move LauncherItemDelegate out from
// ChromeLauncherController and makes separate subclass with it.
-class ChromeLauncherController
- : public ash::LauncherDelegate,
- public ash::LauncherItemDelegate,
- public ash::LauncherModelObserver,
- public ash::ShellObserver,
- public ash::DisplayController::Observer,
- public content::NotificationObserver,
- public extensions::AppIconLoader::Delegate,
- public PrefServiceSyncableObserver,
- public AppSyncUIStateObserver,
- public ExtensionEnableFlowDelegate,
- public ash::ShelfLayoutManagerObserver {
+class ChromeLauncherController : public ash::LauncherDelegate,
+ public ash::LauncherItemDelegate,
+ public ash::LauncherModelObserver,
+ public ash::ShellObserver,
+ public ash::DisplayController::Observer,
+ public content::NotificationObserver,
+ public extensions::AppIconLoader::Delegate,
+ public PrefServiceSyncableObserver,
+ public AppSyncUIStateObserver,
+ public ExtensionEnableFlowDelegate,
+ public ash::ShelfLayoutManagerObserver {
public:
// Indicates if a launcher item is incognito or not.
enum IncognitoState {
@@ -198,12 +198,16 @@
// Opens a new instance of the application identified by |app_id|.
// Used by the app-list, and by pinned-app launcher items.
- void LaunchApp(const std::string& app_id, int event_flags);
+ void LaunchApp(const std::string& app_id,
+ ash::LaunchSource source,
+ int event_flags);
// If |app_id| is running, reactivates the app's most recently active window,
// otherwise launches and activates the app.
// Used by the app-list, and by pinned-app launcher items.
- void ActivateApp(const std::string& app_id, int event_flags);
+ void ActivateApp(const std::string& app_id,
+ ash::LaunchSource source,
+ int event_flags);
// Returns the launch type of app for the specified id.
extensions::ExtensionPrefs::LaunchType GetLaunchType(ash::LauncherID id);
@@ -420,6 +424,15 @@
void DoPinAppWithID(const std::string& app_id);
void DoUnpinAppWithID(const std::string& app_id);
+ // Pin a running app with |launcher_id| internally to |index|. It returns
+ // the index where the item was pinned.
+ int PinRunningAppInternal(int index, ash::LauncherID launcher_id);
+
+ // Unpin a locked application. This is an internal call which converts the
+ // model type of the given app index from a shortcut into an unpinned running
+ // app.
+ void UnpinRunningAppInternal(int index);
+
// Re-syncs launcher model with prefs::kPinnedLauncherApps.
void UpdateAppLaunchersFromPref();
@@ -459,7 +472,7 @@
ash::LauncherID CreateBrowserShortcutLauncherItem();
// Check if the given |web_contents| is in incognito mode.
- bool IsIncognito(content::WebContents* web_contents) const;
+ bool IsIncognito(const content::WebContents* web_contents) const;
// Update browser shortcut's index.
void PersistChromeItemIndex(int index);
@@ -467,15 +480,32 @@
// Get browser shortcut's index from pref.
int GetChromeIconIndexFromPref() const;
+ // Depending on the provided flags, move either the chrome icon, the app icon
+ // or none to the given |target_index|. The provided |chrome_index| and
+ // |app_list_index| locations will get adjusted within this call to finalize
+ // the action and to make sure that the other item can still be moved
+ // afterwards (index adjustments).
+ void MoveChromeOrApplistToFinalPosition(
+ bool is_chrome,
+ bool is_app_list,
+ int target_index,
+ int* chrome_index,
+ int* app_list_index);
+
+ // Finds the index of where to insert the next item.
+ int FindInsertionPoint(bool is_app_list);
+
+ // Get the browser shortcut's index in the shelf using the current's systems
+ // configuration of pinned and known (but not running) apps.
+ int GetChromeIconIndexForCreation();
+
+ // Get the list of pinned programs from the preferences.
+ std::vector<std::string> GetListOfPinnedAppsAndBrowser();
+
// Close all windowed V1 applications of a certain extension which was already
// deleted.
void CloseWindowedAppsFromRemovedExtension(const std::string& app_id);
- // Move a launcher item ignoring the pinned state changes from |index| to
- // |target_index|.
- void MoveItemWithoutPinnedStateChangeNotification(int source_index,
- int target_index);
-
// Register LauncherItemDelegate.
void RegisterLauncherItemDelegate();
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 41b3058..ee1a3dc 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -12,12 +12,13 @@
#include "ash/launcher/launcher.h"
#include "ash/launcher/launcher_button.h"
#include "ash/launcher/launcher_model.h"
-#include "ash/launcher/launcher_util.h"
#include "ash/launcher/launcher_view.h"
+#include "ash/shelf/shelf_util.h"
#include "ash/shell.h"
#include "ash/test/launcher_test_api.h"
#include "ash/test/launcher_view_test_api.h"
#include "ash/test/shell_test_api.h"
+#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -881,14 +882,17 @@
LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB,
NEW_BACKGROUND_TAB);
EXPECT_EQ(++tab_count, tab_strip->count());
- ChromeLauncherController::instance()->LaunchApp(last_loaded_extension_id_, 0);
+ ChromeLauncherController::instance()->LaunchApp(last_loaded_extension_id_,
+ ash::LAUNCH_FROM_UNKNOWN,
+ 0);
}
// Confirm that clicking a icon for an app running in one of 2 maxmized windows
// activates the right window.
IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchMaximized) {
aura::Window* window1 = browser()->window()->GetNativeWindow();
- ash::wm::MaximizeWindow(window1);
+ ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1);
+ window1_state->Maximize();
content::WindowedNotificationObserver open_observer(
chrome::NOTIFICATION_BROWSER_WINDOW_READY,
content::NotificationService::AllSources());
@@ -898,7 +902,7 @@
aura::Window* window2 = browser2->window()->GetNativeWindow();
TabStripModel* tab_strip = browser2->tab_strip_model();
int tab_count = tab_strip->count();
- ash::wm::MaximizeWindow(window2);
+ ash::wm::GetWindowState(window2)->Maximize();
ash::LauncherID shortcut_id = CreateShortcut("app1");
ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
@@ -906,7 +910,7 @@
EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
window1->Show();
- ash::wm::ActivateWindow(window1);
+ window1_state->Activate();
EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status);
ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
@@ -920,9 +924,13 @@
const Extension* extension =
LoadExtension(test_data_dir_.AppendASCII("app1"));
- ChromeLauncherController::instance()->ActivateApp(extension->id(), 0);
+ ChromeLauncherController::instance()->ActivateApp(extension->id(),
+ ash::LAUNCH_FROM_UNKNOWN,
+ 0);
EXPECT_EQ(++tab_count, tab_strip->count());
- ChromeLauncherController::instance()->ActivateApp(extension->id(), 0);
+ ChromeLauncherController::instance()->ActivateApp(extension->id(),
+ ash::LAUNCH_FROM_UNKNOWN,
+ 0);
EXPECT_EQ(tab_count, tab_strip->count());
}
@@ -933,9 +941,13 @@
const Extension* extension =
LoadExtension(test_data_dir_.AppendASCII("app1"));
- ChromeLauncherController::instance()->LaunchApp(extension->id(), 0);
+ ChromeLauncherController::instance()->LaunchApp(extension->id(),
+ ash::LAUNCH_FROM_UNKNOWN,
+ 0);
EXPECT_EQ(++tab_count, tab_strip->count());
- ChromeLauncherController::instance()->LaunchApp(extension->id(), 0);
+ ChromeLauncherController::instance()->LaunchApp(extension->id(),
+ ash::LAUNCH_FROM_UNKNOWN,
+ 0);
EXPECT_EQ(++tab_count, tab_strip->count());
}
@@ -1119,7 +1131,7 @@
IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivationStateCheck) {
TabStripModel* tab_strip = browser()->tab_strip_model();
// Get the browser item index
- int browser_index = ash::launcher::GetBrowserItemIndex(*controller_->model());
+ int browser_index = ash::GetBrowserItemIndex(*controller_->model());
EXPECT_TRUE(browser_index >= 0);
// Even though we are just comming up, the browser should be active.
@@ -1589,7 +1601,21 @@
base::MessageLoop::current()->RunUntilIdle();
EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
EXPECT_EQ(3, model_->item_count()); // And it remains that way.
-}
+
+ // Test #4: Check that by pressing ESC the operation gets cancelled.
+ generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
+ bounds_grid_1.CenterPoint().y());
+ generator.PressLeftButton();
+ generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
+ bounds_launcher_1.CenterPoint().y());
+ base::MessageLoop::current()->RunUntilIdle();
+ // Issue an ESC and see that the operation gets cancelled.
+ generator.PressKey(ui::VKEY_ESCAPE, 0);
+ generator.ReleaseKey(ui::VKEY_ESCAPE, 0);
+ EXPECT_FALSE(grid_view->dragging());
+ EXPECT_FALSE(grid_view->has_dragged_view());
+ generator.ReleaseLeftButton();
+ }
// Do tests for removal of items from the shelf by dragging.
IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, DragOffShelf) {
@@ -1704,24 +1730,24 @@
EXPECT_FALSE(item_controller->IsOpen());
// Activate. This creates new browser
- item_controller->Activate();
+ item_controller->Activate(ash::LAUNCH_FROM_UNKNOWN);
// New Window is created.
running_browser = chrome::GetTotalBrowserCount();
EXPECT_EQ(1u, running_browser);
EXPECT_TRUE(item_controller->IsOpen());
// Minimize Window.
- aura::Window* window = ash::wm::GetActiveWindow();
- ash::wm::MinimizeWindow(window);
- EXPECT_TRUE(ash::wm::IsWindowMinimized(window));
+ ash::wm::WindowState* window_state = ash::wm::GetActiveWindowState();
+ window_state->Minimize();
+ EXPECT_TRUE(window_state->IsMinimized());
// Activate again. This doesn't create new browser.
// It activates window.
- item_controller->Activate();
+ item_controller->Activate(ash::LAUNCH_FROM_UNKNOWN);
running_browser = chrome::GetTotalBrowserCount();
EXPECT_EQ(1u, running_browser);
EXPECT_TRUE(item_controller->IsOpen());
- EXPECT_FALSE(ash::wm::IsWindowMinimized(window));
+ EXPECT_FALSE(window_state->IsMinimized());
}
// Check that GetIDByWindow() returns |LauncherID| of the active tab.
@@ -1733,7 +1759,7 @@
aura::Window* window = browser()->window()->GetNativeWindow();
- int browser_index = ash::launcher::GetBrowserItemIndex(*model_);
+ int browser_index = ash::GetBrowserItemIndex(*model_);
ash::LauncherID browser_id = model_->items()[browser_index].id;
EXPECT_EQ(browser_id, controller_->GetIDByWindow(window));
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
index 6707786..8c59817 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -177,6 +177,43 @@
DISALLOW_COPY_AND_ASSIGN(TestAppTabHelperImpl);
};
+// Test implementation of a V2 app launcher item controller.
+class TestV2AppLauncherItemController : public LauncherItemController {
+ public:
+ TestV2AppLauncherItemController(const std::string& app_id,
+ ChromeLauncherController* controller)
+ : LauncherItemController(LauncherItemController::TYPE_APP,
+ app_id,
+ controller) {
+ }
+
+ virtual ~TestV2AppLauncherItemController() {}
+
+ // Override for LauncherItemController:
+ virtual string16 GetTitle() OVERRIDE { return string16(); }
+ virtual bool IsCurrentlyShownInWindow(aura::Window* window) const OVERRIDE {
+ return true;
+ }
+ virtual bool IsOpen() const OVERRIDE { return true; }
+ virtual bool IsVisible() const OVERRIDE { return true; }
+ virtual void Launch(ash::LaunchSource source, int event_flags) OVERRIDE {}
+ virtual void Activate(ash::LaunchSource source) OVERRIDE {}
+ virtual void Close() OVERRIDE {}
+ virtual void Clicked(const ui::Event& event) OVERRIDE {}
+ virtual void OnRemoved() OVERRIDE {}
+ virtual ChromeLauncherAppMenuItems GetApplicationList(
+ int event_flags) OVERRIDE {
+ ChromeLauncherAppMenuItems items;
+ items.push_back(new ChromeLauncherAppMenuItem(string16(), NULL, false));
+ items.push_back(new ChromeLauncherAppMenuItem(string16(), NULL, false));
+ return items.Pass();
+ }
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(TestV2AppLauncherItemController);
+};
+
} // namespace
class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
@@ -244,6 +281,79 @@
Extension::NO_FLAGS,
extension_misc::kGoogleSearchAppId,
&error);
+ extension5_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
+ manifest,
+ Extension::NO_FLAGS,
+ "cccccccccccccccccccccccccccccccc",
+ &error);
+ extension6_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
+ manifest,
+ Extension::NO_FLAGS,
+ "dddddddddddddddddddddddddddddddd",
+ &error);
+ extension7_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
+ manifest,
+ Extension::NO_FLAGS,
+ "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
+ &error);
+ extension8_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
+ manifest,
+ Extension::NO_FLAGS,
+ "ffffffffffffffffffffffffffffffff",
+ &error);
+ }
+
+ // Creates a running V2 app (not pinned) of type |app_id|.
+ virtual void CreateRunningV2App(const std::string& app_id) {
+ DCHECK(!test_controller_.get());
+ ash::LauncherID id =
+ launcher_controller_->CreateAppShortcutLauncherItemWithType(
+ app_id,
+ model_->item_count(),
+ ash::TYPE_PLATFORM_APP);
+ DCHECK(id);
+ // Change the created launcher controller into a V2 app controller.
+ test_controller_.reset(new TestV2AppLauncherItemController(app_id,
+ launcher_controller_.get()));
+ launcher_controller_->SetItemController(id, test_controller_.get());
+ }
+
+ // Sets the stage for a multi user test.
+ virtual void SetUpMultiUserScenario(base::ListValue* user_a,
+ base::ListValue* user_b) {
+ InitLauncherController();
+ EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus());
+
+ // Set an empty pinned pref to begin with.
+ base::ListValue no_user;
+ SetShelfChromeIconIndex(0);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ no_user.DeepCopy());
+ EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus());
+
+ // Assume all applications have been added already.
+ extension_service_->AddExtension(extension1_.get());
+ extension_service_->AddExtension(extension2_.get());
+ extension_service_->AddExtension(extension3_.get());
+ extension_service_->AddExtension(extension4_.get());
+ extension_service_->AddExtension(extension5_.get());
+ extension_service_->AddExtension(extension6_.get());
+ extension_service_->AddExtension(extension7_.get());
+ extension_service_->AddExtension(extension8_.get());
+ // There should be nothing in the list by now.
+ EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus());
+
+ // Set user a preferences.
+ InsertPrefValue(user_a, 0, extension1_->id());
+ InsertPrefValue(user_a, 1, extension2_->id());
+ InsertPrefValue(user_a, 2, extension3_->id());
+ InsertPrefValue(user_a, 3, extension4_->id());
+ InsertPrefValue(user_a, 4, extension5_->id());
+ InsertPrefValue(user_a, 5, extension6_->id());
+
+ // Set user b preferences.
+ InsertPrefValue(user_b, 0, extension7_->id());
+ InsertPrefValue(user_b, 1, extension8_->id());
}
virtual void TearDown() OVERRIDE {
@@ -253,6 +363,7 @@
model_.reset();
BrowserWithTestWindowTest::TearDown();
+ test_controller_.reset();
}
void AddAppListLauncherItem() {
@@ -305,10 +416,58 @@
}
}
+ // Get the setup of the currently shown launcher items in one string.
+ // Each pinned element will start with a big letter, each running but not
+ // pinned V1 app will start with a small letter and each running but not
+ // pinned V2 app will start with a '*' + small letter.
std::string GetPinnedAppStatus() {
std::string result;
for (int i = 0; i < model_->item_count(); i++) {
switch (model_->items()[i].type) {
+ case ash::TYPE_PLATFORM_APP:
+ result+= "*";
+ // FALLTHROUGH
+ case ash::TYPE_WINDOWED_APP: {
+ const std::string& app =
+ launcher_controller_->GetAppIDForLauncherID(
+ model_->items()[i].id);
+ if (app == extension1_->id()) {
+ result += "app1, ";
+ EXPECT_FALSE(
+ launcher_controller_->IsAppPinned(extension1_->id()));
+ } else if (app == extension2_->id()) {
+ result += "app2, ";
+ EXPECT_FALSE(
+ launcher_controller_->IsAppPinned(extension2_->id()));
+ } else if (app == extension3_->id()) {
+ result += "app3, ";
+ EXPECT_FALSE(
+ launcher_controller_->IsAppPinned(extension3_->id()));
+ } else if (app == extension4_->id()) {
+ result += "app4, ";
+ EXPECT_FALSE(
+ launcher_controller_->IsAppPinned(extension4_->id()));
+ } else if (app == extension5_->id()) {
+ result += "app5, ";
+ EXPECT_FALSE(
+ launcher_controller_->IsAppPinned(extension5_->id()));
+ } else if (app == extension6_->id()) {
+ result += "app6, ";
+ EXPECT_FALSE(
+ launcher_controller_->IsAppPinned(extension6_->id()));
+ } else if (app == extension7_->id()) {
+ result += "app7, ";
+ EXPECT_FALSE(
+ launcher_controller_->IsAppPinned(extension7_->id()));
+ } else if (app == extension8_->id()) {
+ result += "app8, ";
+ EXPECT_FALSE(
+ launcher_controller_->IsAppPinned(extension8_->id()));
+ } else {
+ result += "unknown, ";
+ }
+ break;
+ }
case ash::TYPE_APP_SHORTCUT: {
const std::string& app =
launcher_controller_->GetAppIDForLauncherID(
@@ -325,6 +484,18 @@
} else if (app == extension4_->id()) {
result += "App4, ";
EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
+ } else if (app == extension5_->id()) {
+ result += "App5, ";
+ EXPECT_TRUE(launcher_controller_->IsAppPinned(extension5_->id()));
+ } else if (app == extension6_->id()) {
+ result += "App6, ";
+ EXPECT_TRUE(launcher_controller_->IsAppPinned(extension6_->id()));
+ } else if (app == extension7_->id()) {
+ result += "App7, ";
+ EXPECT_TRUE(launcher_controller_->IsAppPinned(extension7_->id()));
+ } else if (app == extension8_->id()) {
+ result += "App8, ";
+ EXPECT_TRUE(launcher_controller_->IsAppPinned(extension8_->id()));
} else {
result += "unknown, ";
}
@@ -347,7 +518,7 @@
// Set the index at which the chrome icon should be.
void SetShelfChromeIconIndex(int index) {
profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex,
- index + 1);
+ index);
}
// Needed for extension service & friends to work.
@@ -355,9 +526,14 @@
scoped_refptr<Extension> extension2_;
scoped_refptr<Extension> extension3_;
scoped_refptr<Extension> extension4_;
+ scoped_refptr<Extension> extension5_;
+ scoped_refptr<Extension> extension6_;
+ scoped_refptr<Extension> extension7_;
+ scoped_refptr<Extension> extension8_;
scoped_ptr<ChromeLauncherController> launcher_controller_;
scoped_ptr<TestLauncherModelObserver> model_observer_;
scoped_ptr<ash::LauncherModel> model_;
+ scoped_ptr<TestV2AppLauncherItemController> test_controller_;
ExtensionService* extension_service_;
@@ -787,7 +963,7 @@
}
// Check that multiple locks of an application will be properly handled.
-TEST_F(ChromeLauncherControllerTest, CheckMukltiLockApps) {
+TEST_F(ChromeLauncherControllerTest, CheckMultiLockApps) {
InitLauncherController();
// Model should only contain the browser shortcut and app list items.
EXPECT_EQ(2, model_->item_count());
@@ -937,6 +1113,222 @@
EXPECT_EQ(2, model_->item_count());
}
+// Check that a locked (windowed V1 application) will be properly converted
+// between locked and pinned when the order gets changed through a profile /
+// policy change.
+TEST_F(ChromeLauncherControllerTest, RestoreDefaultAndLockedAppsResyncOrder) {
+ InitLauncherController();
+ base::ListValue policy_value0;
+ InsertPrefValue(&policy_value0, 0, extension1_->id());
+ InsertPrefValue(&policy_value0, 1, extension3_->id());
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ policy_value0.DeepCopy());
+ // The shelf layout has always one static item at the beginning (App List).
+ SetShelfChromeIconIndex(0);
+ extension_service_->AddExtension(extension1_.get());
+ EXPECT_EQ("AppList, Chrome, App1, ", GetPinnedAppStatus());
+ extension_service_->AddExtension(extension2_.get());
+ // No new app icon will be generated.
+ EXPECT_EQ("AppList, Chrome, App1, ", GetPinnedAppStatus());
+ // Add the app as locked app which will add it (un-pinned).
+ launcher_controller_->LockV1AppWithID(extension2_->id());
+ EXPECT_EQ("AppList, Chrome, App1, app2, ", GetPinnedAppStatus());
+ extension_service_->AddExtension(extension3_.get());
+ EXPECT_EQ("AppList, Chrome, App1, App3, app2, ", GetPinnedAppStatus());
+
+ // Now request to pin all items which should convert the locked item into a
+ // pinned item.
+ base::ListValue policy_value1;
+ InsertPrefValue(&policy_value1, 0, extension3_->id());
+ InsertPrefValue(&policy_value1, 1, extension2_->id());
+ InsertPrefValue(&policy_value1, 2, extension1_->id());
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ policy_value1.DeepCopy());
+ EXPECT_EQ("AppList, Chrome, App3, App2, App1, ", GetPinnedAppStatus());
+
+ // Going back to a status where there is no requirement for app 2 to be pinned
+ // should convert it back to locked but not pinned and state. The position
+ // is determined by the |LauncherModel|'s weight system. Since at the moment
+ // the weight of a running app has the same as a shortcut, it will remain
+ // where it is. Surely note ideal, but since the sync process can shift around
+ // locations - as well as many other edge cases - this gets nearly impossible
+ // to get right.
+ // TODO(skuhne): Filed crbug.com/293761 to track of this.
+ base::ListValue policy_value2;
+ InsertPrefValue(&policy_value2, 0, extension3_->id());
+ InsertPrefValue(&policy_value2, 1, extension1_->id());
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ policy_value2.DeepCopy());
+ EXPECT_EQ("AppList, Chrome, App3, app2, App1, ", GetPinnedAppStatus());
+
+ // Removing an item should simply close it and everything should shift.
+ base::ListValue policy_value3;
+ InsertPrefValue(&policy_value3, 0, extension3_->id());
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ policy_value3.DeepCopy());
+ EXPECT_EQ("AppList, Chrome, App3, app2, ", GetPinnedAppStatus());
+}
+
+// Check that a running and not pinned V2 application will be properly converted
+// between locked and pinned when the order gets changed through a profile /
+// policy change.
+TEST_F(ChromeLauncherControllerTest,
+ RestoreDefaultAndRunningV2AppsResyncOrder) {
+ InitLauncherController();
+ base::ListValue policy_value0;
+ InsertPrefValue(&policy_value0, 0, extension1_->id());
+ InsertPrefValue(&policy_value0, 1, extension3_->id());
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ policy_value0.DeepCopy());
+ // The shelf layout has always one static item at the beginning (app List).
+ SetShelfChromeIconIndex(0);
+ extension_service_->AddExtension(extension1_.get());
+ EXPECT_EQ("AppList, Chrome, App1, ", GetPinnedAppStatus());
+ extension_service_->AddExtension(extension2_.get());
+ // No new app icon will be generated.
+ EXPECT_EQ("AppList, Chrome, App1, ", GetPinnedAppStatus());
+ // Add the app as an unpinned but running V2 app.
+ CreateRunningV2App(extension2_->id());
+ EXPECT_EQ("AppList, Chrome, App1, *app2, ", GetPinnedAppStatus());
+ extension_service_->AddExtension(extension3_.get());
+ EXPECT_EQ("AppList, Chrome, App1, App3, *app2, ", GetPinnedAppStatus());
+
+ // Now request to pin all items which should convert the locked item into a
+ // pinned item.
+ base::ListValue policy_value1;
+ InsertPrefValue(&policy_value1, 0, extension3_->id());
+ InsertPrefValue(&policy_value1, 1, extension2_->id());
+ InsertPrefValue(&policy_value1, 2, extension1_->id());
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ policy_value1.DeepCopy());
+ EXPECT_EQ("AppList, Chrome, App3, App2, App1, ", GetPinnedAppStatus());
+
+ // Going back to a status where there is no requirement for app 2 to be pinned
+ // should convert it back to running V2 app. Since the position is determined
+ // by the |LauncherModel|'s weight system, it will be after last pinned item.
+ base::ListValue policy_value2;
+ InsertPrefValue(&policy_value2, 0, extension3_->id());
+ InsertPrefValue(&policy_value2, 1, extension1_->id());
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ policy_value2.DeepCopy());
+ EXPECT_EQ("AppList, Chrome, App3, App1, *app2, ", GetPinnedAppStatus());
+
+ // Removing an item should simply close it and everything should shift.
+ base::ListValue policy_value3;
+ InsertPrefValue(&policy_value3, 0, extension3_->id());
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ policy_value3.DeepCopy());
+ EXPECT_EQ("AppList, Chrome, App3, *app2, ", GetPinnedAppStatus());
+}
+
+// Each user has a different set of applications pinned. Check that when
+// switching between the two users, the state gets properly set.
+TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestore) {
+ base::ListValue user_a;
+ base::ListValue user_b;
+ SetUpMultiUserScenario(&user_a, &user_b);
+ // Show user 1.
+ SetShelfChromeIconIndex(6);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_a.DeepCopy());
+ EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome, ",
+ GetPinnedAppStatus());
+
+ // Show user 2.
+ SetShelfChromeIconIndex(4);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_b.DeepCopy());
+
+ EXPECT_EQ("AppList, App7, App8, Chrome, ", GetPinnedAppStatus());
+
+ // Switch back to 1.
+ SetShelfChromeIconIndex(8);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_a.DeepCopy());
+ EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome, ",
+ GetPinnedAppStatus());
+
+ // Switch back to 2.
+ SetShelfChromeIconIndex(4);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_b.DeepCopy());
+ EXPECT_EQ("AppList, App7, App8, Chrome, ", GetPinnedAppStatus());
+}
+
+// Each user has a different set of applications pinned, and one user has an
+// application running. Check that when switching between the two users, the
+// state gets properly set.
+TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestoreWithRunningV2App) {
+ base::ListValue user_a;
+ base::ListValue user_b;
+ SetUpMultiUserScenario(&user_a, &user_b);
+
+ // Run App1 and assume that it is a V2 app.
+ CreateRunningV2App(extension1_->id());
+
+ // Show user 1.
+ SetShelfChromeIconIndex(6);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_a.DeepCopy());
+ EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome, ",
+ GetPinnedAppStatus());
+
+ // Show user 2.
+ SetShelfChromeIconIndex(4);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_b.DeepCopy());
+
+ EXPECT_EQ("AppList, App7, App8, Chrome, *app1, ", GetPinnedAppStatus());
+
+ // Switch back to 1.
+ SetShelfChromeIconIndex(8);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_a.DeepCopy());
+ EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome, ",
+ GetPinnedAppStatus());
+
+ // Switch back to 2.
+ SetShelfChromeIconIndex(4);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_b.DeepCopy());
+ EXPECT_EQ("AppList, App7, App8, Chrome, *app1, ", GetPinnedAppStatus());
+}
+
+// Each user has a different set of applications pinned, and one user has an
+// application running. The chrome icon is not the last item in the list.
+// Check that when switching between the two users, the state gets properly set.
+// There was once a bug associated with this.
+TEST_F(ChromeLauncherControllerTest,
+ UserSwitchIconRestoreWithRunningV2AppChromeInMiddle) {
+ base::ListValue user_a;
+ base::ListValue user_b;
+ SetUpMultiUserScenario(&user_a, &user_b);
+
+ // Run App1 and assume that it is a V2 app.
+ CreateRunningV2App(extension1_->id());
+
+ // Show user 1.
+ SetShelfChromeIconIndex(5);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_a.DeepCopy());
+ EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6, ",
+ GetPinnedAppStatus());
+
+ // Show user 2.
+ SetShelfChromeIconIndex(4);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_b.DeepCopy());
+
+ EXPECT_EQ("AppList, App7, App8, Chrome, *app1, ", GetPinnedAppStatus());
+
+ // Switch back to 1.
+ SetShelfChromeIconIndex(5);
+ profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
+ user_a.DeepCopy());
+ EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6, ",
+ GetPinnedAppStatus());
+}
+
TEST_F(ChromeLauncherControllerTest, Policy) {
extension_service_->AddExtension(extension1_.get());
extension_service_->AddExtension(extension3_.get());
@@ -1517,6 +1909,7 @@
launcher_controller_.reset();
model_.reset(new ash::LauncherModel);
+ AddAppListLauncherItem();
launcher_controller_.reset(
ChromeLauncherController::CreateInstance(profile(), model_.get()));
app_tab_helper = new TestAppTabHelperImpl;
@@ -1524,7 +1917,6 @@
SetAppTabHelper(app_tab_helper);
app_icon_loader = new TestAppIconLoaderImpl;
SetAppIconLoader(app_icon_loader);
- AddAppListLauncherItem();
launcher_controller_->Init();
EXPECT_EQ(1, app_icon_loader->fetch_count());
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_types.h b/chrome/browser/ui/ash/launcher/chrome_launcher_types.h
new file mode 100644
index 0000000..fed638c
--- /dev/null
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_types.h
@@ -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.
+
+#ifndef CHROME_BROWSER_UI_ASH_LAUNCHER_CHROME_LAUNCHER_TYPES_H_
+#define CHROME_BROWSER_UI_ASH_LAUNCHER_CHROME_LAUNCHER_TYPES_H_
+
+namespace ash {
+
+// Source of the launch or activation request, for tracking.
+enum LaunchSource {
+ LAUNCH_FROM_UNKNOWN,
+ LAUNCH_FROM_APP_LIST,
+ LAUNCH_FROM_APP_LIST_SEARCH
+};
+
+} // namespace ash
+
+#endif // CHROME_BROWSER_UI_ASH_LAUNCHER_CHROME_LAUNCHER_TYPES_H_
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
index 113da62..1d679f0 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -11,7 +11,6 @@
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
-#include "ash/wm/property_util.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/prefs/pref_service.h"
diff --git a/chrome/browser/ui/ash/launcher/launcher_item_controller.h b/chrome/browser/ui/ash/launcher/launcher_item_controller.h
index 1ab1f66..9f93e12 100644
--- a/chrome/browser/ui/ash/launcher/launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/launcher_item_controller.h
@@ -10,6 +10,8 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_vector.h"
#include "base/strings/string16.h"
+#include "chrome/browser/ui/ash/launcher/chrome_launcher_types.h"
+#include "ui/events/event.h"
class ChromeLauncherController;
class ChromeLauncherAppMenuItem;
@@ -76,11 +78,11 @@
virtual bool IsVisible() const = 0;
// Launches a new instance of the app associated with this item.
- virtual void Launch(int event_flags) = 0;
+ virtual void Launch(ash::LaunchSource source, int event_flags) = 0;
// Shows and activates the most-recently-active window associated with the
// item, or launches the item if it is not currently open.
- virtual void Activate() = 0;
+ virtual void Activate(ash::LaunchSource source) = 0;
// Closes all windows associated with this item.
virtual void Close() = 0;
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 ec551c1..e05d503 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
@@ -6,7 +6,7 @@
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
-#include "ash/wm/window_settings.h"
+#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h"
#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_v2app.h"
@@ -117,12 +117,14 @@
return false;
}
-void ShellWindowLauncherItemController::Launch(
- int event_flags) {
- launcher_controller()->LaunchApp(app_id(), ui::EF_NONE);
+void ShellWindowLauncherItemController::Launch(ash::LaunchSource source,
+ int event_flags) {
+ launcher_controller()->LaunchApp(app_id(),
+ source,
+ ui::EF_NONE);
}
-void ShellWindowLauncherItemController::Activate() {
+void ShellWindowLauncherItemController::Activate(ash::LaunchSource source) {
DCHECK(!shell_windows_.empty());
ShellWindow* window_to_activate = last_active_shell_window_ ?
last_active_shell_window_ : shell_windows_.back();
@@ -147,7 +149,7 @@
aura::Window* panel_window = panel->GetNativeWindow();
// If the panel is attached on another display, move it to the current
// display and activate it.
- if (ash::wm::GetWindowSettings(panel_window)->panel_attached() &&
+ if (ash::wm::GetWindowState(panel_window)->panel_attached() &&
ash::wm::MoveWindowToEventRoot(panel_window, event)) {
if (!panel->GetBaseWindow()->IsActive())
ShowAndActivateOrMinimize(panel);
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 2ded342..63c1408 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
@@ -59,8 +59,8 @@
virtual bool IsCurrentlyShownInWindow(aura::Window* window) const OVERRIDE;
virtual bool IsOpen() const OVERRIDE;
virtual bool IsVisible() const OVERRIDE;
- virtual void Launch(int event_flags) OVERRIDE;
- virtual void Activate() OVERRIDE;
+ virtual void Launch(ash::LaunchSource source, int event_flags) OVERRIDE;
+ virtual void Activate(ash::LaunchSource source) OVERRIDE;
virtual void Close() OVERRIDE;
virtual void Clicked(const ui::Event& event) OVERRIDE;
virtual void OnRemoved() OVERRIDE {}
diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
index 62327f3..f95c40f 100644
--- a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
@@ -98,9 +98,45 @@
void SessionStateDelegateChromeos::SwitchActiveUser(
const std::string& user_email) {
- // The user_id can be a display email which might be capitalized and has dots.
- chromeos::UserManager::Get()->SwitchActiveUser(
- gaia::CanonicalizeEmail(gaia::SanitizeEmail(user_email)));
+ // Disallow switching to an already active user since that might crash.
+ // Transform the |user_email| into a |user_id| for comparison & switching.
+ std::string user_id =
+ gaia::CanonicalizeEmail(gaia::SanitizeEmail(user_email));
+ if (user_id == chromeos::UserManager::Get()->GetActiveUser()->email())
+ return;
+ chromeos::UserManager::Get()->SwitchActiveUser(user_id);
+}
+
+void SessionStateDelegateChromeos::SwitchActiveUserToNext() {
+ // Make sure there is a user to switch to.
+ if (NumberOfLoggedInUsers() <= 1)
+ return;
+
+ const chromeos::UserList& logged_in_users =
+ chromeos::UserManager::Get()->GetLoggedInUsers();
+
+ std::string user_id = chromeos::UserManager::Get()->GetActiveUser()->email();
+
+ // Get an iterator positioned at the active user.
+ chromeos::UserList::const_iterator it;
+ for (it = logged_in_users.begin();
+ it != logged_in_users.end(); ++it) {
+ if ((*it)->email() == user_id)
+ break;
+ }
+
+ // Active user not found.
+ if (it == logged_in_users.end())
+ return;
+
+ // Get the next user's email, wrapping to the start of the list if necessary.
+ if (++it == logged_in_users.end())
+ user_id = (*logged_in_users.begin())->email();
+ else
+ user_id = (*it)->email();
+
+ // Switch using the transformed |user_id|.
+ chromeos::UserManager::Get()->SwitchActiveUser(user_id);
}
void SessionStateDelegateChromeos::AddSessionStateObserver(
diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.h b/chrome/browser/ui/ash/session_state_delegate_chromeos.h
index 344b561..56fd9c3 100644
--- a/chrome/browser/ui/ash/session_state_delegate_chromeos.h
+++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.h
@@ -39,6 +39,7 @@
ash::MultiProfileIndex index) const OVERRIDE;
virtual void GetLoggedInUsers(ash::UserIdList* users) OVERRIDE;
virtual void SwitchActiveUser(const std::string& user_email) OVERRIDE;
+ virtual void SwitchActiveUserToNext() OVERRIDE;
virtual void AddSessionStateObserver(
ash::SessionStateObserver* observer) OVERRIDE;
virtual void RemoveSessionStateObserver(
diff --git a/chrome/browser/ui/ash/session_state_delegate_views.cc b/chrome/browser/ui/ash/session_state_delegate_views.cc
index 933b2f3..499b3f9 100644
--- a/chrome/browser/ui/ash/session_state_delegate_views.cc
+++ b/chrome/browser/ui/ash/session_state_delegate_views.cc
@@ -77,6 +77,10 @@
NOTIMPLEMENTED();
}
+void SessionStateDelegate::SwitchActiveUserToNext() {
+ NOTIMPLEMENTED();
+}
+
void SessionStateDelegate::AddSessionStateObserver(
ash::SessionStateObserver* observer) {
NOTIMPLEMENTED();
diff --git a/chrome/browser/ui/ash/session_state_delegate_views.h b/chrome/browser/ui/ash/session_state_delegate_views.h
index d209e2a..d8e5441 100644
--- a/chrome/browser/ui/ash/session_state_delegate_views.h
+++ b/chrome/browser/ui/ash/session_state_delegate_views.h
@@ -36,6 +36,7 @@
ash::MultiProfileIndex index) const OVERRIDE;
virtual void GetLoggedInUsers(ash::UserIdList* users) OVERRIDE;
virtual void SwitchActiveUser(const std::string& user_email) OVERRIDE;
+ virtual void SwitchActiveUserToNext() OVERRIDE;
virtual void AddSessionStateObserver(
ash::SessionStateObserver* observer) OVERRIDE;
virtual void RemoveSessionStateObserver(
diff --git a/chrome/browser/ui/ash/window_positioner.cc b/chrome/browser/ui/ash/window_positioner.cc
index 41ad8dd..b11ebcd 100644
--- a/chrome/browser/ui/ash/window_positioner.cc
+++ b/chrome/browser/ui/ash/window_positioner.cc
@@ -7,6 +7,7 @@
#include "ash/shell.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/window_resizer.h"
+#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
@@ -109,11 +110,11 @@
if (windows[i] && windows[i]->IsVisible() && windows[i]->layer() &&
(!windows[i]->transparent() ||
windows[i]->layer()->GetTargetOpacity() == 1.0)) {
+ ash::wm::WindowState* window_state = ash::wm::GetWindowState(windows[i]);
// When any window is maximized we cannot find any free space.
- if (ash::wm::IsWindowMaximized(windows[i]) ||
- ash::wm::IsWindowFullscreen(windows[i]))
+ if (window_state->IsMaximizedOrFullscreen())
return gfx::Rect(0, 0, 0, 0);
- if (ash::wm::IsWindowNormal(windows[i]))
+ if (window_state->IsNormalShowState())
regions.push_back(&windows[i]->bounds());
}
}
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 328b570..a63ebce 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
@@ -52,6 +52,18 @@
#if !defined(OS_CHROMEOS)
#if defined(USE_ASH)
active_desktop_monitor_.reset(new ActiveDesktopMonitor(GetInitialDesktop()));
+#endif
+#endif
+
+#if !defined(USE_ASH) && defined(OS_LINUX) && defined(USE_X11)
+ // TODO(erg): Refactor this into a dlopen call when we add a GTK3 port.
+ views::LinuxUI::SetInstance(BuildGtk2UI());
+#endif
+}
+
+void ChromeBrowserMainExtraPartsAura::PostMainMessageLoopStart() {
+#if !defined(OS_CHROMEOS)
+#if defined(USE_ASH)
if (!chrome::ShouldOpenAshOnStartup())
#endif
{
@@ -59,11 +71,6 @@
views::CreateDesktopScreen());
}
#endif
-
-#if !defined(USE_ASH) && defined(OS_LINUX) && defined(USE_X11)
- // TODO(erg): Refactor this into a dlopen call when we add a GTK3 port.
- views::LinuxUI::SetInstance(BuildGtk2UI());
-#endif
}
void ChromeBrowserMainExtraPartsAura::PostMainMessageLoopRun() {
diff --git a/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.h b/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.h
index 8ba39ab..a199fe8 100644
--- a/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.h
+++ b/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.h
@@ -19,6 +19,7 @@
// Overridden from ChromeBrowserMainExtraParts:
virtual void ToolkitInitialized() OVERRIDE;
+ virtual void PostMainMessageLoopStart() OVERRIDE;
virtual void PostMainMessageLoopRun() OVERRIDE;
private:
diff --git a/chrome/browser/ui/auto_login_infobar_delegate.cc b/chrome/browser/ui/auto_login_infobar_delegate.cc
index bdf6fe3..3e25caa 100644
--- a/chrome/browser/ui/auto_login_infobar_delegate.cc
+++ b/chrome/browser/ui/auto_login_infobar_delegate.cc
@@ -39,7 +39,7 @@
#include "ui/base/l10n/l10n_util.h"
#if defined(OS_ANDROID)
-#include "chrome/browser/ui/auto_login_infobar_delegate_android.h"
+#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h"
#endif
using content::NavigationController;
diff --git a/chrome/browser/ui/auto_login_prompter.cc b/chrome/browser/ui/auto_login_prompter.cc
index 9d9bff0..70311db 100644
--- a/chrome/browser/ui/auto_login_prompter.cc
+++ b/chrome/browser/ui/auto_login_prompter.cc
@@ -31,16 +31,18 @@
bool FetchUsernameThroughSigninManager(Profile* profile, std::string* output) {
// In an incognito window these services are not available.
- ProfileOAuth2TokenService* token_service =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
- if (!token_service || !token_service->RefreshTokenIsAvailable())
- return false;
-
SigninManagerBase* signin_manager =
SigninManagerFactory::GetInstance()->GetForProfile(profile);
if (!signin_manager)
return false;
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+ if (!token_service || !token_service->RefreshTokenIsAvailable(
+ token_service->GetPrimaryAccountId())) {
+ return false;
+ }
+
*output = signin_manager->GetAuthenticatedUsername();
return true;
}
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
index 2cda6e0..f870455 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
@@ -567,7 +567,8 @@
IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, WalletCreditCardDisabled) {
controller()->OnUserNameFetchSuccess("user@example.com");
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
// An expired card will be forced into edit mode.
wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentWithDetails(
"instrument_id",
@@ -732,7 +733,8 @@
// Set up some Wallet state.
controller()->OnUserNameFetchSuccess("user@example.com");
- controller()->OnDidGetWalletItems(wallet::GetTestWalletItems());
+ controller()->OnDidGetWalletItems(
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser();
ASSERT_TRUE(account_chooser->IsItemCheckedAt(0));
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
index 2640ec9..29b4768 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
@@ -113,7 +113,7 @@
const color_utils::HSL kGrayImageShift = {-1, 0, 0.8};
// Limit Wallet items refresh rate to at most once per minute.
-const int kWalletItemsRefreshRateSeconds = 60;
+const int64 kWalletItemsRefreshRateSeconds = 60;
// The number of milliseconds to delay enabling the submit button after showing
// the dialog. This delay prevents users from accidentally clicking the submit
@@ -141,10 +141,13 @@
};
// Returns true if |card_type| is supported by Wallet.
-bool IsWalletSupportedCard(const std::string& card_type) {
+bool IsWalletSupportedCard(const std::string& card_type,
+ const wallet::WalletItems& wallet_items) {
return card_type == autofill::kVisaCard ||
card_type == autofill::kMasterCard ||
- card_type == autofill::kDiscoverCard;
+ card_type == autofill::kDiscoverCard ||
+ (card_type == autofill::kAmericanExpressCard &&
+ wallet_items.is_amex_allowed());
}
// Returns true if |input| should be used to fill a site-requested |field| which
@@ -469,7 +472,7 @@
const int kCardWidthPx = 300;
const int kCardHeightPx = 190;
const gfx::Size size(kCardWidthPx, kCardHeightPx);
- gfx::Canvas canvas(size, ui::SCALE_FACTOR_100P, false);
+ gfx::Canvas canvas(size, 1.0f, false);
gfx::Rect display_rect(size);
@@ -641,6 +644,13 @@
GetMetricLogger().LogDialogSecurityMetric(
AutofillMetrics::SECURITY_METRIC_DIALOG_SHOWN);
+ // Determine what field types should be included in the dialog.
+ // Note that RequestingCreditCardInfo() below relies on parsed field types.
+ bool has_types = false;
+ bool has_sections = false;
+ form_structure_.ParseFieldTypesFromAutocompleteAttributes(
+ &has_types, &has_sections);
+
if (RequestingCreditCardInfo() && !TransmissionWillBeSecure()) {
GetMetricLogger().LogDialogSecurityMetric(
AutofillMetrics::SECURITY_METRIC_CREDIT_CARD_OVER_HTTP);
@@ -651,12 +661,6 @@
AutofillMetrics::SECURITY_METRIC_CROSS_ORIGIN_FRAME);
}
- // Determine what field types should be included in the dialog.
- bool has_types = false;
- bool has_sections = false;
- form_structure_.ParseFieldTypesFromAutocompleteAttributes(
- &has_types, &has_sections);
-
// Fail if the author didn't specify autocomplete types.
if (!has_types) {
callback_.Run(NULL);
@@ -716,7 +720,7 @@
void AutofillDialogControllerImpl::TabActivated() {
// If the user switched away from this tab and then switched back, reload the
// Wallet items, in case they've changed.
- int seconds_elapsed_since_last_refresh =
+ int64 seconds_elapsed_since_last_refresh =
(base::TimeTicks::Now() - last_wallet_items_fetch_timestamp_).InSeconds();
if (IsPayingWithWallet() && wallet_items_ &&
seconds_elapsed_since_last_refresh >= kWalletItemsRefreshRateSeconds) {
@@ -880,7 +884,6 @@
string.text = l10n_util::GetStringUTF16(
IDS_AUTOFILL_DIALOG_CARD_GENERATION_DONE);
- state.strings.push_back(DialogOverlayString());
} else {
// Start the refresher if it isn't running. Wait one second before pumping
// updates to the view.
@@ -2874,7 +2877,8 @@
// Wallet only accepts MasterCard, Visa and Discover. No AMEX.
if (IsPayingWithWallet() &&
- !IsWalletSupportedCard(CreditCard::GetCreditCardType(number))) {
+ !IsWalletSupportedCard(CreditCard::GetCreditCardType(number),
+ *wallet_items_)) {
return l10n_util::GetStringUTF16(
IDS_AUTOFILL_DIALOG_VALIDATION_CREDIT_CARD_NOT_SUPPORTED_BY_WALLET);
}
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
index d229e5d..73d8cf9 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
@@ -106,7 +106,8 @@
}
scoped_ptr<wallet::WalletItems> CompleteAndValidWalletItems() {
- scoped_ptr<wallet::WalletItems> items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
items->AddInstrument(wallet::GetTestMaskedInstrument());
items->AddAddress(wallet::GetTestShippingAddress());
return items.Pass();
@@ -803,7 +804,8 @@
SwitchToWallet();
// Setup some wallet state.
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
controller()->OnDidGetWalletItems(wallet_items.Pass());
DetailOutputMap wallet_outputs;
@@ -871,24 +873,36 @@
ValidateCCNumber(SECTION_CC, kTestCCNumberMaster, true);
ValidateCCNumber(SECTION_CC, kTestCCNumberDiscover, true);
ValidateCCNumber(SECTION_CC, kTestCCNumberAmex, true);
-
ValidateCCNumber(SECTION_CC, kTestCCNumberIncomplete, false);
ValidateCCNumber(SECTION_CC, kTestCCNumberInvalid, false);
// Switch to Wallet which will not accept AMEX.
SwitchToWallet();
- // Setup some wallet state.
- controller()->OnDidGetWalletItems(wallet::GetTestWalletItems());
+ // Setup some wallet state on a merchant for which Wallet doesn't
+ // support AMEX.
+ controller()->OnDidGetWalletItems(
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
// Should accept Visa, Master and Discover, but not AMEX.
ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberVisa, true);
ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberMaster, true);
ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberDiscover, true);
-
ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberAmex, false);
ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberIncomplete, false);
ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberInvalid, false);
+
+ // Setup some wallet state on a merchant for which Wallet supports AMEX.
+ controller()->OnDidGetWalletItems(
+ wallet::GetTestWalletItems(wallet::AMEX_ALLOWED));
+
+ // Should accept Visa, Master, Discover, and AMEX.
+ ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberVisa, true);
+ ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberMaster, true);
+ ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberDiscover, true);
+ ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberAmex, true);
+ ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberIncomplete, false);
+ ValidateCCNumber(SECTION_CC_BILLING, kTestCCNumberInvalid, false);
}
TEST_F(AutofillDialogControllerTest, AutofillProfiles) {
@@ -1260,7 +1274,8 @@
// Makes sure the default object IDs are respected.
TEST_F(AutofillDialogControllerTest, WalletDefaultItems) {
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
@@ -1289,7 +1304,8 @@
// Tests that invalid and AMEX default instruments are ignored.
TEST_F(AutofillDialogControllerTest, SelectInstrument) {
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
// Tests if default instrument is invalid, then, the first valid instrument is
// selected instead of the default instrument.
wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
@@ -1304,12 +1320,14 @@
EXPECT_TRUE(controller()->MenuModelForSection(SECTION_CC_BILLING)->
IsItemCheckedAt(0));
- // Tests if default instrument is AMEX, then, the first valid instrument is
+ // Tests if default instrument is AMEX but Wallet doesn't support
+ // AMEX on this merchant, then the first valid instrument is
// selected instead of the default instrument.
- wallet_items = wallet::GetTestWalletItems();
+ wallet_items = wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
- wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentAmex());
+ wallet_items->AddInstrument(
+ wallet::GetTestMaskedInstrumentAmex(wallet::AMEX_DISALLOWED));
wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
@@ -1319,10 +1337,27 @@
EXPECT_TRUE(controller()->MenuModelForSection(SECTION_CC_BILLING)->
IsItemCheckedAt(0));
+ // Tests if default instrument is AMEX and it is allowed on this merchant,
+ // then it is selected.
+ wallet_items = wallet::GetTestWalletItems(wallet::AMEX_ALLOWED);
+ wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
+ wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
+ wallet_items->AddInstrument(
+ wallet::GetTestMaskedInstrumentAmex(wallet::AMEX_ALLOWED));
+ wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
+
+ controller()->OnDidGetWalletItems(wallet_items.Pass());
+ // 4 suggestions and "add", "manage".
+ EXPECT_EQ(6,
+ controller()->MenuModelForSection(SECTION_CC_BILLING)->GetItemCount());
+ EXPECT_TRUE(controller()->MenuModelForSection(SECTION_CC_BILLING)->
+ IsItemCheckedAt(2));
+
// Tests if only have AMEX and invalid instrument, then "add" is selected.
- wallet_items = wallet::GetTestWalletItems();
+ wallet_items = wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentInvalid());
- wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentAmex());
+ wallet_items->AddInstrument(
+ wallet::GetTestMaskedInstrumentAmex(wallet::AMEX_DISALLOWED));
controller()->OnDidGetWalletItems(wallet_items.Pass());
// 2 suggestions and "add", "manage".
@@ -1340,7 +1375,8 @@
testing::NotNull(),
_)).Times(1);
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
// If there is no shipping address in wallet, it will default to
@@ -1359,7 +1395,8 @@
testing::IsNull(),
_)).Times(1);
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddAddress(wallet::GetTestShippingAddress());
SubmitWithWalletItems(wallet_items.Pass());
}
@@ -1371,7 +1408,8 @@
testing::IsNull(),
_)).Times(1);
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddAddress(wallet::GetTestShippingAddress());
wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentInvalid());
SubmitWithWalletItems(wallet_items.Pass());
@@ -1383,7 +1421,8 @@
testing::NotNull(),
_)).Times(1);
- controller()->OnDidGetWalletItems(wallet::GetTestWalletItems());
+ controller()->OnDidGetWalletItems(
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
AcceptAndLoadFakeFingerprint();
}
@@ -1416,7 +1455,8 @@
EXPECT_CALL(*controller()->GetTestingWalletClient(),
SaveToWalletMock(_, _, _)).Times(0);
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
scoped_ptr<wallet::WalletItems::MaskedInstrument> instrument =
wallet::GetTestMaskedInstrument();
// Copy billing address as shipping address, and assign an id to it.
@@ -1437,7 +1477,8 @@
// Test that the local view contents is used when saving a new instrument and
// the user has selected "Same as billing".
TEST_F(AutofillDialogControllerTest, SaveInstrumentSameAsBilling) {
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
@@ -1478,7 +1519,8 @@
EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(1);
- controller()->OnDidGetWalletItems(wallet::GetTestWalletItems());
+ controller()->OnDidGetWalletItems(
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
controller()->OnCancel();
}
@@ -1497,7 +1539,8 @@
EXPECT_EQ("chrome", autofill_manage_url.scheme());
SwitchToWallet();
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
@@ -1658,7 +1701,8 @@
// |WalletClientDelegate::OnDid{Save,Update}*()| call. This can happen if Online
// Wallet's server validation differs from Chrome's local validation.
TEST_F(AutofillDialogControllerTest, WalletServerSideValidation) {
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
controller()->OnAccept();
@@ -1680,7 +1724,8 @@
// Simulates receiving unrecoverable Wallet server validation errors.
TEST_F(AutofillDialogControllerTest, WalletServerSideValidationUnrecoverable) {
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
controller()->OnAccept();
@@ -1728,7 +1773,8 @@
// Start over and sign in a user with an incomplete account.
SetUpControllerWithFormData(DefaultFormData());
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
@@ -1835,7 +1881,8 @@
SetUpControllerWithFormData(DefaultFormData());
SwitchToWallet();
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
controller()->OnAccept();
@@ -1936,7 +1983,8 @@
// view. Called once for each incomplete suggestion.
EXPECT_CALL(*controller()->GetView(), UpdateForErrors()).Times(1);
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentWithIdAndAddress(
"id", wallet::GetTestMinimalAddress()));
scoped_ptr<wallet::Address> address(wallet::GetTestShippingAddress());
@@ -1954,7 +2002,8 @@
TEST_F(AutofillDialogControllerTest, RiskNeverLoadsWithPendingLegalDocuments) {
EXPECT_CALL(*controller(), LoadRiskFingerprintData()).Times(0);
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddLegalDocument(wallet::GetTestLegalDocument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
controller()->OnAccept();
@@ -1963,7 +2012,8 @@
TEST_F(AutofillDialogControllerTest, RiskLoadsAfterAcceptingLegalDocuments) {
EXPECT_CALL(*controller(), LoadRiskFingerprintData()).Times(0);
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddLegalDocument(wallet::GetTestLegalDocument());
controller()->OnDidGetWalletItems(wallet_items.Pass());
@@ -1980,7 +2030,8 @@
TEST_F(AutofillDialogControllerTest, NoManageMenuItemForNewWalletUsers) {
// Make sure the menu model item is created for a returning Wallet user.
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
wallet_items->AddAddress(wallet::GetTestShippingAddress());
controller()->OnDidGetWalletItems(wallet_items.Pass());
@@ -2050,7 +2101,8 @@
EXPECT_CALL(*controller()->GetTestingWalletClient(),
GetFullWallet(_)).Times(1);
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
SubmitWithWalletItems(wallet_items.Pass());
controller()->OnDidGetFullWallet(wallet::GetTestFullWalletInstrumentOnly());
@@ -2060,7 +2112,8 @@
TEST_F(AutofillDialogControllerTest, NotProdNotification) {
// To make IsPayingWithWallet() true.
- controller()->OnDidGetWalletItems(wallet::GetTestWalletItems());
+ controller()->OnDidGetWalletItems(
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
CommandLine* command_line = CommandLine::ForCurrentProcess();
ASSERT_FALSE(command_line->HasSwitch(switches::kWalletServiceUseProd));
@@ -2074,7 +2127,8 @@
// Ensure Wallet instruments marked expired by the server are shown as invalid.
TEST_F(AutofillDialogControllerTest, WalletExpiredCard) {
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentExpired());
controller()->OnDidGetWalletItems(wallet_items.Pass());
@@ -2159,7 +2213,8 @@
// Switch into Wallet mode and initialize some Wallet data.
SwitchToWallet();
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
wallet_items->AddAddress(wallet::GetTestNonDefaultShippingAddress());
@@ -2194,7 +2249,7 @@
controller()->TabActivated();
// Simulate a response that includes different items.
- wallet_items = wallet::GetTestWalletItems();
+ wallet_items = wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrumentExpired());
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
@@ -2217,7 +2272,8 @@
// Switch into Wallet mode and initialize some Wallet data.
SwitchToWallet();
- scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
+ scoped_ptr<wallet::WalletItems> wallet_items =
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
wallet_items->AddInstrument(wallet::GetTestNonDefaultMaskedInstrument());
wallet_items->AddAddress(wallet::GetTestNonDefaultShippingAddress());
@@ -2244,7 +2300,8 @@
// Simulate a response that includes different default values.
wallet_items =
wallet::GetTestWalletItemsWithDefaultIds("new_default_instrument_id",
- "new_default_address_id");
+ "new_default_address_id",
+ wallet::AMEX_DISALLOWED);
scoped_ptr<wallet::Address> other_address = wallet::GetTestShippingAddress();
other_address->set_object_id("other_address_id");
scoped_ptr<wallet::Address> new_default_address =
@@ -2278,7 +2335,8 @@
EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_));
controller()->TabActivated();
- controller()->OnDidGetWalletItems(wallet::GetTestWalletItems());
+ controller()->OnDidGetWalletItems(
+ wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
EXPECT_FALSE(controller()->MenuModelForSection(SECTION_CC_BILLING));
EXPECT_EQ(
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 dbf7a04..7d46087 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_sign_in_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.
@@ -13,18 +13,24 @@
AutofillDialogSignInDelegate::AutofillDialogSignInDelegate(
AutofillDialogView* dialog_view,
content::WebContents* web_contents,
- content::WebContentsDelegate* wrapped_delegate)
+ content::WebContentsDelegate* wrapped_delegate,
+ const gfx::Size& minimum_size,
+ const gfx::Size& maximum_size)
: WebContentsObserver(web_contents),
dialog_view_(dialog_view),
- min_width_(400),
- wrapped_delegate_(wrapped_delegate) {
+ wrapped_delegate_(wrapped_delegate),
+ minimum_size_(minimum_size),
+ maximum_size_(maximum_size) {
+ DCHECK(dialog_view_);
DCHECK(wrapped_delegate_);
web_contents->SetDelegate(this);
+ EnableAutoResize();
}
void AutofillDialogSignInDelegate::ResizeDueToAutoResize(
- content::WebContents* source, const gfx::Size& pref_size) {
- dialog_view_->OnSignInResize(pref_size);
+ content::WebContents* source,
+ const gfx::Size& preferred_size) {
+ dialog_view_->OnSignInResize(preferred_size);
}
content::WebContents* AutofillDialogSignInDelegate::OpenURLFromTab(
@@ -46,26 +52,16 @@
void AutofillDialogSignInDelegate::RenderViewCreated(
content::RenderViewHost* render_view_host) {
- SetMinWidth(min_width_);
+ EnableAutoResize();
- // Set the initial size as soon as we have an RVH to avoid
- // bad size jumping.
- dialog_view_->OnSignInResize(GetMinSize());
+ // Set the initial size as soon as we have an RVH to avoid bad size jumping.
+ dialog_view_->OnSignInResize(minimum_size_);
}
-void AutofillDialogSignInDelegate::SetMinWidth(int width) {
- min_width_ = width;
+void AutofillDialogSignInDelegate::EnableAutoResize() {
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);
+ host->EnableAutoResize(minimum_size_, maximum_size_);
}
} // 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 6c4a149..c1d730f 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_sign_in_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.
@@ -7,6 +7,7 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
+#include "ui/gfx/size.h"
namespace autofill {
@@ -23,11 +24,13 @@
public:
AutofillDialogSignInDelegate(AutofillDialogView* dialog_view,
content::WebContents* web_contents,
- content::WebContentsDelegate* wrapped_delegate);
+ content::WebContentsDelegate* wrapped_delegate,
+ const gfx::Size& minimum_size,
+ const gfx::Size& maximum_size);
// WebContentsDelegate implementation.
virtual void ResizeDueToAutoResize(content::WebContents* source,
- const gfx::Size& pref_size) OVERRIDE;
+ const gfx::Size& preferred_size) OVERRIDE;
virtual content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) OVERRIDE;
@@ -42,20 +45,20 @@
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;
+ // Enables auto-resizing for this view, if possible, constrained to the
+ // minimum and maximum size allowed by the delegate.
+ void EnableAutoResize();
- AutofillDialogView* dialog_view_;
- int min_width_;
+ // The dialog view hosting this sign in page.
+ AutofillDialogView* const dialog_view_;
// The delegate for the WebContents hosting this dialog.
content::WebContentsDelegate* const wrapped_delegate_;
+
+ // The minimum and maximum sizes that the sign-in view may have.
+ const gfx::Size minimum_size_;
+ const gfx::Size maximum_size_;
};
} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index d6db9da..4440230 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -39,9 +39,6 @@
// The vertical height of a separator in pixels.
const size_t kSeparatorHeight = 1;
-// The maximum amount of characters to display from either the name or subtext.
-const size_t kMaxTextLength = 15;
-
#if !defined(OS_ANDROID)
const size_t kNamePadding = AutofillPopupView::kNamePadding;
const size_t kIconPadding = AutofillPopupView::kIconPadding;
diff --git a/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc
index 0159a39..d13db3d 100644
--- a/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc
@@ -26,14 +26,6 @@
namespace autofill {
-namespace {
-
-static const int kMaxGeneratedCardTimesToShow = 5;
-static const char kWalletGeneratedCardLearnMoreLink[] =
- "http://support.google.com/wallet/bin/answer.py?hl=en&answer=2740044";
-
-} // namespace
-
CreditCardDescription::CreditCardDescription() {}
CreditCardDescription::~CreditCardDescription() {}
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
index b391f64..a29ba45 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
+++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -335,7 +335,16 @@
EXPECT_EQ(ASCIIToUTF16(search_string), model->CurrentMatch(NULL).contents);
}
-IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, WindowFeatures) {
+// This test fails on linux AURA with this change
+// https://codereview.chromium.org/23903056
+// BUG=https://code.google.com/p/chromium/issues/detail?id=295299
+// TODO(ananta). Debug and fix this test.
+#if defined(USE_AURA) && defined(OS_LINUX)
+#define MAYBE_WindowFeatures DISABLED_WindowFeatures
+#else
+#define MAYBE_WindowFeatures WindowFeatures
+#endif
+IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, MAYBE_WindowFeatures) {
WebContents* popup =
RunCheckTest(browser(),
base::FilePath(FILE_PATH_LITERAL("popup-window-open.html")),
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 850ba73..acc4a17 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -223,11 +223,6 @@
namespace {
-// The URL to be loaded to display the "Report a broken page" form.
-const char kBrokenPageUrl[] =
- "https://www.google.com/support/chrome/bin/request.py?contact_type="
- "broken_website&format=inproduct&p.page_title=$1&p.page_url=$2";
-
// How long we wait before updating the browser chrome while loading a page.
const int kUIUpdateCoalescingTimeMS = 200;
@@ -1053,6 +1048,22 @@
int reason) {
content::RecordAction(UserMetricsAction("ActiveTabChanged"));
+ // Switch the find bar to the new tab if necessary. This must be done before
+ // changing focus for unittests to pass.
+ // TODO(pkasting): http://crbug.com/297385 Move this to near the end of this
+ // function (where it used to be) once the find bar properly restores
+ // selections across tab changes.
+ if (HasFindBarController()) {
+ find_bar_controller_->ChangeWebContents(new_contents);
+ find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true);
+ }
+
+ // Let the BrowserWindow do its handling. On e.g. views this changes the
+ // focused object, which should happen before we update the toolbar below,
+ // since the omnibox expects the correct element to already be focused when it
+ // is updated.
+ window_->OnActiveTabChanged(old_contents, new_contents, index, reason);
+
// Discarded tabs always get reloaded.
if (tab_strip_model_->IsTabDiscarded(index)) {
LOG(WARNING) << "Reloading discarded tab at " << index;
@@ -1088,11 +1099,6 @@
tab_strip_model_->GetActiveWebContents())->GetStatusText());
}
- if (HasFindBarController()) {
- find_bar_controller_->ChangeWebContents(new_contents);
- find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true);
- }
-
// Update sessions. Don't force creation of sessions. If sessions doesn't
// exist, the change will be picked up by sessions when created.
SessionService* session_service =
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 960b62e..4d1813f 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -31,6 +31,7 @@
#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/translate/translate_tab_helper.h"
#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
+#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
#include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h"
#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
#include "chrome/browser/ui/browser.h"
@@ -230,6 +231,9 @@
void Proceed() {
interstitial_page_->Proceed();
}
+ void DontProceed() {
+ interstitial_page_->DontProceed();
+ }
virtual std::string GetHTMLContents() OVERRIDE {
return "<h1>INTERSTITIAL</h1>";
@@ -1686,6 +1690,56 @@
EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU));
}
+// Ensure that creating an interstitial page closes any JavaScript dialogs
+// that were present on the previous page. See http://crbug.com/295695.
+IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialClosesDialogs) {
+ ASSERT_TRUE(test_server()->Start());
+ host_resolver()->AddRule("www.example.com", "127.0.0.1");
+ GURL url(test_server()->GetURL("empty.html"));
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ contents->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
+ string16(),
+ ASCIIToUTF16("alert('Dialog showing!');"));
+ AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
+ EXPECT_TRUE(alert->IsValid());
+ AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
+ EXPECT_TRUE(dialog_queue->HasActiveDialog());
+
+ TestInterstitialPage* interstitial = NULL;
+ {
+ scoped_refptr<content::MessageLoopRunner> loop_runner(
+ new content::MessageLoopRunner);
+
+ InterstitialObserver observer(contents,
+ loop_runner->QuitClosure(),
+ base::Closure());
+ interstitial = new TestInterstitialPage(contents, false, GURL());
+ loop_runner->Run();
+ }
+
+ // The interstitial should have closed the dialog.
+ EXPECT_TRUE(contents->ShowingInterstitialPage());
+ EXPECT_FALSE(dialog_queue->HasActiveDialog());
+
+ {
+ scoped_refptr<content::MessageLoopRunner> loop_runner(
+ new content::MessageLoopRunner);
+
+ InterstitialObserver observer(contents,
+ base::Closure(),
+ loop_runner->QuitClosure());
+ interstitial->DontProceed();
+ loop_runner->Run();
+ // interstitial is deleted now.
+ }
+
+ // Make sure input events still work in the renderer process.
+ EXPECT_FALSE(contents->GetRenderProcessHost()->IgnoreInputEvents());
+}
+
+
IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialCloseTab) {
WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index fea6d8d..2afe9be 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -12,7 +12,7 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/sessions/tab_restore_service.h"
@@ -1194,7 +1194,7 @@
bool enable = IsShowingMainUI() &&
!profile()->IsOffTheRecord() &&
profile_manager_ &&
- AvatarMenuModel::ShouldShowAvatarMenu();
+ AvatarMenu::ShouldShowAvatarMenu();
command_updater_.UpdateCommandEnabled(IDC_SHOW_AVATAR_MENU,
enable);
}
diff --git a/chrome/browser/ui/browser_instant_controller.cc b/chrome/browser/ui/browser_instant_controller.cc
index 662eca7..378d276 100644
--- a/chrome/browser/ui/browser_instant_controller.cc
+++ b/chrome/browser/ui/browser_instant_controller.cc
@@ -5,16 +5,12 @@
#include "chrome/browser/ui/browser_instant_controller.h"
#include "base/bind.h"
-#include "base/prefs/pref_service.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_web_ui.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"
-#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.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/omnibox/location_bar.h"
@@ -25,9 +21,7 @@
#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/pref_names.h"
#include "chrome/common/url_constants.h"
-#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
@@ -42,16 +36,12 @@
: browser_(browser),
instant_(this),
instant_unload_handler_(browser) {
- profile_pref_registrar_.Init(profile()->GetPrefs());
- profile_pref_registrar_.Add(
- prefs::kDefaultSearchProviderID,
- base::Bind(&BrowserInstantController::OnDefaultSearchProviderChanged,
- base::Unretained(this)));
browser_->search_model()->AddObserver(this);
InstantService* instant_service =
InstantServiceFactory::GetForProfile(profile());
instant_service->OnBrowserInstantControllerCreated();
+ instant_service->AddObserver(this);
}
BrowserInstantController::~BrowserInstantController() {
@@ -59,6 +49,7 @@
InstantService* instant_service =
InstantServiceFactory::GetForProfile(profile());
+ instant_service->RemoveObserver(this);
instant_service->OnBrowserInstantControllerDestroyed();
}
@@ -273,25 +264,20 @@
instant_.InstantSupportChanged(new_state.instant_support);
}
-void BrowserInstantController::OnDefaultSearchProviderChanged(
- const std::string& pref_name) {
- DCHECK_EQ(pref_name, std::string(prefs::kDefaultSearchProviderID));
+////////////////////////////////////////////////////////////////////////////////
+// BrowserInstantController, InstantServiceObserver implementation:
- Profile* browser_profile = profile();
- const TemplateURL* template_url =
- TemplateURLServiceFactory::GetForProfile(browser_profile)->
- GetDefaultSearchProvider();
- if (!template_url) {
- // A NULL |template_url| could mean either this notification is sent during
- // the browser start up operation or the user now has no default search
- // provider. There is no way for the user to reach this state using the
- // Chrome settings. Only explicitly poking at the DB or bugs in the Sync
- // could cause that, neither of which we support.
- return;
- }
+void BrowserInstantController::DefaultSearchProviderChanged() {
+ ReloadTabsInInstantProcess();
+}
+void BrowserInstantController::GoogleURLUpdated() {
+ ReloadTabsInInstantProcess();
+}
+
+void BrowserInstantController::ReloadTabsInInstantProcess() {
InstantService* instant_service =
- InstantServiceFactory::GetForProfile(browser_profile);
+ InstantServiceFactory::GetForProfile(profile());
if (!instant_service)
return;
diff --git a/chrome/browser/ui/browser_instant_controller.h b/chrome/browser/ui/browser_instant_controller.h
index 66598ef..a187a8c 100644
--- a/chrome/browser/ui/browser_instant_controller.h
+++ b/chrome/browser/ui/browser_instant_controller.h
@@ -9,7 +9,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "base/prefs/pref_change_registrar.h"
+#include "chrome/browser/search/instant_service_observer.h"
#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"
@@ -27,7 +27,8 @@
class Rect;
}
-class BrowserInstantController : public SearchModelObserver {
+class BrowserInstantController : public SearchModelObserver,
+ public InstantServiceObserver {
public:
explicit BrowserInstantController(Browser* browser);
virtual ~BrowserInstantController();
@@ -91,11 +92,13 @@
virtual void ModelChanged(const SearchModel::State& old_state,
const SearchModel::State& new_state) OVERRIDE;
- // 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 InstantServiceObserver:
+ virtual void DefaultSearchProviderChanged() OVERRIDE;
+ virtual void GoogleURLUpdated() OVERRIDE;
+
+ // Reloads the tabs in instant process to ensure that their privileged status
+ // is still valid.
+ void ReloadTabsInInstantProcess();
// Replaces the contents at tab |index| with |new_contents| and deletes the
// existing contents.
@@ -107,8 +110,6 @@
InstantController instant_;
InstantUnloadHandler instant_unload_handler_;
- PrefChangeRegistrar profile_pref_registrar_;
-
DISALLOW_COPY_AND_ASSIGN(BrowserInstantController);
};
diff --git a/chrome/browser/ui/browser_instant_controller_unittest.cc b/chrome/browser/ui/browser_instant_controller_unittest.cc
new file mode 100644
index 0000000..52540aa
--- /dev/null
+++ b/chrome/browser/ui/browser_instant_controller_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 <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_vector.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/search/instant_service.h"
+#include "chrome/browser/search/instant_service_observer.h"
+#include "chrome/browser/search/instant_unittest_base.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/browser/ui/browser_instant_controller.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace chrome {
+
+namespace {
+
+class BrowserInstantControllerTest : public InstantUnitTestBase {
+ protected:
+ friend class FakeWebContentsObserver;
+};
+
+const struct TabReloadTestCase {
+ const char* description;
+ const char* start_url;
+ bool start_in_instant_process;
+ bool should_reload;
+ bool end_in_instant_process;
+} kTabReloadTestCases[] = {
+ {"Local Embedded NTP", chrome::kChromeSearchLocalNtpUrl,
+ true, true, true},
+ {"Remote Embedded NTP", "https://www.google.com/instant?strk",
+ true, true, false},
+ {"Remote Embedded SERP", "https://www.google.com/url?strk&bar=search+terms",
+ true, true, false},
+ {"Other NTP", "https://bar.com/instant?strk",
+ false, false, false}
+};
+
+class FakeWebContentsObserver : public content::WebContentsObserver {
+ public:
+ FakeWebContentsObserver(BrowserInstantControllerTest* base_test,
+ content::WebContents* contents)
+ : WebContentsObserver(contents),
+ contents_(contents),
+ base_test_(base_test),
+ url_(contents->GetURL()),
+ num_reloads_(0) {}
+
+ virtual void NavigateToPendingEntry(
+ const GURL& url,
+ content::NavigationController::ReloadType reload_type) OVERRIDE {
+ // The tab reload event doesn't work with BrowserWithTestWindowTest.
+ // So we capture the NavigateToPendingEntry, and use the
+ // BrowserWithTestWindowTest::NavigateAndCommit to simulate the complete
+ // reload. Note that this will again trigger NavigateToPendingEntry, so we
+ // remove this as observer.
+ content::NavigationController* controller =
+ &web_contents()->GetController();
+ Observe(NULL);
+
+ if (url_ == url)
+ num_reloads_++;
+
+ base_test_->NavigateAndCommit(controller, url);
+ }
+
+ int num_reloads() const {
+ return num_reloads_;
+ }
+
+ content::WebContents* contents() {
+ return contents_;
+ }
+
+ protected:
+ friend class BrowserInstantControllerTest;
+ FRIEND_TEST_ALL_PREFIXES(BrowserInstantControllerTest,
+ DefaultSearchProviderChanged);
+ FRIEND_TEST_ALL_PREFIXES(BrowserInstantControllerTest,
+ GoogleBaseURLUpdated);
+
+ private:
+ content::WebContents* contents_;
+ BrowserInstantControllerTest* base_test_;
+ const GURL& url_;
+ int num_reloads_;
+};
+
+TEST_F(BrowserInstantControllerTest, DefaultSearchProviderChanged) {
+ size_t num_tests = arraysize(kTabReloadTestCases);
+ ScopedVector<FakeWebContentsObserver> observers;
+ for (size_t i = 0; i < num_tests; ++i) {
+ const TabReloadTestCase& test = kTabReloadTestCases[i];
+ AddTab(browser(), GURL(test.start_url));
+ content::WebContents* contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+
+ // Validate initial instant state.
+ EXPECT_EQ(test.start_in_instant_process,
+ instant_service_->IsInstantProcess(
+ contents->GetRenderProcessHost()->GetID()))
+ << test.description;
+
+ // Setup an observer to verify reload or absence thereof.
+ observers.push_back(new FakeWebContentsObserver(this, contents));
+ }
+
+ SetDefaultSearchProvider("https://bar.com/");
+
+ for (size_t i = 0; i < num_tests; ++i) {
+ FakeWebContentsObserver* observer = observers[i];
+ const TabReloadTestCase& test = kTabReloadTestCases[i];
+ content::WebContents* contents = observer->contents();
+
+ // Validate final instant state.
+ EXPECT_EQ(test.end_in_instant_process,
+ instant_service_->IsInstantProcess(
+ contents->GetRenderProcessHost()->GetID()))
+ << test.description;
+
+ // Ensure only the expected tabs(contents) reloaded.
+ EXPECT_EQ(test.should_reload ? 1 : 0, observer->num_reloads())
+ << test.description;
+ }
+}
+
+TEST_F(BrowserInstantControllerTest, GoogleBaseURLUpdated) {
+ const size_t num_tests = arraysize(kTabReloadTestCases);
+ ScopedVector<FakeWebContentsObserver> observers;
+ for (size_t i = 0; i < num_tests; ++i) {
+ const TabReloadTestCase& test = kTabReloadTestCases[i];
+ AddTab(browser(), GURL(test.start_url));
+ content::WebContents* contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+
+ // Validate initial instant state.
+ EXPECT_EQ(test.start_in_instant_process,
+ instant_service_->IsInstantProcess(
+ contents->GetRenderProcessHost()->GetID()))
+ << test.description;
+
+ // Setup an observer to verify reload or absence thereof.
+ observers.push_back(new FakeWebContentsObserver(this, contents));
+ }
+
+ NotifyGoogleBaseURLUpdate("https://www.google.es/");
+
+ for (size_t i = 0; i < num_tests; ++i) {
+ const TabReloadTestCase& test = kTabReloadTestCases[i];
+ FakeWebContentsObserver* observer = observers[i];
+ content::WebContents* contents = observer->contents();
+
+ // Validate final instant state.
+ EXPECT_EQ(test.end_in_instant_process,
+ instant_service_->IsInstantProcess(
+ contents->GetRenderProcessHost()->GetID()))
+ << test.description;
+
+ // Ensure only the expected tabs(contents) reloaded.
+ EXPECT_EQ(test.should_reload ? 1 : 0, observer->num_reloads())
+ << test.description;
+ }
+}
+
+TEST_F(BrowserInstantControllerTest, BrowserWindowLifecycle) {
+ scoped_ptr<BrowserWindow> window(CreateBrowserWindow());
+ Browser::CreateParams params(profile(), chrome::HOST_DESKTOP_TYPE_NATIVE);
+ params.window = window.get();
+ scoped_ptr<Browser> browser(new Browser(params));
+ InstantServiceObserver* bic;
+ bic = browser->instant_controller();
+ EXPECT_TRUE(IsInstantServiceObserver(bic))
+ << "New BrowserInstantController should register as InstantServiceObserver";
+
+ browser.reset(NULL);
+ window.reset(NULL);
+ EXPECT_FALSE(IsInstantServiceObserver(bic))
+ << "New BrowserInstantController should register as InstantServiceObserver";
+}
+
+} // namespace
+
+} // namespace chrome
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h
index 07bc569..f219b74 100644
--- a/chrome/browser/ui/browser_window.h
+++ b/chrome/browser/ui/browser_window.h
@@ -111,6 +111,14 @@
// Sets the starred state for the current tab.
virtual void SetStarredState(bool is_starred) = 0;
+ // Called when the active tab changes. Subclasses which implement
+ // TabStripModelObserver should implement this instead of ActiveTabChanged();
+ // the Browser will call this method while processing that one.
+ virtual void OnActiveTabChanged(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason) = 0;
+
// Called to force the zoom state to for the active tab to be recalculated.
// |can_show_bubble| is true when a user presses the zoom up or down keyboard
// shortcuts and will be false in other cases (e.g. switching tabs, "clicking"
diff --git a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.h b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.h
index 9125829..8250715 100644
--- a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.h
+++ b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.h
@@ -22,8 +22,11 @@
// The extension id of the currently focused packaged app.
base::scoped_nsobject<NSString> appId_;
// Items that need a doppelganger.
+ base::scoped_nsobject<DoppelgangerMenuItem> aboutDoppelganger_;
base::scoped_nsobject<DoppelgangerMenuItem> hideDoppelganger_;
base::scoped_nsobject<DoppelgangerMenuItem> quitDoppelganger_;
+ base::scoped_nsobject<DoppelgangerMenuItem> newDoppelganger_;
+ base::scoped_nsobject<DoppelgangerMenuItem> openDoppelganger_;
base::scoped_nsobject<DoppelgangerMenuItem> allToFrontDoppelganger_;
// Menu items for the currently focused packaged app.
base::scoped_nsobject<NSMenuItem> appMenuItem_;
diff --git a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm
index 52afc07..5f3cae9 100644
--- a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm
+++ b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm
@@ -145,7 +145,7 @@
- (void)addMenuItems:(const extensions::Extension*)app;
// If the window belongs to the currently focused app, remove the menu items and
// unhide Chrome menu items.
-- (void)removeMenuItems:(NSString*)appId;
+- (void)removeMenuItems;
// If the currently focused window belongs to a platform app, quit the app.
- (void)quitCurrentPlatformApp;
// If the currently focused window belongs to a platform app, hide the app.
@@ -170,6 +170,13 @@
}
- (void)buildAppMenuItems {
+ aboutDoppelganger_.reset([[DoppelgangerMenuItem alloc]
+ initWithController:self
+ menuTag:IDC_CHROME_MENU
+ itemTag:IDC_ABOUT
+ resourceId:IDS_ABOUT_MAC
+ action:nil
+ keyEquivalent:@""]);
hideDoppelganger_.reset([[DoppelgangerMenuItem alloc]
initWithController:self
menuTag:IDC_CHROME_MENU
@@ -184,6 +191,23 @@
resourceId:IDS_EXIT_MAC
action:@selector(quitCurrentPlatformApp)
keyEquivalent:@"q"]);
+ newDoppelganger_.reset([[DoppelgangerMenuItem alloc]
+ initWithController:self
+ menuTag:IDC_FILE_MENU
+ itemTag:IDC_NEW_WINDOW
+ resourceId:0
+ action:nil
+ keyEquivalent:@"n"]);
+ // For apps, the "Window" part of "New Window" is dropped to match the default
+ // menu set given to Cocoa Apps.
+ [[newDoppelganger_ menuItem] setTitle:l10n_util::GetNSString(IDS_NEW_MAC)];
+ openDoppelganger_.reset([[DoppelgangerMenuItem alloc]
+ initWithController:self
+ menuTag:IDC_FILE_MENU
+ itemTag:IDC_OPEN_FILE
+ resourceId:0
+ action:nil
+ keyEquivalent:@"o"]);
allToFrontDoppelganger_.reset([[DoppelgangerMenuItem alloc]
initWithController:self
menuTag:IDC_WINDOW_MENU
@@ -200,16 +224,29 @@
[appMenuItem_ setSubmenu:appMenu];
[appMenu setAutoenablesItems:NO];
+ [appMenu addItem:[aboutDoppelganger_ menuItem]];
+ [[aboutDoppelganger_ menuItem] setEnabled:NO]; // Not implemented yet.
+ [appMenu addItem:[NSMenuItem separatorItem]];
[appMenu addItem:[hideDoppelganger_ menuItem]];
[appMenu addItem:[NSMenuItem separatorItem]];
[appMenu addItem:[quitDoppelganger_ menuItem]];
// File menu.
fileMenuItem_.reset([NewTopLevelItemFrom(IDC_FILE_MENU) retain]);
+ [[fileMenuItem_ submenu] addItem:[newDoppelganger_ menuItem]];
+ [[fileMenuItem_ submenu] addItem:[openDoppelganger_ menuItem]];
+ [[fileMenuItem_ submenu] addItem:[NSMenuItem separatorItem]];
AddDuplicateItem(fileMenuItem_, IDC_FILE_MENU, IDC_CLOSE_WINDOW);
- // Edit menu. This is copied entirely.
+ // Edit menu. This copies the menu entirely and removes
+ // "Paste and Match Style" and "Find". This is because the last two items,
+ // "Start Dictation" and "Special Characters" are added by OSX, so we can't
+ // copy them explicitly.
editMenuItem_.reset([[[NSApp mainMenu] itemWithTag:IDC_EDIT_MENU] copy]);
+ NSMenu* editMenu = [editMenuItem_ submenu];
+ [editMenu removeItem:[editMenu
+ itemWithTag:IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE]];
+ [editMenu removeItem:[editMenu itemWithTag:IDC_FIND_MENU]];
// Window menu.
windowMenuItem_.reset([NewTopLevelItemFrom(IDC_WINDOW_MENU) retain]);
@@ -229,34 +266,31 @@
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(windowMainStatusChanged:)
- name:NSWindowDidResignMainNotification
- object:nil];
-
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(windowMainStatusChanged:)
name:NSWindowWillCloseNotification
object:nil];
}
- (void)windowMainStatusChanged:(NSNotification*)notification {
id window = [notification object];
- id windowController = [window windowController];
- if (![windowController isKindOfClass:[NativeAppWindowController class]])
- return;
-
- apps::ShellWindow* shellWindow =
- apps::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile(
- window);
- if (!shellWindow)
- return;
-
NSString* name = [notification name];
if ([name isEqualToString:NSWindowDidBecomeMainNotification]) {
- [self addMenuItems:shellWindow->extension()];
- } else if ([name isEqualToString:NSWindowDidResignMainNotification] ||
- [name isEqualToString:NSWindowWillCloseNotification]) {
- [self removeMenuItems:base::SysUTF8ToNSString(shellWindow->extension_id())];
+ apps::ShellWindow* shellWindow =
+ apps::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile(
+ window);
+ if (shellWindow)
+ [self addMenuItems:shellWindow->extension()];
+ else
+ [self removeMenuItems];
+ } else if ([name isEqualToString:NSWindowWillCloseNotification]) {
+ // If there are any other windows that can become main, leave the menu. It
+ // will be changed when another window becomes main. Otherwise, restore the
+ // Chrome menu.
+ for (NSWindow* w : [NSApp windows]) {
+ if ([w canBecomeMainWindow] && ![w isEqual:window])
+ return;
+ }
+
+ [self removeMenuItems];
} else {
NOTREACHED();
}
@@ -269,7 +303,7 @@
if ([appId_ isEqualToString:appId])
return;
- [self removeMenuItems:appId_];
+ [self removeMenuItems];
appId_.reset([appId copy]);
// Hide Chrome menu items.
@@ -277,8 +311,11 @@
for (NSMenuItem* item in [mainMenu itemArray])
[item setHidden:YES];
+ [aboutDoppelganger_ enableForApp:app];
[hideDoppelganger_ enableForApp:app];
[quitDoppelganger_ enableForApp:app];
+ [newDoppelganger_ enableForApp:app];
+ [openDoppelganger_ enableForApp:app];
[appMenuItem_ setTitle:appId];
[[appMenuItem_ submenu] setTitle:title];
@@ -289,8 +326,8 @@
[mainMenu addItem:windowMenuItem_];
}
-- (void)removeMenuItems:(NSString*)appId {
- if (![appId_ isEqualToString:appId])
+- (void)removeMenuItems {
+ if (!appId_)
return;
appId_.reset();
@@ -305,8 +342,11 @@
for (NSMenuItem* item in [mainMenu itemArray])
[item setHidden:NO];
+ [aboutDoppelganger_ disable];
[hideDoppelganger_ disable];
[quitDoppelganger_ disable];
+ [newDoppelganger_ disable];
+ [openDoppelganger_ disable];
}
- (void)quitCurrentPlatformApp {
diff --git a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm
index 8d282dd..09ca5fa 100644
--- a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm
+++ b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm
@@ -6,6 +6,7 @@
#import <Cocoa/Cocoa.h>
+#include "apps/native_app_window.h"
#include "apps/shell_window_registry.h"
#include "base/command_line.h"
#include "base/mac/scoped_nsobject.h"
@@ -14,6 +15,8 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_iterator.h"
+#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
@@ -104,18 +107,18 @@
object:app_2_shell_window->GetNativeWindow()];
CheckHasAppMenus(app_2_);
- // When the app window loses focus, the menu items for the app should be
+ // When a browser window is focused, the menu items for the app should be
// removed.
- [[NSNotificationCenter defaultCenter]
- postNotificationName:NSWindowDidResignMainNotification
- object:app_2_shell_window->GetNativeWindow()];
- CheckNoAppMenus();
-
- // When an app window is closed, the menu items for the app should be removed.
+ BrowserWindow* chrome_window = chrome::BrowserIterator()->window();
[[NSNotificationCenter defaultCenter]
postNotificationName:NSWindowDidBecomeMainNotification
- object:app_2_shell_window->GetNativeWindow()];
- CheckHasAppMenus(app_2_);
+ object:chrome_window->GetNativeWindow()];
+ CheckNoAppMenus();
+
+ // When an app window is closed and there are no other app windows, the menu
+ // items for the app should be removed.
+ app_1_shell_window->GetBaseWindow()->Close();
+ chrome_window->Close();
[[NSNotificationCenter defaultCenter]
postNotificationName:NSWindowWillCloseNotification
object:app_2_shell_window->GetNativeWindow()];
@@ -126,6 +129,17 @@
ExtensionUninstallUpdatesMenuBar) {
SetUpApps();
+ // This essentially tests that a NSWindowWillCloseNotification gets fired when
+ // an app is uninstalled. We need to close the other windows first since the
+ // menu only changes on a NSWindowWillCloseNotification if there are no other
+ // windows.
+ apps::ShellWindow* app_2_shell_window =
+ apps::ShellWindowRegistry::Get(profile())->
+ GetShellWindowsForApp(app_2_->id()).front();
+ app_2_shell_window->GetBaseWindow()->Close();
+
+ chrome::BrowserIterator()->window()->Close();
+
apps::ShellWindow* app_1_shell_window =
apps::ShellWindowRegistry::Get(profile())->
GetShellWindowsForApp(app_1_->id()).front();
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
index 4b0764b..43107fe 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
@@ -468,6 +468,8 @@
ui::WindowShowState NativeAppWindowCocoa::GetRestoredState() const {
if (IsMaximized())
return ui::SHOW_STATE_MAXIMIZED;
+ if (IsFullscreen())
+ return ui::SHOW_STATE_FULLSCREEN;
return ui::SHOW_STATE_NORMAL;
}
@@ -849,10 +851,12 @@
else if (NSEqualPoints(frame.origin, screen.origin))
is_maximized_ = true;
+ UpdateRestoredBounds();
shell_window_->OnNativeWindowChanged();
}
void NativeAppWindowCocoa::WindowDidMove() {
+ UpdateRestoredBounds();
shell_window_->OnNativeWindowChanged();
}
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm
index ee66dfe..e4b4694 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm
@@ -30,12 +30,7 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/platform_font.h"
-namespace {
-
const CGFloat kAccountChooserHeight = 20.0;
-const CGFloat kRelatedControlVerticalSpacing = 8.0;
-
-} // namespace;
namespace autofill {
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_overlay_controller.mm b/chrome/browser/ui/cocoa/autofill/autofill_overlay_controller.mm
index d571892..e159185 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_overlay_controller.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_overlay_controller.mm
@@ -72,7 +72,7 @@
- (CGFloat)heightForWidth:(CGFloat)width {
CGFloat height = kOverlayTextInterlineSpacing;
- for (NSTextView* label in [self subviews]) {
+ for (NSTextField* label in [self subviews]) {
height += NSHeight([label frame]);
height += kOverlayTextInterlineSpacing;
}
@@ -108,8 +108,8 @@
- (void)performLayout {
CGFloat y = NSMaxY([self bounds]) - autofill::kArrowHeight -
kOverlayTextInterlineSpacing;
- for (NSTextView* label in [self subviews]) {
- DCHECK([label isKindOfClass:[NSTextView class]]);
+ for (NSTextField* label in [self subviews]) {
+ DCHECK([label isKindOfClass:[NSTextField class]]);
CGFloat labelHeight = NSHeight([label frame]);
[label setFrame:NSMakeRect(0, y - labelHeight,
NSWidth([self bounds]), labelHeight)];
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 e7660fc..c4171cd 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_view_unittest.mm
@@ -161,4 +161,4 @@
ASSERT_FALSE([delegate didFire]);
[test_window() sendEvent:down_event];
EXPECT_TRUE([delegate didFire]);
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_sign_in_container.mm b/chrome/browser/ui/cocoa/autofill/autofill_sign_in_container.mm
index 63c3891..510b182 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_sign_in_container.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_sign_in_container.mm
@@ -30,7 +30,9 @@
signInDelegate_.reset(
new autofill::AutofillDialogSignInDelegate(
dialog_, webContents_.get(),
- dialog_->delegate()->GetWebContents()->GetDelegate()));
+ dialog_->delegate()->GetWebContents()->GetDelegate(),
+ // TODO(groby): Implement proper minimum and maximum sizing on Mac.
+ dialog_->GetSize(), dialog_->GetSize()));
NSView* webContentView = webContents_->GetView()->GetNativeView();
[self setView:webContentView];
}
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
index 9e30b1d..cced54a 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
@@ -11,7 +11,8 @@
#include "base/strings/sys_string_conversions.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/bookmarks/bookmark_node_data.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/profiles/profile.h"
@@ -672,7 +673,7 @@
if (!animate)
[self closeFolderAndStopTrackingMenus];
- bookmark_utils::RecordBookmarkLaunch([self bookmarkLaunchLocation]);
+ RecordBookmarkLaunch([self bookmarkLaunchLocation]);
}
// Common function to open a bookmark folder of any type.
@@ -682,7 +683,7 @@
// Only record the action if it's the initial folder being opened.
if (!showFolderMenus_)
- bookmark_utils::RecordBookmarkFolderOpen([self bookmarkLaunchLocation]);
+ RecordBookmarkFolderOpen([self bookmarkLaunchLocation]);
showFolderMenus_ = !showFolderMenus_;
if (sender == offTheSideButton_)
@@ -726,10 +727,10 @@
return (AnimatableView*)[self view];
}
-- (bookmark_utils::BookmarkLaunchLocation)bookmarkLaunchLocation {
+- (BookmarkLaunchLocation)bookmarkLaunchLocation {
return currentState_ == BookmarkBar::DETACHED ?
- bookmark_utils::LAUNCH_DETACHED_BAR :
- bookmark_utils::LAUNCH_ATTACHED_BAR;
+ BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR :
+ BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR;
}
// Position the right-side buttons including the off-the-side chevron.
@@ -1225,7 +1226,7 @@
WindowOpenDisposition disposition =
ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
[self openURL:GURL(chrome::kChromeUIAppsURL) disposition:disposition];
- bookmark_utils::RecordAppsPageOpen([self bookmarkLaunchLocation]);
+ RecordBookmarkAppsPageOpen([self bookmarkLaunchLocation]);
}
// To avoid problems with sync, changes that may impact the current
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 c530a23..5cc38da 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm
@@ -22,8 +22,6 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
-const CGFloat kBorderRadius = 3.0;
-
@interface BookmarkBarToolbarView (Private)
- (void)drawAsDetachedBubble;
@end
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controller.mm
index ba20edd..760c2dd 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controller.mm
@@ -126,7 +126,8 @@
}
[bookmarkBarController_ closeFolderAndStopTrackingMenus];
- [bookmarkBarController_ unhighlightBookmark:bookmarkNode_];
+ if (bookmarkNode_)
+ [bookmarkBarController_ unhighlightBookmark:bookmarkNode_];
}
- (void)cancelTracking {
diff --git a/chrome/browser/ui/cocoa/browser/avatar_label_button.h b/chrome/browser/ui/cocoa/browser/avatar_label_button.h
index 6244c27..7584c14 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_label_button.h
+++ b/chrome/browser/ui/cocoa/browser/avatar_label_button.h
@@ -8,13 +8,12 @@
#import <Cocoa/Cocoa.h>
#import "base/mac/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/nine_part_button_cell.h"
@interface AvatarLabelButton : NSButton
@end
// Draws the button cell for the avatar label.
-@interface AvatarLabelButtonCell : NinePartButtonCell
+@interface AvatarLabelButtonCell : NSButtonCell
// Returns the size of the label text (including boundaries).
- (NSSize)labelTextSize;
diff --git a/chrome/browser/ui/cocoa/browser/avatar_label_button.mm b/chrome/browser/ui/cocoa/browser/avatar_label_button.mm
index a37d011..6ae29f0 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_label_button.mm
+++ b/chrome/browser/ui/cocoa/browser/avatar_label_button.mm
@@ -8,6 +8,7 @@
#include "chrome/browser/ui/cocoa/themed_window.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "ui/base/cocoa/appkit_utils.h"
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/theme_provider.h"
@@ -35,6 +36,9 @@
- (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect])) {
+ [self setBezelStyle:NSSmallSquareBezelStyle];
+ [self setTitle:l10n_util::GetNSString(IDS_MANAGED_USER_AVATAR_LABEL)];
+ [self setFont:[NSFont labelFontOfSize:12.0]];
// Increase the frame by the size of the label to be displayed.
NSSize textSize = [[self cell] labelTextSize];
frameRect.size = NSMakeSize(frameRect.size.width + textSize.width,
@@ -52,24 +56,6 @@
@implementation AvatarLabelButtonCell
-- (id)init {
- const int resourceIds[9] = {
- IDR_MANAGED_USER_LABEL_TOP_LEFT, IDR_MANAGED_USER_LABEL_TOP,
- IDR_MANAGED_USER_LABEL_TOP_RIGHT, IDR_MANAGED_USER_LABEL_LEFT,
- IDR_MANAGED_USER_LABEL_CENTER, IDR_MANAGED_USER_LABEL_RIGHT,
- IDR_MANAGED_USER_LABEL_BOTTOM_LEFT, IDR_MANAGED_USER_LABEL_BOTTOM,
- IDR_MANAGED_USER_LABEL_BOTTOM_RIGHT
- };
- if ((self = [super initWithResourceIds:resourceIds])) {
- NSString* title = l10n_util::GetNSString(IDS_MANAGED_USER_AVATAR_LABEL);
- [self accessibilitySetOverrideValue:title
- forAttribute:NSAccessibilityTitleAttribute];
- [self setTitle:title];
- [self setFont:[NSFont labelFontOfSize:12.0]];
- }
- return self;
-}
-
- (NSSize)labelTextSize {
NSSize size = [[self attributedTitle] size];
size.width += kLabelTextLeftSpacing + kLabelTextRightSpacing;
@@ -77,6 +63,21 @@
return size;
}
+- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView {
+ ui::NinePartImageIds imageIds = {
+ IDR_MANAGED_USER_LABEL_TOP_LEFT,
+ IDR_MANAGED_USER_LABEL_TOP,
+ IDR_MANAGED_USER_LABEL_TOP_RIGHT,
+ IDR_MANAGED_USER_LABEL_LEFT,
+ IDR_MANAGED_USER_LABEL_CENTER,
+ IDR_MANAGED_USER_LABEL_RIGHT,
+ IDR_MANAGED_USER_LABEL_BOTTOM_LEFT,
+ IDR_MANAGED_USER_LABEL_BOTTOM,
+ IDR_MANAGED_USER_LABEL_BOTTOM_RIGHT
+ };
+ ui::DrawNinePartImage(frame, imageIds, NSCompositeSourceOver, 1.0, true);
+}
+
- (NSRect)titleRectForBounds:(NSRect)theRect {
theRect.origin = NSMakePoint(kLabelTextLeftSpacing, kLabelTextBottomSpacing);
theRect.size = [[self attributedTitle] size];
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 b0eb8f0..2f8465a 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h
@@ -12,15 +12,15 @@
#import "chrome/browser/ui/cocoa/base_bubble_controller.h"
#import "ui/base/cocoa/tracking_area.h"
-class AvatarMenuModel;
+class AvatarMenu;
class Browser;
// This window controller manages the bubble that displays a "menu" of profiles.
// It is brought open by clicking on the avatar icon in the window frame.
@interface AvatarMenuBubbleController : BaseBubbleController {
@private
- // The model that contains the data from the backend.
- scoped_ptr<AvatarMenuModel> model_;
+ // The menu that contains the data from the backend.
+ scoped_ptr<AvatarMenu> menu_;
// Array of the below view controllers.
base::scoped_nsobject<NSMutableArray> items_;
@@ -29,7 +29,7 @@
BOOL expanded_;
}
-// Designated initializer. The browser is passed to the model for profile
+// Designated initializer. The browser is passed to the menu for profile
// information.
- (id)initWithBrowser:(Browser*)parentBrowser
anchoredAt:(NSPoint)point;
@@ -57,8 +57,8 @@
// The parent menu controller; owns this.
__weak AvatarMenuBubbleController* controller_;
- // The AvatarMenuModel::item.model_index field.
- size_t modelIndex_;
+ // The index of the item in the AvatarMenu.
+ size_t menuIndex_;
// Tracks whether this item is currently highlighted.
BOOL isHighlighted_;
@@ -77,7 +77,7 @@
__weak NSTextField* emailField_;
__weak NSButton* editButton_;
}
-@property(readonly, nonatomic) size_t modelIndex;
+@property(readonly, nonatomic) size_t menuIndex;
@property(assign, nonatomic) BOOL isHighlighted;
@property(assign, nonatomic) IBOutlet NSImageView* iconView;
@property(assign, nonatomic) IBOutlet NSImageView* activeView;
@@ -86,7 +86,7 @@
@property(assign, nonatomic) IBOutlet NSButton* editButton;
// Designated initializer.
-- (id)initWithModelIndex:(size_t)modelIndex
+- (id)initWithMenuIndex:(size_t)menuIndex
menuController:(AvatarMenuBubbleController*)controller;
// Actions that are forwarded to the |controller_|.
@@ -127,7 +127,7 @@
// Testing API /////////////////////////////////////////////////////////////////
@interface AvatarMenuBubbleController (ExposedForTesting)
-- (id)initWithModel:(AvatarMenuModel*)model
+- (id)initWithMenu:(AvatarMenu*)menu
parentWindow:(NSWindow*)parent
anchoredAt:(NSPoint)point;
- (void)performLayout;
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 f0ed688..0f635be 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.mm
@@ -8,7 +8,7 @@
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
@@ -25,7 +25,7 @@
#include "ui/gfx/image/image.h"
@interface AvatarMenuBubbleController (Private)
-- (AvatarMenuModel*)model;
+- (AvatarMenu*)menu;
- (NSView*)configureManagedUserInformation:(CGFloat)width;
- (NSButton*)configureNewUserButton:(CGFloat)yOffset
updateWidthAdjust:(CGFloat*)widthAdjust;
@@ -72,11 +72,12 @@
// to be positioned incorrectly. Since the bubble will be dismissed on losing
// key status, it's impossible for the user to edit the information in a
// meaningful way such that it would need to be redrawn.
- AvatarMenuModel* model = new AvatarMenuModel(
+ AvatarMenu* menu = new AvatarMenu(
&g_browser_process->profile_manager()->GetProfileInfoCache(),
NULL, parentBrowser);
+ menu->RebuildMenu();
- if ((self = [self initWithModel:model
+ if ((self = [self initWithMenu:menu
parentWindow:parentBrowser->window()->GetNativeWindow()
anchoredAt:point])) {
}
@@ -84,18 +85,18 @@
}
- (IBAction)newProfile:(id)sender {
- model_->AddNewProfile(ProfileMetrics::ADD_NEW_USER_ICON);
+ menu_->AddNewProfile(ProfileMetrics::ADD_NEW_USER_ICON);
}
- (IBAction)switchToProfile:(id)sender {
// Check the event flags to see if a new window should be crated.
bool always_create = ui::WindowOpenDispositionFromNSEvent(
[NSApp currentEvent]) == NEW_WINDOW;
- model_->SwitchToProfile([sender modelIndex], always_create);
+ menu_->SwitchToProfile([sender menuIndex], always_create);
}
- (IBAction)editProfile:(id)sender {
- model_->EditProfile([sender modelIndex]);
+ menu_->EditProfile([sender menuIndex]);
}
- (IBAction)switchProfile:(id)sender {
@@ -105,7 +106,7 @@
// Private /////////////////////////////////////////////////////////////////////
-- (id)initWithModel:(AvatarMenuModel*)model
+- (id)initWithMenu:(AvatarMenu*)menu
parentWindow:(NSWindow*)parent
anchoredAt:(NSPoint)point {
// Use an arbitrary height because it will reflect the size of the content.
@@ -119,7 +120,7 @@
if ((self = [super initWithWindow:window
parentWindow:parent
anchoredAt:point])) {
- model_.reset(model);
+ menu_.reset(menu);
[window accessibilitySetOverrideValue:
l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_NAME)
@@ -138,11 +139,11 @@
updateWidthAdjust:(CGFloat*)widthAdjust
setYOffset:(CGFloat)yOffset {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- const AvatarMenuModel::Item& item = model_->GetItemAt(itemIndex);
+ const AvatarMenu::Item& item = menu_->GetItemAt(itemIndex);
// Create the item view controller. Autorelease it because it will be owned
// by the |items_| array.
AvatarMenuItemController* itemView =
- [[[AvatarMenuItemController alloc] initWithModelIndex:item.model_index
+ [[[AvatarMenuItemController alloc] initWithMenuIndex:itemIndex
menuController:self] autorelease];
itemView.iconView.image = item.icon.ToNSImage();
@@ -213,7 +214,7 @@
CGFloat yOffset = kLinkSpacing;
CGFloat widthAdjust = 0;
- if (model_->ShouldShowAddNewProfileLink()) {
+ if (menu_->ShouldShowAddNewProfileLink()) {
// Since drawing happens bottom-up, start with the "New User" link.
NSButton* newButton =
[self configureNewUserButton:yOffset updateWidthAdjust:&widthAdjust];
@@ -231,7 +232,7 @@
}
// Loop over the profiles in reverse, constructing the menu items.
- for (int i = model_->GetNumberOfItems() - 1; i >= 0; --i) {
+ for (int i = menu_->GetNumberOfItems() - 1; i >= 0; --i) {
AvatarMenuItemController* itemView = [self initAvatarItem:i
updateWidthAdjust:&widthAdjust
setYOffset:yOffset];
@@ -269,7 +270,7 @@
// will have to adjust its frame later after adding general information about
// managed users.
AvatarMenuItemController* itemView =
- [self initAvatarItem:model_->GetActiveProfileIndex()
+ [self initAvatarItem:menu_->GetActiveProfileIndex()
updateWidthAdjust:&widthAdjust
setYOffset:yOffset];
@@ -308,7 +309,7 @@
items_.reset([[NSMutableArray alloc] init]);
[contentView setSubviews:[NSArray array]];
- if (model_->GetManagedUserInformation().empty() || expanded_)
+ if (menu_->GetManagedUserInformation().empty() || expanded_)
[self initMenuContents];
else
[self initManagedUserContents];
@@ -321,11 +322,11 @@
// Add the limited user icon on the left side of the information TextView.
base::scoped_nsobject<NSImageView> iconView(
[[NSImageView alloc] initWithFrame:NSMakeRect(5, 0, 16, 16)]);
- [iconView setImage:model_->GetManagedUserIcon().ToNSImage()];
+ [iconView setImage:menu_->GetManagedUserIcon().ToNSImage()];
[container addSubview:iconView];
NSString* info =
- base::SysUTF16ToNSString(model_->GetManagedUserInformation());
+ base::SysUTF16ToNSString(menu_->GetManagedUserInformation());
NSDictionary* attributes =
@{ NSFontAttributeName : [NSFont labelFontOfSize:12] };
base::scoped_nsobject<NSAttributedString> attrString(
@@ -463,7 +464,7 @@
@implementation AvatarMenuItemController
-@synthesize modelIndex = modelIndex_;
+@synthesize menuIndex = menuIndex_;
@synthesize isHighlighted = isHighlighted_;
@synthesize iconView = iconView_;
@synthesize activeView = activeView_;
@@ -471,11 +472,11 @@
@synthesize emailField = emailField_;
@synthesize editButton = editButton_;
-- (id)initWithModelIndex:(size_t)modelIndex
+- (id)initWithMenuIndex:(size_t)menuIndex
menuController:(AvatarMenuBubbleController*)controller {
if ((self = [super initWithNibName:@"AvatarMenuItem"
bundle:base::mac::FrameworkBundle()])) {
- modelIndex_ = modelIndex;
+ menuIndex_ = menuIndex;
controller_ = controller;
[self loadView];
[nameField_ setAutoresizingMask:NSViewNotSizable];
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 e91fb3b..1f7d23f 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
@@ -9,8 +9,8 @@
#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/avatar_menu.h"
+#include "chrome/browser/profiles/avatar_menu_observer.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
#include "chrome/test/base/testing_browser_process.h"
@@ -34,19 +34,20 @@
manager_.CreateTestingProfile("test2", scoped_ptr<PrefServiceSyncable>(),
ASCIIToUTF16("Test 2"), 0, std::string());
- model_ = new AvatarMenuModel(manager_.profile_info_cache(), NULL, NULL);
+ menu_ = new AvatarMenu(manager_.profile_info_cache(), NULL, NULL);
+ menu_->RebuildMenu();
NSRect frame = [test_window() frame];
NSPoint point = NSMakePoint(NSMidX(frame), NSMidY(frame));
controller_ =
- [[AvatarMenuBubbleController alloc] initWithModel:model()
+ [[AvatarMenuBubbleController alloc] initWithMenu:menu()
parentWindow:test_window()
anchoredAt:point];
}
TestingProfileManager* manager() { return &manager_; }
AvatarMenuBubbleController* controller() { return controller_; }
- AvatarMenuModel* model() { return model_; }
+ AvatarMenu* menu() { return menu_; }
AvatarMenuItemController* GetHighlightedItem() {
for (AvatarMenuItemController* item in [controller() items]) {
@@ -63,7 +64,7 @@
AvatarMenuBubbleController* controller_;
// Weak; owned by |controller_|.
- AvatarMenuModel* model_;
+ AvatarMenu* menu_;
};
TEST_F(AvatarMenuBubbleControllerTest, InitialLayout) {
@@ -182,7 +183,7 @@
TEST_F(AvatarMenuBubbleControllerTest, HighlightForEventType) {
base::scoped_nsobject<TestingAvatarMenuItemController> item(
- [[TestingAvatarMenuItemController alloc] initWithModelIndex:0
+ [[TestingAvatarMenuItemController alloc] initWithMenuIndex:0
menuController:nil]);
// Test non-active states first.
[[item activeView] setHidden:YES];
diff --git a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm
index 3880b11..cc4193c 100644
--- a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm
@@ -97,7 +97,7 @@
trackingArea_.reset([[CrTrackingArea alloc]
initWithRect:NSZeroRect
options:NSTrackingMouseEnteredAndExited |
- NSTrackingActiveInKeyWindow |
+ NSTrackingActiveAlways |
NSTrackingInVisibleRect
owner:self
userInfo:nil]);
@@ -304,14 +304,26 @@
- (void)drawRect:(NSRect)rect {
NSRect bounds = [self bounds];
+ NSAttributedString* title = [self attributedTitle];
if ([self hoverState] != kHoverStateNone) {
ui::NativeTheme* nativeTheme = ui::NativeTheme::instance();
[gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor(
ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor)) set];
NSRectFillUsingOperation(bounds, NSCompositeSourceOver);
+
+ // Change the title color.
+ base::scoped_nsobject<NSMutableAttributedString> selectedTitle(
+ [[NSMutableAttributedString alloc] initWithAttributedString:title]);
+ NSColor* selectedTitleColor =
+ gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor(
+ ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor));
+ [selectedTitle addAttribute:NSForegroundColorAttributeName
+ value:selectedTitleColor
+ range:NSMakeRange(0, [title length])];
+ title = selectedTitle.autorelease();
}
- [[self cell] drawTitle:[self attributedTitle]
+ [[self cell] drawTitle:title
withFrame:bounds
inView:self];
}
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h
index 44d1447..efd9e94 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h
@@ -58,6 +58,10 @@
virtual void UpdateDevTools() OVERRIDE;
virtual void UpdateLoadingAnimations(bool should_animate) OVERRIDE;
virtual void SetStarredState(bool is_starred) OVERRIDE;
+ virtual void OnActiveTabChanged(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason) OVERRIDE;
virtual void ZoomChangedForActiveTab(bool can_show_bubble) OVERRIDE;
virtual gfx::Rect GetRestoredBounds() const OVERRIDE;
virtual ui::WindowShowState GetRestoredState() const OVERRIDE;
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
index be60f5f..a26e674 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -305,6 +305,17 @@
[controller_ setStarredState:is_starred ? YES : NO];
}
+void BrowserWindowCocoa::OnActiveTabChanged(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason) {
+ // TODO(pkasting): Perhaps the code in
+ // TabStripController::activateTabWithContents should move here? Or this
+ // should call that (instead of TabStripModelObserverBridge doing so)? It's
+ // not obvious to me why Mac doesn't handle tab changes in BrowserWindow the
+ // way views and GTK do.
+}
+
void BrowserWindowCocoa::ZoomChangedForActiveTab(bool can_show_bubble) {
[controller_ zoomChangedForActiveTab:can_show_bubble ? YES : NO];
}
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 9d73a30..58048b9 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -17,7 +17,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/fullscreen.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -1503,7 +1503,7 @@
return NO;
}
- return AvatarMenuModel::ShouldShowAvatarMenu();
+ return AvatarMenu::ShouldShowAvatarMenu();
}
- (BOOL)isBookmarkBarVisible {
diff --git a/chrome/browser/ui/cocoa/confirm_bubble_cocoa.mm b/chrome/browser/ui/cocoa/confirm_bubble_cocoa.mm
index 474bf21..d8fd880 100644
--- a/chrome/browser/ui/cocoa/confirm_bubble_cocoa.mm
+++ b/chrome/browser/ui/cocoa/confirm_bubble_cocoa.mm
@@ -13,8 +13,6 @@
#include "ui/gfx/image/image.h"
#include "ui/gfx/point.h"
-namespace {
-
// The width for the message text. We break lines so the specified message fits
// into this width.
const int kMaxMessageWidth = 400;
@@ -36,9 +34,6 @@
// Vertical spacing between controls that are logically related.
const int kRelatedControlVerticalSpacing = 8;
-// Horizontal spacing between controls that are logically unrelated.
-const int kUnrelatedControlHorizontalSpacing = 12;
-
// Vertical spacing between the edge of the window and the
// top or bottom of a button.
const int kButtonVEdgeMargin = 6;
@@ -47,8 +42,6 @@
// left or right of a button.
const int kButtonHEdgeMargin = 7;
-} // namespace
-
namespace chrome {
void ShowConfirmBubble(gfx::NativeView view,
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 39e4a3f..eed5dbb 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_button.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_button.mm
@@ -199,7 +199,7 @@
{
gfx::ScopedNSGraphicsContextSaveGState scopedGState;
[GetButtonShadow(buttonState) set];
- [[NSColor blackColor] set];
+ [[[controlView window] backgroundColor] set];
[path fill];
}
[GetButtonGradient(buttonState) drawInBezierPath:path angle:90.0];
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 6ac1b02..ef4eadd 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
@@ -45,10 +45,6 @@
// Height of the "Clear" button in the geolocation bubble.
const int kGeoClearButtonHeight = 17;
-// Padding between radio buttons and "Load all plugins" button
-// in the plugin bubble.
-const int kLoadAllPluginsButtonVerticalPadding = 8;
-
// General padding between elements in the geolocation bubble.
const int kGeoPadding = 8;
@@ -112,7 +108,8 @@
// longgest item as the width of the popup menu.
CGFloat BuildPopUpMenuFromModel(NSPopUpButton* button,
ContentSettingMediaMenuModel* model,
- const std::string& title) {
+ const std::string& title,
+ bool disabled) {
[[button cell] setControlSize:NSSmallControlSize];
[[button cell] setArrowPosition:NSPopUpArrowAtBottom];
[button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
@@ -152,6 +149,11 @@
[button setEnabled:NO];
} else {
SetTitleForPopUpButton(button, base::SysUTF8ToNSString(title));
+
+ // Disable the device selection when the website is managing the devices
+ // itself.
+ if (disabled)
+ [button setEnabled:NO];
}
return menuWidth;
@@ -524,7 +526,7 @@
[cell setAlignment:NSRightTextAlignment];
[GTMUILocalizerAndLayoutTweaker sizeToFitView:label];
maxLabelWidth = std::max(maxLabelWidth, [label frame].size.width);
- [[self bubble] addSubview:label];
+ [[self bubble] addSubview:label];
// |buttonFrame| will be resized and repositioned later on.
NSRect buttonFrame = NSMakeRect(NSMinX(radioFrame), 0, 0, 0);
@@ -542,7 +544,8 @@
mediaMenus_[button] = menuParts;
CGFloat width = BuildPopUpMenuFromModel(button,
menuParts->model.get(),
- it->second.selected_device.name);
+ it->second.selected_device.name,
+ it->second.disabled);
maxMenuWidth = std::max(maxMenuWidth, width);
[[self bubble] addSubview:button
@@ -552,7 +555,7 @@
maxMenuHeight = std::max(maxMenuHeight, [button frame].size.height);
}
- // Make room for the media menu(s) and enlarege the windows to fit the views.
+ // Make room for the media menu(s) and enlarge the windows to fit the views.
// The bubble view and its subviews autosize themselves when the window is
// enlarged.
int delta = media_menus.size() * maxMenuHeight +
diff --git a/chrome/browser/ui/cocoa/download/download_item_cell.mm b/chrome/browser/ui/cocoa/download/download_item_cell.mm
index 4928951..03a37fc 100644
--- a/chrome/browser/ui/cocoa/download/download_item_cell.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_cell.mm
@@ -51,9 +51,6 @@
// y coordinate of status message, in view coords.
const CGFloat kSecondaryTextPosTop = 18;
-// Grey value of status text.
-const CGFloat kSecondaryTextColor = 0.5;
-
// Width of dropdown area on the right (includes 1px for the border on each
// side).
const CGFloat kDropdownAreaWidth = 14;
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 63b1efa..59794fe 100644
--- a/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.mm
@@ -136,10 +136,12 @@
y_pos = CreateAttachedCheckboxes(y_pos, controller_->AttachedPermissions());
- y_pos = CreateCheckboxSeparator(y_pos);
+ if (!controller_->UnattachedPermissions().empty()) {
+ y_pos = CreateCheckboxSeparator(y_pos);
- y_pos = CreateUnattachedCheckboxes(
- y_pos, controller_->UnattachedPermissions());
+ y_pos = CreateUnattachedCheckboxes(
+ y_pos, controller_->UnattachedPermissions());
+ }
[checkbox_container_ setFrame:NSMakeRect(0, 0, kCheckboxMaxWidth, y_pos + 2)];
@@ -296,6 +298,7 @@
[checkbox setAction:@selector(onCheckboxToggled:)];
[checkboxes_ addObject:checkbox];
+ // TODO(gbillock): Would be nice to add middle text elide behavior here.
[checkbox setTitle:base::SysUTF16ToNSString(
gallery.GetGalleryDisplayName())];
[checkbox setToolTip:base::SysUTF16ToNSString(gallery.GetGalleryTooltip())];
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 82b0bf0..7c669d5 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
@@ -24,10 +24,6 @@
// Assumes -setFlipped:YES.
const NSInteger kResultsYOffset = 4;
-// How far the editor insets itself, for purposes of determining if
-// decorations need to be trimmed.
-const CGFloat kEditorHorizontalInset = 3.0;
-
// Conveniences to centralize width+offset calculations.
CGFloat WidthForResults(NSAttributedString* resultsString) {
return kResultsXOffset + ceil([resultsString size].width) +
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 249ff56..0648bbd 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
@@ -26,9 +26,6 @@
// the time.
const CGFloat kWidth(300.0);
-// A narrow width for tests which test things that don't fit.
-const CGFloat kNarrowWidth(5.0);
-
class FindBarTextFieldCellTest : public CocoaTest {
public:
FindBarTextFieldCellTest() {
diff --git a/chrome/browser/ui/cocoa/hyperlink_text_view.mm b/chrome/browser/ui/cocoa/hyperlink_text_view.mm
index 178d6a2..0a2ac49 100644
--- a/chrome/browser/ui/cocoa/hyperlink_text_view.mm
+++ b/chrome/browser/ui/cocoa/hyperlink_text_view.mm
@@ -76,6 +76,7 @@
// addAttributes for text that has NSLinkAttributeName. Set to nil to allow
// custom attributes to take precendence.
[self setLinkTextAttributes:nil];
+ [self setDisplaysLinkToolTips:NO];
}
- (void)fixupCursor {
diff --git a/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.mm b/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.mm
index 2df80ef..c50a25b 100644
--- a/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.mm
+++ b/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.mm
@@ -28,8 +28,6 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
-namespace {
-const CGFloat kAnimationDuration = 0.12;
const CGFloat kBottomBorderHeightPx = 1.0;
const CGFloat kButtonHeightPx = 26.0;
const CGFloat kButtonLeftMarginPx = 2.0;
@@ -37,7 +35,6 @@
const CGFloat kDropArrowLeftMarginPx = 3.0;
const CGFloat kToolbarMinHeightPx = 36.0;
const CGFloat kToolbarMaxHeightPx = 72.0;
-} // namespace
@interface ExtensionInfoBarController(Private)
// Called when the extension's hosted NSView has been resized.
@@ -109,7 +106,7 @@
scoped_ptr<gfx::Canvas> canvas(
new gfx::Canvas(
gfx::Size(image_size + kDropArrowLeftMarginPx + drop_image->width(),
- image_size), ui::SCALE_FACTOR_100P, false));
+ image_size), 1.0f, false));
canvas->DrawImageInt(*icon,
0, 0, icon->width(), icon->height(),
0, 0, image_size, image_size,
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h
index fdaefae..2dbe1c3 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h
@@ -26,8 +26,13 @@
// If YES then the text field will not draw a focus ring or show the insertion
// pointer.
BOOL hideFocusState_;
+
+ // YES if this field is shown in a popup window.
+ BOOL isPopupMode_;
}
+@property(assign, nonatomic) BOOL isPopupMode;
+
// Line height used for text in this cell.
- (CGFloat)lineHeight;
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 ac53430..1f0b755 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
@@ -13,8 +13,11 @@
#import "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
#import "chrome/browser/ui/cocoa/nsview_additions.h"
#import "chrome/common/extensions/feature_switch.h"
+#include "grit/theme_resources.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
+#import "ui/base/cocoa/appkit_utils.h"
#import "ui/base/cocoa/tracking_area.h"
+#include "ui/base/resource/resource_bundle.h"
using extensions::FeatureSwitch;
@@ -28,6 +31,30 @@
NSString* const kButtonDecorationKey = @"ButtonDecoration";
+const ui::NinePartImageIds kPopupBorderImageIds = {
+ IDR_OMNIBOX_POPUP_BORDER_TOP_LEFT,
+ IDR_OMNIBOX_POPUP_BORDER_TOP,
+ IDR_OMNIBOX_POPUP_BORDER_TOP_RIGHT,
+ IDR_OMNIBOX_POPUP_BORDER_LEFT,
+ IDR_OMNIBOX_POPUP_BORDER_CENTER,
+ IDR_OMNIBOX_POPUP_BORDER_RIGHT,
+ IDR_OMNIBOX_POPUP_BORDER_BOTTOM_LEFT,
+ IDR_OMNIBOX_POPUP_BORDER_BOTTOM,
+ IDR_OMNIBOX_POPUP_BORDER_BOTTOM_RIGHT
+};
+
+const ui::NinePartImageIds kNormalBorderImageIds = {
+ IDR_OMNIBOX_BORDER_TOP_LEFT,
+ IDR_OMNIBOX_BORDER_TOP,
+ IDR_OMNIBOX_BORDER_TOP_RIGHT,
+ IDR_OMNIBOX_BORDER_LEFT,
+ IDR_OMNIBOX_BORDER_CENTER,
+ IDR_OMNIBOX_BORDER_RIGHT,
+ IDR_OMNIBOX_BORDER_BOTTOM_LEFT,
+ IDR_OMNIBOX_BORDER_BOTTOM,
+ IDR_OMNIBOX_BORDER_BOTTOM_RIGHT
+};
+
// How far to inset the right-hand decorations from the field's bounds.
// TODO(shess): Why is this different from |kLeftDecorationXOffset|?
// |kDecorationOuterXOffset|?
@@ -184,6 +211,8 @@
@implementation AutocompleteTextFieldCell
+@synthesize isPopupMode = isPopupMode_;
+
- (CGFloat)topTextFrameOffset {
return 3.0;
}
@@ -324,6 +353,45 @@
return NSMakeRect(minX, NSMinY(textFrame), maxX - minX, NSHeight(textFrame));
}
+- (void)drawWithFrame:(NSRect)frame inView:(NSView*)controlView {
+ // Background color.
+ const CGFloat lineWidth = [controlView cr_lineWidth];
+ if (isPopupMode_) {
+ [[self backgroundColor] set];
+ NSRectFillUsingOperation(NSInsetRect(frame, 1, 1), NSCompositeSourceOver);
+ } else {
+ CGFloat insetSize = lineWidth == 0.5 ? 1.5 : 2.0;
+ NSRect fillRect = NSInsetRect(frame, insetSize, insetSize);
+ [[self backgroundColor] set];
+ [[NSBezierPath bezierPathWithRoundedRect:fillRect
+ xRadius:kCornerRadius
+ yRadius:kCornerRadius] fill];
+ }
+
+ // Border.
+ ui::DrawNinePartImage(frame,
+ isPopupMode_ ? kPopupBorderImageIds
+ : kNormalBorderImageIds,
+ NSCompositeSourceOver,
+ 1.0,
+ true);
+
+ // Interior contents.
+ [self drawInteriorWithFrame:frame inView:controlView];
+
+ // Focus ring.
+ if ([self showsFirstResponder]) {
+ NSRect focusRingRect = NSInsetRect(frame, lineWidth, lineWidth);
+ [[[NSColor keyboardFocusIndicatorColor]
+ colorWithAlphaComponent:0.5 / lineWidth] set];
+ NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:focusRingRect
+ xRadius:kCornerRadius
+ yRadius:kCornerRadius];
+ [path setLineWidth:lineWidth * 2.0];
+ [path stroke];
+ }
+}
+
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
std::vector<LocationBarDecoration*> decorations;
std::vector<NSRect> decorationFrames;
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 def7ede..9e792ab 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
@@ -33,9 +33,6 @@
// the time.
const CGFloat kWidth(300.0);
-// A narrow width for tests which test things that don't fit.
-const CGFloat kNarrowWidth(5.0);
-
class MockDecoration : public LocationBarDecoration {
public:
virtual CGFloat GetWidthForSpace(CGFloat width) { return 20.0; }
diff --git a/chrome/browser/ui/cocoa/location_bar/bubble_decoration.h b/chrome/browser/ui/cocoa/location_bar/bubble_decoration.h
index 6a1d1cc..21aaac1 100644
--- a/chrome/browser/ui/cocoa/location_bar/bubble_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/bubble_decoration.h
@@ -10,6 +10,7 @@
#include "base/gtest_prod_util.h"
#include "base/mac/scoped_nsobject.h"
#include "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
+#import "ui/base/cocoa/appkit_utils.h"
// Draws an outlined rounded rect, with an optional image to the left
// and an optional text label to the right.
@@ -23,12 +24,14 @@
NSImage* GetImage();
void SetImage(NSImage* image);
void SetLabel(NSString* label);
- void SetColors(NSColor* border_color,
- NSColor* background_color,
- NSColor* text_color);
+ void SetTextColor(NSColor* text_color);
+ virtual ui::NinePartImageIds GetBubbleImageIds() = 0;
// Implement |LocationBarDecoration|.
virtual void DrawInFrame(NSRect frame, NSView* control_view) OVERRIDE;
+ virtual void DrawWithBackgroundInFrame(NSRect background_frame,
+ NSRect frame,
+ NSView* control_view) OVERRIDE;
virtual CGFloat GetWidthForSpace(CGFloat width) OVERRIDE;
protected:
@@ -54,11 +57,6 @@
// Contains attribute for drawing |label_|.
base::scoped_nsobject<NSMutableDictionary> attributes_;
- // Colors used to draw the bubble, should be set by the subclass
- // constructor.
- 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/bubble_decoration.mm b/chrome/browser/ui/cocoa/location_bar/bubble_decoration.mm
index 155c42f..df70ed9 100644
--- a/chrome/browser/ui/cocoa/location_bar/bubble_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/bubble_decoration.mm
@@ -10,19 +10,12 @@
namespace {
+// This is used to increase the right margin of this decoration.
+const CGFloat kRightSideMargin = 1.0;
+
// Padding between the icon/label and bubble edges.
const CGFloat kBubblePadding = 3.0;
-// The image needs to be in the same position as for the location
-// icon, which implies that the bubble's padding in the Omnibox needs
-// to differ from the location icon's. Indeed, that's how the views
-// implementation handles the problem. This draws the bubble edge a
-// little bit further left, which is easier but no less hacky.
-const CGFloat kLeftSideOverdraw = 2.0;
-
-// Omnibox corner radius is |4.0|, this needs to look tight WRT that.
-const CGFloat kBubbleCornerRadius = 2.0;
-
// Padding between the icon and label.
const CGFloat kIconLabelPadding = 4.0;
@@ -81,31 +74,14 @@
}
void BubbleDecoration::DrawInFrame(NSRect frame, NSView* control_view) {
- const NSRect decorationFrame = NSInsetRect(frame, 0.0, kBackgroundYInset);
-
- // The inset is to put the border down the middle of the pixel.
- NSRect bubbleFrame = NSInsetRect(decorationFrame, 0.5, 0.5);
- bubbleFrame.origin.x -= kLeftSideOverdraw;
- bubbleFrame.size.width += kLeftSideOverdraw;
- NSBezierPath* path =
- [NSBezierPath bezierPathWithRoundedRect:bubbleFrame
- xRadius:kBubbleCornerRadius
- yRadius:kBubbleCornerRadius];
-
- [background_color_ setFill];
- [path fill];
-
- [border_color_ setStroke];
- [path setLineWidth:1.0];
- [path stroke];
-
- CGFloat textOffset = NSMinX(decorationFrame);
+ const NSRect decoration_frame = NSInsetRect(frame, 0.0, kBackgroundYInset);
+ CGFloat textOffset = NSMinX(decoration_frame);
if (image_) {
// Center the image vertically.
const NSSize imageSize = [image_ size];
- NSRect imageRect = decorationFrame;
+ NSRect imageRect = decoration_frame;
imageRect.origin.y +=
- std::floor((NSHeight(decorationFrame) - imageSize.height) / 2.0);
+ std::floor((NSHeight(decoration_frame) - imageSize.height) / 2.0);
imageRect.size = imageSize;
[image_ drawInRect:imageRect
fromRect:NSZeroRect // Entire image
@@ -119,11 +95,22 @@
if (label_) {
NSRect textRect = frame;
textRect.origin.x = textOffset;
- textRect.size.width = NSMaxX(decorationFrame) - NSMinX(textRect);
+ textRect.size.width = NSMaxX(decoration_frame) - NSMinX(textRect);
DrawLabel(label_, attributes_, textRect);
}
}
+void BubbleDecoration::DrawWithBackgroundInFrame(NSRect background_frame,
+ NSRect frame,
+ NSView* control_view) {
+ NSRect rect = NSInsetRect(background_frame, 0, 1);
+ rect.size.width -= kRightSideMargin;
+ ui::DrawNinePartImage(
+ rect, GetBubbleImageIds(), NSCompositeSourceOver, 1.0, true);
+
+ DrawInFrame(frame, control_view);
+}
+
NSImage* BubbleDecoration::GetImage() {
return image_;
}
@@ -140,10 +127,6 @@
label_.reset([label copy]);
}
-void BubbleDecoration::SetColors(NSColor* border_color,
- NSColor* background_color,
- NSColor* text_color) {
- border_color_.reset([border_color retain]);
- background_color_.reset([background_color retain]);
+void BubbleDecoration::SetTextColor(NSColor* text_color) {
[attributes_ setObject:text_color forKey:NSForegroundColorAttributeName];
}
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 dafcd11..5c0048d 100644
--- a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h
@@ -68,7 +68,6 @@
base::scoped_nsobject<ContentSettingAnimationState> animation_;
CGFloat text_width_;
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 ab03319..f15469f 100644
--- a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
@@ -20,7 +20,9 @@
#include "chrome/browser/ui/content_settings/content_setting_image_model.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/web_contents.h"
+#include "grit/theme_resources.h"
#include "net/base/net_util.h"
+#include "ui/base/cocoa/appkit_utils.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
@@ -330,26 +332,20 @@
void ContentSettingDecoration::DrawInFrame(NSRect frame, NSView* control_view) {
if ([animation_ animationState] != kNoAnimation) {
- // Draw the background. Cache the gradient.
- if (!gradient_) {
- // Colors chosen to match Windows code.
- NSColor* start_color =
- [NSColor colorWithCalibratedRed:1.0 green:0.97 blue:0.83 alpha:1.0];
- NSColor* end_color =
- [NSColor colorWithCalibratedRed:1.0 green:0.90 blue:0.68 alpha:1.0];
- NSArray* color_array =
- [NSArray arrayWithObjects:start_color, end_color, nil];
- gradient_.reset([[NSGradient alloc] initWithColors:color_array]);
- }
-
- gfx::ScopedNSGraphicsContextSaveGState scopedGState;
-
NSRect background_rect = NSInsetRect(frame, 0.0, kBorderPadding);
- [gradient_ drawInRect:background_rect angle:90.0];
- NSColor* border_color =
- [NSColor colorWithCalibratedRed:0.91 green:0.73 blue:0.4 alpha:1.0];
- [border_color set];
- NSFrameRect(background_rect);
+ const ui::NinePartImageIds image_ids = {
+ IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_TOP_LEFT,
+ IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_TOP,
+ IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_TOP_RIGHT,
+ IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_LEFT,
+ IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_CENTER,
+ IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_RIGHT,
+ IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_BOTTOM_LEFT,
+ IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_BOTTOM,
+ IDR_OMNIBOX_CONTENT_SETTING_BUBBLE_BOTTOM_RIGHT
+ };
+ ui::DrawNinePartImage(
+ background_rect, image_ids, NSCompositeSourceOver, 1.0, true);
// Draw the icon.
NSImage* icon = GetImage();
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 b17e7d8..2e52c37 100644
--- a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h
@@ -42,6 +42,9 @@
virtual bool OnMousePressed(NSRect frame) OVERRIDE;
virtual bool AcceptsMousePress() OVERRIDE;
+ // Implement |BubbleDecoration|.
+ virtual ui::NinePartImageIds GetBubbleImageIds() OVERRIDE;
+
private:
// The real label. BubbleDecoration's label may be elided.
base::scoped_nsobject<NSString> full_label_;
diff --git a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.mm b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.mm
index 1a2abc7..fc17ad5 100644
--- a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.mm
@@ -7,6 +7,7 @@
#import "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#import "chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h"
+#include "grit/theme_resources.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/font.h"
@@ -49,10 +50,7 @@
EVBubbleDecoration::EVBubbleDecoration(LocationIconDecoration* location_icon)
: location_icon_(location_icon) {
// Color tuples stolen from location_bar_view_gtk.cc.
- NSColor* border_color = ColorWithRGBBytes(0x90, 0xc3, 0x90);
- NSColor* background_color = ColorWithRGBBytes(0xef, 0xfc, 0xef);
- NSColor* text_color = ColorWithRGBBytes(0x07, 0x95, 0x00);
- SetColors(border_color, background_color, text_color);
+ SetTextColor(ColorWithRGBBytes(0x07, 0x95, 0x00));
}
EVBubbleDecoration::~EVBubbleDecoration() {}
@@ -120,3 +118,17 @@
bool EVBubbleDecoration::AcceptsMousePress() {
return true;
}
+
+ui::NinePartImageIds EVBubbleDecoration::GetBubbleImageIds() {
+ return {
+ IDR_OMNIBOX_EV_BUBBLE_TOP_LEFT,
+ IDR_OMNIBOX_EV_BUBBLE_TOP,
+ IDR_OMNIBOX_EV_BUBBLE_TOP_RIGHT,
+ IDR_OMNIBOX_EV_BUBBLE_LEFT,
+ IDR_OMNIBOX_EV_BUBBLE_CENTER,
+ IDR_OMNIBOX_EV_BUBBLE_RIGHT,
+ IDR_OMNIBOX_EV_BUBBLE_BOTTOM_LEFT,
+ IDR_OMNIBOX_EV_BUBBLE_BOTTOM,
+ IDR_OMNIBOX_EV_BUBBLE_BOTTOM_RIGHT
+ };
+}
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 75773c0..15cd2c6 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
@@ -123,6 +123,9 @@
base::Unretained(this)));
browser_->search_model()->AddObserver(this);
+
+ [[field_ cell] setIsPopupMode:
+ !browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)];
}
LocationBarViewMac::~LocationBarViewMac() {
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 000245c..96b6d13 100644
--- a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h
@@ -26,6 +26,9 @@
// return the resulting width.
virtual CGFloat GetWidthForSpace(CGFloat width) OVERRIDE;
+ // Implements |BubbleDecoration|.
+ virtual ui::NinePartImageIds GetBubbleImageIds() OVERRIDE;
+
void SetImage(NSImage* image);
private:
diff --git a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.mm b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.mm
index 2299da4..e7d654f 100644
--- a/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.mm
@@ -14,14 +14,7 @@
SelectedKeywordDecoration::SelectedKeywordDecoration() {
search_image_.reset([OmniboxViewMac::ImageForResource(
IDR_KEYWORD_SEARCH_MAGNIFIER) retain]);
-
- // Matches the color of the highlighted line in the popup.
- NSColor* background_color = [NSColor selectedControlColor];
-
- // Match focus ring's inner color.
- NSColor* border_color =
- [[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:0.5];
- SetColors(border_color, background_color, [NSColor blackColor]);
+ SetTextColor([NSColor blackColor]);
}
SelectedKeywordDecoration::~SelectedKeywordDecoration() {}
@@ -46,6 +39,20 @@
return GetWidthForImageAndLabel(nil, partial_string_);
}
+ui::NinePartImageIds SelectedKeywordDecoration::GetBubbleImageIds() {
+ return {
+ IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_TOP_LEFT,
+ IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_TOP,
+ IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_TOP_RIGHT,
+ IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_LEFT,
+ IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_CENTER,
+ IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_RIGHT,
+ IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_BOTTOM_LEFT,
+ IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_BOTTOM,
+ IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_BOTTOM_RIGHT
+ };
+}
+
void SelectedKeywordDecoration::SetKeyword(const string16& short_name,
bool is_extension_keyword) {
const string16 min_name(location_bar_util::CalculateMinString(short_name));
diff --git a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm
index d6a3fd2..469feae 100644
--- a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm
@@ -70,8 +70,10 @@
// If the page is at default zoom then hiding the zoom decoration was
// suppressed while the bubble was open. Now that the bubble is closed
// the decoration can be hidden.
- if (IsAtDefaultZoom())
+ if (IsAtDefaultZoom() && IsVisible()) {
SetVisible(false);
+ owner_->OnDecorationsChanged();
+ }
};
bubble_ =
[[ZoomBubbleController alloc] initWithParentWindow:[field window]
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
index 9b4fcf6..106c4e4 100644
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
+++ b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
@@ -69,6 +69,7 @@
[window setDelegate:self];
[self initializeContentsWithAppName:appName];
model_ = model.Pass();
+ model_->SetViewDialogWindowId([window windowNumber]);
doneCallback_ = callback;
items_.reset([[NSMutableArray alloc] init]);
bridge_.reset(new DesktopMediaPickerBridge(self));
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm
index 0f209a6..7c518b9 100644
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm
@@ -71,6 +71,10 @@
virtual void SetThumbnailSize(const gfx::Size& thumbnail_size) OVERRIDE {
}
+ virtual void SetViewDialogWindowId(
+ content::DesktopMediaID::Id dialog_id) OVERRIDE {
+ }
+
virtual void StartUpdating(Observer* observer) OVERRIDE {
observer_ = observer;
diff --git a/chrome/browser/ui/cocoa/nine_part_button_cell.h b/chrome/browser/ui/cocoa/nine_part_button_cell.h
deleted file mode 100644
index 493c698..0000000
--- a/chrome/browser/ui/cocoa/nine_part_button_cell.h
+++ /dev/null
@@ -1,31 +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_NINE_PART_BUTTON_CELL_H_
-#define CHROME_BROWSER_UI_COCOA_NINE_PART_BUTTON_CELL_H_
-
-#import <Cocoa/Cocoa.h>
-
-#import "base/mac/scoped_nsobject.h"
-
-// Handles painting of a button using images from a ResourceBundle. The
-// constructor expects an array of 9 image resource ids. The images
-// corresponding to the resource ids are assigned to a 3 by 3 grid in row major
-// order, i.e.
-// _________________
-// |_id0_|_id1_|_id2_|
-// |_id3_|_id4_|_id5_|
-// |_id6_|_id7_|_id8_|
-@interface NinePartButtonCell : NSButtonCell {
- @private
- base::scoped_nsobject<NSMutableArray> images_;
-}
-
-// Loads the images from the ResourceBundle using the provided image resource
-// ids and sets the image of the cell.
-- (id)initWithResourceIds:(const int[9])ids;
-
-@end // @interface NinePartButtonCell
-
-#endif // CHROME_BROWSER_UI_COCOA_NINE_PART_BUTTON_CELL_H_
diff --git a/chrome/browser/ui/cocoa/nine_part_button_cell.mm b/chrome/browser/ui/cocoa/nine_part_button_cell.mm
deleted file mode 100644
index e156232..0000000
--- a/chrome/browser/ui/cocoa/nine_part_button_cell.mm
+++ /dev/null
@@ -1,125 +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/nine_part_button_cell.h"
-
-#include <algorithm>
-
-#include "ui/base/resource/resource_bundle.h"
-
-@implementation NinePartButtonCell
-
-- (id)initWithResourceIds:(const int[9])ids {
- if ((self = [super initImageCell:nil])) {
- images_.reset([[NSMutableArray alloc] initWithCapacity:9]);
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- for (NSInteger i = 0; i < 9; ++i)
- [images_ addObject:rb.GetNativeImageNamed(ids[i]).ToNSImage()];
- [self setBezeled:YES];
- [self setBezelStyle:NSSmallSquareBezelStyle];
- }
- return self;
-}
-
-- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView {
- NSSize targetSize = frame.size;
-
- // Retrieve the sizes of the images (except the size of the center image,
- // which will be scaled anyway).
- NSSize topLeft = [[images_ objectAtIndex:0] size];
- NSSize top = [[images_ objectAtIndex:1] size];
- NSSize topRight = [[images_ objectAtIndex:2] size];
- NSSize left = [[images_ objectAtIndex:3] size];
- NSSize right = [[images_ objectAtIndex:5] size];
- NSSize bottomLeft = [[images_ objectAtIndex:6] size];
- NSSize bottom = [[images_ objectAtIndex:7] size];
- NSSize bottomRight = [[images_ objectAtIndex:8] size];
-
- // Determine the minimum width of images on the left side.
- CGFloat minLeftWidth =
- std::min(topLeft.width, std::min(left.width, bottomLeft.width));
- // Determine the minimum width of images on the right side.
- CGFloat minRightWidth =
- std::min(topRight.width, std::min(right.width, bottomRight.width));
- // Determine the minimum height of images on the top side.
- CGFloat minTopHeight =
- std::min(topLeft.height, std::min(top.height, topRight.height));
- // Determine the minimum height of images on the bottom side.
- CGFloat minBottomHeight =
- std::min(bottomLeft.height, std::min(bottom.height, bottomRight.height));
-
- // Now paint the center image and extend it in all directions to the edges of
- // images with the smallest height/width.
- NSSize centerSize =
- NSMakeSize(targetSize.width - minLeftWidth - minRightWidth,
- targetSize.height - minTopHeight - minBottomHeight);
- NSRect centerRect = NSMakeRect(
- minLeftWidth, minBottomHeight, centerSize.width, centerSize.height);
- [[images_ objectAtIndex:4] drawInRect:centerRect
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0];
-
- // Paint the corner images next.
- NSRect topLeftRect = NSMakeRect(
- 0, targetSize.height - topLeft.height, topLeft.width, topLeft.height);
- [[images_ objectAtIndex:0] drawInRect:topLeftRect
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0];
- NSRect topRightRect = NSMakeRect(targetSize.width - topRight.width,
- targetSize.height - topRight.height,
- topRight.width,
- topRight.height);
- [[images_ objectAtIndex:2] drawInRect:topRightRect
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0];
- NSRect bottomLeftRect = NSMakeRect(
- 0, 0, bottomLeft.width, bottomLeft.height);
- [[images_ objectAtIndex:6] drawInRect:bottomLeftRect
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0];
- NSRect bottomRightRect = NSMakeRect(targetSize.width - bottomRight.width,
- 0,
- bottomRight.width,
- bottomRight.height);
- [[images_ objectAtIndex:8] drawInRect:bottomRightRect
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0];
-
- // Now paint the remaining images.
- NSRect topRect = NSMakeRect(minLeftWidth,
- targetSize.height - top.height,
- centerSize.width,
- top.height);
- [[images_ objectAtIndex:1] drawInRect:topRect
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0];
- NSRect leftRect =
- NSMakeRect(0, minBottomHeight, left.width, centerSize.height);
- [[images_ objectAtIndex:3] drawInRect:leftRect
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0];
- NSRect rightRect = NSMakeRect(targetSize.width - minRightWidth,
- minBottomHeight,
- right.width,
- centerSize.height);
- [[images_ objectAtIndex:5] drawInRect:rightRect
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0];
- NSRect bottomRect =
- NSMakeRect(minLeftWidth, 0, centerSize.width, bottom.height);
- [[images_ objectAtIndex:7] drawInRect:bottomRect
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/nine_part_button_cell_unittest.mm b/chrome/browser/ui/cocoa/nine_part_button_cell_unittest.mm
deleted file mode 100644
index e44da40..0000000
--- a/chrome/browser/ui/cocoa/nine_part_button_cell_unittest.mm
+++ /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.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/mac/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/nine_part_button_cell.h"
-#include "grit/theme_resources.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class NinePartButtonCellTest : public CocoaTest {
- public:
- NinePartButtonCellTest() {
- const int resourceIds[9] = {
- IDR_MANAGED_USER_LABEL_TOP_LEFT, IDR_MANAGED_USER_LABEL_TOP,
- IDR_MANAGED_USER_LABEL_TOP_RIGHT, IDR_MANAGED_USER_LABEL_LEFT,
- IDR_MANAGED_USER_LABEL_CENTER, IDR_MANAGED_USER_LABEL_RIGHT,
- IDR_MANAGED_USER_LABEL_BOTTOM_LEFT, IDR_MANAGED_USER_LABEL_BOTTOM,
- IDR_MANAGED_USER_LABEL_BOTTOM_RIGHT
- };
- NSRect content_frame = [[test_window() contentView] frame];
- button_.reset([[NSButton alloc] initWithFrame:content_frame]);
- base::scoped_nsobject<NinePartButtonCell> cell(
- [[NinePartButtonCell alloc] initWithResourceIds:resourceIds]);
- [button_ setCell:cell.get()];
- [[test_window() contentView] addSubview:button_];
- }
-
- protected:
- base::scoped_nsobject<NSButton> button_;
-};
-
-TEST_VIEW(NinePartButtonCellTest, button_)
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 c78d63a..db6cb80 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
@@ -15,8 +15,6 @@
namespace {
-const float kLargeWidth = 10000;
-
// Returns the length of the run starting at |location| for which
// |attributeName| remains the same.
NSUInteger RunLengthForAttribute(NSAttributedString* string,
diff --git a/chrome/browser/ui/cocoa/panels/panel_cocoa.mm b/chrome/browser/ui/cocoa/panels/panel_cocoa.mm
index b8f8aba..9ab696e 100644
--- a/chrome/browser/ui/cocoa/panels/panel_cocoa.mm
+++ b/chrome/browser/ui/cocoa/panels/panel_cocoa.mm
@@ -16,15 +16,6 @@
using content::NativeWebKeyboardEvent;
using content::WebContents;
-namespace {
-
-// Use this instead of 0 for minimum size of a window when doing opening and
-// closing animations, since OSX window manager does not like 0-sized windows
-// (according to avi@).
-const int kMinimumWindowSize = 1;
-
-} // namespace
-
// This creates a shim window class, which in turn creates a Cocoa window
// controller which in turn creates actual NSWindow by loading a nib.
// Overall chain of ownership is:
@@ -346,6 +337,7 @@
virtual bool VerifyActiveState(bool is_active) OVERRIDE;
virtual bool VerifyAppIcon() const OVERRIDE;
virtual bool VerifySystemMinimizeState() const OVERRIDE;
+ virtual bool IsWindowVisible() const OVERRIDE;
virtual bool IsWindowSizeKnown() const OVERRIDE;
virtual bool IsAnimatingBounds() const OVERRIDE;
virtual bool IsButtonVisible(
@@ -425,6 +417,10 @@
return true;
}
+bool CocoaNativePanelTesting::IsWindowVisible() const {
+ return [[native_panel_window_->controller_ window] isVisible];
+}
+
bool CocoaNativePanelTesting::IsWindowSizeKnown() const {
return true;
}
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 90ba6e0..a4601eb 100644
--- a/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/panels/panel_stack_window_cocoa.mm
@@ -293,7 +293,7 @@
// Provide the custom miniwindow image since there is nothing painted for
// the background stack window.
gfx::Size stack_window_size = GetStackWindowBounds().size();
- gfx::Canvas canvas(stack_window_size, ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(stack_window_size, 1.0f, true);
int y = 0;
Panels::const_iterator iter = panels_.begin();
for (; iter != panels_.end(); ++iter) {
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 223161b..eaf40da 100644
--- a/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.mm
+++ b/chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.mm
@@ -21,8 +21,6 @@
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
#include "ui/gfx/image/image.h"
-const int kButtonPadding = 5;
-
// 'Glint' is a glowing light animation on the titlebar to attract user's
// attention. Numbers are arbitrary, based on several tries.
const double kGlintAnimationDuration = 1.5;
diff --git a/chrome/browser/ui/cocoa/profile_menu_controller.h b/chrome/browser/ui/cocoa/profile_menu_controller.h
index d7e552b..ee0bbc6 100644
--- a/chrome/browser/ui/cocoa/profile_menu_controller.h
+++ b/chrome/browser/ui/cocoa/profile_menu_controller.h
@@ -9,7 +9,7 @@
#include "base/memory/scoped_ptr.h"
-class AvatarMenuModel;
+class AvatarMenu;
class Browser;
namespace ProfileMenuControllerInternal {
@@ -21,11 +21,11 @@
// whenever the active browser changes.
@interface ProfileMenuController : NSObject {
@private
- // The model for the profile submenu.
- scoped_ptr<AvatarMenuModel> model_;
+ // The controller for the profile submenu.
+ scoped_ptr<AvatarMenu> menu_;
// An observer to be notified when the active browser changes and when the
- // model changes.
+ // menu model changes.
scoped_ptr<ProfileMenuControllerInternal::Observer> observer_;
// The main menu item to which the profile menu is attached.
diff --git a/chrome/browser/ui/cocoa/profile_menu_controller.mm b/chrome/browser/ui/cocoa/profile_menu_controller.mm
index cdccc9e..ce2b9e5 100644
--- a/chrome/browser/ui/cocoa/profile_menu_controller.mm
+++ b/chrome/browser/ui/cocoa/profile_menu_controller.mm
@@ -7,8 +7,8 @@
#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"
-#include "chrome/browser/profiles/avatar_menu_model_observer.h"
+#include "chrome/browser/profiles/avatar_menu.h"
+#include "chrome/browser/profiles/avatar_menu_observer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_info_interface.h"
@@ -29,7 +29,7 @@
namespace ProfileMenuControllerInternal {
class Observer : public chrome::BrowserListObserver,
- public AvatarMenuModelObserver {
+ public AvatarMenuObserver {
public:
Observer(ProfileMenuController* controller) : controller_(controller) {
BrowserList::AddObserver(this);
@@ -48,8 +48,8 @@
[controller_ activeBrowserChangedTo:browser];
}
- // AvatarMenuModelObserver:
- virtual void OnAvatarMenuModelChanged(AvatarMenuModel* model) OVERRIDE {
+ // AvatarMenuObserver:
+ virtual void OnAvatarMenuChanged(AvatarMenu* menu) OVERRIDE {
[controller_ rebuildMenu];
}
@@ -82,29 +82,29 @@
}
- (IBAction)switchToProfileFromMenu:(id)sender {
- model_->SwitchToProfile([sender tag], false);
+ menu_->SwitchToProfile([sender tag], false);
ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_MENU);
}
- (IBAction)switchToProfileFromDock:(id)sender {
// Explicitly bring to the foreground when taking action from the dock.
[NSApp activateIgnoringOtherApps:YES];
- model_->SwitchToProfile([sender tag], false);
+ menu_->SwitchToProfile([sender tag], false);
ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_DOCK);
}
- (IBAction)editProfile:(id)sender {
- model_->EditProfile(model_->GetActiveProfileIndex());
+ menu_->EditProfile(menu_->GetActiveProfileIndex());
}
- (IBAction)newProfile:(id)sender {
- model_->AddNewProfile(ProfileMetrics::ADD_NEW_USER_MENU);
+ menu_->AddNewProfile(ProfileMetrics::ADD_NEW_USER_MENU);
}
- (BOOL)insertItemsIntoMenu:(NSMenu*)menu
atOffset:(NSInteger)offset
fromDock:(BOOL)dock {
- if (!model_ || !model_->ShouldShowAvatarMenu())
+ if (!menu_ || !menu_->ShouldShowAvatarMenu())
return NO;
if (dock) {
@@ -118,14 +118,14 @@
[menu insertItem:header atIndex:offset++];
}
- for (size_t i = 0; i < model_->GetNumberOfItems(); ++i) {
- const AvatarMenuModel::Item& itemData = model_->GetItemAt(i);
+ for (size_t i = 0; i < menu_->GetNumberOfItems(); ++i) {
+ const AvatarMenu::Item& itemData = menu_->GetItemAt(i);
NSString* name = base::SysUTF16ToNSString(itemData.name);
SEL action = dock ? @selector(switchToProfileFromDock:)
: @selector(switchToProfileFromMenu:);
NSMenuItem* item = [self createItemWithTitle:name
action:action];
- [item setTag:itemData.model_index];
+ [item setTag:itemData.menu_index];
if (dock) {
[item setIndentationLevel:1];
} else {
@@ -139,20 +139,18 @@
}
- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
- size_t activeProfileIndex = model_->GetActiveProfileIndex();
- ProfileInfoCache* cache =
- &g_browser_process->profile_manager()->GetProfileInfoCache();
- BOOL profileIsManaged = cache->ProfileIsManagedAtIndex(activeProfileIndex);
+ const AvatarMenu::Item& itemData = menu_->GetItemAt(
+ menu_->GetActiveProfileIndex());
if ([menuItem action] == @selector(switchToProfileFromDock:) ||
[menuItem action] == @selector(switchToProfileFromMenu:)) {
- if (!profileIsManaged)
+ if (!itemData.managed)
return YES;
- return [menuItem tag] == static_cast<NSInteger>(activeProfileIndex);
+ return [menuItem tag] == static_cast<NSInteger>(itemData.menu_index);
}
if ([menuItem action] == @selector(newProfile:))
- return !profileIsManaged;
+ return !itemData.managed;
return YES;
}
@@ -165,10 +163,11 @@
- (void)initializeMenu {
observer_.reset(new ProfileMenuControllerInternal::Observer(self));
- model_.reset(new AvatarMenuModel(
+ menu_.reset(new AvatarMenu(
&g_browser_process->profile_manager()->GetProfileInfoCache(),
observer_.get(),
NULL));
+ menu_->RebuildMenu();
[[self menu] addItem:[NSMenuItem separatorItem]];
@@ -189,12 +188,12 @@
// Notifies the controller that the active browser has changed and that the
// menu item and menu need to be updated to reflect that.
- (void)activeBrowserChangedTo:(Browser*)browser {
- // Tell the model that the browser has changed.
- model_->set_browser(browser);
+ // Tell the menu that the browser has changed.
+ menu_->ActiveBrowserChanged(browser);
// If |browser| is NULL, it may be because the current profile was deleted
// and there are no other loaded profiles. In this case, calling
- // |model_->GetActiveProfileIndex()| may result in a profile being loaded,
+ // |menu_->GetActiveProfileIndex()| may result in a profile being loaded,
// which is inappropriate to do on the UI thread.
//
// An early return provides the desired behavior:
@@ -205,11 +204,11 @@
if (!browser)
return;
- size_t active_profile_index = model_->GetActiveProfileIndex();
+ size_t active_profile_index = menu_->GetActiveProfileIndex();
// Update the state for the menu items.
- for (size_t i = 0; i < model_->GetNumberOfItems(); ++i) {
- size_t tag = model_->GetItemAt(i).model_index;
+ for (size_t i = 0; i < menu_->GetNumberOfItems(); ++i) {
+ size_t tag = menu_->GetItemAt(i).menu_index;
[[[self menu] itemWithTag:tag]
setState:active_profile_index == tag ? NSOnState
: NSOffState];
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 51087ef..563c2a1 100644
--- a/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.mm
+++ b/chrome/browser/ui/cocoa/profile_signin_confirmation_view_controller.mm
@@ -32,8 +32,6 @@
const CGFloat kWindowMinWidth = 500;
const CGFloat kButtonGap = 6;
-const SkColor kDialogAlertBarBackgroundColor = 0xFFF6F6F6;
-const SkColor kDialogAlertBarBorderColor = 0xFFE1E1E1;
const CGFloat kDialogAlertBarBorderWidth = 1;
// Shift the origin of |view|'s frame by the given amount in the
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 9c7e83d..7b9fee6 100644
--- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
@@ -79,8 +79,10 @@
- (void)ensureContentsSizeDoesNotChange {
NSView* contentsContainer = [self view];
NSArray* subviews = [contentsContainer subviews];
- if ([subviews count] > 0)
- [[subviews objectAtIndex:0] setAutoresizingMask:NSViewNotSizable];
+ if ([subviews count] > 0) {
+ NSView* currentSubview = [subviews objectAtIndex:0];
+ [currentSubview setAutoresizingMask:NSViewNotSizable];
+ }
}
// Call when the tab view is properly sized and the render widget host view
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
deleted file mode 100644
index 32a9525..0000000
--- a/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h
+++ /dev/null
@@ -1,38 +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_UI_COCOA_TABS_TAB_AUDIO_INDICATOR_VIEW_MAC_H_
-#define CHROME_BROWSER_UI_COCOA_TABS_TAB_AUDIO_INDICATOR_VIEW_MAC_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/memory/scoped_ptr.h"
-
-namespace content {
-class WebContents;
-}
-namespace gfx {
-class AnimationContainer;
-}
-class TabAudioIndicator;
-class TabAudioIndicatorDelegateMac;
-
-// A view that draws an audio indicator on top of a favicon.
-@interface TabAudioIndicatorViewMac : NSView {
- @private
- scoped_ptr<TabAudioIndicator> tabAudioIndicator_;
- scoped_ptr<TabAudioIndicatorDelegateMac> delegate_;
-}
-
-- (void)setIsPlayingAudio:(BOOL)isPlayingAudio;
-
-- (void)setBackgroundImage:(NSImage*)backgroundImage;
-
-- (void)setAnimationContainer:(gfx::AnimationContainer*)animationContainer;
-
-- (BOOL)isAnimating;
-
-@end
-
-#endif // CHROME_BROWSER_UI_COCOA_TABS_TAB_AUDIO_INDICATOR_VIEW_MAC_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.mm b/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.mm
deleted file mode 100644
index 3790ba0..0000000
--- a/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.mm
+++ /dev/null
@@ -1,66 +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.
-
-#import "chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h"
-
-#include "chrome/browser/ui/tabs/tab_audio_indicator.h"
-#include "ui/gfx/canvas_skia_paint.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
-
-class TabAudioIndicatorDelegateMac : public TabAudioIndicator::Delegate {
- public:
- explicit TabAudioIndicatorDelegateMac(TabAudioIndicatorViewMac* view)
- : view_(view) {
- }
-
- virtual ~TabAudioIndicatorDelegateMac() {}
-
- virtual void ScheduleAudioIndicatorPaint() OVERRIDE {
- [view_ setNeedsDisplay:YES];
- }
-
- private:
- TabAudioIndicatorViewMac* view_;
-
- DISALLOW_COPY_AND_ASSIGN(TabAudioIndicatorDelegateMac);
-};
-
-@interface TabAudioIndicatorViewMac ()
-@end
-
-@implementation TabAudioIndicatorViewMac
-
-- (id)initWithFrame:(NSRect)frame {
- if ((self = [super initWithFrame:frame])) {
- delegate_.reset(new TabAudioIndicatorDelegateMac(self));
- tabAudioIndicator_.reset(new TabAudioIndicator(delegate_.get()));
- }
- return self;
-}
-
-- (void)setIsPlayingAudio:(BOOL)isPlayingAudio {
- tabAudioIndicator_->SetIsPlayingAudio(isPlayingAudio);
-}
-
-- (void)setBackgroundImage:(NSImage*)backgroundImage {
- gfx::Image image([backgroundImage retain]);
- tabAudioIndicator_->set_favicon(*image.ToImageSkia());
-}
-
-- (void)setAnimationContainer:(gfx::AnimationContainer*)animationContainer {
- tabAudioIndicator_->SetAnimationContainer(animationContainer);
-}
-
-- (BOOL)isAnimating {
- return tabAudioIndicator_->IsAnimating();
-}
-
-- (void)drawRect:(NSRect)rect {
- gfx::CanvasSkiaPaint canvas(rect, false);
- canvas.set_composite_alpha(true);
- tabAudioIndicator_->Paint(&canvas, gfx::Rect(NSRectToCGRect([self bounds])));
-}
-
-@end
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
deleted file mode 100644
index 099b23e..0000000
--- a/chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac_unittest.mm
+++ /dev/null
@@ -1,37 +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.
-
-#import "chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h"
-
-#include "base/mac/scoped_nsobject.h"
-#include "base/message_loop/message_loop.h"
-#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
-
-class TabAudioIndicatorViewMacTest : public CocoaTest {
- protected:
- TabAudioIndicatorViewMacTest() {
- base::scoped_nsobject<TabAudioIndicatorViewMac> view(
- [[TabAudioIndicatorViewMac alloc]
- initWithFrame:NSMakeRect(0, 0, 16, 16)]);
- view_ = view.get();
- [[test_window() contentView] addSubview:view_];
-
- base::scoped_nsobject<NSImage> image(
- [[NSImage alloc] initWithSize:NSMakeSize(16, 16)]);
- [image lockFocus];
- NSRectFill(NSMakeRect(0, 0, 16, 16));
- [image unlockFocus];
-
- [view_ setBackgroundImage:image];
- [view_ setIsPlayingAudio:YES];
- }
-
- TabAudioIndicatorViewMac* view_;
- base::MessageLoopForUI message_loop_; // Needed for gfx::LinearAnimation.
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TabAudioIndicatorViewMacTest);
-};
-
-TEST_VIEW(TabAudioIndicatorViewMacTest, view_)
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.h b/chrome/browser/ui/cocoa/tabs/tab_controller.h
index 3b516f7..2cfef89 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.h
@@ -42,6 +42,7 @@
@private
base::scoped_nsobject<NSView> iconView_;
base::scoped_nsobject<NSTextField> titleView_;
+ base::scoped_nsobject<NSView> audioIndicatorView_;
base::scoped_nsobject<HoverCloseButton> closeButton_;
NSRect originalIconFrame_; // frame of iconView_ as loaded from nib
@@ -82,6 +83,7 @@
@property(assign, nonatomic) GURL url;
@property(assign, nonatomic) NSView* iconView;
@property(readonly, nonatomic) NSTextField* titleView;
+@property(assign, nonatomic) NSView* audioIndicatorView;
@property(readonly, nonatomic) HoverCloseButton* closeButton;
// Minimum and maximum allowable tab width. The minimum width does not show
@@ -121,6 +123,7 @@
- (NSString*)toolTip;
- (int)iconCapacity;
- (BOOL)shouldShowIcon;
+- (BOOL)shouldShowAudioIndicator;
- (BOOL)shouldShowCloseButton;
@end // TabController(TestingAPI)
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
index 5f9bb2f..8185c7f 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
@@ -273,6 +273,20 @@
return titleView_;
}
+- (NSView*)audioIndicatorView {
+ return audioIndicatorView_;
+}
+
+- (void)setAudioIndicatorView:(NSView*)audioIndicatorView {
+ if (audioIndicatorView == audioIndicatorView_)
+ return;
+ [audioIndicatorView_ removeFromSuperview];
+ audioIndicatorView_.reset([audioIndicatorView retain]);
+ [self updateVisibility];
+ if (audioIndicatorView_)
+ [[self view] addSubview:audioIndicatorView_];
+}
+
- (HoverCloseButton*)closeButton {
return closeButton_;
}
@@ -286,26 +300,49 @@
// how much space we have available.
- (int)iconCapacity {
CGFloat width = NSMaxX([closeButton_ frame]) - NSMinX(originalIconFrame_);
- CGFloat iconWidth = NSWidth(originalIconFrame_);
+ const int kPaddingBetweenIcons = 2;
+ CGFloat iconWidth = NSWidth(originalIconFrame_) + kPaddingBetweenIcons;
return width / iconWidth;
}
// Returns YES if we should show the icon. When tabs get too small, we clip
// the favicon before the close button for selected tabs, and prefer the
-// favicon for unselected tabs. The icon can also be suppressed more directly
+// favicon for unselected tabs. Exception: We clip the favicon before the audio
+// indicator in all cases. The icon can also be suppressed more directly
// by clearing iconView_.
- (BOOL)shouldShowIcon {
if (!iconView_)
return NO;
+ const BOOL shouldShowAudioIndicator = [self shouldShowAudioIndicator];
+ if ([self mini])
+ return !shouldShowAudioIndicator;
+ int required_capacity = shouldShowAudioIndicator ? 2 : 1;
+ if ([self selected]) {
+ // Active tabs give priority to the close button, then the audio indicator,
+ // then the favicon.
+ ++required_capacity;
+ } else {
+ // Non-selected tabs give priority to the audio indicator, then the favicon,
+ // and finally the close button.
+ }
+ return [self iconCapacity] >= required_capacity;
+}
+// Returns YES if we should show the audio indicator. When tabs get too small,
+// we clip the audio indicator before the close button for selected tabs, and
+// prefer the audio indicator for unselected tabs.
+- (BOOL)shouldShowAudioIndicator {
+ if (!audioIndicatorView_)
+ return NO;
if ([self mini])
return YES;
-
- int iconCapacity = [self iconCapacity];
- if ([self selected])
- return iconCapacity >= 2;
- return iconCapacity >= 1;
+ if ([self selected]) {
+ // The active tab clips the audio indicator before the close button.
+ return [self iconCapacity] >= 2;
+ }
+ // Non-selected tabs clip close button before the audio indicator.
+ return [self iconCapacity] >= 1;
}
// Returns YES if we should be showing the close button. The selected tab
@@ -332,6 +369,34 @@
[closeButton_ setHidden:!newShowCloseButton];
+ BOOL newShowAudioIndicator = [self shouldShowAudioIndicator];
+
+ if (audioIndicatorView_) {
+ [audioIndicatorView_ setHidden:!newShowAudioIndicator];
+
+ NSRect newFrame = [audioIndicatorView_ frame];
+ if ([self app] || [self mini]) {
+ // Tab is pinned: Position the audio indicator in the center.
+ const CGFloat tabWidth = [self app] ?
+ [TabController appTabWidth] : [TabController miniTabWidth];
+ newFrame.origin.x = std::floor((tabWidth - NSWidth(newFrame)) / 2);
+ newFrame.origin.y = NSMinY(originalIconFrame_) -
+ std::floor((NSHeight(newFrame) - NSHeight(originalIconFrame_)) / 2);
+ } else {
+ // The Frame for the audioIndicatorView_ depends on whether iconView_
+ // and/or closeButton_ are visible, and where they have been positioned.
+ const NSRect closeButtonFrame = [closeButton_ frame];
+ newFrame.origin.x = NSMinX(closeButtonFrame);
+ // Position to the left of the close button when it is showing.
+ if (newShowCloseButton)
+ newFrame.origin.x -= NSWidth(newFrame);
+ // Audio indicator is centered vertically, with respect to closeButton_.
+ newFrame.origin.y = NSMinY(closeButtonFrame) -
+ std::floor((NSHeight(newFrame) - NSHeight(closeButtonFrame)) / 2);
+ }
+ [audioIndicatorView_ setFrame:newFrame];
+ }
+
// Adjust the title view based on changes to the icon's and close button's
// visibility.
NSRect oldTitleFrame = [titleView_ frame];
@@ -345,7 +410,10 @@
newTitleFrame.origin.x = originalIconFrame_.origin.x;
}
- if (newShowCloseButton) {
+ if (newShowAudioIndicator) {
+ newTitleFrame.size.width = NSMinX([audioIndicatorView_ frame]) -
+ newTitleFrame.origin.x;
+ } else if (newShowCloseButton) {
newTitleFrame.size.width = NSMinX([closeButton_ frame]) -
newTitleFrame.origin.x;
} else {
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
index 0267e79..ab580340 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
@@ -10,9 +10,12 @@
#import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
#import "chrome/browser/ui/cocoa/tabs/tab_controller_target.h"
#import "chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.h"
+#include "grit/theme_resources.h"
+#include "grit/ui_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
#include "testing/platform_test.h"
+#include "ui/base/resource/resource_bundle.h"
// Implements the target interface for the tab, which gets sent messages when
// the tab is clicked on by the user and when its close box is clicked.
@@ -91,11 +94,137 @@
return NSMaxX(superFrame) - NSMaxX(subFrame);
}
+// Helper to create an NSImageView that contains an image fetched from
+// ui::ResourceBundle.
+NSImageView* CreateImageViewFromResourceBundle(int resource_id) {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ NSImage* const image = rb.GetNativeImageNamed(resource_id).ToNSImage();
+ CHECK(!!image);
+ NSRect frame;
+ frame.size = [image size];
+ NSImageView* const view = [[NSImageView alloc] initWithFrame:frame];
+ [view setImage:image];
+ return view;
+}
+
// The dragging code in TabView makes heavy use of autorelease pools so
// inherit from CocoaTest to have one created for us.
class TabControllerTest : public CocoaTest {
public:
TabControllerTest() { }
+
+ static void CheckForExpectedLayoutAndVisibilityOfSubviews(
+ const TabController* controller) {
+ // Check whether subviews should be visible when they are supposed to be,
+ // given Tab size and TabRendererData state.
+ if ([controller mini]) {
+ if ([controller projecting])
+ EXPECT_TRUE([controller shouldShowIcon]);
+ else
+ EXPECT_TRUE([controller shouldShowIcon] !=
+ [controller shouldShowAudioIndicator]);
+ EXPECT_FALSE([controller shouldShowCloseButton]);
+ } else if ([controller selected]) {
+ EXPECT_TRUE([controller shouldShowCloseButton]);
+ switch ([controller iconCapacity]) {
+ case 0:
+ case 1:
+ EXPECT_FALSE([controller shouldShowIcon]);
+ EXPECT_FALSE([controller shouldShowAudioIndicator]);
+ break;
+ case 2:
+ if ([controller projecting])
+ EXPECT_TRUE([controller shouldShowIcon]);
+ else
+ EXPECT_TRUE([controller shouldShowIcon] !=
+ [controller shouldShowAudioIndicator]);
+ break;
+ default:
+ EXPECT_LE(3, [controller iconCapacity]);
+ EXPECT_TRUE([controller shouldShowIcon]);
+ if ([controller projecting])
+ EXPECT_FALSE([controller shouldShowAudioIndicator]);
+ else
+ EXPECT_TRUE(!![controller audioIndicatorView] ==
+ [controller shouldShowAudioIndicator]);
+ break;
+ }
+ } else { // Tab not selected/active and not mini tab.
+ switch ([controller iconCapacity]) {
+ case 0:
+ EXPECT_FALSE([controller shouldShowCloseButton]);
+ EXPECT_FALSE([controller shouldShowIcon]);
+ EXPECT_FALSE([controller shouldShowAudioIndicator]);
+ break;
+ case 1:
+ EXPECT_FALSE([controller shouldShowCloseButton]);
+ if ([controller projecting])
+ EXPECT_TRUE([controller shouldShowIcon]);
+ else
+ EXPECT_TRUE([controller shouldShowIcon] !=
+ [controller shouldShowAudioIndicator]);
+ break;
+ default:
+ EXPECT_LE(2, [controller iconCapacity]);
+ EXPECT_TRUE([controller shouldShowIcon]);
+ if ([controller projecting])
+ EXPECT_FALSE([controller shouldShowAudioIndicator]);
+ else
+ EXPECT_TRUE(!![controller audioIndicatorView] ==
+ [controller shouldShowAudioIndicator]);
+ break;
+ }
+ }
+
+ // Make sure the NSView's "isHidden" state jives with the "shouldShowXXX."
+ EXPECT_TRUE([controller shouldShowIcon] ==
+ (!![controller iconView] && ![[controller iconView] isHidden]));
+ EXPECT_TRUE([controller mini] == [[controller titleView] isHidden]);
+ EXPECT_TRUE([controller shouldShowAudioIndicator] ==
+ (!![controller audioIndicatorView] &&
+ ![[controller audioIndicatorView] isHidden]));
+ EXPECT_TRUE([controller shouldShowCloseButton] !=
+ [[controller closeButton] isHidden]);
+
+ // Check positioning of elements with respect to each other, and that they
+ // are fully within the tab frame.
+ const NSRect tabFrame = [[controller view] frame];
+ const NSRect titleFrame = [[controller titleView] frame];
+ if ([controller shouldShowIcon]) {
+ const NSRect iconFrame = [[controller iconView] frame];
+ EXPECT_LE(NSMinX(tabFrame), NSMinX(iconFrame));
+ if (NSWidth(titleFrame) > 0)
+ EXPECT_LE(NSMaxX(iconFrame), NSMinX(titleFrame));
+ EXPECT_LE(NSMinY(tabFrame), NSMinY(iconFrame));
+ EXPECT_LE(NSMaxY(iconFrame), NSMaxY(tabFrame));
+ }
+ if ([controller shouldShowIcon] && [controller shouldShowAudioIndicator]) {
+ EXPECT_LE(NSMaxX([[controller iconView] frame]),
+ NSMinX([[controller audioIndicatorView] frame]));
+ }
+ if ([controller shouldShowAudioIndicator]) {
+ const NSRect audioIndicatorFrame =
+ [[controller audioIndicatorView] frame];
+ if (NSWidth(titleFrame) > 0)
+ EXPECT_LE(NSMaxX(titleFrame), NSMinX(audioIndicatorFrame));
+ EXPECT_LE(NSMaxX(audioIndicatorFrame), NSMaxX(tabFrame));
+ EXPECT_LE(NSMinY(tabFrame), NSMinY(audioIndicatorFrame));
+ EXPECT_LE(NSMaxY(audioIndicatorFrame), NSMaxY(tabFrame));
+ }
+ if ([controller shouldShowAudioIndicator] &&
+ [controller shouldShowCloseButton]) {
+ EXPECT_LE(NSMaxX([[controller audioIndicatorView] frame]),
+ NSMinX([[controller closeButton] frame]));
+ }
+ if ([controller shouldShowCloseButton]) {
+ const NSRect closeButtonFrame = [[controller closeButton] frame];
+ if (NSWidth(titleFrame) > 0)
+ EXPECT_LE(NSMaxX(titleFrame), NSMinX(closeButtonFrame));
+ EXPECT_LE(NSMaxX(closeButtonFrame), NSMaxX(tabFrame));
+ EXPECT_LE(NSMinY(tabFrame), NSMinY(closeButtonFrame));
+ EXPECT_LE(NSMaxY(closeButtonFrame), NSMaxY(tabFrame));
+ }
+ }
};
// Tests creating the controller, sticking it in a window, and removing it.
@@ -355,4 +484,73 @@
[[controller titleView] frame]));
}
+// A comprehensive test of the layout and visibility of all elements (favicon,
+// throbber indicators, titile text, audio indicator, and close button) over all
+// relevant combinations of tab state. This test overlaps with parts of the
+// other tests above.
+TEST_F(TabControllerTest, LayoutAndVisibilityOfSubviews) {
+ NSWindow* const window = test_window();
+
+ // Create TabController instance and place its view into the test window.
+ base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
+ [[window contentView] addSubview:[controller view]];
+
+ // Create favicon and audio indicator icon views.
+ base::scoped_nsobject<NSImageView> faviconView(
+ CreateImageViewFromResourceBundle(IDR_DEFAULT_FAVICON));
+ base::scoped_nsobject<NSImageView> audioIndicatorView(
+ CreateImageViewFromResourceBundle(IDR_TAB_AUDIO_INDICATOR));
+
+ [controller setIconView:faviconView];
+
+ // Perform layout over all possible combinations, checking for correct
+ // results.
+ for (int is_mini_tab = 0; is_mini_tab < 2; ++is_mini_tab) {
+ for (int is_active_tab = 0; is_active_tab < 2; ++is_active_tab) {
+ for (int is_audio_playing = 0; is_audio_playing < 2; ++is_audio_playing) {
+ for (int is_capturing = 0; is_capturing < 2; ++is_capturing) {
+ SCOPED_TRACE(::testing::Message()
+ << (is_active_tab ? "Active" : "Inactive") << ' '
+ << (is_mini_tab ? "Mini " : "")
+ << "Tab with is_audio_playing=" << !!is_audio_playing
+ << " and is_capturing=" << !!is_capturing);
+
+ // Simulate what tab_strip_controller would do to set up the
+ // TabController state.
+ [controller setMini:(is_mini_tab ? YES : NO)];
+ [controller setActive:(is_active_tab ? YES : NO)];
+ if (is_capturing) {
+ [controller setProjecting:YES];
+ [controller setAudioIndicatorView:nil];
+ } else {
+ [controller setProjecting:NO];
+ if (is_audio_playing)
+ [controller setAudioIndicatorView:audioIndicatorView];
+ else
+ [controller setAudioIndicatorView:nil];
+ }
+
+ // Test layout for every width from maximum to minimum.
+ NSRect tabFrame = [[controller view] frame];
+ int min_width;
+ if (is_mini_tab) {
+ tabFrame.size.width = min_width = [TabController miniTabWidth];
+ } else {
+ tabFrame.size.width = [TabController maxTabWidth];
+ min_width = is_active_tab ? [TabController minSelectedTabWidth] :
+ [TabController minTabWidth];
+ }
+ while (NSWidth(tabFrame) >= min_width) {
+ SCOPED_TRACE(::testing::Message()
+ << "width=" << tabFrame.size.width);
+ [[controller view] setFrame:tabFrame];
+ CheckForExpectedLayoutAndVisibilityOfSubviews(controller);
+ --tabFrame.size.width;
+ }
+ }
+ }
+ }
+ }
+}
+
} // namespace
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 a607809..ef55d15 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.h
@@ -23,7 +23,6 @@
backgroundImage:(NSImage*)backgroundImage
projectorImage:(NSImage*)projectorImage
throbImage:(NSImage*)throbImage
- durationMS:(int)durationMS
animationContainer:(gfx::AnimationContainer*)animationContainer;
@end
diff --git a/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.mm b/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.mm
index 7295028..2f5d685 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.mm
@@ -4,18 +4,18 @@
#import "chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.h"
+#include "ui/gfx/animation/animation.h"
+
@implementation TabProjectingImageView
- (id)initWithFrame:(NSRect)rect
backgroundImage:(NSImage*)backgroundImage
projectorImage:(NSImage*)projectorImage
throbImage:(NSImage*)throbImage
- durationMS:(int)durationMS
animationContainer:(gfx::AnimationContainer*)animationContainer {
if ((self = [super initWithFrame:rect
backgroundImage:backgroundImage
throbImage:throbImage
- durationMS:durationMS
throbPosition:kThrobPositionOverlay
animationContainer:animationContainer])) {
projectorImage_.reset([projectorImage retain]);
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 4361e50..caa49aa 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
@@ -37,7 +37,6 @@
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.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index 8c57621..911dd5d 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -36,7 +36,6 @@
#import "chrome/browser/ui/cocoa/new_tab_button.h"
#import "chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.h"
#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
-#import "chrome/browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h"
#import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
#import "chrome/browser/ui/cocoa/tabs/tab_projecting_image_view.h"
#import "chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.h"
@@ -104,16 +103,9 @@
// Time (in seconds) in which tabs animate to their final position.
const NSTimeInterval kAnimationDuration = 0.125;
-// The amount by which the profile menu button is offset (from tab tabs or new
-// tab button).
-const CGFloat kProfileMenuButtonOffset = 6.0;
-
// The width and height of the icon + glow for projecting mode.
const CGFloat kProjectingIconWidthAndHeight = 32.0;
-// Throbbing duration on webrtc "this web page is watching you" favicon overlay.
-const int kRecordingDurationMs = 1000;
-
// Helper class for doing NSAnimationContext calls that takes a bool to disable
// all the work. Useful for code that wants to conditionally animate.
class ScopedNSAnimationContextGroup {
@@ -165,7 +157,7 @@
base::scoped_nsobject<NSImage> result([[NSImage alloc] initWithSize:size]);
[NSGraphicsContext saveGraphicsState];
for (ui::ScaleFactor scale_factor : ui::GetSupportedScaleFactors()) {
- float scale = GetScaleFactorScale(scale_factor);
+ float scale = GetImageScale(scale_factor);
NSBitmapImageRep *bmpImageRep = [[[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:size.width * scale
@@ -1620,12 +1612,10 @@
if (newState == kTabDone || oldState != newState ||
oldHasIcon != newHasIcon) {
NSView* iconView = nil;
+ NSImageView* audioIndicatorView = nil;
if (newHasIcon) {
if (newState == kTabDone) {
NSImageView* imageView = [self iconImageViewForContents:contents];
- TabAudioIndicatorViewMac* tabAudioIndicatorViewMac =
- base::mac::ObjCCast<TabAudioIndicatorViewMac>(
- [tabController iconView]);
ui::ThemeProvider* theme = [[tabStripView_ window] themeProvider];
if (theme && [tabController projecting]) {
@@ -1643,7 +1633,6 @@
backgroundImage:[imageView image]
projectorImage:projector
throbImage:projectorGlow
- durationMS:kRecordingDurationMs
animationContainer:animationContainer_.get()] autorelease];
iconView = projectingView;
@@ -1661,27 +1650,24 @@
initWithFrame:frame
backgroundImage:favIconMasked
throbImage:recording
- durationMS:kRecordingDurationMs
throbPosition:kThrobPositionBottomRight
animationContainer:animationContainer_.get()] autorelease];
iconView = recordingView;
- } else if (chrome::IsPlayingAudio(contents) ||
- [tabAudioIndicatorViewMac isAnimating]) {
- if (!tabAudioIndicatorViewMac) {
- NSRect frame =
- NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
- tabAudioIndicatorViewMac = [[[TabAudioIndicatorViewMac alloc]
- initWithFrame:frame] autorelease];
- [tabAudioIndicatorViewMac
- setAnimationContainer:animationContainer_.get()];
- }
- [tabAudioIndicatorViewMac
- setIsPlayingAudio:chrome::IsPlayingAudio(contents)];
- [tabAudioIndicatorViewMac setBackgroundImage:[imageView image]];
- iconView = tabAudioIndicatorViewMac;
} else {
iconView = imageView;
+
+ if (theme && chrome::IsPlayingAudio(contents)) {
+ NSImage* const image =
+ theme->GetNSImageNamed(IDR_TAB_AUDIO_INDICATOR);
+ if (image) {
+ NSRect frame;
+ frame.size = [image size];
+ audioIndicatorView =
+ [[[NSImageView alloc] initWithFrame:frame] autorelease];
+ [audioIndicatorView setImage:image];
+ }
+ }
}
} else if (newState == kTabCrashed) {
NSImage* oldImage = [[self iconImageViewForContents:contents] image];
@@ -1707,6 +1693,7 @@
//DCHECK_LE(NSMaxX([iconView frame]),
// NSWidth([[tabController view] frame]) - kTabOverlap);
}
+ [tabController setAudioIndicatorView:audioIndicatorView];
}
}
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.mm b/chrome/browser/ui/cocoa/tabs/tab_view.mm
index d30443e..8bb0a13 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_view.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_view.mm
@@ -25,8 +25,6 @@
// Constants for inset and control points for tab shape.
const CGFloat kInsetMultiplier = 2.0/3.0;
-const CGFloat kControlPoint1Multiplier = 1.0/3.0;
-const CGFloat kControlPoint2Multiplier = 3.0/8.0;
// The amount of time in seconds during which each type of glow increases, holds
// steady, and decreases, respectively.
diff --git a/chrome/browser/ui/cocoa/tabs/throbbing_image_view.h b/chrome/browser/ui/cocoa/tabs/throbbing_image_view.h
index e0d42f9..075d941 100644
--- a/chrome/browser/ui/cocoa/tabs/throbbing_image_view.h
+++ b/chrome/browser/ui/cocoa/tabs/throbbing_image_view.h
@@ -9,10 +9,14 @@
#include "base/mac/scoped_nsobject.h"
#include "base/memory/scoped_ptr.h"
-#include "ui/gfx/animation/throb_animation.h"
class ThrobbingImageViewAnimationDelegate;
+namespace gfx {
+class Animation;
+class AnimationContainer;
+} // namespace gfx
+
// Where to position the throb image. For the overlay position, the throb image
// will be drawn with the same size as the background image. For the bottom
// right position, it will have its original size.
@@ -25,7 +29,7 @@
@protected
base::scoped_nsobject<NSImage> backgroundImage_;
base::scoped_nsobject<NSImage> throbImage_;
- scoped_ptr<gfx::ThrobAnimation> throbAnimation_;
+ scoped_ptr<gfx::Animation> throbAnimation_;
@private
scoped_ptr<ThrobbingImageViewAnimationDelegate> delegate_;
@@ -35,7 +39,6 @@
- (id)initWithFrame:(NSRect)rect
backgroundImage:(NSImage*)backgroundImage
throbImage:(NSImage*)throbImage
- durationMS:(int)durationMS
throbPosition:(ThrobPosition)throbPosition
animationContainer:(gfx::AnimationContainer*)animationContainer;
diff --git a/chrome/browser/ui/cocoa/tabs/throbbing_image_view.mm b/chrome/browser/ui/cocoa/tabs/throbbing_image_view.mm
index 8821a95..e5de04a 100644
--- a/chrome/browser/ui/cocoa/tabs/throbbing_image_view.mm
+++ b/chrome/browser/ui/cocoa/tabs/throbbing_image_view.mm
@@ -4,6 +4,8 @@
#import "chrome/browser/ui/cocoa/tabs/throbbing_image_view.h"
+#include "chrome/browser/ui/tabs/tab_utils.h"
+#include "ui/gfx/animation/animation.h"
#include "ui/gfx/animation/animation_delegate.h"
class ThrobbingImageViewAnimationDelegate : public gfx::AnimationDelegate {
@@ -21,7 +23,6 @@
- (id)initWithFrame:(NSRect)rect
backgroundImage:(NSImage*)backgroundImage
throbImage:(NSImage*)throbImage
- durationMS:(int)durationMS
throbPosition:(ThrobPosition)throbPosition
animationContainer:(gfx::AnimationContainer*)animationContainer {
if ((self = [super initWithFrame:rect])) {
@@ -29,10 +30,11 @@
throbImage_.reset([throbImage retain]);
delegate_.reset(new ThrobbingImageViewAnimationDelegate(self));
- throbAnimation_.reset(new gfx::ThrobAnimation(delegate_.get()));
+
+ throbAnimation_ = chrome::CreateTabRecordingIndicatorAnimation();
+ throbAnimation_->set_delegate(delegate_.get());
throbAnimation_->SetContainer(animationContainer);
- throbAnimation_->SetThrobDuration(durationMS);
- throbAnimation_->StartThrobbing(-1);
+ throbAnimation_->Start();
throbPosition_ = throbPosition;
}
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 9f506de..5ce2b13 100644
--- a/chrome/browser/ui/cocoa/tabs/throbbing_image_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/throbbing_image_view_unittest.mm
@@ -24,7 +24,6 @@
[[ThrobbingImageView alloc] initWithFrame:NSMakeRect(0, 0, 16, 16)
backgroundImage:image
throbImage:image
- durationMS:20
throbPosition:kThrobPositionOverlay
animationContainer:NULL]);
view_ = view.get();
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
index e882233..6d77910 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -604,6 +604,12 @@
content_settings->set_password_action(PasswordFormManager::BLACKLIST);
}
+void SavePasswordBubbleModel::OnDoneClicked() {
+ TabSpecificContentSettings* content_settings =
+ TabSpecificContentSettings::FromWebContents(web_contents());
+ content_settings->set_password_action(PasswordFormManager::DO_NOTHING);
+}
+
void SavePasswordBubbleModel::OnSaveClicked() {
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
@@ -862,6 +868,13 @@
}
void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
+ TabSpecificContentSettings* content_settings =
+ TabSpecificContentSettings::FromWebContents(web_contents());
+ const std::string& requested_microphone =
+ content_settings->media_stream_requested_audio_device();
+ const std::string& requested_camera =
+ content_settings->media_stream_requested_video_device();
+
// Add microphone menu.
PrefService* prefs = profile()->GetPrefs();
MediaCaptureDevicesDispatcher* dispatcher =
@@ -885,8 +898,18 @@
MediaMenu mic_menu;
mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
if (!microphones.empty()) {
- std::string preferred_mic =
- prefs->GetString(prefs::kDefaultAudioCaptureDevice);
+ std::string preferred_mic;
+ if (requested_microphone.empty()) {
+ preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
+ mic_menu.disabled = false;
+ } else {
+ // Set the |disabled| to true in order to disable the device selection
+ // menu on the media settings bubble. This must be done if the website
+ // manages the microphone devices itself.
+ preferred_mic = requested_microphone;
+ mic_menu.disabled = true;
+ }
+
mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
mic_menu.selected_device = mic_menu.default_device;
}
@@ -900,8 +923,17 @@
camera_menu.label =
l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
if (!cameras.empty()) {
- std::string preferred_camera =
- prefs->GetString(prefs::kDefaultVideoCaptureDevice);
+ std::string preferred_camera;
+ if (requested_camera.empty()) {
+ preferred_camera = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
+ camera_menu.disabled = false;
+ } else {
+ // Disable the menu since the website is managing the camera devices
+ // itself.
+ preferred_camera = requested_camera;
+ camera_menu.disabled = true;
+ }
+
camera_menu.default_device =
GetMediaDeviceById(preferred_camera, cameras);
camera_menu.selected_device = camera_menu.default_device;
@@ -1340,6 +1372,10 @@
ContentSettingBubbleModel::DomainList::~DomainList() {}
+ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
+
+ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
+
ContentSettingBubbleModel::BubbleContent::BubbleContent()
: radio_group_enabled(false),
custom_link_enabled(false) {
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.h b/chrome/browser/ui/content_settings/content_setting_bubble_model.h
index 1f4f994..dfea645 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model.h
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.h
@@ -64,9 +64,13 @@
};
struct MediaMenu {
+ MediaMenu();
+ ~MediaMenu();
+
std::string label;
content::MediaStreamDevice default_device;
content::MediaStreamDevice selected_device;
+ bool disabled;
};
typedef std::map<content::MediaStreamType, MediaMenu> MediaMenuMap;
@@ -198,6 +202,7 @@
Profile* profile);
virtual ~SavePasswordBubbleModel();
virtual void OnCancelClicked() OVERRIDE;
+ virtual void OnDoneClicked() OVERRIDE;
virtual void OnSaveClicked() OVERRIDE;
private:
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
index 9bd24ab..8274edd 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
@@ -120,11 +120,11 @@
TabSpecificContentSettings::FromWebContents(web_contents());
std::string request_host = "google.com";
GURL security_origin("http://" + request_host);
- MediaStreamDevicesController::MediaStreamTypePermissionMap
+ MediaStreamDevicesController::MediaStreamTypeSettingsMap
request_permissions;
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -181,11 +181,11 @@
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
- MediaStreamDevicesController::MediaStreamTypePermissionMap
+ MediaStreamDevicesController::MediaStreamTypeSettingsMap
request_permissions;
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_BLOCKED_BY_USER;
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_BLOCKED_BY_USER;
content_settings->OnMediaStreamPermissionSet(url, request_permissions);
{
@@ -254,9 +254,9 @@
TabSpecificContentSettings::FromWebContents(web_contents());
std::string request_host = "google.com";
GURL security_origin("http://" + request_host);
- MediaStreamDevicesController::MediaStreamTypePermissionMap
+ MediaStreamDevicesController::MediaStreamTypeSettingsMap
request_permissions;
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -286,7 +286,7 @@
bubble_content.media_menus.begin()->first);
// Change the microphone access.
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_BLOCKED_BY_USER;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -324,9 +324,9 @@
TabSpecificContentSettings::FromWebContents(web_contents());
std::string request_host = "google.com";
GURL security_origin("http://" + request_host);
- MediaStreamDevicesController::MediaStreamTypePermissionMap
+ MediaStreamDevicesController::MediaStreamTypeSettingsMap
request_permissions;
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -356,7 +356,7 @@
bubble_content.media_menus.begin()->first);
// Change the camera access.
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_BLOCKED_BY_USER;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -396,9 +396,9 @@
GURL security_origin("http://" + request_host);
// Firstly, add microphone access.
- MediaStreamDevicesController::MediaStreamTypePermissionMap
+ MediaStreamDevicesController::MediaStreamTypeSettingsMap
request_permissions;
- request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
@@ -425,7 +425,7 @@
bubble_content.media_menus.begin()->first);
// Then add camera access.
- request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE] =
+ request_permissions[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
MediaStreamDevicesController::MEDIA_ALLOWED;
content_settings->OnMediaStreamPermissionSet(security_origin,
request_permissions);
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc
index 56abb77..d9db1b6 100644
--- a/chrome/browser/ui/extensions/application_launch.cc
+++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -19,11 +19,14 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/ui/app_list/app_list_service.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_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/extensions/extension_enable_flow.h"
+#include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/web_applications/web_app.h"
@@ -268,6 +271,122 @@
return contents;
}
+// Attempts to launch a packaged app, prompting the user to enable it if
+// necessary. If a prompt is required it will be shown inside the AppList.
+// This class manages its own lifetime.
+class EnableViaAppListFlow : public ExtensionEnableFlowDelegate {
+ public:
+ EnableViaAppListFlow(ExtensionService* service,
+ Profile* profile,
+ const std::string& extension_id,
+ const base::Closure& callback)
+ : service_(service),
+ profile_(profile),
+ extension_id_(extension_id),
+ callback_(callback) {
+ }
+
+ virtual ~EnableViaAppListFlow() {
+ }
+
+ void Run() {
+ DCHECK(!service_->IsExtensionEnabled(extension_id_));
+ flow_.reset(new ExtensionEnableFlow(profile_, extension_id_, this));
+ flow_->StartForCurrentlyNonexistentWindow(
+ base::Bind(&EnableViaAppListFlow::ShowAppList, base::Unretained(this)));
+ }
+
+ private:
+ gfx::NativeWindow ShowAppList() {
+ AppListService::Get()->Show();
+ return AppListService::Get()->GetAppListWindow();
+ }
+
+ // ExtensionEnableFlowDelegate overrides.
+ virtual void ExtensionEnableFlowFinished() OVERRIDE {
+ const Extension* extension =
+ service_->GetExtensionById(extension_id_, false);
+ if (!extension)
+ return;
+ callback_.Run();
+ delete this;
+ }
+
+ virtual void ExtensionEnableFlowAborted(bool user_initiated) OVERRIDE {
+ delete this;
+ }
+
+ ExtensionService* service_;
+ Profile* profile_;
+ std::string extension_id_;
+ base::Closure callback_;
+ scoped_ptr<ExtensionEnableFlow> flow_;
+
+ DISALLOW_COPY_AND_ASSIGN(EnableViaAppListFlow);
+};
+
+WebContents* OpenEnabledApplication(const chrome::AppLaunchParams& params) {
+ Profile* profile = params.profile;
+ const extensions::Extension* extension = params.extension;
+ extension_misc::LaunchContainer container = params.container;
+ const GURL& override_url = params.override_url;
+ const gfx::Rect& override_bounds = params.override_bounds;
+ WebContents* tab = NULL;
+ ExtensionPrefs* prefs = extensions::ExtensionSystem::Get(profile)->
+ extension_service()->extension_prefs();
+ prefs->SetActiveBit(extension->id(), true);
+
+ UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchContainer", container, 100);
+
+ if (extension->is_platform_app()) {
+#if !defined(OS_CHROMEOS)
+ SigninManager* signin_manager =
+ SigninManagerFactory::GetForProfile(profile);
+ if (signin_manager && signin_manager->GetAuthenticatedUsername().empty()) {
+ const char kEnforceSigninToUseAppsFieldTrial[] = "EnforceSigninToUseApps";
+
+ std::string field_trial_value =
+ base::FieldTrialList::FindFullName(kEnforceSigninToUseAppsFieldTrial);
+
+ // Only enforce signin if the field trial is set.
+ if (!field_trial_value.empty()) {
+ GURL gurl(l10n_util::GetStringFUTF8(IDS_APP_LAUNCH_NOT_SIGNED_IN_LINK,
+ UTF8ToUTF16(extension->id())));
+ chrome::NavigateParams params(profile, gurl,
+ content::PAGE_TRANSITION_LINK);
+ chrome::Navigate(¶ms);
+ return NULL;
+ }
+ }
+#endif
+
+ apps::LaunchPlatformAppWithCommandLine(
+ profile, extension, params.command_line, params.current_directory);
+ return NULL;
+ }
+
+ switch (container) {
+ case extension_misc::LAUNCH_NONE: {
+ NOTREACHED();
+ break;
+ }
+ case extension_misc::LAUNCH_PANEL:
+ case extension_misc::LAUNCH_WINDOW:
+ tab = OpenApplicationWindow(profile, extension, container,
+ override_url, NULL, override_bounds);
+ break;
+ case extension_misc::LAUNCH_TAB: {
+ tab = OpenApplicationTab(profile, extension, override_url,
+ params.disposition);
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+ return tab;
+}
+
} // namespace
namespace chrome {
@@ -332,66 +451,24 @@
}
WebContents* OpenApplication(const AppLaunchParams& params) {
+ return OpenEnabledApplication(params);
+}
+
+
+void OpenApplicationWithReenablePrompt(const chrome::AppLaunchParams& params) {
Profile* profile = params.profile;
const extensions::Extension* extension = params.extension;
- extension_misc::LaunchContainer container = params.container;
- const GURL& override_url = params.override_url;
- const gfx::Rect& override_bounds = params.override_bounds;
- WebContents* tab = NULL;
- ExtensionPrefs* prefs = extensions::ExtensionSystem::Get(profile)->
- extension_service()->extension_prefs();
- prefs->SetActiveBit(extension->id(), true);
-
- UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchContainer", container, 100);
-
- if (extension->is_platform_app()) {
-#if !defined(OS_CHROMEOS)
- SigninManager* signin_manager =
- SigninManagerFactory::GetForProfile(profile);
- if (signin_manager && signin_manager->GetAuthenticatedUsername().empty()) {
- const char kEnforceSigninToUseAppsFieldTrial[] = "EnforceSigninToUseApps";
-
- std::string field_trial_value =
- base::FieldTrialList::FindFullName(kEnforceSigninToUseAppsFieldTrial);
-
- // Only enforce signin if the field trial is set.
- if (!field_trial_value.empty()) {
- GURL gurl(l10n_util::GetStringFUTF8(IDS_APP_LAUNCH_NOT_SIGNED_IN_LINK,
- UTF8ToUTF16(extension->id())));
- chrome::NavigateParams params(profile, gurl,
- content::PAGE_TRANSITION_LINK);
- chrome::Navigate(¶ms);
- return NULL;
- }
- }
-#endif
-
- apps::LaunchPlatformAppWithCommandLine(
- profile, extension, params.command_line, params.current_directory);
- return NULL;
+ ExtensionService* service =
+ extensions::ExtensionSystem::Get(profile)->extension_service();
+ if (!service->IsExtensionEnabled(extension->id())) {
+ (new EnableViaAppListFlow(
+ service, profile, extension->id(),
+ base::Bind(base::IgnoreResult(OpenEnabledApplication), params)))->Run();
+ return;
}
- switch (container) {
- case extension_misc::LAUNCH_NONE: {
- NOTREACHED();
- break;
- }
- case extension_misc::LAUNCH_PANEL:
- case extension_misc::LAUNCH_WINDOW:
- tab = OpenApplicationWindow(profile, extension, container,
- override_url, NULL, override_bounds);
- break;
- case extension_misc::LAUNCH_TAB: {
- tab = OpenApplicationTab(profile, extension, override_url,
- params.disposition);
- break;
- }
- default:
- NOTREACHED();
- break;
- }
- return tab;
+ OpenEnabledApplication(params);
}
WebContents* OpenAppShortcutWindow(Profile* profile,
diff --git a/chrome/browser/ui/extensions/application_launch.h b/chrome/browser/ui/extensions/application_launch.h
index 334f1bc..6f01631 100644
--- a/chrome/browser/ui/extensions/application_launch.h
+++ b/chrome/browser/ui/extensions/application_launch.h
@@ -72,6 +72,9 @@
base::FilePath current_directory;
};
+// Opens the application, possibly prompting the user to re-enable it.
+void OpenApplicationWithReenablePrompt(const AppLaunchParams& params);
+
// Open the application in a way specified by |params|.
content::WebContents* OpenApplication(const AppLaunchParams& params);
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.cc b/chrome/browser/ui/extensions/extension_enable_flow.cc
index b1ec1a9..2ec1f98 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.cc
+++ b/chrome/browser/ui/extensions/extension_enable_flow.cc
@@ -41,6 +41,12 @@
Run();
}
+void ExtensionEnableFlow::StartForCurrentlyNonexistentWindow(
+ base::Callback<gfx::NativeWindow(void)> window_getter) {
+ window_getter_ = window_getter;
+ Run();
+}
+
void ExtensionEnableFlow::Run() {
ExtensionService* service =
extensions::ExtensionSystem::Get(profile_)->extension_service();
@@ -92,6 +98,8 @@
}
void ExtensionEnableFlow::CreatePrompt() {
+ if (!window_getter_.is_null())
+ parent_window_ = window_getter_.Run();
prompt_.reset(parent_contents_ ?
new ExtensionInstallPrompt(parent_contents_) :
new ExtensionInstallPrompt(profile_, parent_window_, this));
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.h b/chrome/browser/ui/extensions/extension_enable_flow.h
index 4a1548c..dea94f0 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.h
+++ b/chrome/browser/ui/extensions/extension_enable_flow.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "content/public/browser/notification_observer.h"
@@ -40,10 +41,14 @@
// Starts the flow and the logic continues on |delegate_| after enabling is
// finished or aborted. Note that |delegate_| could be called synchronously
// before this call returns when there is no need to show UI to finish the
- // enabling flow. Two variations of the flow are supported: one with a
- // parent WebContents and the other with a native parent window.
+ // enabling flow. Three variations of the flow are supported:
+ // - one with a parent WebContents
+ // - one with a native parent window
+ // - one with a callback for creating a parent window
void StartForWebContents(content::WebContents* parent_contents);
void StartForNativeWindow(gfx::NativeWindow parent_window);
+ void StartForCurrentlyNonexistentWindow(
+ base::Callback<gfx::NativeWindow(void)> window_getter);
const std::string& extension_id() const { return extension_id_; }
@@ -92,6 +97,10 @@
// exclusive with |parent_contents_| above.
gfx::NativeWindow parent_window_;
+ // Called to acquire a parent window for the prompt. This is used for clients
+ // who only want to create a window if it is required.
+ base::Callback<gfx::NativeWindow(void)> window_getter_;
+
scoped_ptr<ExtensionInstallPrompt> prompt_;
content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
index 7880d95..5f1752e 100644
--- a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
+++ b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
@@ -21,7 +21,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/overscroll_configuration.h"
#include "content/public/common/renderer_preferences.h"
-#include "ui/base/gestures/gesture_configuration.h"
+#include "ui/events/gestures/gesture_configuration.h"
#if defined(USE_ASH)
#include "chrome/browser/ui/immersive_fullscreen_configuration.h"
@@ -106,7 +106,7 @@
// The list of prefs we want to observe.
// Note that this collection of settings should correspond to the settings used
-// in ui/base/gestures/gesture_configuration.h
+// in ui/events/gestures/gesture_configuration.h
const char* kPrefsToObserve[] = {
prefs::kFlingAccelerationCurveCoefficient0,
prefs::kFlingAccelerationCurveCoefficient1,
diff --git a/chrome/browser/ui/global_error/global_error_service.cc b/chrome/browser/ui/global_error/global_error_service.cc
index 2acf270..041efd3 100644
--- a/chrome/browser/ui/global_error/global_error_service.cc
+++ b/chrome/browser/ui/global_error/global_error_service.cc
@@ -21,6 +21,9 @@
}
void GlobalErrorService::AddGlobalError(GlobalError* error) {
+ // Verify that we're not adding NULL errors. TODO(sail) Make this a DCHECK
+ // once crbug.com/278543 is fixed.
+ CHECK(error);
errors_.push_back(error);
NotifyErrorsChanged(error);
}
diff --git a/chrome/browser/ui/gtk/accelerators_gtk.cc b/chrome/browser/ui/gtk/accelerators_gtk.cc
index 23deda5..875df31 100644
--- a/chrome/browser/ui/gtk/accelerators_gtk.cc
+++ b/chrome/browser/ui/gtk/accelerators_gtk.cc
@@ -11,7 +11,6 @@
#include "base/memory/singleton.h"
#include "chrome/app/chrome_command_ids.h"
#include "ui/base/accelerators/platform_accelerator_gtk.h"
-#include "ui/events/event_conversion_gtk.h"
#include "ui/events/keycodes/keyboard_code_conversion_gtk.h"
namespace {
diff --git a/chrome/browser/ui/gtk/apps/native_app_window_gtk.cc b/chrome/browser/ui/gtk/apps/native_app_window_gtk.cc
index 12a3d5d..4819a02 100644
--- a/chrome/browser/ui/gtk/apps/native_app_window_gtk.cc
+++ b/chrome/browser/ui/gtk/apps/native_app_window_gtk.cc
@@ -211,6 +211,8 @@
ui::WindowShowState NativeAppWindowGtk::GetRestoredState() const {
if (IsMaximized())
return ui::SHOW_STATE_MAXIMIZED;
+ if (IsFullscreen())
+ return ui::SHOW_STATE_FULLSCREEN;
return ui::SHOW_STATE_NORMAL;
}
@@ -596,7 +598,12 @@
}
bool NativeAppWindowGtk::IsFullscreenOrPending() const {
- return content_thinks_its_fullscreen_;
+ // |content_thinks_its_fullscreen_| is used when transitioning, and when
+ // the state change will not be made for some time. However, it is possible
+ // for a state update to be made before the final fullscreen state comes.
+ // In that case, |content_thinks_its_fullscreen_| will be cleared, but we
+ // will fall back to |IsFullscreen| which will soon have the correct state.
+ return content_thinks_its_fullscreen_ || IsFullscreen();
}
bool NativeAppWindowGtk::IsDetached() const {
diff --git a/chrome/browser/ui/gtk/apps/native_app_window_gtk.h b/chrome/browser/ui/gtk/apps/native_app_window_gtk.h
index be113a9..1827416 100644
--- a/chrome/browser/ui/gtk/apps/native_app_window_gtk.h
+++ b/chrome/browser/ui/gtk/apps/native_app_window_gtk.h
@@ -15,8 +15,8 @@
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/base/gtk/gtk_signal.h"
#include "ui/base/x/active_window_watcher_x_observer.h"
-#include "ui/base/x/x11_atom_cache.h"
#include "ui/gfx/rect.h"
+#include "ui/gfx/x/x11_atom_cache.h"
class ExtensionKeybindingRegistryGtk;
class Profile;
diff --git a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc
index d68d933..65d0b42 100644
--- a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc
+++ b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc
@@ -8,7 +8,7 @@
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
@@ -45,11 +45,12 @@
new_profile_link_(NULL),
minimum_width_(kBubbleMinWidth),
switching_(false) {
- avatar_menu_model_.reset(new AvatarMenuModel(
+ avatar_menu_.reset(new AvatarMenu(
&g_browser_process->profile_manager()->GetProfileInfoCache(),
this, browser));
+ avatar_menu_->RebuildMenu();
- OnAvatarMenuModelChanged(avatar_menu_model_.get());
+ OnAvatarMenuChanged(avatar_menu_.get());
bubble_ = BubbleGtk::Show(anchor,
rect,
@@ -77,8 +78,8 @@
bubble_ = NULL;
}
-void AvatarMenuBubbleGtk::OnAvatarMenuModelChanged(
- AvatarMenuModel* avatar_menu_model) {
+void AvatarMenuBubbleGtk::OnAvatarMenuChanged(
+ AvatarMenu* avatar_menu) {
items_.clear();
minimum_width_ = kBubbleMinWidth;
@@ -91,7 +92,7 @@
GdkModifierType modifier_state;
gtk_get_current_event_state(&modifier_state);
guint modifier_state_uint = modifier_state;
- avatar_menu_model_->SwitchToProfile(profile_index,
+ avatar_menu_->SwitchToProfile(profile_index,
event_utils::DispositionFromGdkState(modifier_state_uint) == NEW_WINDOW);
CloseBubble();
}
@@ -99,7 +100,7 @@
void AvatarMenuBubbleGtk::EditProfile(size_t profile_index) {
if (!bubble_)
return;
- avatar_menu_model_->EditProfile(profile_index);
+ avatar_menu_->EditProfile(profile_index);
CloseBubble();
}
@@ -115,20 +116,20 @@
void AvatarMenuBubbleGtk::OnNewProfileLinkClicked(GtkWidget* link) {
if (!bubble_)
return;
- avatar_menu_model_->AddNewProfile(ProfileMetrics::ADD_NEW_USER_ICON);
+ avatar_menu_->AddNewProfile(ProfileMetrics::ADD_NEW_USER_ICON);
CloseBubble();
}
void AvatarMenuBubbleGtk::OnSwitchProfileLinkClicked(GtkWidget* link) {
switching_ = true;
- OnAvatarMenuModelChanged(avatar_menu_model_.get());
+ OnAvatarMenuChanged(avatar_menu_.get());
}
void AvatarMenuBubbleGtk::InitMenuContents() {
- size_t profile_count = avatar_menu_model_->GetNumberOfItems();
+ size_t profile_count = avatar_menu_->GetNumberOfItems();
GtkWidget* items_vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing);
for (size_t i = 0; i < profile_count; ++i) {
- AvatarMenuModel::Item menu_item = avatar_menu_model_->GetItemAt(i);
+ AvatarMenu::Item menu_item = avatar_menu_->GetItemAt(i);
AvatarMenuItemGtk* item = new AvatarMenuItemGtk(
this, menu_item, i, theme_service_);
items_.push_back(item);
@@ -140,7 +141,7 @@
}
gtk_box_pack_start(GTK_BOX(inner_contents_), items_vbox, TRUE, TRUE, 0);
- if (avatar_menu_model_->ShouldShowAddNewProfileLink()) {
+ if (avatar_menu_->ShouldShowAddNewProfileLink()) {
gtk_box_pack_start(GTK_BOX(inner_contents_),
gtk_hseparator_new(), TRUE, TRUE, 0);
@@ -157,13 +158,12 @@
gtk_box_pack_start(GTK_BOX(inner_contents_), link_align, FALSE, FALSE, 0);
}
-
}
void AvatarMenuBubbleGtk::InitManagedUserContents() {
- int active_index = avatar_menu_model_->GetActiveProfileIndex();
- AvatarMenuModel::Item menu_item =
- avatar_menu_model_->GetItemAt(active_index);
+ int active_index = avatar_menu_->GetActiveProfileIndex();
+ AvatarMenu::Item menu_item =
+ avatar_menu_->GetItemAt(active_index);
AvatarMenuItemGtk* item = new AvatarMenuItemGtk(
this, menu_item, active_index, theme_service_);
items_.push_back(item);
@@ -175,7 +175,7 @@
// 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();
+ avatar_menu_->GetManagedUserIcon().ToGdkPixbuf();
GtkWidget* limited_user_img = gtk_image_new_from_pixbuf(limited_user_pixbuf);
GtkWidget* icon_align = gtk_alignment_new(0, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(icon_align), limited_user_img);
@@ -184,7 +184,7 @@
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());
+ UTF16ToUTF8(avatar_menu_->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);
@@ -222,7 +222,7 @@
g_signal_connect(inner_contents_, "size-request",
G_CALLBACK(OnSizeRequestThunk), this);
- if (avatar_menu_model_->GetManagedUserInformation().empty() || switching_)
+ if (avatar_menu_->GetManagedUserInformation().empty() || switching_)
InitMenuContents();
else
InitManagedUserContents();
diff --git a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h
index f611f68..4515dcb 100644
--- a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h
+++ b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h
@@ -11,19 +11,19 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
-#include "chrome/browser/profiles/avatar_menu_model_observer.h"
+#include "chrome/browser/profiles/avatar_menu_observer.h"
#include "chrome/browser/ui/gtk/avatar_menu_item_gtk.h"
#include "chrome/browser/ui/gtk/bubble/bubble_gtk.h"
#include "ui/base/gtk/gtk_signal.h"
-class AvatarMenuModel;
+class AvatarMenu;
class Browser;
class GtkThemeService;
// This bubble is displayed when the user clicks on the avatar button.
// It displays a list of profiles and allows users to switch between profiles.
class AvatarMenuBubbleGtk : public BubbleDelegateGtk,
- public AvatarMenuModelObserver,
+ public AvatarMenuObserver,
public AvatarMenuItemGtk::Delegate {
public:
AvatarMenuBubbleGtk(Browser* browser,
@@ -36,9 +36,9 @@
virtual void BubbleClosing(BubbleGtk* bubble,
bool closed_by_escape) OVERRIDE;
- // AvatarMenuModelObserver implementation.
- virtual void OnAvatarMenuModelChanged(
- AvatarMenuModel* avatar_menu_model) OVERRIDE;
+ // AvatarMenuObserver implementation.
+ virtual void OnAvatarMenuChanged(
+ AvatarMenu* avatar_menu) OVERRIDE;
// AvatarMenuItemGtk::Delegate implementation.
virtual void OpenProfile(size_t profile_index) OVERRIDE;
@@ -65,7 +65,7 @@
void CloseBubble();
// A model of all the profile information to be displayed in the menu.
- scoped_ptr<AvatarMenuModel> avatar_menu_model_;
+ scoped_ptr<AvatarMenu> avatar_menu_;
// A weak pointer to the parent widget of all widgets in the bubble.
GtkWidget* contents_;
diff --git a/chrome/browser/ui/gtk/avatar_menu_item_gtk.cc b/chrome/browser/ui/gtk/avatar_menu_item_gtk.cc
index aabd490..f5b8bc1 100644
--- a/chrome/browser/ui/gtk/avatar_menu_item_gtk.cc
+++ b/chrome/browser/ui/gtk/avatar_menu_item_gtk.cc
@@ -44,7 +44,7 @@
} // namespace
AvatarMenuItemGtk::AvatarMenuItemGtk(Delegate* delegate,
- const AvatarMenuModel::Item& item,
+ const AvatarMenu::Item& item,
size_t item_index,
GtkThemeService* theme_service)
: delegate_(delegate),
@@ -201,8 +201,7 @@
// of the profile icon.
if (item_.active) {
const SkBitmap* avatar_image = item_.icon.ToSkBitmap();
- gfx::ImageSkiaRep avatar_image_rep =
- gfx::ImageSkiaRep(*avatar_image, ui::SCALE_FACTOR_100P);
+ gfx::ImageSkiaRep avatar_image_rep = gfx::ImageSkiaRep(*avatar_image, 1.0f);
gfx::Canvas canvas(avatar_image_rep, /* is_opaque */ true);
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
diff --git a/chrome/browser/ui/gtk/avatar_menu_item_gtk.h b/chrome/browser/ui/gtk/avatar_menu_item_gtk.h
index 5fe6655..058e134 100644
--- a/chrome/browser/ui/gtk/avatar_menu_item_gtk.h
+++ b/chrome/browser/ui/gtk/avatar_menu_item_gtk.h
@@ -7,7 +7,7 @@
#include <gtk/gtk.h>
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "ui/base/gtk/gtk_signal.h"
@@ -32,7 +32,7 @@
};
AvatarMenuItemGtk(Delegate* delegate,
- const AvatarMenuModel::Item& item,
+ const AvatarMenu::Item& item,
size_t item_index,
GtkThemeService* theme_service);
virtual ~AvatarMenuItemGtk();
@@ -73,7 +73,7 @@
Delegate* delegate_;
// Profile information to display for this item, e.g. user name, sync status.
- AvatarMenuModel::Item item_;
+ AvatarMenu::Item item_;
// The index of this profile. The delegate uses this value to distinguish
// which profile should be switched to.
diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc
index 50d0da6..b6679b5 100644
--- a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc
+++ b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc
@@ -15,7 +15,7 @@
#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/bookmarks/bookmark_stats.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -587,11 +587,10 @@
return count;
}
-bookmark_utils::BookmarkLaunchLocation
- BookmarkBarGtk::GetBookmarkLaunchLocation() const {
+BookmarkLaunchLocation BookmarkBarGtk::GetBookmarkLaunchLocation() const {
return bookmark_bar_state_ == BookmarkBar::DETACHED ?
- bookmark_utils::LAUNCH_DETACHED_BAR :
- bookmark_utils::LAUNCH_ATTACHED_BAR;
+ BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR :
+ BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR;
}
void BookmarkBarGtk::SetOverflowButtonAppearance() {
@@ -1187,7 +1186,7 @@
event_utils::DispositionForCurrentButtonPressEvent(),
browser_->profile());
- bookmark_utils::RecordBookmarkLaunch(GetBookmarkLaunchLocation());
+ RecordBookmarkLaunch(GetBookmarkLaunchLocation());
}
void BookmarkBarGtk::OnButtonDragBegin(GtkWidget* button,
@@ -1264,7 +1263,7 @@
content::PAGE_TRANSITION_AUTO_BOOKMARK,
false);
browser_->OpenURL(params);
- bookmark_utils::RecordAppsPageOpen(GetBookmarkLaunchLocation());
+ RecordBookmarkAppsPageOpen(GetBookmarkLaunchLocation());
}
void BookmarkBarGtk::OnFolderClicked(GtkWidget* sender) {
@@ -1277,7 +1276,7 @@
GdkEvent* event = gtk_get_current_event();
if (event->button.button == 1 ||
(event->button.button == 2 && sender == overflow_button_)) {
- bookmark_utils::RecordBookmarkFolderOpen(GetBookmarkLaunchLocation());
+ RecordBookmarkFolderOpen(GetBookmarkLaunchLocation());
PopupForButton(sender);
} else if (event->button.button == 2) {
const BookmarkNode* node = GetNodeForToolButton(sender);
diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.h b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.h
index d565a90..6db67ed 100644
--- a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.h
+++ b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.h
@@ -15,7 +15,7 @@
#include "base/memory/weak_ptr.h"
#include "base/prefs/pref_member.h"
#include "chrome/browser/bookmarks/bookmark_model_observer.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/ui/bookmarks/bookmark_bar.h"
#include "chrome/browser/ui/bookmarks/bookmark_bar_instructions_delegate.h"
#include "chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h"
@@ -143,8 +143,9 @@
// bookmark bar model has.
int GetBookmarkButtonCount();
- // Returns LAUNCH_DETACHED_BAR or LAUNCH_ATTACHED_BAR based on detached state.
- bookmark_utils::BookmarkLaunchLocation GetBookmarkLaunchLocation() const;
+ // Returns BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR or
+ // BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR based on detached state.
+ BookmarkLaunchLocation GetBookmarkLaunchLocation() const;
// Set the appearance of the overflow button appropriately (either chromium
// style or GTK style).
diff --git a/chrome/browser/ui/gtk/browser_titlebar.cc b/chrome/browser/ui/gtk/browser_titlebar.cc
index 3400691..42ce7c8 100644
--- a/chrome/browser/ui/gtk/browser_titlebar.cc
+++ b/chrome/browser/ui/gtk/browser_titlebar.cc
@@ -20,7 +20,7 @@
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -1089,7 +1089,7 @@
if (!browser_window_->browser()->is_type_tabbed())
return false;
- return AvatarMenuModel::ShouldShowAvatarMenu();
+ return AvatarMenu::ShouldShowAvatarMenu();
}
bool BrowserTitlebar::IsOffTheRecord() {
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc
index ebc5d2b..60460ef 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.cc
+++ b/chrome/browser/ui/gtk/browser_window_gtk.cc
@@ -790,6 +790,35 @@
toolbar_->GetLocationBarView()->SetStarred(is_starred);
}
+void BrowserWindowGtk::OnActiveTabChanged(WebContents* old_contents,
+ WebContents* new_contents,
+ int index,
+ int reason) {
+ TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::ActiveTabChanged");
+ if (old_contents && !old_contents->IsBeingDestroyed())
+ old_contents->GetView()->StoreFocus();
+
+ // Update various elements that are interested in knowing the current
+ // WebContents.
+ UpdateDevToolsForContents(new_contents);
+ infobar_container_->ChangeInfoBarService(
+ InfoBarService::FromWebContents(new_contents));
+ contents_container_->SetTab(new_contents);
+
+ // TODO(estade): after we manage browser activation, add a check to make sure
+ // we are the active browser before calling RestoreFocus().
+ if (!browser_->tab_strip_model()->closing_all()) {
+ new_contents->GetView()->RestoreFocus();
+ FindTabHelper* find_tab_helper =
+ FindTabHelper::FromWebContents(new_contents);
+ if (find_tab_helper->find_ui_active())
+ browser_->GetFindBarController()->find_bar()->SetFocusAndSelection();
+ }
+
+ // Update all the UI bits.
+ UpdateTitleBar();
+ MaybeShowBookmarkBar(false);
+}
void BrowserWindowGtk::ZoomChangedForActiveTab(bool can_show_bubble) {
toolbar_->GetLocationBarView()->ZoomChangedForActiveTab(
can_show_bubble && !toolbar_->IsWrenchMenuShowing());
@@ -1216,36 +1245,6 @@
contents_container_->DetachTab(contents);
}
-void BrowserWindowGtk::ActiveTabChanged(WebContents* old_contents,
- WebContents* new_contents,
- int index,
- int reason) {
- TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::ActiveTabChanged");
- if (old_contents && !old_contents->IsBeingDestroyed())
- old_contents->GetView()->StoreFocus();
-
- // Update various elements that are interested in knowing the current
- // WebContents.
- UpdateDevToolsForContents(new_contents);
- infobar_container_->ChangeInfoBarService(
- InfoBarService::FromWebContents(new_contents));
- contents_container_->SetTab(new_contents);
-
- // TODO(estade): after we manage browser activation, add a check to make sure
- // we are the active browser before calling RestoreFocus().
- if (!browser_->tab_strip_model()->closing_all()) {
- new_contents->GetView()->RestoreFocus();
- FindTabHelper* find_tab_helper =
- FindTabHelper::FromWebContents(new_contents);
- if (find_tab_helper->find_ui_active())
- browser_->GetFindBarController()->find_bar()->SetFocusAndSelection();
- }
-
- // Update all the UI bits.
- UpdateTitleBar();
- MaybeShowBookmarkBar(false);
-}
-
void BrowserWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
// Do nothing if we're in the process of closing the browser window.
if (!window_)
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h
index 1e6aa03..fc7e690 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.h
+++ b/chrome/browser/ui/gtk/browser_window_gtk.h
@@ -93,6 +93,10 @@
virtual void UpdateDevTools() OVERRIDE;
virtual void UpdateLoadingAnimations(bool should_animate) OVERRIDE;
virtual void SetStarredState(bool is_starred) OVERRIDE;
+ virtual void OnActiveTabChanged(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason) OVERRIDE;
virtual void ZoomChangedForActiveTab(bool can_show_bubble) OVERRIDE;
virtual gfx::Rect GetRestoredBounds() const OVERRIDE;
virtual ui::WindowShowState GetRestoredState() const OVERRIDE;
@@ -186,10 +190,6 @@
// Overridden from TabStripModelObserver:
virtual void TabDetachedAt(content::WebContents* contents,
int index) OVERRIDE;
- virtual void ActiveTabChanged(content::WebContents* old_contents,
- content::WebContents* new_contents,
- int index,
- int reason) OVERRIDE;
// Overridden from ActiveWindowWatcherXObserver.
virtual void ActiveWindowChanged(GdkWindow* active_window) OVERRIDE;
diff --git a/chrome/browser/ui/gtk/content_setting_bubble_gtk.cc b/chrome/browser/ui/gtk/content_setting_bubble_gtk.cc
index 4e82e8f..1760e19 100644
--- a/chrome/browser/ui/gtk/content_setting_bubble_gtk.cc
+++ b/chrome/browser/ui/gtk/content_setting_bubble_gtk.cc
@@ -195,11 +195,9 @@
radio_group.radio_items.begin();
i != radio_group.radio_items.end(); ++i) {
std::string elided = BuildElidedText(*i);
- GtkWidget* radio =
- radio_group_gtk_.empty() ?
- gtk_radio_button_new(NULL) :
- gtk_radio_button_new_from_widget(
- GTK_RADIO_BUTTON(radio_group_gtk_[0]));
+ GtkWidget* radio = radio_group_gtk_.empty() ?
+ gtk_radio_button_new(NULL) :
+ gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(radio_group_gtk_[0]));
GtkWidget* label =
theme_provider->BuildLabel(elided.c_str(), ui::kGdkBlack);
gtk_container_add(GTK_CONTAINER(radio), label);
@@ -221,12 +219,12 @@
// Layout code for the media device menus.
if (content_setting_bubble_model_->content_type() ==
- CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
+ CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
GtkWidget* table = gtk_table_new(content.media_menus.size(), 2, FALSE);
int menu_width = 0;
int row = 0;
- for (ContentSettingBubbleModel::MediaMenuMap::const_iterator
- i(content.media_menus.begin());
+ for (ContentSettingBubbleModel::MediaMenuMap::const_iterator i(
+ content.media_menus.begin());
i != content.media_menus.end();
++i, ++row) {
GtkWidget* label = theme_provider->BuildLabel(
@@ -259,21 +257,26 @@
media_menus_[button] = gtk_menu;
if (!gtk_menu->menu_model->GetItemCount()) {
- // Show a "None available" title and grey out the menu when there is no
- // available device.
+ // Show a "None available" title and grey out the menu when there is
+ // no available device.
UpdateMenuLabel(
gtk_menu->type,
l10n_util::GetStringUTF8(IDS_MEDIA_MENU_NO_DEVICE_TITLE));
gtk_widget_set_sensitive(button, FALSE);
}
+ // Disable the device selection when the website is managing the devices
+ // itself.
+ if (i->second.disabled)
+ gtk_widget_set_sensitive(button, FALSE);
+
// Use the longest width of the menus as the width of the menu buttons.
GtkRequisition menu_req;
gtk_widget_size_request(gtk_menu->menu->widget(), &menu_req);
menu_width = std::max(menu_width, menu_req.width);
- g_signal_connect(button, "clicked", G_CALLBACK(OnMenuButtonClickedThunk),
- this);
+ g_signal_connect(button, "clicked",
+ G_CALLBACK(OnMenuButtonClickedThunk), this);
gtk_table_attach(GTK_TABLE(table), button, 1, 2, row, row + 1,
GTK_FILL, GTK_FILL, ui::kControlSpacing * 2,
ui::kControlSpacing / 2);
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 065807d..bac15bf 100644
--- a/chrome/browser/ui/gtk/extensions/media_galleries_dialog_gtk.cc
+++ b/chrome/browser/ui/gtk/extensions/media_galleries_dialog_gtk.cc
@@ -102,27 +102,29 @@
checkbox_container);
}
- // Separator line and unattached volumes header text.
- GtkWidget* separator = gtk_hseparator_new();
- gtk_box_pack_start(GTK_BOX(checkbox_container), separator, FALSE, FALSE, 0);
-
- GtkWidget* unattached_hbox = gtk_hbox_new(FALSE, ui::kLabelSpacing);
- GtkWidget* unattached_text = gtk_label_new(UTF16ToUTF8(
- controller_->GetUnattachedLocationsHeader()).c_str());
- gtk_label_set_line_wrap(GTK_LABEL(unattached_text), FALSE);
- gtk_box_pack_start(GTK_BOX(unattached_hbox), unattached_text,
- FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(checkbox_container), unattached_hbox,
- FALSE, FALSE, 0);
-
- // Unattached galleries checkboxes
const GalleryPermissionsVector unattached_permissions =
controller_->UnattachedPermissions();
- for (GalleryPermissionsVector::const_iterator iter =
- unattached_permissions.begin();
- iter != unattached_permissions.end(); ++iter) {
- UpdateGalleryInContainer(iter->pref_info, iter->allowed,
- checkbox_container);
+ if (!unattached_permissions.empty()) {
+ // Separator line and unattached volumes header text.
+ GtkWidget* separator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(checkbox_container), separator, FALSE, FALSE, 0);
+
+ GtkWidget* unattached_hbox = gtk_hbox_new(FALSE, ui::kLabelSpacing);
+ GtkWidget* unattached_text = gtk_label_new(UTF16ToUTF8(
+ controller_->GetUnattachedLocationsHeader()).c_str());
+ gtk_label_set_line_wrap(GTK_LABEL(unattached_text), FALSE);
+ gtk_box_pack_start(GTK_BOX(unattached_hbox), unattached_text,
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(checkbox_container), unattached_hbox,
+ FALSE, FALSE, 0);
+
+ // Unattached galleries checkboxes
+ for (GalleryPermissionsVector::const_iterator iter =
+ unattached_permissions.begin();
+ iter != unattached_permissions.end(); ++iter) {
+ UpdateGalleryInContainer(iter->pref_info, iter->allowed,
+ checkbox_container);
+ }
}
GtkWidget* bottom_area = gtk_hbox_new(FALSE, ui::kControlSpacing);
@@ -188,6 +190,7 @@
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), permitted);
std::string label = UTF16ToUTF8(gallery.GetGalleryDisplayName());
+ // TODO(gbillock): Would be nice to add middle elide behavior here.
gtk_button_set_label(GTK_BUTTON(widget), label.c_str());
}
diff --git a/chrome/browser/ui/gtk/gtk_theme_service.cc b/chrome/browser/ui/gtk/gtk_theme_service.cc
index 97e0ec5..a4d3562 100644
--- a/chrome/browser/ui/gtk/gtk_theme_service.cc
+++ b/chrome/browser/ui/gtk/gtk_theme_service.cc
@@ -1040,7 +1040,7 @@
SkColor base = it->second;
gfx::Canvas canvas(gfx::Size(kToolbarImageWidth, kToolbarImageHeight),
- ui::SCALE_FACTOR_100P, true);
+ 1.0f, true);
int gradient_size;
GdkColor* gradient_top_color = NULL;
diff --git a/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.cc b/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.cc
index c12d975..0575aea 100644
--- a/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.cc
+++ b/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.cc
@@ -171,7 +171,7 @@
static const int kDropArrowLeftMargin = 3;
scoped_ptr<gfx::Canvas> canvas(new gfx::Canvas(
gfx::Size(image_size + kDropArrowLeftMargin + drop_image->width(),
- image_size), ui::SCALE_FACTOR_100P, false));
+ image_size), 1.0f, false));
canvas->DrawImageInt(*icon, 0, 0, icon->width(), icon->height(), 0, 0,
image_size, image_size, false);
canvas->DrawImageInt(*drop_image, image_size + kDropArrowLeftMargin,
diff --git a/chrome/browser/ui/gtk/panels/panel_gtk.cc b/chrome/browser/ui/gtk/panels/panel_gtk.cc
index 73678c7..c45b6ea 100644
--- a/chrome/browser/ui/gtk/panels/panel_gtk.cc
+++ b/chrome/browser/ui/gtk/panels/panel_gtk.cc
@@ -144,7 +144,7 @@
}
gfx::Image CreateImageForColor(SkColor color) {
- gfx::Canvas canvas(gfx::Size(1, 1), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(1, 1), 1.0f, true);
canvas.DrawColor(color);
return gfx::Image(gfx::ImageSkia(canvas.ExtractImageRep()));
}
@@ -994,8 +994,17 @@
}
void PanelGtk::FullScreenModeChanged(bool is_full_screen) {
- // Nothing to do here as z-order rules for panels ensures that they're below
- // any app running in full screen mode.
+ // No need to hide panels when entering the full-screen mode because the
+ // full-screen window will automatically be placed above all other windows.
+ if (is_full_screen)
+ return;
+
+ // Show the panel if not yet when leaving the full-screen mode. This is
+ // because the panel is not shown when it is being created under full-screen
+ // mode.
+ GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_));
+ if (!GDK_IS_WINDOW(gdk_window) || !gdk_window_is_visible(gdk_window))
+ ShowPanelInactive();
}
void PanelGtk::PanelExpansionStateChanging(
@@ -1105,6 +1114,7 @@
virtual bool VerifyActiveState(bool is_active) OVERRIDE;
virtual bool VerifyAppIcon() const OVERRIDE;
virtual bool VerifySystemMinimizeState() const OVERRIDE;
+ virtual bool IsWindowVisible() const OVERRIDE;
virtual bool IsWindowSizeKnown() const OVERRIDE;
virtual bool IsAnimatingBounds() const OVERRIDE;
virtual bool IsButtonVisible(
@@ -1200,6 +1210,12 @@
return true;
}
+bool GtkNativePanelTesting::IsWindowVisible() const {
+ GdkWindow* gdk_window =
+ gtk_widget_get_window(GTK_WIDGET(panel_gtk_->GetNativePanelWindow()));
+ return GDK_IS_WINDOW(gdk_window) && gdk_window_is_visible(gdk_window);
+}
+
bool GtkNativePanelTesting::IsWindowSizeKnown() const {
return !GetFrameSize().IsEmpty();
}
diff --git a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc
index da3ab4b..ed447e2 100644
--- a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc
+++ b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc
@@ -89,8 +89,6 @@
// Duration for when the title of an inactive mini-tab changes.
const int kMiniTitleChangeThrobDuration = 1000;
-const int kRecordingDurationMs = 1000;
-
// The horizontal offset used to position the close button in the tab.
const int kCloseButtonHorzFuzz = 4;
@@ -711,15 +709,16 @@
g_object_unref(pixbuf);
if (!favicon_overlay_animation_.get()) {
- favicon_overlay_animation_.reset(new gfx::ThrobAnimation(this));
- favicon_overlay_animation_->SetThrobDuration(kRecordingDurationMs);
+ favicon_overlay_animation_ =
+ chrome::CreateTabRecordingIndicatorAnimation();
+ favicon_overlay_animation_->set_delegate(this);
}
if (!favicon_overlay_animation_->is_animating())
- favicon_overlay_animation_->StartThrobbing(-1);
+ favicon_overlay_animation_->Start();
} else {
data_.cairo_overlay.Reset();
if (favicon_overlay_animation_.get())
- favicon_overlay_animation_->Stop();
+ favicon_overlay_animation_.reset();
}
}
@@ -946,8 +945,7 @@
cairo_paint(cr);
}
- if (data_.cairo_overlay.valid() && favicon_overlay_animation_.get() &&
- favicon_overlay_animation_->is_animating()) {
+ if (data_.cairo_overlay.valid() && favicon_overlay_animation_.get()) {
if (data_.capture_state == PROJECTING) {
theme_service_->GetImageNamed(IDR_TAB_CAPTURE).ToCairo()->
SetSource(cr,
diff --git a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h
index 4735bdb..a1b9fcc 100644
--- a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h
+++ b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h
@@ -411,7 +411,7 @@
scoped_ptr<gfx::ThrobAnimation> mini_title_animation_;
// Animation used when the favicon has an overlay (e.g. for recording).
- scoped_ptr<gfx::ThrobAnimation> favicon_overlay_animation_;
+ scoped_ptr<gfx::Animation> favicon_overlay_animation_;
// Contains the loading animation state.
LoadingAnimation loading_animation_;
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
index 5c66d9d..8b58624 100644
--- a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
+++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
@@ -83,7 +83,6 @@
const int kSkiaToGDKMultiplier = 257;
-
// TODO(erg): ThemeService has a whole interface just for reading default
// constants. Figure out what to do with that more long term; for now, just
// copy the constants themselves here.
@@ -364,6 +363,58 @@
return IsOverridableImage(id);
}
+SkColor Gtk2UI::GetFocusRingColor() const {
+ return focus_ring_color_;
+}
+
+SkColor Gtk2UI::GetThumbActiveColor() const {
+ return thumb_active_color_;
+}
+
+SkColor Gtk2UI::GetThumbInactiveColor() const {
+ return thumb_inactive_color_;
+}
+
+SkColor Gtk2UI::GetTrackColor() const {
+ return track_color_;
+}
+
+SkColor Gtk2UI::GetActiveSelectionBgColor() const {
+ return active_selection_bg_color_;
+}
+
+SkColor Gtk2UI::GetActiveSelectionFgColor() const {
+ return active_selection_fg_color_;
+}
+
+SkColor Gtk2UI::GetInactiveSelectionBgColor() const {
+ return inactive_selection_bg_color_;
+}
+
+SkColor Gtk2UI::GetInactiveSelectionFgColor() const {
+ return inactive_selection_fg_color_;
+}
+
+double Gtk2UI::GetCursorBlinkInterval() const {
+ // From http://library.gnome.org/devel/gtk/unstable/GtkSettings.html, this is
+ // the default value for gtk-cursor-blink-time.
+ static const gint kGtkDefaultCursorBlinkTime = 1200;
+
+ // Dividing GTK's cursor blink cycle time (in milliseconds) by this value
+ // yields an appropriate value for
+ // content::RendererPreferences::caret_blink_interval. This matches the
+ // logic in the WebKit GTK port.
+ static const double kGtkCursorBlinkCycleFactor = 2000.0;
+
+ gint cursor_blink_time = kGtkDefaultCursorBlinkTime;
+ gboolean cursor_blink = TRUE;
+ g_object_get(gtk_settings_get_default(),
+ "gtk-cursor-blink-time", &cursor_blink_time,
+ "gtk-cursor-blink", &cursor_blink,
+ NULL);
+ return cursor_blink ? (cursor_blink_time / kGtkCursorBlinkCycleFactor) : 0.0;
+}
+
ui::NativeTheme* Gtk2UI::GetNativeTheme() const {
return NativeThemeGtk2::instance();
}
@@ -868,7 +919,7 @@
SkColor base = it->second;
gfx::Canvas canvas(gfx::Size(kToolbarImageWidth, kToolbarImageHeight),
- ui::SCALE_FACTOR_100P, true);
+ 1.0f, true);
int gradient_size;
GdkColor* gradient_top_color = NULL;
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.h b/chrome/browser/ui/libgtk2ui/gtk2_ui.h
index ab2b6e7..da6e908 100644
--- a/chrome/browser/ui/libgtk2ui/gtk2_ui.h
+++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.h
@@ -51,6 +51,15 @@
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 SkColor GetFocusRingColor() const OVERRIDE;
+ virtual SkColor GetThumbActiveColor() const OVERRIDE;
+ virtual SkColor GetThumbInactiveColor() const OVERRIDE;
+ virtual SkColor GetTrackColor() const OVERRIDE;
+ virtual SkColor GetActiveSelectionBgColor() const OVERRIDE;
+ virtual SkColor GetActiveSelectionFgColor() const OVERRIDE;
+ virtual SkColor GetInactiveSelectionBgColor() const OVERRIDE;
+ virtual SkColor GetInactiveSelectionFgColor() const OVERRIDE;
+ virtual double GetCursorBlinkInterval() const OVERRIDE;
virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
virtual bool GetDefaultUsesSystemTheme() const OVERRIDE;
virtual void SetDownloadCount(int count) const OVERRIDE;
diff --git a/chrome/browser/ui/login/login_prompt_browsertest.cc b/chrome/browser/ui/login/login_prompt_browsertest.cc
index f7252ab..d8cb7e4 100644
--- a/chrome/browser/ui/login/login_prompt_browsertest.cc
+++ b/chrome/browser/ui/login/login_prompt_browsertest.cc
@@ -203,14 +203,12 @@
typedef WindowedNavigationObserver<chrome::NOTIFICATION_AUTH_SUPPLIED>
WindowedAuthSuppliedObserver;
-const char* kPrefetchAuthPage = "files/login/prefetch.html";
+const char kPrefetchAuthPage[] = "files/login/prefetch.html";
-const char* kMultiRealmTestPage = "files/login/multi_realm.html";
-const int kMultiRealmTestRealmCount = 2;
-const int kMultiRealmTestResourceCount = 4;
+const char kMultiRealmTestPage[] = "files/login/multi_realm.html";
+const int kMultiRealmTestRealmCount = 2;
-const char* kSingleRealmTestPage = "files/login/single_realm.html";
-const int kSingleRealmTestResourceCount = 6;
+const char kSingleRealmTestPage[] = "files/login/single_realm.html";
const char* kAuthBasicPage = "auth-basic";
const char* kAuthDigestPage = "auth-digest";
diff --git a/chrome/browser/ui/metro_pin_tab_helper_win.cc b/chrome/browser/ui/metro_pin_tab_helper_win.cc
index 064bccf..58255d7 100644
--- a/chrome/browser/ui/metro_pin_tab_helper_win.cc
+++ b/chrome/browser/ui/metro_pin_tab_helper_win.cc
@@ -85,7 +85,7 @@
SkColor dominant_color = color_utils::CalculateKMeanColorOfBitmap(bitmap);
SkPaint paint;
paint.setColor(dominant_color);
- gfx::Canvas canvas(gfx::Size(kLogoWidth, kLogoHeight), ui::SCALE_FACTOR_100P,
+ gfx::Canvas canvas(gfx::Size(kLogoWidth, kLogoHeight), 1.0f,
true);
canvas.DrawRect(gfx::Rect(0, 0, kLogoWidth, kLogoHeight), paint);
@@ -381,7 +381,7 @@
if (favicon_tab_helper->FaviconIsValid()) {
// Only the 1x bitmap data is needed.
favicon = favicon_tab_helper->GetFavicon().AsImageSkia().GetRepresentation(
- ui::SCALE_FACTOR_100P).sk_bitmap();
+ 1.0f).sk_bitmap();
}
favicon_chooser_.reset(new FaviconChooser(this, title, url_str, favicon));
diff --git a/chrome/browser/ui/network_profile_bubble.cc b/chrome/browser/ui/network_profile_bubble.cc
index c2169b1..6de46c3 100644
--- a/chrome/browser/ui/network_profile_bubble.cc
+++ b/chrome/browser/ui/network_profile_bubble.cc
@@ -128,7 +128,7 @@
// Try to create some non-empty temp file in the profile dir and use
// it to check if there is a reparse-point free path to it.
if (file_util::CreateTemporaryFileInDir(profile_folder, &temp_file) &&
- file_util::WriteFile(temp_file, ".", 1)) {
+ (file_util::WriteFile(temp_file, ".", 1) == 1)) {
base::FilePath normalized_temp_file;
if (!file_util::NormalizeFilePath(temp_file, &normalized_temp_file))
profile_on_network = true;
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
index 0893a93..f643364 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
@@ -22,7 +22,7 @@
#include "chrome/browser/autocomplete/history_url_provider.h"
#include "chrome/browser/autocomplete/keyword_provider.h"
#include "chrome/browser/autocomplete/search_provider.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
@@ -772,7 +772,7 @@
}
if (match.starred)
- bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_OMNIBOX);
+ RecordBookmarkLaunch(BOOKMARK_LAUNCH_LOCATION_OMNIBOX);
}
bool OmniboxEditModel::AcceptKeyword(EnteredKeywordModeMethod entered_method) {
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index 8a3b3d8..9f39b0e 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -68,8 +68,6 @@
const wchar_t kSearchSingleCharKeys[] = { ui::VKEY_Z, 0 };
const char kSearchSingleCharURL[] = "http://www.foo.com/search?q=z";
-const char kHistoryPageURL[] = "chrome://history/#q=abc";
-
const char kDesiredTLDHostname[] = "www.bar.com";
const wchar_t kDesiredTLDKeys[] = { ui::VKEY_B, ui::VKEY_A, ui::VKEY_R, 0 };
@@ -1286,7 +1284,7 @@
}
// http://crbug.com/158913
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_WIN)
#define MAYBE_Escape DISABLED_Escape
#else
#define MAYBE_Escape Escape
diff --git a/chrome/browser/ui/panels/base_panel_browser_test.cc b/chrome/browser/ui/panels/base_panel_browser_test.cc
index c14adb1..4f0f123 100644
--- a/chrome/browser/ui/panels/base_panel_browser_test.cc
+++ b/chrome/browser/ui/panels/base_panel_browser_test.cc
@@ -80,6 +80,7 @@
DesktopBarAlignment alignment) const OVERRIDE;
virtual DesktopBarVisibility GetDesktopBarVisibility(
DesktopBarAlignment alignment) const OVERRIDE;
+ virtual bool IsFullScreen() OVERRIDE;
// Overridden from MockDisplaySettingsProvider:
virtual void SetPrimaryDisplay(
@@ -93,6 +94,7 @@
DesktopBarAlignment alignment, DesktopBarVisibility visibility) OVERRIDE;
virtual void SetDesktopBarThickness(DesktopBarAlignment alignment,
int thickness) OVERRIDE;
+ virtual void EnableFullScreenMode(bool enabled) OVERRIDE;
private:
gfx::Rect primary_display_area_;
@@ -100,12 +102,14 @@
gfx::Rect secondary_display_area_;
gfx::Rect secondary_work_area_;
MockDesktopBar mock_desktop_bars[3];
+ bool full_screen_enabled_;
DISALLOW_COPY_AND_ASSIGN(MockDisplaySettingsProviderImpl);
};
-MockDisplaySettingsProviderImpl::MockDisplaySettingsProviderImpl() {
+MockDisplaySettingsProviderImpl::MockDisplaySettingsProviderImpl()
+ : full_screen_enabled_(false) {
memset(mock_desktop_bars, 0, sizeof(mock_desktop_bars));
}
@@ -171,6 +175,10 @@
return mock_desktop_bars[static_cast<int>(alignment)].visibility;
}
+bool MockDisplaySettingsProviderImpl::IsFullScreen() {
+ return full_screen_enabled_;
+}
+
void MockDisplaySettingsProviderImpl::EnableAutoHidingDesktopBar(
DesktopBarAlignment alignment, bool enabled, int thickness) {
MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]);
@@ -222,6 +230,11 @@
OnAutoHidingDesktopBarThicknessChanged(alignment, thickness));
}
+void MockDisplaySettingsProviderImpl::EnableFullScreenMode(bool enabled) {
+ full_screen_enabled_ = enabled;
+ CheckFullScreenMode(PERFORM_FULLSCREEN_CHECK);
+}
+
} // namespace
const base::FilePath::CharType* BasePanelBrowserTest::kTestDir =
diff --git a/chrome/browser/ui/panels/base_panel_browser_test.h b/chrome/browser/ui/panels/base_panel_browser_test.h
index abda71c..79806a9 100644
--- a/chrome/browser/ui/panels/base_panel_browser_test.h
+++ b/chrome/browser/ui/panels/base_panel_browser_test.h
@@ -36,6 +36,7 @@
DesktopBarVisibility visibility) = 0;
virtual void SetDesktopBarThickness(DesktopBarAlignment alignment,
int thickness) = 0;
+ virtual void EnableFullScreenMode(bool enabled) = 0;
};
BasePanelBrowserTest();
diff --git a/chrome/browser/ui/panels/detached_panel_browsertest.cc b/chrome/browser/ui/panels/detached_panel_browsertest.cc
index 1f54da4..04d7913 100644
--- a/chrome/browser/ui/panels/detached_panel_browsertest.cc
+++ b/chrome/browser/ui/panels/detached_panel_browsertest.cc
@@ -207,3 +207,48 @@
panel_manager->CloseAll();
}
+
+IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest,
+ KeepShowingDetachedPanelCreatedBeforeFullScreenMode) {
+ // Create a detached panel.
+ CreatePanelParams params("1", gfx::Rect(300, 200, 250, 200), SHOW_AS_ACTIVE);
+ params.create_mode = PanelManager::CREATE_AS_DETACHED;
+ Panel* panel = CreatePanelWithParams(params);
+ scoped_ptr<NativePanelTesting> panel_testing(CreateNativePanelTesting(panel));
+
+ // Panel should be visible at first.
+ EXPECT_TRUE(panel_testing->IsWindowVisible());
+
+ // Panel's visibility should not be affected when entering full-screen mode.
+ mock_display_settings_provider()->EnableFullScreenMode(true);
+ EXPECT_TRUE(panel_testing->IsWindowVisible());
+
+ // Panel's visibility should not be affected when leaving full-screen mode.
+ mock_display_settings_provider()->EnableFullScreenMode(false);
+ EXPECT_TRUE(panel_testing->IsWindowVisible());
+
+ PanelManager::GetInstance()->CloseAll();
+}
+
+IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest,
+ HideDetachedPanelCreatedOnFullScreenMode) {
+ // Enable full-screen mode first.
+ mock_display_settings_provider()->EnableFullScreenMode(true);
+
+ // Create a detached panel without waiting it to be shown since it is not
+ // supposed to be shown on full-screen mode.
+ CreatePanelParams params("1", gfx::Rect(300, 200, 250, 200), SHOW_AS_ACTIVE);
+ params.create_mode = PanelManager::CREATE_AS_DETACHED;
+ params.wait_for_fully_created = false;
+ Panel* panel = CreatePanelWithParams(params);
+ scoped_ptr<NativePanelTesting> panel_testing(CreateNativePanelTesting(panel));
+
+ // Panel should not be shown on full-screen mode.
+ EXPECT_FALSE(panel_testing->IsWindowVisible());
+
+ // Panel should become visible when leaving full-screen mode.
+ mock_display_settings_provider()->EnableFullScreenMode(false);
+ EXPECT_TRUE(panel_testing->IsWindowVisible());
+
+ PanelManager::GetInstance()->CloseAll();
+}
diff --git a/chrome/browser/ui/panels/native_panel.h b/chrome/browser/ui/panels/native_panel.h
index 0ad1134..f870d5b 100644
--- a/chrome/browser/ui/panels/native_panel.h
+++ b/chrome/browser/ui/panels/native_panel.h
@@ -132,6 +132,7 @@
// minimized by the system.
virtual bool VerifySystemMinimizeState() const = 0;
+ virtual bool IsWindowVisible() const = 0;
virtual bool IsWindowSizeKnown() const = 0;
virtual bool IsAnimatingBounds() const = 0;
virtual bool IsButtonVisible(panel::TitlebarButtonType button_type) const = 0;
diff --git a/chrome/browser/ui/panels/panel_browsertest.cc b/chrome/browser/ui/panels/panel_browsertest.cc
index e429973..341c903 100644
--- a/chrome/browser/ui/panels/panel_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browsertest.cc
@@ -1715,6 +1715,55 @@
EXPECT_EQ(0, panel_manager->num_panels());
}
+IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
+ HideDockedPanelCreatedBeforeFullScreenMode) {
+ // Create a docked panel.
+ Panel* panel = CreatePanel("PanelTest");
+ scoped_ptr<NativePanelTesting> panel_testing(CreateNativePanelTesting(panel));
+
+ // Panel should be visible at first.
+ EXPECT_TRUE(panel_testing->IsWindowVisible());
+
+ // Panel should become hidden when entering full-screen mode.
+ // Note that this is not needed on Linux because the full-screen window will
+ // be always placed above any other windows.
+ mock_display_settings_provider()->EnableFullScreenMode(true);
+#if defined(OS_LINUX)
+ EXPECT_TRUE(panel_testing->IsWindowVisible());
+#else
+ EXPECT_FALSE(panel_testing->IsWindowVisible());
+#endif
+
+ // Panel should become visible when leaving full-screen mode.
+ mock_display_settings_provider()->EnableFullScreenMode(false);
+ EXPECT_TRUE(panel_testing->IsWindowVisible());
+
+ PanelManager::GetInstance()->CloseAll();
+}
+
+IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
+ HideDockedPanelCreatedOnFullScreenMode) {
+ // Enable full-screen mode first.
+ mock_display_settings_provider()->EnableFullScreenMode(true);
+
+ // Create a docked panel without waiting for it to be shown since it is not
+ // supposed to be shown on full-screen mode.
+ CreatePanelParams params("1", gfx::Rect(0, 0, 250, 200), SHOW_AS_ACTIVE);
+ params.wait_for_fully_created = false;
+ Panel* panel = CreatePanelWithParams(params);
+ scoped_ptr<NativePanelTesting> panel_testing(
+ CreateNativePanelTesting(panel));
+
+ // Panel should not be shown on full-screen mode.
+ EXPECT_FALSE(panel_testing->IsWindowVisible());
+
+ // Panel should become visible when leaving full-screen mode.
+ mock_display_settings_provider()->EnableFullScreenMode(false);
+ EXPECT_TRUE(panel_testing->IsWindowVisible());
+
+ PanelManager::GetInstance()->CloseAll();
+}
+
class PanelExtensionApiTest : public ExtensionApiTest {
protected:
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
diff --git a/chrome/browser/ui/panels/panel_manager.cc b/chrome/browser/ui/panels/panel_manager.cc
index 837e30c..9553849 100644
--- a/chrome/browser/ui/panels/panel_manager.cc
+++ b/chrome/browser/ui/panels/panel_manager.cc
@@ -206,12 +206,7 @@
std::vector<Panel*> all_panels = panels();
for (std::vector<Panel*>::const_iterator iter = all_panels.begin();
iter != all_panels.end(); ++iter) {
- Panel* panel = *iter;
- PanelCollection* panel_collection = panel->collection();
- // When the panel is not always on top, there is no need to hide/show
- // the panel in response to entering/leaving full-screen mode.
- if (panel_collection && panel_collection->UsesAlwaysOnTopPanels())
- panel->FullScreenModeChanged(is_full_screen);
+ (*iter)->FullScreenModeChanged(is_full_screen);
}
}
diff --git a/chrome/browser/ui/panels/stacked_panel_browsertest.cc b/chrome/browser/ui/panels/stacked_panel_browsertest.cc
index a8e30d3..42103aa 100644
--- a/chrome/browser/ui/panels/stacked_panel_browsertest.cc
+++ b/chrome/browser/ui/panels/stacked_panel_browsertest.cc
@@ -1453,3 +1453,33 @@
panel_manager->CloseAll();
}
+
+IN_PROC_BROWSER_TEST_F(StackedPanelBrowserTest,
+ KeepShowingStackedPanelCreatedBeforeFullScreenMode) {
+ PanelManager* panel_manager = PanelManager::GetInstance();
+
+ // Create 2 stacked panels.
+ StackedPanelCollection* stack = panel_manager->CreateStack();
+ Panel* panel1 = CreateStackedPanel("1", gfx::Rect(100, 50, 200, 150), stack);
+ Panel* panel2 = CreateStackedPanel("2", gfx::Rect(0, 0, 150, 100), stack);
+ scoped_ptr<NativePanelTesting> panel1_testing(
+ CreateNativePanelTesting(panel1));
+ scoped_ptr<NativePanelTesting> panel2_testing(
+ CreateNativePanelTesting(panel2));
+
+ // Panels should be visible at first.
+ EXPECT_TRUE(panel1_testing->IsWindowVisible());
+ EXPECT_TRUE(panel2_testing->IsWindowVisible());
+
+ // Panels' visibility should not be affected when entering full-screen mode.
+ mock_display_settings_provider()->EnableFullScreenMode(true);
+ EXPECT_TRUE(panel1_testing->IsWindowVisible());
+ EXPECT_TRUE(panel2_testing->IsWindowVisible());
+
+ // Panels' visibility should not be affected when leaving full-screen mode.
+ mock_display_settings_provider()->EnableFullScreenMode(false);
+ EXPECT_TRUE(panel1_testing->IsWindowVisible());
+ EXPECT_TRUE(panel2_testing->IsWindowVisible());
+
+ panel_manager->CloseAll();
+}
diff --git a/chrome/browser/ui/pdf/pdf_unsupported_feature.cc b/chrome/browser/ui/pdf/pdf_unsupported_feature.cc
index fde1364..520b951 100644
--- a/chrome/browser/ui/pdf/pdf_unsupported_feature.cc
+++ b/chrome/browser/ui/pdf/pdf_unsupported_feature.cc
@@ -54,9 +54,11 @@
namespace {
-static const char kAdobeReaderIdentifier[] = "adobe-reader";
-static const char kAdobeReaderUpdateUrl[] =
- "http://www.adobe.com/go/getreader_chrome";
+const char kAdobeReaderUpdateUrl[] = "http://www.adobe.com/go/getreader_chrome";
+
+#if defined(OS_WIN) && defined(ENABLE_PLUGIN_INSTALLATION)
+const char kAdobeReaderIdentifier[] = "adobe-reader";
+#endif
// The prompt delegate used to ask the user if they want to use Adobe Reader
// by default.
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc
index 4a0e3aa..db0b657 100644
--- a/chrome/browser/ui/prefs/prefs_tab_helper.cc
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc
@@ -424,6 +424,10 @@
pref_change_registrar_.Add(prefs::kEnableDoNotTrack, renderer_callback);
pref_change_registrar_.Add(prefs::kEnableReferrers, renderer_callback);
+#if !defined(OS_MACOSX)
+ pref_change_registrar_.Add(prefs::kFullscreenAllowed, renderer_callback);
+#endif
+
PrefChangeRegistrar::NamedChangeCallback webkit_callback = base::Bind(
&PrefsTabHelper::OnWebPrefChanged, base::Unretained(this));
for (int i = 0; i < kPrefsToObserveLength; ++i) {
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.h b/chrome/browser/ui/prefs/prefs_tab_helper.h
index 6a09ed1..431c48e 100644
--- a/chrome/browser/ui/prefs/prefs_tab_helper.h
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.h
@@ -58,7 +58,7 @@
content::NotificationRegistrar registrar_;
PrefChangeRegistrar pref_change_registrar_;
base::WeakPtrFactory<PrefsTabHelper> weak_ptr_factory_;
- scoped_ptr<base::CallbackRegistry<void>::Subscription>
+ scoped_ptr<base::CallbackRegistry<void(void)>::Subscription>
style_sheet_subscription_;
DISALLOW_COPY_AND_ASSIGN(PrefsTabHelper);
diff --git a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
index 2459c6c..a1142c5 100644
--- a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
+++ b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
@@ -367,25 +367,6 @@
DISALLOW_COPY_AND_ASSIGN(InstantPolicyTest);
};
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, ExtendedModeIsOn) {
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- EXPECT_TRUE(chrome::IsInstantExtendedAPIEnabled());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NTPIsPreloaded) {
- // Setup Instant.
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- 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
-
IN_PROC_BROWSER_TEST_F(InstantExtendedNetworkTest, NTPReactsToNetworkChanges) {
// Setup Instant.
ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
@@ -461,658 +442,6 @@
EXPECT_TRUE(instant_service->ntp_prerenderer()->ntp()->IsLocal());
}
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPIsUsedInSameTab) {
- // Setup Instant.
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- 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);
-
- // Open new tab. Preloaded NTP contents should have been used.
- ui_test_utils::NavigateToURLWithDisposition(
- browser(),
- GURL(chrome::kChromeUINewTabURL),
- CURRENT_TAB,
- ui_test_utils::BROWSER_TEST_NONE);
- content::WebContents* active_tab =
- browser()->tab_strip_model()->GetActiveWebContents();
- EXPECT_EQ(ntp_contents, active_tab);
- EXPECT_TRUE(chrome::IsInstantNTP(active_tab));
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPForWrongProvider) {
- // Setup Instant.
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- 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);
- GURL ntp_url = ntp_contents->GetURL();
-
- // Change providers.
- SetInstantURL("chrome://blank");
-
- // Open new tab. Preloaded NTP contents should have not 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_NE(ntp_url, active_tab->GetURL());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPRenderProcessGone) {
- // Setup Instant.
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- // NTP contents should be preloaded.
- ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
- EXPECT_FALSE(instant()->ntp()->IsLocal());
-
- // NTP not reloaded after being killed.
- instant()->InstantPageRenderProcessGone(instant()->ntp()->contents());
- EXPECT_EQ(NULL, instant()->ntp());
-
- // Open new tab. Should use local NTP.
- 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_EQ(instant()->GetLocalInstantURL(), active_tab->GetURL().spec());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPDoesntSupportInstant) {
- // Setup Instant.
- GURL instant_url = test_server()->GetURL("files/empty.html?strk=1");
- InstantTestBase::Init(instant_url);
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- // NTP contents should have fallen back to the local page.
- ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
- EXPECT_TRUE(instant()->ntp()->IsLocal());
-
- // Open new tab. Should use local NTP.
- 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_EQ(instant()->GetLocalInstantURL(), active_tab->GetURL().spec());
-}
-
-// Flaky, http://crbug.com/240852 .
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_OmniboxHasFocusOnNewTab) {
- // Setup Instant.
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- // Explicitly unfocus the omnibox.
- EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
- ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
- EXPECT_FALSE(omnibox()->model()->has_focus());
-
- // 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);
-
- // Omnibox should have focus.
- EXPECT_TRUE(omnibox()->model()->has_focus());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxEmptyOnNewTabPage) {
- // 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);
-
- // Omnibox should be empty.
- EXPECT_TRUE(omnibox()->GetText().empty());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NoFaviconOnNewTabPage) {
- // 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);
-
- // No favicon should be shown.
- content::WebContents* active_tab =
- browser()->tab_strip_model()->GetActiveWebContents();
- FaviconTabHelper* favicon_tab_helper =
- FaviconTabHelper::FromWebContents(active_tab);
- EXPECT_FALSE(favicon_tab_helper->ShouldDisplayFavicon());
-
- // Favicon should be shown off the NTP.
- ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL));
- active_tab = browser()->tab_strip_model()->GetActiveWebContents();
- favicon_tab_helper = FaviconTabHelper::FromWebContents(active_tab);
- EXPECT_TRUE(favicon_tab_helper->ShouldDisplayFavicon());
-}
-
-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()));
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- // Get a handle to the NTP and the current state of the JS.
- ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
- 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(ntp));
- }
-
- EXPECT_EQ(1, on_most_visited_change_calls_);
-
- // Make sure we have at least two Most Visited Items and save that number.
- // TODO(pedrosimonetti): For now, we're relying on the fact that the Top
- // Sites will have at lease two items in it. The correct approach would be
- // adding those items to the Top Sites manually before starting the test.
- EXPECT_GT(most_visited_items_count_, 1);
- int old_most_visited_items_count = most_visited_items_count_;
-
- // Delete the fist Most Visited Item.
- int rid = first_most_visited_item_id_;
- std::ostringstream stream;
- stream << "newTabPageHandle.deleteMostVisitedItem(" << rid << ");";
- EXPECT_TRUE(content::ExecuteScript(ntp, stream.str()));
- observer.Wait();
-
- // Update Most Visited state.
- 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);
-
- // Undo the deletion of the fist Most Visited Item.
- stream.str(std::string());
- stream << "newTabPageHandle.undoMostVisitedDeletion(" << rid << ");";
- EXPECT_TRUE(content::ExecuteScript(ntp, stream.str()));
- observer.Wait();
-
- // Update Most Visited state.
- 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);
-
- // Delete the fist Most Visited Item.
- rid = first_most_visited_item_id_;
- stream.str(std::string());
- stream << "newTabPageHandle.deleteMostVisitedItem(" << rid << ");";
- EXPECT_TRUE(content::ExecuteScript(ntp, stream.str()));
- observer.Wait();
-
- // Update Most Visited state.
- 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(content::ExecuteScript(ntp, stream.str()));
- observer.Wait();
-
- // Update Most Visited state.
- 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);
-
- // Delete the second Most Visited Item.
- stream.str(std::string());
- stream << "newTabPageHandle.undoAllMostVisitedDeletions();";
- EXPECT_TRUE(content::ExecuteScript(ntp, stream.str()));
- observer.Wait();
-
- // Update Most Visited state.
- 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);
-}
-
-// TODO(dhollowa): Fix flakes. http://crbug.com/179930.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_FaviconAccess) {
- // Create a favicon.
- history::TopSites* top_sites = browser()->profile()->GetTopSites();
- GURL url("http://www.google.com/foo.html");
- gfx::Image thumbnail(CreateBitmap(SK_ColorWHITE));
- ThumbnailScore high_score(0.0, true, true, base::Time::Now());
- EXPECT_TRUE(top_sites->SetPageThumbnail(url, thumbnail, high_score));
-
- 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_WAIT_FOR_TAB);
-
- content::RenderViewHost* rvh =
- browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost();
-
- // Get the favicons.
- const std::string chrome_favicon_url(
- "chrome://favicon/largest/http://www.google.com/foo.html");
- const std::string search_favicon_url(
- "chrome-search://favicon/largest/http://www.google.com/foo.html");
- bool loaded = false;
- ASSERT_TRUE(LoadImage(rvh, chrome_favicon_url, &loaded));
- EXPECT_FALSE(loaded) << chrome_favicon_url;
- ASSERT_TRUE(LoadImage(rvh, search_favicon_url, &loaded));
- 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()));
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- ui_test_utils::NavigateToURLWithDisposition(
- browser(),
- GURL(chrome::kChromeUINewTabURL),
- NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
- const content::WebContents* tab =
- browser()->tab_strip_model()->GetActiveWebContents();
-
- // Instant-provided NTP should not have any bindings enabled.
- EXPECT_EQ(0, tab->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()));
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- // 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();
-
- // The commited Instant page should not have any bindings enabled.
- EXPECT_EQ(0, tab->GetRenderViewHost()->GetEnabledBindings());
-}
-
-// 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) {
- // No need to setup Instant.
- set_browser(browser());
-
- BookmarkModel* bookmark_model =
- BookmarkModelFactory::GetForProfile(browser()->profile());
- ASSERT_TRUE(bookmark_model);
- test::WaitForBookmarkModelToLoad(bookmark_model);
- bookmark_utils::AddIfNotBookmarked(bookmark_model, GURL("http://angeline/"),
- ASCIIToUTF16("angeline"));
-
- SetOmniboxText("angeline");
-
- bool found_bookmark_match = false;
-
- const AutocompleteResult& result = omnibox()->model()->result();
- for (AutocompleteResult::const_iterator iter = result.begin();
- !found_bookmark_match && iter != result.end(); ++iter) {
- found_bookmark_match = iter->type == AutocompleteMatchType::BOOKMARK_TITLE;
- }
-
- EXPECT_TRUE(found_bookmark_match);
-}
-
-// Test that hitting Esc to clear the omnibox works. http://crbug.com/231744.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_EscapeClearsOmnibox) {
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- // Navigate to the Instant NTP, and wait for it to be recognized.
- content::WindowedNotificationObserver instant_tab_observer(
- chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
- content::NotificationService::AllSources());
- ui_test_utils::NavigateToURLWithDisposition(
- browser(),
- GURL(chrome::kChromeUINewTabURL),
- NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
- instant_tab_observer.Wait();
-
- content::WebContents* contents =
- browser()->tab_strip_model()->GetActiveWebContents();
-
- // Type a query. Verify that the query is seen by the page.
- SetOmniboxText("mojo");
- std::string query;
- EXPECT_TRUE(GetStringFromJS(contents, "chrome.embeddedSearch.searchBox.value",
- &query));
- EXPECT_EQ("mojo", query);
-
- EXPECT_TRUE(content::ExecuteScript(contents,
- "onChangeCalls = submitCount = 0;"));
-
- // Hit Escape, and verify that the page sees that the query is cleared.
- SendEscape();
- EXPECT_TRUE(GetStringFromJS(contents, "chrome.embeddedSearch.searchBox.value",
- &query));
- EXPECT_EQ("", query);
- EXPECT_EQ("", GetOmniboxText());
-
- EXPECT_TRUE(UpdateSearchState(contents));
- EXPECT_LT(0, on_change_calls_);
- EXPECT_EQ(0, submit_count_);
- EXPECT_LT(0, on_esc_key_press_event_calls_);
-}
-
-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()));
- FocusOmnibox();
-
- // 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.
- SetOmniboxText("foo");
- EXPECT_EQ(ASCIIToUTF16("foo"), omnibox()->GetText());
- browser()->window()->GetLocationBar()->AcceptInput();
- observer.Wait();
-
- // Set URL-like search terms for the instant tab.
- content::WebContents* instant_tab = instant()->instant_tab()->contents();
- content::NavigationEntry* visible_entry =
- instant_tab->GetController().GetVisibleEntry();
- visible_entry->SetExtraData(sessions::kSearchTermsKey,
- ASCIIToUTF16("http://example.com"));
- SetOmniboxText("http://example.com");
- omnibox()->model()->SetInputInProgress(false);
- omnibox()->CloseOmniboxPopup();
-
- // Accept the omnibox input.
- EXPECT_FALSE(omnibox()->model()->user_input_in_progress());
- EXPECT_TRUE(browser()->toolbar_model()->WouldPerformSearchTermReplacement());
- GURL instant_tab_url = instant_tab->GetURL();
- browser()->window()->GetLocationBar()->AcceptInput();
- EXPECT_EQ(instant_tab_url, instant_tab->GetURL());
-}
-
-// 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()));
- FocusOmnibox();
-
- // 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.
- SetOmniboxText("foo");
- EXPECT_EQ(ASCIIToUTF16("foo"), omnibox()->GetText());
- browser()->window()->GetLocationBar()->AcceptInput();
- observer.Wait();
-
- // Set URL-like search terms for the instant tab.
- content::WebContents* instant_tab = instant()->instant_tab()->contents();
- content::NavigationEntry* visible_entry =
- instant_tab->GetController().GetVisibleEntry();
- const char kEvilJS[] = "javascript:document.title='evil';1;";
- visible_entry->SetExtraData(sessions::kSearchTermsKey, ASCIIToUTF16(kEvilJS));
- SetOmniboxText(kEvilJS);
- omnibox()->model()->SetInputInProgress(false);
- omnibox()->CloseOmniboxPopup();
-
- // Accept the omnibox input.
- EXPECT_FALSE(omnibox()->model()->user_input_in_progress());
- EXPECT_TRUE(browser()->toolbar_model()->WouldPerformSearchTermReplacement());
- browser()->window()->GetLocationBar()->AcceptInput();
- // Force some Javascript to run in the renderer so the inline javascript:
- // would be forced to run if it's going to.
- EXPECT_TRUE(content::ExecuteScript(instant_tab, "1;"));
- EXPECT_NE(ASCIIToUTF16("evil"), instant_tab->GetTitle());
-}
-
-IN_PROC_BROWSER_TEST_F(
- InstantExtendedTest,
- DISABLED_ReloadSearchAfterBackReloadsCorrectQuery) {
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- FocusOmnibox();
-
- // Create an observer to wait for the instant tab to support Instant.
- content::WindowedNotificationObserver observer(
- chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
- content::NotificationService::AllSources());
-
- // Search for [foo].
- SetOmniboxText("foo");
- EXPECT_EQ(ASCIIToUTF16("foo"), omnibox()->GetText());
- browser()->window()->GetLocationBar()->AcceptInput();
- observer.Wait();
-
- // Search again for [bar].
- content::WebContents* instant_tab = instant()->instant_tab()->contents();
- EXPECT_TRUE(content::ExecuteScript(instant_tab,
- "suggestion = 'bart';"));
- SetOmniboxTextAndWaitForSuggestion("bar");
-
- // Accept the new query and wait for the page to navigate.
- content::WindowedNotificationObserver nav_observer(
- content::NOTIFICATION_NAV_ENTRY_COMMITTED,
- content::NotificationService::AllSources());
- browser()->window()->GetLocationBar()->AcceptInput();
- nav_observer.Wait();
-
- // Press back button and reload.
- content::WindowedNotificationObserver back_observer(
- content::NOTIFICATION_NAV_ENTRY_COMMITTED,
- content::NotificationService::AllSources());
- instant_tab->GetController().GoBack();
- back_observer.Wait();
- EXPECT_EQ("foo", GetOmniboxText());
- FocusOmnibox();
- content::WindowedNotificationObserver reload_observer(
- content::NOTIFICATION_NAV_ENTRY_COMMITTED,
- content::NotificationService::AllSources());
- browser()->window()->GetLocationBar()->AcceptInput();
- reload_observer.Wait();
-
- EXPECT_EQ("foo", GetOmniboxText());
-}
-
-class InstantExtendedFirstTabTest : public InProcessBrowserTest,
- public InstantTestBase {
- public:
- InstantExtendedFirstTabTest() {}
- protected:
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- command_line->AppendSwitch(switches::kEnableInstantExtendedAPI);
- command_line->AppendSwitch(switches::kDisableLocalFirstLoadNTP);
- }
-};
-
-// Flaky: http://crbug.com/238863
-IN_PROC_BROWSER_TEST_F(
- InstantExtendedFirstTabTest, DISABLED_RedirectToLocalOnLoadFailure) {
- // Create a new window to test the first NTP load.
- ui_test_utils::NavigateToURLWithDisposition(
- browser(),
- GURL(chrome::kChromeUINewTabURL),
- NEW_WINDOW,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
-
- const BrowserList* browser_list = BrowserList::GetInstance(
- chrome::GetActiveDesktop());
- ASSERT_EQ(2u, browser_list->size());
- set_browser(browser_list->get(1));
-
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- // Also make sure our instant_tab_ is loaded.
- if (!instant()->instant_tab_) {
- content::WindowedNotificationObserver instant_tab_observer(
- chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
- content::NotificationService::AllSources());
- instant_tab_observer.Wait();
- }
-
- // NTP contents should be preloaded.
- ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
- EXPECT_TRUE(instant()->ntp()->IsLocal());
-
- // Instant tab contents should be preloaded.
- ASSERT_NE(static_cast<InstantTab*>(NULL), instant()->instant_tab());
- EXPECT_TRUE(instant()->instant_tab()->IsLocal());
-}
-
-// Broken on mac: http://crbug.com/247448
-#if defined(OS_MACOSX)
-#define MAYBE_KeyboardTogglesVoiceSearch DISABLED_KeyboardTogglesVoiceSearch
-#else
-#define MAYBE_KeyboardTogglesVoiceSearch KeyboardTogglesVoiceSearch
-#endif
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, MAYBE_KeyboardTogglesVoiceSearch) {
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- // Open new tab and test that toggle is fired.
- ui_test_utils::NavigateToURLWithDisposition(
- browser(),
- GURL(chrome::kChromeUINewTabURL),
- 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(active_tab));
- EXPECT_EQ(1, on_toggle_voice_search_calls_);
-}
-
-// Test to verify that the omnibox search query is updated on browser
-// back/forward button press events.
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest, UpdateSearchQueryOnNavigation) {
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
-
- // Focus omnibox.
- FocusOmniboxAndWaitForInstantNTPSupport();
- SetOmniboxText("flowers");
-
- // Commit the search by pressing 'Enter'.
- PressEnterAndWaitForNavigation();
- 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());
-}
-
-#endif // HTML_INSTANT_EXTENDED_POPUP
-
-#if !defined(HTML_INSTANT_EXTENDED_POPUP)
IN_PROC_BROWSER_TEST_F(InstantExtendedTest, SearchReusesInstantTab) {
ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
FocusOmniboxAndWaitForInstantNTPSupport();
@@ -1212,8 +541,6 @@
EXPECT_THAT(url, HasSubstr("&es_sm="));
}
-#endif // if !defined(HTML_INSTANT_EXTENDED_POPUP)
-
// Test to verify that switching tabs should not dispatch onmostvisitedchanged
// events.
IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NoMostVisitedChangedOnTabSwitch) {
@@ -1571,121 +898,6 @@
EXPECT_EQ(1, on_most_visited_change_calls_);
}
-// Flaky: crbug.com/267096
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
- DISABLED_OnDefaultSearchProviderChanged) {
- InstantService* instant_service =
- InstantServiceFactory::GetForProfile(browser()->profile());
- ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
-
- // Setup Instant.
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- FocusOmniboxAndWaitForInstantNTPSupport();
- EXPECT_EQ(1, instant_service->GetInstantProcessCount());
-
- // Navigating to the NTP should use the Instant render process.
- content::WindowedNotificationObserver new_tab_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);
- new_tab_observer.Wait();
-
- content::WebContents* ntp_contents =
- browser()->tab_strip_model()->GetActiveWebContents();
- EXPECT_TRUE(chrome::IsInstantNTP(ntp_contents));
- EXPECT_TRUE(instant_service->IsInstantProcess(
- ntp_contents->GetRenderProcessHost()->GetID()));
- GURL ntp_url = ntp_contents->GetURL();
-
- AddBlankTabAndShow(browser());
- content::WebContents* active_tab =
- browser()->tab_strip_model()->GetActiveWebContents();
- EXPECT_FALSE(chrome::IsInstantNTP(active_tab));
- EXPECT_FALSE(instant_service->IsInstantProcess(
- active_tab->GetRenderProcessHost()->GetID()));
-
- TemplateURLData data;
- data.short_name = ASCIIToUTF16("t");
- data.SetURL("http://defaultturl/q={searchTerms}");
- data.suggestions_url = "http://defaultturl2/q={searchTerms}";
- data.instant_url = "http://does/not/exist";
- data.alternate_urls.push_back(data.instant_url + "#q={searchTerms}");
- data.search_terms_replacement_key = "strk";
-
- TemplateURL* template_url = new TemplateURL(browser()->profile(), data);
- TemplateURLService* service =
- TemplateURLServiceFactory::GetForProfile(browser()->profile());
- ui_test_utils::WaitForTemplateURLServiceToLoad(service);
- service->Add(template_url); // Takes ownership of |template_url|.
-
- // Change the default search provider.
- content::WindowedNotificationObserver observer(
- content::NOTIFICATION_LOAD_STOP,
- content::Source<content::NavigationController>(
- &ntp_contents->GetController()));
- service->SetDefaultSearchProvider(template_url);
- observer.Wait();
-
- // |ntp_contents| should not use the Instant render process.
- EXPECT_FALSE(chrome::IsInstantNTP(ntp_contents));
- EXPECT_FALSE(instant_service->IsInstantProcess(
- ntp_contents->GetRenderProcessHost()->GetID()));
- // Make sure the URL remains the same.
- EXPECT_EQ(ntp_url, ntp_contents->GetURL());
-}
-
-IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
- ReloadLocalNTPOnSearchProviderChange) {
- // Setup Instant.
- ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
- FocusOmniboxAndWaitForInstantNTPSupport();
-
- // Navigate to Local NTP.
- content::WindowedNotificationObserver new_tab_observer(
- content::NOTIFICATION_NAV_ENTRY_COMMITTED,
- content::NotificationService::AllSources());
- ui_test_utils::NavigateToURLWithDisposition(
- browser(),
- GURL(chrome::kChromeSearchLocalNtpUrl),
- CURRENT_TAB,
- ui_test_utils::BROWSER_TEST_NONE);
- new_tab_observer.Wait();
-
- content::WebContents* ntp_contents =
- browser()->tab_strip_model()->GetActiveWebContents();
- GURL ntp_url = ntp_contents->GetURL();
-
- TemplateURLData data;
- data.short_name = ASCIIToUTF16("t");
- data.SetURL("http://defaultturl/q={searchTerms}");
- data.suggestions_url = "http://defaultturl2/q={searchTerms}";
- data.instant_url = "http://does/not/exist";
- data.alternate_urls.push_back(data.instant_url + "#q={searchTerms}");
- data.search_terms_replacement_key = "strk";
-
- TemplateURL* template_url = new TemplateURL(browser()->profile(), data);
- TemplateURLService* service =
- TemplateURLServiceFactory::GetForProfile(browser()->profile());
- ui_test_utils::WaitForTemplateURLServiceToLoad(service);
- service->Add(template_url); // Takes ownership of |template_url|.
-
- // Change the default search provider. This will reload the local NTP and the
- // page URL will remain the same.
- content::WindowedNotificationObserver observer(
- content::NOTIFICATION_LOAD_STOP,
- content::Source<content::NavigationController>(
- &ntp_contents->GetController()));
- service->SetDefaultSearchProvider(template_url);
- observer.Wait();
-
- // Make sure the URL remains the same.
- EXPECT_EQ(ntp_url, ntp_contents->GetURL());
-}
-
IN_PROC_BROWSER_TEST_F(InstantExtendedPrefetchTest, SetPrefetchQuery) {
ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
FocusOmniboxAndWaitForInstantNTPSupport();
@@ -1803,3 +1015,31 @@
// the search terms is sufficient.
EXPECT_NE(ASCIIToUTF16("foo"), omnibox()->GetText());
}
+
+// Check that clicking on a result sends the correct referrer.
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, Referrer) {
+ ASSERT_TRUE(test_server()->Start());
+ GURL result_url =
+ test_server()->GetURL("files/referrer_policy/referrer-policy-log.html");
+ ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+ FocusOmniboxAndWaitForInstantNTPSupport();
+
+ // Type a query and press enter to get results.
+ SetOmniboxText("query");
+ PressEnterAndWaitForNavigation();
+
+ // Simulate going to a result.
+ content::WebContents* contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ std::ostringstream stream;
+ stream << "var link = document.createElement('a');";
+ stream << "link.href = \"" << result_url.spec() << "\";";
+ stream << "document.body.appendChild(link);";
+ stream << "link.click();";
+ EXPECT_TRUE(content::ExecuteScript(contents, stream.str()));
+
+ content::WaitForLoadStop(contents);
+ std::string expected_title =
+ "Referrer is " + instant_url().GetWithEmptyPath().spec();
+ EXPECT_EQ(ASCIIToUTF16(expected_title), contents->GetTitle());
+}
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 af3206f..0cc5290 100644
--- a/chrome/browser/ui/search/instant_extended_manual_interactive_uitest.cc
+++ b/chrome/browser/ui/search/instant_extended_manual_interactive_uitest.cc
@@ -98,7 +98,7 @@
InstantService* instant_service =
InstantServiceFactory::GetForProfile(browser()->profile());
ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
- instant_service->ntp_prerenderer()->ReloadStaleNTP();
+ instant_service->ntp_prerenderer()->ReloadInstantNTP();
FocusOmniboxAndWaitForInstantNTPSupport();
content::WindowedNotificationObserver observer(
@@ -120,7 +120,7 @@
InstantService* instant_service =
InstantServiceFactory::GetForProfile(browser()->profile());
ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
- instant_service->ntp_prerenderer()->ReloadStaleNTP();
+ instant_service->ntp_prerenderer()->ReloadInstantNTP();
FocusOmniboxAndWaitForInstantNTPSupport();
// Open a new tab page.
diff --git a/chrome/browser/ui/search/instant_ntp_prerenderer.cc b/chrome/browser/ui/search/instant_ntp_prerenderer.cc
index 7b3957a..d25c0c0 100644
--- a/chrome/browser/ui/search/instant_ntp_prerenderer.cc
+++ b/chrome/browser/ui/search/instant_ntp_prerenderer.cc
@@ -45,6 +45,7 @@
InstantNTPPrerenderer::InstantNTPPrerenderer(Profile* profile,
+ InstantService* instant_service,
PrefService* prefs)
: profile_(profile) {
DCHECK(profile);
@@ -54,23 +55,26 @@
profile_pref_registrar_.Init(prefs);
profile_pref_registrar_.Add(
prefs::kSearchSuggestEnabled,
- base::Bind(&InstantNTPPrerenderer::ReloadStaleNTP,
- base::Unretained(this)));
- profile_pref_registrar_.Add(
- prefs::kDefaultSearchProviderID,
- base::Bind(&InstantNTPPrerenderer::OnDefaultSearchProviderChanged,
+ base::Bind(&InstantNTPPrerenderer::ReloadInstantNTP,
base::Unretained(this)));
}
net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
+
+ // Allow instant_service to be null for unit tets.
+ if (instant_service)
+ instant_service->AddObserver(this);
}
InstantNTPPrerenderer::~InstantNTPPrerenderer() {
+ InstantService* instant_service =
+ InstantServiceFactory::GetForProfile(profile_);
+ if (instant_service)
+ instant_service->RemoveObserver(this);
net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
}
-void InstantNTPPrerenderer::PreloadInstantNTP() {
- DCHECK(!ntp());
- ReloadStaleNTP();
+void InstantNTPPrerenderer::ReloadInstantNTP() {
+ ResetNTP(GetInstantURL());
}
scoped_ptr<content::WebContents> InstantNTPPrerenderer::ReleaseNTPContents() {
@@ -84,7 +88,7 @@
scoped_ptr<content::WebContents> ntp_contents = ntp_->ReleaseContents();
// Preload a new InstantNTP.
- ResetNTP(GetInstantURL());
+ ReloadInstantNTP();
return ntp_contents.Pass();
}
@@ -175,7 +179,7 @@
return;
if (!ntp() || ntp()->IsLocal())
- ResetNTP(GetInstantURL());
+ ReloadInstantNTP();
}
void InstantNTPPrerenderer::InstantSupportDetermined(
@@ -245,28 +249,15 @@
ResetNTP(GetLocalInstantURL());
}
-void InstantNTPPrerenderer::OnDefaultSearchProviderChanged(
- const std::string& pref_name) {
- DCHECK_EQ(pref_name, std::string(prefs::kDefaultSearchProviderID));
- if (!ntp())
- return;
-
- ResetNTP(GetInstantURL());
-}
-
void InstantNTPPrerenderer::ResetNTP(const std::string& instant_url) {
// 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, profile_));
- ntp_->InitContents(base::Bind(&InstantNTPPrerenderer::ReloadStaleNTP,
+ ntp_->InitContents(base::Bind(&InstantNTPPrerenderer::ReloadInstantNTP,
base::Unretained(this)));
}
-void InstantNTPPrerenderer::ReloadStaleNTP() {
- ResetNTP(GetInstantURL());
-}
-
bool InstantNTPPrerenderer::PageIsCurrent() const {
const std::string& instant_url = GetInstantURL();
if (instant_url.empty() ||
@@ -298,3 +289,11 @@
// (unless the finch flag to use the remote NTP is set).
return !(InStartup() && chrome::ShouldPreferRemoteNTPOnStartup());
}
+
+void InstantNTPPrerenderer::DefaultSearchProviderChanged() {
+ ReloadInstantNTP();
+}
+
+void InstantNTPPrerenderer::GoogleURLUpdated() {
+ ReloadInstantNTP();
+}
diff --git a/chrome/browser/ui/search/instant_ntp_prerenderer.h b/chrome/browser/ui/search/instant_ntp_prerenderer.h
index 933e0a8..10d3292 100644
--- a/chrome/browser/ui/search/instant_ntp_prerenderer.h
+++ b/chrome/browser/ui/search/instant_ntp_prerenderer.h
@@ -11,14 +11,14 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_change_registrar.h"
+#include "chrome/browser/search/instant_service_observer.h"
#include "chrome/browser/ui/search/instant_page.h"
#include "content/public/browser/web_contents.h"
#include "net/base/network_change_notifier.h"
-class InstantExtendedTest;
class InstantNTP;
class InstantService;
-class InstantTestBase;
+class PrefService;
class Profile;
// InstantNTPPrerenderer maintains a prerendered instance of InstantNTP.
@@ -31,13 +31,15 @@
// InstantNTPPrerenderer is owned by InstantService.
class InstantNTPPrerenderer
: public InstantPage::Delegate,
- public net::NetworkChangeNotifier::NetworkChangeObserver {
+ public net::NetworkChangeNotifier::NetworkChangeObserver,
+ public InstantServiceObserver {
public:
- InstantNTPPrerenderer(Profile* profile, PrefService* prefs);
+ InstantNTPPrerenderer(Profile* profile, InstantService* instant_service,
+ PrefService* prefs);
virtual ~InstantNTPPrerenderer();
// Preloads |ntp_| with a new InstantNTP.
- void PreloadInstantNTP();
+ void ReloadInstantNTP();
// Releases and returns the InstantNTP WebContents. May be NULL. Loads a new
// WebContents for the InstantNTP.
@@ -137,16 +139,13 @@
virtual void UndoAllMostVisitedDeletions() OVERRIDE;
virtual void InstantPageLoadFailed(content::WebContents* contents) OVERRIDE;
- // Called when the default search provider changes. Resets InstantNTP.
- void OnDefaultSearchProviderChanged(const std::string& pref_name);
+ // Overridden from InstantServiceObserver:
+ virtual void DefaultSearchProviderChanged() OVERRIDE;
+ virtual void GoogleURLUpdated() OVERRIDE;
// Recreates |ntp_| using |instant_url|.
void ResetNTP(const std::string& instant_url);
- // Resets |ntp_| with a new InstantNTP. Called when |ntp_| is stale or when a
- // pref is changed.
- void ReloadStaleNTP();
-
// Returns true if |ntp_| has an up-to-date Instant URL and supports Instant.
// Note that local URLs will not pass this check.
bool PageIsCurrent() const;
diff --git a/chrome/browser/ui/search/instant_ntp_prerenderer_unittest.cc b/chrome/browser/ui/search/instant_ntp_prerenderer_unittest.cc
index 917e01a..c3899b7 100644
--- a/chrome/browser/ui/search/instant_ntp_prerenderer_unittest.cc
+++ b/chrome/browser/ui/search/instant_ntp_prerenderer_unittest.cc
@@ -3,11 +3,9 @@
// found in the LICENSE file.
#include "base/memory/scoped_ptr.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/histogram_samples.h"
-#include "base/metrics/statistics_recorder.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/search/instant_service_factory.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/ui/search/instant_ntp.h"
#include "chrome/browser/ui/search/instant_ntp_prerenderer.h"
@@ -17,10 +15,6 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::HistogramBase;
-using base::HistogramSamples;
-using base::StatisticsRecorder;
-
class TestableInstantNTP : public InstantNTP {
public:
TestableInstantNTP(InstantNTPPrerenderer* ntp_prerenderer,
@@ -62,13 +56,15 @@
class TestableInstantNTPPrerenderer : public InstantNTPPrerenderer {
public:
- explicit TestableInstantNTPPrerenderer(TestingProfile* profile)
- : InstantNTPPrerenderer(profile, NULL),
+ explicit TestableInstantNTPPrerenderer(TestingProfile* profile,
+ InstantService* instant_service)
+ : InstantNTPPrerenderer(profile, instant_service, NULL),
test_instant_url_("http://test_url"),
override_javascript_enabled_(true),
test_javascript_enabled_(true),
test_in_startup_(false),
- test_ntp_(NULL) {}
+ test_ntp_(NULL) {
+ }
// Overrides from InstantNTPPrerenderer
virtual std::string GetInstantURL() const OVERRIDE {
@@ -125,10 +121,15 @@
class InstantNTPPrerendererTest : public testing::Test {
public:
- InstantNTPPrerendererTest()
- : instant_ntp_prerenderer_(new TestableInstantNTPPrerenderer(&profile_)) {
- base::StatisticsRecorder::Initialize();
+ virtual void SetUp() OVERRIDE {
chrome::EnableInstantExtendedAPIForTesting();
+ instant_service_ = InstantServiceFactory::GetForProfile(&profile_);
+ instant_ntp_prerenderer_.reset(
+ new TestableInstantNTPPrerenderer(&profile_, instant_service_));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ instant_ntp_prerenderer_.reset();
}
TestableInstantNTPPrerenderer* instant_ntp_prerenderer() {
@@ -142,6 +143,7 @@
private:
content::TestBrowserThreadBundle thread_bundle_;
scoped_ptr<TestableInstantNTPPrerenderer> instant_ntp_prerenderer_;
+ InstantService* instant_service_;
mutable TestingProfile profile_;
};
diff --git a/chrome/browser/ui/search/instant_test_utils.cc b/chrome/browser/ui/search/instant_test_utils.cc
index 67d1d19..c576e37 100644
--- a/chrome/browser/ui/search/instant_test_utils.cc
+++ b/chrome/browser/ui/search/instant_test_utils.cc
@@ -61,7 +61,7 @@
InstantService* instant_service =
InstantServiceFactory::GetForProfile(browser_->profile());
ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
- instant_service->ntp_prerenderer()->ReloadStaleNTP();
+ instant_service->ntp_prerenderer()->ReloadInstantNTP();
}
void InstantTestBase::SetInstantURL(const std::string& url) {
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index f23794b..781b089 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -73,7 +73,7 @@
#endif
#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX)
-#include "ui/base/touch/touch_factory_x11.h"
+#include "ui/events/x/touch_factory_x11.h"
#endif
#if defined(OS_WIN)
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 0bd8cd1..ff38772 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -298,6 +298,14 @@
DISALLOW_COPY_AND_ASSIGN(WebContentsCloseObserver);
};
+const Extension* GetDisabledPlatformApp(Profile* profile,
+ const std::string& extension_id) {
+ ExtensionService* service =
+ extensions::ExtensionSystem::Get(profile)->extension_service();
+ const Extension* extension = service->GetExtensionById(extension_id, true);
+ return extension && extension->is_platform_app() ? extension : NULL;
+}
+
} // namespace
namespace internals {
@@ -350,7 +358,21 @@
}
AppListService::InitAll(profile);
- if (command_line_.HasSwitch(switches::kShowAppList)) {
+ if (command_line_.HasSwitch(switches::kAppId)) {
+ std::string app_id = command_line_.GetSwitchValueASCII(switches::kAppId);
+ const Extension* extension = GetDisabledPlatformApp(profile, app_id);
+ // If |app_id| is a disabled platform app we handle it specially here,
+ // otherwise it will be handled below.
+ if (extension) {
+ RecordCmdLineAppHistogram(extensions::Manifest::TYPE_PLATFORM_APP);
+ chrome::AppLaunchParams params(profile, extension,
+ extension_misc::LAUNCH_NONE, NEW_WINDOW);
+ params.command_line = &command_line_;
+ params.current_directory = cur_dir_;
+ OpenApplicationWithReenablePrompt(params);
+ return true;
+ }
+ } else if (command_line_.HasSwitch(switches::kShowAppList)) {
AppListService::RecordShowTimings(command_line_);
AppListService::Get()->ShowForProfile(profile);
return true;
diff --git a/chrome/browser/ui/sync/one_click_signin_helper.cc b/chrome/browser/ui/sync/one_click_signin_helper.cc
index 7f8b56b..8ee53a1 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper.cc
@@ -385,8 +385,23 @@
StartSync(args, start_mode);
RedirectToNtpOrAppsPageIfNecessary(contents, args.source);
} else {
- if (signin::IsContinueUrlForWebBasedSigninFlow(contents->GetVisibleURL()))
+ // Perform a redirection to the NTP/Apps page to hide the blank page when
+ // the action is CLOSE or CREATE_NEW_USER. The redirection is useful when
+ // the action is CREATE_NEW_USER because the "Create new user" page might
+ // be opened in a different tab that is already showing settings.
+ //
+ // Don't redirect when this callback is called while there is a navigation
+ // in progress. Otherwise, there would be 2 nested navigations and a crash
+ // would occur (crbug.com/293261).
+ //
+ // Also, don't redirect when the visible URL is not a blank page: if the
+ // source is SOURCE_WEBSTORE_INSTALL, |contents| might be showing an app
+ // page that shouldn't be hidden.
+ if (!contents->IsLoading() &&
+ signin::IsContinueUrlForWebBasedSigninFlow(
+ contents->GetVisibleURL())) {
RedirectToNtpOrAppsPage(contents, args.source);
+ }
if (action == ConfirmEmailDialogDelegate::CREATE_NEW_USER) {
chrome::ShowSettingsSubPage(args.browser,
std::string(chrome::kSearchUsersSubPage));
diff --git a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
index cbc7413..d3e945b 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
@@ -195,6 +195,7 @@
: TestProfileSyncService(NULL,
profile,
NULL,
+ NULL,
ProfileSyncService::MANUAL_START,
false), // synchronous_backend_init
first_setup_in_progress_(false) {}
diff --git a/chrome/browser/ui/tabs/tab_audio_indicator.cc b/chrome/browser/ui/tabs/tab_audio_indicator.cc
deleted file mode 100644
index a133640..0000000
--- a/chrome/browser/ui/tabs/tab_audio_indicator.cc
+++ /dev/null
@@ -1,165 +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/tabs/tab_audio_indicator.h"
-
-#include "grit/theme_resources.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/animation/animation_container.h"
-#include "ui/gfx/animation/linear_animation.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/skia_util.h"
-
-namespace {
-
-// The number of columns to draw for the equalizer graphic.
-const size_t kEqualizerColumnCount = 3;
-
-// The equalizer cycles between these frames. An equalizer frame is 2 columns
-// where each column ranges from 0 to 4.
-const size_t kEqualizerFrames[][kEqualizerColumnCount] = {
- { 1, 1, 1 },
- { 1, 2, 2 },
- { 2, 2, 3 },
- { 3, 3, 2 },
- { 3, 2, 1 },
- { 2, 1, 2 },
- { 1, 2, 3 },
- { 2, 1, 2 },
- { 3, 2, 1 },
- { 3, 2, 1 },
- { 2, 3, 2 },
- { 1, 2, 3 },
- { 2, 1, 2 },
-};
-
-// The space between equalizer levels.
-const int kEqualizerColumnPadding = 1;
-
-// The duration of each equalizer frame.
-const size_t kAnimationCycleDurationMs = 250;
-
-// The duration of the "ending" animation once audio stops playing.
-const size_t kAnimationEndingDurationMs = 1000;
-
-// Target frames per second. In reality fewer frames are drawn because the
-// equalizer levels change slowly.
-const int kFPS = 15;
-
-} // namespace
-
-TabAudioIndicator::TabAudioIndicator(Delegate* delegate)
- : delegate_(delegate),
- frame_index_(0),
- state_(STATE_NOT_ANIMATING) {
-}
-
-TabAudioIndicator::~TabAudioIndicator() {
-}
-
-void TabAudioIndicator::SetAnimationContainer(
- gfx::AnimationContainer* animation_container) {
- animation_container_ = animation_container;
-}
-
-void TabAudioIndicator::SetIsPlayingAudio(bool is_playing_audio) {
- if (is_playing_audio && state_ != STATE_ANIMATING) {
- state_ = STATE_ANIMATING;
- animation_.reset(
- new gfx::LinearAnimation(kAnimationCycleDurationMs, kFPS, this));
- animation_->SetContainer(animation_container_.get());
- animation_->Start();
- } else if (!is_playing_audio && state_ == STATE_ANIMATING) {
- state_ = STATE_ANIMATION_ENDING;
- animation_.reset(
- new gfx::LinearAnimation(kAnimationEndingDurationMs, kFPS, this));
- animation_->SetContainer(animation_container_.get());
- animation_->Start();
- }
-}
-
-bool TabAudioIndicator::IsAnimating() {
- return state_ != STATE_NOT_ANIMATING;
-}
-
-void TabAudioIndicator::Paint(gfx::Canvas* canvas, const gfx::Rect& rect) {
- canvas->Save();
- canvas->ClipRect(rect);
-
- // Draw 3 equalizer columns. |IDR_AUDIO_EQUALIZER_COLUMN| is a column of the
- // equalizer with 4 levels. The current level is between 0 and 4 so the
- // image is shifted down and then drawn.
- if (state_ != STATE_NOT_ANIMATING) {
- ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- gfx::ImageSkia* image(rb.GetImageSkiaNamed(IDR_AUDIO_EQUALIZER_COLUMN));
- int x = rect.right();
- std::vector<int> levels = GetCurrentEqualizerLevels();
- for (int i = levels.size() - 1; i >= 0; --i) {
- x -= image->width();
- if (levels[i] == 0)
- continue;
-
- // Shift the image down by the level.
- int y = rect.bottom() - levels[i] * 2;
- canvas->DrawImageInt(*image, x, y);
-
- // Clip the equalizer column so the favicon doesn't obscure it.
- gfx::Rect equalizer_rect(x, y, image->width(), image->height());
- canvas->sk_canvas()->clipRect(
- gfx::RectToSkRect(equalizer_rect), SkRegion::kDifference_Op);
-
- // Padding is baked into both sides of the icons so overlap the images.
- x += kEqualizerColumnPadding;
- }
-
- // Cache the levels that were just drawn. This is used to prevent
- // unnecessary drawing when animation progress doesn't result in equalizer
- // levels changing.
- last_displayed_equalizer_levels_ = levels;
- }
-
- if (!favicon_.isNull()) {
- int dst_x = rect.x() - (favicon_.width() - rect.width()) / 2;
- int dst_y = rect.y() - (favicon_.height()- rect.height()) / 2;
- canvas->DrawImageInt(favicon_, dst_x, dst_y);
- }
-
- canvas->Restore();
-}
-
-void TabAudioIndicator::AnimationProgressed(const gfx::Animation* animation) {
- std::vector<int> levels = GetCurrentEqualizerLevels();
- if (last_displayed_equalizer_levels_ != levels)
- delegate_->ScheduleAudioIndicatorPaint();
-}
-
-void TabAudioIndicator::AnimationEnded(const gfx::Animation* animation) {
- if (state_ == STATE_ANIMATING) {
- // The current equalizer frame animation has finished. Start animating the
- // next frame.
- frame_index_ = (frame_index_ + 1) % arraysize(kEqualizerFrames);
- animation_->Start();
- } else if (state_ == STATE_ANIMATION_ENDING) {
- // The "ending" animation has stopped. Update the tab state so that the UI
- // can update the tab icon.
- state_ = STATE_NOT_ANIMATING;
- delegate_->ScheduleAudioIndicatorPaint();
- }
-}
-
-std::vector<int> TabAudioIndicator::GetCurrentEqualizerLevels() const {
- int next_frame_index = (frame_index_ + 1) % arraysize(kEqualizerFrames);
- std::vector<int> levels;
- // For all 2 columsn of the equalizer, tween between the current equalizer
- // level and the target equalizer level.
- for (size_t i = 0; i < kEqualizerColumnCount; ++i) {
- int start = kEqualizerFrames[frame_index_][i];
- int end = state_ == STATE_ANIMATION_ENDING
- ? 0
- : kEqualizerFrames[next_frame_index][i];
- levels.push_back(animation_->CurrentValueBetween(start, end));
- }
- return levels;
-}
diff --git a/chrome/browser/ui/tabs/tab_audio_indicator.h b/chrome/browser/ui/tabs/tab_audio_indicator.h
deleted file mode 100644
index dcbdab2..0000000
--- a/chrome/browser/ui/tabs/tab_audio_indicator.h
+++ /dev/null
@@ -1,83 +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_UI_TABS_TAB_AUDIO_INDICATOR_H_
-#define CHROME_BROWSER_UI_TABS_TAB_AUDIO_INDICATOR_H_
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/gfx/animation/animation_delegate.h"
-#include "ui/gfx/image/image_skia.h"
-
-namespace gfx {
-class Animation;
-class AnimationContainer;
-class Canvas;
-class LinearAnimation;
-class Rect;
-}
-
-// This class is used to draw an animating tab audio indicator.
-class TabAudioIndicator : public gfx::AnimationDelegate {
- public:
- class Delegate {
- public:
- virtual void ScheduleAudioIndicatorPaint() = 0;
-
- protected:
- virtual ~Delegate() {}
- };
-
- explicit TabAudioIndicator(Delegate* delegate);
- virtual ~TabAudioIndicator();
-
- void set_favicon(const gfx::ImageSkia& favicon) { favicon_ = favicon; }
-
- void SetAnimationContainer(gfx::AnimationContainer* animation_container);
- void SetIsPlayingAudio(bool is_playing_audio);
- bool IsAnimating();
-
- void Paint(gfx::Canvas* canvas, const gfx::Rect& rect);
-
- private:
- enum State {
- STATE_NOT_ANIMATING,
- STATE_ANIMATING,
- STATE_ANIMATION_ENDING,
- };
-
- FRIEND_TEST_ALL_PREFIXES(TabAudioIndicatorTest, AnimationState);
- FRIEND_TEST_ALL_PREFIXES(TabAudioIndicatorTest, SchedulePaint);
-
- // AnimationDelegate:
- virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
- virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
-
- // Gets the equalizer levels for all 3 columns. The values are tweened between
- // the current and target frame.
- std::vector<int> GetCurrentEqualizerLevels() const;
-
- Delegate* delegate_;
- scoped_ptr<gfx::LinearAnimation> animation_;
- scoped_refptr<gfx::AnimationContainer> animation_container_;
- gfx::ImageSkia favicon_;
-
- // The equalizer frame that's currently being displayed.
- size_t frame_index_;
-
- // The equalizer levels that were last displayed. This is used to prevent
- // unnecessary drawing when animation progress doesn't result in equalizer
- // levels changing.
- std::vector<int> last_displayed_equalizer_levels_;
-
- State state_;
-
- DISALLOW_COPY_AND_ASSIGN(TabAudioIndicator);
-};
-
-#endif // CHROME_BROWSER_UI_TABS_TAB_AUDIO_INDICATOR_H_
diff --git a/chrome/browser/ui/tabs/tab_audio_indicator_unittest.cc b/chrome/browser/ui/tabs/tab_audio_indicator_unittest.cc
deleted file mode 100644
index 4d41539..0000000
--- a/chrome/browser/ui/tabs/tab_audio_indicator_unittest.cc
+++ /dev/null
@@ -1,74 +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/tabs/tab_audio_indicator.h"
-
-#include "base/message_loop/message_loop.h"
-#include "grit/theme_resources.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/animation/linear_animation.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/rect.h"
-
-class TabAudioIndicatorTest : public TabAudioIndicator::Delegate,
- public testing::Test {
- protected:
- TabAudioIndicatorTest() : schedule_paint_count_(0) {}
-
- virtual void ScheduleAudioIndicatorPaint() OVERRIDE {
- ++schedule_paint_count_;
- }
-
- int schedule_paint_count_;
- base::MessageLoopForUI message_loop_; // Needed for gfx::LinearAnimation.
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TabAudioIndicatorTest);
-};
-
-TEST_F(TabAudioIndicatorTest, AnimationState) {
- // Start animating.
- TabAudioIndicator indicator(this);
- indicator.SetIsPlayingAudio(true);
- EXPECT_EQ(TabAudioIndicator::STATE_ANIMATING, indicator.state_);
- EXPECT_TRUE(indicator.IsAnimating());
-
- // Once the audio stops the indicator should switch to ending animation.
- indicator.SetIsPlayingAudio(false);
- EXPECT_EQ(TabAudioIndicator::STATE_ANIMATION_ENDING, indicator.state_);
- EXPECT_TRUE(indicator.IsAnimating());
-
- // Once the ending animation is complete animation should stop.
- indicator.animation_->End();
- EXPECT_EQ(TabAudioIndicator::STATE_NOT_ANIMATING, indicator.state_);
- EXPECT_FALSE(indicator.IsAnimating());
-}
-
-TEST_F(TabAudioIndicatorTest, Paint) {
- TabAudioIndicator indicator(this);
- indicator.SetIsPlayingAudio(true);
-
- gfx::Rect rect(0, 0, 16, 16);
- gfx::Canvas canvas(rect.size(), ui::SCALE_FACTOR_100P, true);
-
- // Nothing to test here. Just exercise the paint code to verify that nothing
- // leaks or crashes.
- indicator.Paint(&canvas, rect);
-
- // Paint with a favicon.
- ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- indicator.set_favicon(*rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_16));
- indicator.Paint(&canvas, rect);
-}
-
-TEST_F(TabAudioIndicatorTest, SchedulePaint) {
- TabAudioIndicator indicator(this);
- indicator.SetIsPlayingAudio(true);
-
- indicator.animation_->SetCurrentValue(1.0);
- schedule_paint_count_ = 0;
- indicator.AnimationProgressed(NULL);
- EXPECT_EQ(1, schedule_paint_count_);
-}
diff --git a/chrome/browser/ui/tabs/tab_utils.cc b/chrome/browser/ui/tabs/tab_utils.cc
index 00afb25..4a63151 100644
--- a/chrome/browser/ui/tabs/tab_utils.cc
+++ b/chrome/browser/ui/tabs/tab_utils.cc
@@ -10,9 +10,66 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "ui/gfx/animation/multi_animation.h"
namespace chrome {
+namespace {
+
+// Animation that throbs in (towards 1.0) and out (towards 0.0), and ends in the
+// "in" state.
+class TabRecordingIndicatorAnimation : public gfx::MultiAnimation {
+ public:
+ virtual ~TabRecordingIndicatorAnimation() {}
+
+ // Overridden to provide alternating "towards in" and "towards out" behavior.
+ virtual double GetCurrentValue() const OVERRIDE;
+
+ static scoped_ptr<TabRecordingIndicatorAnimation> Create();
+
+ private:
+ TabRecordingIndicatorAnimation(const gfx::MultiAnimation::Parts& parts,
+ const base::TimeDelta interval)
+ : MultiAnimation(parts, interval) {}
+
+ // Throbbing fade in/out duration on "this web page is watching and/or
+ // listening to you" favicon overlay.
+ static const int kCaptureIndicatorCycleDurationMs = 1000;
+
+ // Number of times to "toggle throb" the recording and tab capture indicators
+ // when they first appear.
+ static const int kCaptureIndicatorThrobCycles = 5;
+
+ // Interval between frame updates of the recording and tab capture indicator
+ // throb animations.
+ static const int kCaptureIndicatorFrameIntervalMs = 50; // 20 FPS
+};
+
+double TabRecordingIndicatorAnimation::GetCurrentValue() const {
+ return current_part_index() % 2 ?
+ 1.0 - MultiAnimation::GetCurrentValue() :
+ MultiAnimation::GetCurrentValue();
+}
+
+scoped_ptr<TabRecordingIndicatorAnimation>
+TabRecordingIndicatorAnimation::Create() {
+ MultiAnimation::Parts parts;
+ COMPILE_ASSERT(kCaptureIndicatorThrobCycles % 2 != 0,
+ must_be_odd_so_animation_finishes_in_showing_state);
+ for (int i = 0; i < kCaptureIndicatorThrobCycles; ++i) {
+ parts.push_back(MultiAnimation::Part(
+ kCaptureIndicatorCycleDurationMs, gfx::Tween::EASE_IN));
+ }
+ const base::TimeDelta interval =
+ base::TimeDelta::FromMilliseconds(kCaptureIndicatorFrameIntervalMs);
+ scoped_ptr<TabRecordingIndicatorAnimation> animation(
+ new TabRecordingIndicatorAnimation(parts, interval));
+ animation->set_continuous(false);
+ return animation.Pass();
+}
+
+} // namespace
+
bool ShouldShowProjectingIndicator(content::WebContents* contents) {
scoped_refptr<MediaStreamCaptureIndicator> indicator =
MediaCaptureDevicesDispatcher::GetInstance()->
@@ -52,4 +109,8 @@
return indicator->IsCapturingAudio(contents);
}
+scoped_ptr<gfx::Animation> CreateTabRecordingIndicatorAnimation() {
+ return TabRecordingIndicatorAnimation::Create().PassAs<gfx::Animation>();
+}
+
} // namespace chrome
diff --git a/chrome/browser/ui/tabs/tab_utils.h b/chrome/browser/ui/tabs/tab_utils.h
index 29b6547..76b0d37 100644
--- a/chrome/browser/ui/tabs/tab_utils.h
+++ b/chrome/browser/ui/tabs/tab_utils.h
@@ -5,10 +5,16 @@
#ifndef CHROME_BROWSER_UI_TABS_TAB_UTILS_H_
#define CHROME_BROWSER_UI_TABS_TAB_UTILS_H_
-namespace content{
+#include "base/memory/scoped_ptr.h"
+
+namespace content {
class WebContents;
} // namespace content
+namespace gfx {
+class Animation;
+} // namespace gfx
+
namespace chrome {
// Returns whether we should show a projecting favicon indicator for this tab.
@@ -27,6 +33,11 @@
// Returns whether the given |contents| is capturing video.
bool IsCapturingAudio(content::WebContents* contents);
+// Returns an Animation that throbs a few times, and ends in the fully-on
+// state. This is meant to be used for the tab recording/capture favicon
+// overlay.
+scoped_ptr<gfx::Animation> CreateTabRecordingIndicatorAnimation();
+
} // namespace chrome
#endif // CHROME_BROWSER_UI_TABS_TAB_UTILS_H_
diff --git a/chrome/browser/ui/toolbar/wrench_icon_painter_unittest.cc b/chrome/browser/ui/toolbar/wrench_icon_painter_unittest.cc
index 43b30f9..f513aaa 100644
--- a/chrome/browser/ui/toolbar/wrench_icon_painter_unittest.cc
+++ b/chrome/browser/ui/toolbar/wrench_icon_painter_unittest.cc
@@ -37,7 +37,7 @@
// leaks or crashes.
TEST_F(WrenchIconPainterTest, Paint) {
gfx::Rect rect(0, 0, 29, 29);
- gfx::Canvas canvas(rect.size(), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(rect.size(), 1.0f, true);
painter_.Paint(&canvas, theme_provider_, rect, WrenchIconPainter::BEZEL_NONE);
painter_.Paint(
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc
index fbd3904..e6fadea 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -675,18 +675,24 @@
// it won't show in the existing wrench menu. To fix this we need to some
// how update the menu if new errors are added.
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ // GetSignedInServiceErrors() can modify the global error list, so call it
+ // before iterating through that list below.
+ std::vector<GlobalError*> signin_errors =
+ signin_ui_util::GetSignedInServiceErrors(
+ browser_->profile()->GetOriginalProfile());
const GlobalErrorService::GlobalErrorList& errors =
GlobalErrorServiceFactory::GetForProfile(browser_->profile())->errors();
for (GlobalErrorService::GlobalErrorList::const_iterator
it = errors.begin(); it != errors.end(); ++it) {
GlobalError* error = *it;
+ // Verify that we're not getting NULL errors. TODO(sail) Make this a DCHECK
+ // once crbug.com/278543 is fixed.
+ CHECK(error);
if (error->HasMenuItem()) {
- // Don't add a signin error if it's already being displayed elsewhere.
#if !defined(OS_CHROMEOS)
- std::vector<GlobalError*> errors =
- signin_ui_util::GetSignedInServiceErrors(
- browser_->profile()->GetOriginalProfile());
- if (std::find(errors.begin(), errors.end(), error) != errors.end()) {
+ // Don't add a signin error if it's already being displayed elsewhere.
+ if (std::find(signin_errors.begin(), signin_errors.end(), error) !=
+ signin_errors.end()) {
MenuModel* model = this;
int index = 0;
if (MenuModel::GetModelAndIndexForCommandId(
diff --git a/chrome/browser/ui/uma_browsing_activity_observer.cc b/chrome/browser/ui/uma_browsing_activity_observer.cc
index 046da4f..f0a53be 100644
--- a/chrome/browser/ui/uma_browsing_activity_observer.cc
+++ b/chrome/browser/ui/uma_browsing_activity_observer.cc
@@ -50,7 +50,7 @@
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
- const content::LoadCommittedDetails& load =
+ const content::LoadCommittedDetails load =
*content::Details<content::LoadCommittedDetails>(details).ptr();
content::NavigationController* controller =
@@ -58,6 +58,11 @@
// Track whether the page loaded is a search results page (SRP). Track
// the non-SRP navigations as well so there is a control.
content::RecordAction(content::UserMetricsAction("NavEntryCommitted"));
+ // Attempting to determine the cause of a crash originating from
+ // IsSearchResultsPageFromDefaultSearchProvider but manifesting in
+ // TemplateURLRef::ExtractSearchTermsFromURL(...).
+ // See http://crbug.com/291348.
+ CHECK(load.entry);
if (TemplateURLServiceFactory::GetForProfile(
Profile::FromBrowserContext(controller->GetBrowserContext()))->
IsSearchResultsPageFromDefaultSearchProvider(
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 9979a33..884e63a 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
@@ -11,6 +11,7 @@
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
+#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
@@ -40,6 +41,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
+#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/pref_names.h"
#include "chrome/installer/launcher_support/chrome_launcher_support.h"
#include "chrome/installer/util/browser_distribution.h"
@@ -50,6 +52,8 @@
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/google_chrome_strings.h"
+#include "net/base/url_util.h"
+#include "ui/app_list/app_list_model.h"
#include "ui/app_list/pagination_model.h"
#include "ui/app_list/views/app_list_view.h"
#include "ui/base/l10n/l10n_util.h"
@@ -62,10 +66,6 @@
#include "ui/views/widget/widget.h"
#include "win8/util/win8_util.h"
-#if defined(GOOGLE_CHROME_BUILD)
-#include "chrome/installer/util/install_util.h"
-#endif
-
#if defined(USE_AURA)
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
@@ -368,10 +368,14 @@
virtual void CreateNewWindow(Profile* profile, bool incognito) OVERRIDE;
virtual void ActivateApp(Profile* profile,
const extensions::Extension* extension,
+ AppListSource source,
int event_flags) OVERRIDE;
virtual void LaunchApp(Profile* profile,
const extensions::Extension* extension,
+ AppListSource source,
int event_flags) OVERRIDE;
+ virtual void ShowForProfileByPath(
+ const base::FilePath& profile_path) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(AppListControllerDelegateWin);
};
@@ -609,6 +613,10 @@
view_->OnSigninStatusChanged();
}
+ void SetProfileByPath(const base::FilePath profile_path) {
+ view_->SetProfileByPath(profile_path);
+ }
+
private:
void UpdateArrowPositionAndAnchorPoint(const gfx::Point& cursor) {
gfx::Screen* screen =
@@ -685,13 +693,26 @@
return;
}
- DismissAppList();
- CreateViewForProfile(requested_profile);
+ // If the current view exists, switch the delegate's profile and rebuild the
+ // model.
+ if (!view_) {
+ CreateViewForProfile(requested_profile);
+ } else if (requested_profile != profile_) {
+ profile_ = requested_profile;
+ view_->SetProfileByPath(requested_profile->GetPath());
+ }
DCHECK(view_);
EnsureHaveKeepAliveForView();
- gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
- view_->ShowNearCursor(cursor);
+ // If the app list isn't visible, move the app list to the cursor position
+ // before showing it.
+ if (!IsAppListVisible()) {
+ gfx::Point cursor =
+ gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
+ view_->ShowNearCursor(cursor);
+ } else {
+ view_->Show();
+ }
}
gfx::NativeWindow GetWindow() {
@@ -881,6 +902,13 @@
return false;
}
+void AppListControllerDelegateWin::ShowForProfileByPath(
+ const base::FilePath& profile_path) {
+ AppListService* service = AppListController::GetInstance();
+ service->SetProfilePath(profile_path);
+ service->Show();
+}
+
void AppListControllerDelegateWin::OnShowExtensionPrompt() {
AppListController::GetInstance()->set_can_close(false);
}
@@ -922,15 +950,34 @@
}
void AppListControllerDelegateWin::ActivateApp(
- Profile* profile, const extensions::Extension* extension, int event_flags) {
- LaunchApp(profile, extension, event_flags);
+ Profile* profile,
+ const extensions::Extension* extension,
+ AppListSource source,
+ int event_flags) {
+ LaunchApp(profile, extension, source, event_flags);
}
void AppListControllerDelegateWin::LaunchApp(
- Profile* profile, const extensions::Extension* extension, int event_flags) {
+ Profile* profile,
+ const extensions::Extension* extension,
+ AppListSource source,
+ int event_flags) {
AppListServiceImpl::RecordAppListAppLaunch();
- chrome::OpenApplication(chrome::AppLaunchParams(
- profile, extension, NEW_FOREGROUND_TAB));
+
+ chrome::AppLaunchParams params(
+ profile, extension, NEW_FOREGROUND_TAB);
+
+ if (source != LAUNCH_FROM_UNKNOWN &&
+ extension->id() == extension_misc::kWebStoreAppId) {
+ // Set an override URL to include the source.
+ GURL extension_url = extensions::AppLaunchInfo::GetFullLaunchURL(extension);
+ params.override_url = net::AppendQueryParameter(
+ extension_url,
+ extension_urls::kWebstoreSourceField,
+ AppListSourceToString(source));
+ }
+
+ chrome::OpenApplication(params);
}
AppListController::AppListController()
@@ -980,7 +1027,6 @@
RecordAppListLaunch();
}
-
void AppListController::DismissAppList() {
shower_->DismissAppList();
}
@@ -994,7 +1040,10 @@
if (!IsWarmupNeeded())
return;
+ base::Time before_warmup(base::Time::Now());
shower_->WarmupForProfile(initial_profile);
+ UMA_HISTOGRAM_TIMES("Apps.AppListWarmupDuration",
+ base::Time::Now() - before_warmup);
}
void AppListController::SetAppListNextPaintCallback(
@@ -1100,19 +1149,12 @@
void AppListController::ScheduleWarmup() {
// Post a task to create the app list. This is posted to not impact startup
// time.
- const int kInitWindowDelay = 5;
+ const int kInitWindowDelay = 30;
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&AppListController::LoadProfileForWarmup,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(kInitWindowDelay));
-
- // Send app list usage stats after a delay.
- const int kSendUsageStatsDelay = 5;
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&AppListController::SendAppListStats),
- base::TimeDelta::FromSeconds(kSendUsageStatsDelay));
}
bool AppListController::IsWarmupNeeded() {
diff --git a/chrome/browser/ui/views/apps/native_app_window_views.cc b/chrome/browser/ui/views/apps/native_app_window_views.cc
index 1a64752..6e0c449 100644
--- a/chrome/browser/ui/views/apps/native_app_window_views.cc
+++ b/chrome/browser/ui/views/apps/native_app_window_views.cc
@@ -44,7 +44,7 @@
#include "ash/shell.h"
#include "ash/wm/custom_frame_view_ash.h"
#include "ash/wm/panels/panel_frame_view.h"
-#include "ash/wm/window_settings.h"
+#include "ash/wm/window_state.h"
#include "chrome/browser/ui/ash/ash_util.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/root_window.h"
@@ -285,7 +285,7 @@
preferred_size_.width(),
preferred_size_.height());
aura::Window* native_window = GetNativeWindow();
- ash::wm::GetWindowSettings(native_window)->set_panel_attached(false);
+ ash::wm::GetWindowState(native_window)->set_panel_attached(false);
native_window->SetDefaultParentByRootWindow(
native_window->GetRootWindow(), native_window->GetBoundsInScreen());
window_->SetBounds(window_bounds);
@@ -325,11 +325,9 @@
ui::WindowShowState NativeAppWindowViews::GetRestoredState() const {
if (IsMaximized())
return ui::SHOW_STATE_MAXIMIZED;
-#if defined(USE_ASH)
- // On Ash, restore fullscreen.
if (IsFullscreen())
return ui::SHOW_STATE_FULLSCREEN;
-
+#if defined(USE_ASH)
// Use kRestoreShowStateKey in case a window is minimized/hidden.
ui::WindowShowState restore_state =
window_->GetNativeWindow()->GetProperty(
@@ -412,7 +410,7 @@
if (!shell_window_->window_type_is_panel())
return false;
#if defined(USE_ASH)
- return ash::wm::GetWindowSettings(window_->GetNativeWindow())->
+ return ash::wm::GetWindowState(window_->GetNativeWindow())->
panel_attached();
#else
return true;
@@ -750,8 +748,7 @@
if (!shell_window_->window_type_is_panel())
return false;
#if defined(USE_ASH)
- return !ash::wm::GetWindowSettings(window_->GetNativeWindow())->
- panel_attached();
+ return !ash::wm::GetWindowState(window_->GetNativeWindow())->panel_attached();
#else
return false;
#endif
diff --git a/chrome/browser/ui/views/ash/tab_scrubber.cc b/chrome/browser/ui/views/ash/tab_scrubber.cc
index 8cf7d97..9cc6f46 100644
--- a/chrome/browser/ui/views/ash/tab_scrubber.cc
+++ b/chrome/browser/ui/views/ash/tab_scrubber.cc
@@ -18,9 +18,9 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "ui/aura/window.h"
-#include "ui/base/gestures/gesture_configuration.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#include "ui/events/gestures/gesture_configuration.h"
#include "ui/views/controls/glow_hover_controller.h"
namespace {
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
index 8cd6ff4..f26786b 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
@@ -69,6 +69,12 @@
namespace {
+// The default height of the stack of messages in the overlay view.
+const int kDefaultMessageStackHeight = 90;
+
+// The width for the section container.
+const int kSectionContainerWidth = 440;
+
// The minimum useful height of the contents area of the dialog.
const int kMinimumContentsHeight = 100;
@@ -106,7 +112,7 @@
const int kOverlayTextInterlineSpacing = 10;
// Spacing below image and above text messages in overlay view.
-const int kOverlayImageBottomMargin = 50;
+const int kOverlayImageBottomMargin = 100;
// A dimmer text color used in various parts of the dialog. TODO(estade): should
// this be part of NativeTheme? Currently the value is duplicated in several
@@ -639,8 +645,6 @@
message_stack_->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
kOverlayTextInterlineSpacing));
- message_stack_->set_border(views::Border::CreateEmptyBorder(
- kDialogEdgePadding, kDialogEdgePadding, 0, kDialogEdgePadding));
}
AutofillDialogViews::OverlayView::~OverlayView() {}
@@ -666,19 +670,30 @@
image_view_->SetImage(state.image.ToImageSkia());
+ int label_height = 0;
message_stack_->RemoveAllChildViews(true);
- for (size_t i = 0; i < state.strings.size(); ++i) {
+ if (!state.strings.empty() && !state.strings[0].text.empty()) {
+ const DialogOverlayString& string = state.strings[0];
views::Label* label = new views::Label();
label->SetAutoColorReadabilityEnabled(false);
label->SetMultiLine(true);
- label->SetText(state.strings[i].text);
- label->SetFont(state.strings[i].font);
- label->SetEnabledColor(state.strings[i].text_color);
- label->SetHorizontalAlignment(state.strings[i].alignment);
+ label->SetText(string.text);
+ label->SetFont(string.font);
+ label->SetEnabledColor(string.text_color);
+ label->SetHorizontalAlignment(string.alignment);
message_stack_->AddChildView(label);
+ label_height = label->GetPreferredSize().height();
}
message_stack_->SetVisible(message_stack_->child_count() > 0);
+ const int kVerticalPadding = std::max(
+ (kDefaultMessageStackHeight - label_height) / 2, kDialogEdgePadding);
+ message_stack_->set_border(
+ views::Border::CreateEmptyBorder(kVerticalPadding,
+ kDialogEdgePadding,
+ kVerticalPadding,
+ kDialogEdgePadding));
+
SetVisible(true);
InvalidateLayout();
if (parent())
@@ -697,7 +712,7 @@
}
int message_height = message_stack_->GetHeightForWidth(bounds.width());
- int y = bounds.bottom() - views::kButtonVEdgeMarginNew - message_height;
+ int y = bounds.bottom() - message_height;
message_stack_->SetBounds(bounds.x(), y, bounds.width(), message_height);
gfx::Size image_size = image_view_->GetPreferredSize();
@@ -876,13 +891,13 @@
label_bar->SetLayoutManager(label_bar_layout);
const int kColumnSetId = 0;
views::ColumnSet* columns = label_bar_layout->AddColumnSet(kColumnSetId);
- // TODO(estade): do something about this '480'.
- columns->AddColumn(views::GridLayout::LEADING,
- views::GridLayout::LEADING,
- 0,
- views::GridLayout::FIXED,
- 480,
- 0);
+ columns->AddColumn(
+ views::GridLayout::LEADING,
+ views::GridLayout::LEADING,
+ 0,
+ views::GridLayout::FIXED,
+ kSectionContainerWidth - proxy_button->GetPreferredSize().width(),
+ 0);
columns->AddColumn(views::GridLayout::LEADING,
views::GridLayout::LEADING,
0,
@@ -920,15 +935,12 @@
void AutofillDialogViews::SectionContainer::OnMouseMoved(
const ui::MouseEvent& event) {
- if (!forward_mouse_events_)
- return;
-
- SetActive(true);
+ SetActive(ShouldForwardEvent(event));
}
void AutofillDialogViews::SectionContainer::OnMouseEntered(
const ui::MouseEvent& event) {
- if (!forward_mouse_events_)
+ if (!ShouldForwardEvent(event))
return;
SetActive(true);
@@ -938,17 +950,17 @@
void AutofillDialogViews::SectionContainer::OnMouseExited(
const ui::MouseEvent& event) {
- if (!forward_mouse_events_)
+ SetActive(false);
+ if (!ShouldForwardEvent(event))
return;
- SetActive(false);
proxy_button_->OnMouseExited(ProxyEvent(event));
SchedulePaint();
}
bool AutofillDialogViews::SectionContainer::OnMousePressed(
const ui::MouseEvent& event) {
- if (!forward_mouse_events_)
+ if (!ShouldForwardEvent(event))
return false;
return proxy_button_->OnMousePressed(ProxyEvent(event));
@@ -956,12 +968,35 @@
void AutofillDialogViews::SectionContainer::OnMouseReleased(
const ui::MouseEvent& event) {
- if (!forward_mouse_events_)
+ if (!ShouldForwardEvent(event))
return;
proxy_button_->OnMouseReleased(ProxyEvent(event));
}
+views::View* AutofillDialogViews::SectionContainer::GetEventHandlerForPoint(
+ const gfx::Point& point) {
+ views::View* handler = views::View::GetEventHandlerForPoint(point);
+ // If the event is not in the label bar and there's no background to be
+ // cleared, let normal event handling take place.
+ if (!background() &&
+ point.y() > child_at(0)->bounds().bottom()) {
+ return handler;
+ }
+
+ // Special case for (CVC) inputs in the suggestion view.
+ if (forward_mouse_events_ &&
+ handler->GetAncestorWithClassName(DecoratedTextfield::kViewClassName)) {
+ return handler;
+ }
+
+ // Special case for the proxy button itself.
+ if (handler == proxy_button_)
+ return handler;
+
+ return this;
+}
+
// static
ui::MouseEvent AutofillDialogViews::SectionContainer::ProxyEvent(
const ui::MouseEvent& event) {
@@ -970,6 +1005,12 @@
return event_copy;
}
+bool AutofillDialogViews::SectionContainer::ShouldForwardEvent(
+ const ui::MouseEvent& event) {
+ // Always forward events on the label bar.
+ return forward_mouse_events_ || event.y() <= child_at(0)->bounds().bottom();
+}
+
// AutofillDialogViews::SuggestedButton ----------------------------------------
AutofillDialogViews::SuggestedButton::SuggestedButton(
@@ -1410,7 +1451,8 @@
sign_in_delegate_.reset(
new AutofillDialogSignInDelegate(
this, sign_in_webview_->GetWebContents(),
- delegate_->GetWebContents()->GetDelegate()));
+ delegate_->GetWebContents()->GetDelegate(),
+ GetMinimumSignInViewSize(), GetMaximumSignInViewSize()));
sign_in_webview_->LoadInitialURL(wallet::GetSignInUrl());
sign_in_webview_->SetVisible(true);
@@ -1551,11 +1593,6 @@
error_bubble_->UpdatePosition();
}
-void AutofillDialogViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- if (sign_in_delegate_)
- sign_in_delegate_->SetMinWidth(GetContentsBounds().width());
-}
-
base::string16 AutofillDialogViews::GetWindowTitle() const {
base::string16 title = delegate_->DialogTitle();
// Hack alert: we don't want the dialog to jiggle when a title is added or
@@ -1791,20 +1828,18 @@
if (scrollable_area_->visible()) {
// 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(
- delegate_->GetWebContents()->GetView()->GetNativeView());
- int browser_window_height =
- widget ? widget->GetContentsView()->bounds().height() : INT_MAX;
- const int kWindowDecorationHeight = 200;
- int browser_constrained_height =
- browser_window_height - height - kWindowDecorationHeight;
+ int footnote_height = 0;
if (footnote_view_->visible())
- browser_constrained_height -= footnote_view_->GetHeightForWidth(width);
+ footnote_height = footnote_view_->GetHeightForWidth(width);
+ // TODO(estade): Replace this magic constant with a semantic computation.
+ const int kWindowDecorationHeight = 120;
+ int browser_constrained_scroll_height =
+ GetBrowserViewHeight() - kWindowDecorationHeight - height -
+ footnote_height;
int scroll_height = std::min(
scroll_size.height(),
- std::max(kMinimumContentsHeight, browser_constrained_height));
+ std::max(kMinimumContentsHeight, browser_constrained_scroll_height));
height += scroll_height;
}
@@ -1812,6 +1847,32 @@
return gfx::Size(width + insets.width(), height + insets.height());
}
+int AutofillDialogViews::GetBrowserViewHeight() const {
+ return delegate_->GetWebContents()->GetView()->GetContainerSize().height();
+}
+
+gfx::Size AutofillDialogViews::InsetSize(const gfx::Size& size) const {
+ gfx::Insets insets = GetInsets();
+ return gfx::Size(size.width() - insets.width(),
+ size.height() - insets.height());
+}
+
+gfx::Size AutofillDialogViews::GetMinimumSignInViewSize() const {
+ return InsetSize(GetDialogClientView()->size());
+}
+
+gfx::Size AutofillDialogViews::GetMaximumSignInViewSize() const {
+ // The sign-in view should never grow beyond the browser window, unless the
+ // minimum dialog height has already exceeded this limit.
+ gfx::Size size = GetDialogClientView()->size();
+ // TODO(isherman): This computation seems to come out about 30 pixels too
+ // large, possibly due to an invisible bubble border.
+ const int non_client_view_height = GetSize().height() - size.height();
+ size.set_height(
+ std::max(size.height(), GetBrowserViewHeight() - non_client_view_height));
+ return InsetSize(size);
+}
+
void AutofillDialogViews::InitChildViews() {
button_strip_extra_view_ = new LayoutPropagationView();
button_strip_extra_view_->SetLayoutManager(
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.h b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
index 7c56f94..59a1a17 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.h
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
@@ -114,7 +114,6 @@
// 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 base::string16 GetWindowTitle() const OVERRIDE;
@@ -336,15 +335,20 @@
virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
+ // This is needed because not all events percolate up the views hierarchy.
+ virtual View* GetEventHandlerForPoint(const gfx::Point& point) OVERRIDE;
private:
// Converts |event| to one suitable for |proxy_button_|.
static ui::MouseEvent ProxyEvent(const ui::MouseEvent& event);
+ // Returns true if the given event should be forwarded to |proxy_button_|.
+ bool ShouldForwardEvent(const ui::MouseEvent& event);
+
// Mouse events on |this| are sent to this button.
views::Button* proxy_button_; // Weak reference.
- // When true, mouse events will be forwarded to |proxy_button_|.
+ // When true, all mouse events will be forwarded to |proxy_button_|.
bool forward_mouse_events_;
DISALLOW_COPY_AND_ASSIGN(SectionContainer);
@@ -477,6 +481,18 @@
gfx::Size CalculatePreferredSize();
+ // Returns the height of the initiating WebContents' view.
+ int GetBrowserViewHeight() const;
+
+ // Returns the |size| inset by |GetInsets()|.
+ gfx::Size InsetSize(const gfx::Size& size) const;
+
+ // Returns the minimum size of the sign in view for this dialog.
+ gfx::Size GetMinimumSignInViewSize() const;
+
+ // Returns the maximum size of the sign in view for this dialog.
+ gfx::Size GetMaximumSignInViewSize() const;
+
void InitChildViews();
// Creates and returns a view that holds all detail sections.
diff --git a/chrome/browser/ui/views/avatar_menu_bubble_view.cc b/chrome/browser/ui/views/avatar_menu_bubble_view.cc
index 3089862..401ff60 100644
--- a/chrome/browser/ui/views/avatar_menu_bubble_view.cc
+++ b/chrome/browser/ui/views/avatar_menu_bubble_view.cc
@@ -11,7 +11,7 @@
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_info_util.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -216,8 +216,9 @@
class ProfileItemView : public views::CustomButton,
public HighlightDelegate {
public:
- ProfileItemView(const AvatarMenuModel::Item& item,
- AvatarMenuBubbleView* parent);
+ ProfileItemView(const AvatarMenu::Item& item,
+ AvatarMenuBubbleView* parent,
+ AvatarMenu* menu);
virtual gfx::Size GetPreferredSize() OVERRIDE;
virtual void Layout() OVERRIDE;
@@ -229,7 +230,7 @@
virtual void OnHighlightStateChanged() OVERRIDE;
virtual void OnFocusStateChanged(bool has_focus) OVERRIDE;
- const AvatarMenuModel::Item& item() const { return item_; }
+ const AvatarMenu::Item& item() const { return item_; }
EditProfileLink* edit_link() { return edit_link_; }
private:
@@ -237,8 +238,9 @@
bool IsHighlighted();
- AvatarMenuModel::Item item_;
+ AvatarMenu::Item item_;
AvatarMenuBubbleView* parent_;
+ AvatarMenu* menu_;
views::ImageView* image_view_;
views::Label* name_label_;
views::Label* sync_state_label_;
@@ -247,11 +249,13 @@
DISALLOW_COPY_AND_ASSIGN(ProfileItemView);
};
-ProfileItemView::ProfileItemView(const AvatarMenuModel::Item& item,
- AvatarMenuBubbleView* parent)
+ProfileItemView::ProfileItemView(const AvatarMenu::Item& item,
+ AvatarMenuBubbleView* parent,
+ AvatarMenu* menu)
: views::CustomButton(parent),
item_(item),
- parent_(parent) {
+ parent_(parent),
+ menu_(menu) {
set_notify_enter_exit_on_child(true);
image_view_ = new ProfileImageView();
@@ -365,7 +369,8 @@
sync_state_label_->SetBackgroundColor(color);
edit_link_->SetBackgroundColor(color);
- bool show_edit = IsHighlighted() && item_.active;
+ bool show_edit = IsHighlighted() && item_.active &&
+ menu_->ShouldShowEditProfileLink();
sync_state_label_->SetVisible(!show_edit);
edit_link_->SetVisible(show_edit);
SchedulePaint();
@@ -518,9 +523,11 @@
managed_user_info_(NULL),
separator_switch_users_(NULL),
expanded_(false) {
- avatar_menu_model_.reset(new AvatarMenuModel(
+ avatar_menu_.reset(new AvatarMenu(
&g_browser_process->profile_manager()->GetProfileInfoCache(),
- this, browser_));
+ this,
+ browser_));
+ avatar_menu_->RebuildMenu();
}
AvatarMenuBubbleView::~AvatarMenuBubbleView() {
@@ -651,7 +658,7 @@
chrome::ShowSettingsSubPage(browser_, subpage);
return;
} else if (sender->tag() == IDS_PROFILES_PROFILE_SIGNOUT_BUTTON) {
- avatar_menu_model_->BeginSignOut();
+ avatar_menu_->BeginSignOut();
return;
}
@@ -660,7 +667,7 @@
if (sender == item_view) {
// Clicking on the active profile shouldn't do anything.
if (!item_view->item().active) {
- avatar_menu_model_->SwitchToProfile(
+ avatar_menu_->SwitchToProfile(
i, ui::DispositionFromEventFlags(event.flags()) == NEW_WINDOW);
}
break;
@@ -670,19 +677,19 @@
void AvatarMenuBubbleView::LinkClicked(views::Link* source, int event_flags) {
if (source == buttons_view_) {
- avatar_menu_model_->AddNewProfile(ProfileMetrics::ADD_NEW_USER_ICON);
+ avatar_menu_->AddNewProfile(ProfileMetrics::ADD_NEW_USER_ICON);
return;
}
if (source == switch_profile_link_) {
expanded_ = true;
- OnAvatarMenuModelChanged(avatar_menu_model_.get());
+ OnAvatarMenuChanged(avatar_menu_.get());
return;
}
for (size_t i = 0; i < item_views_.size(); ++i) {
ProfileItemView* item_view = item_views_[i];
if (source == item_view->edit_link()) {
- avatar_menu_model_->EditProfile(i);
+ avatar_menu_->EditProfile(i);
return;
}
}
@@ -694,7 +701,7 @@
void AvatarMenuBubbleView::Init() {
// Build the menu for the first time.
- OnAvatarMenuModelChanged(avatar_menu_model_.get());
+ OnAvatarMenuChanged(avatar_menu_.get());
AddAccelerator(ui::Accelerator(ui::VKEY_DOWN, ui::EF_NONE));
AddAccelerator(ui::Accelerator(ui::VKEY_UP, ui::EF_NONE));
}
@@ -705,10 +712,12 @@
}
void AvatarMenuBubbleView::InitMenuContents(
- AvatarMenuModel* avatar_menu_model) {
- for (size_t i = 0; i < avatar_menu_model->GetNumberOfItems(); ++i) {
- const AvatarMenuModel::Item& item = avatar_menu_model->GetItemAt(i);
- ProfileItemView* item_view = new ProfileItemView(item, this);
+ AvatarMenu* avatar_menu) {
+ for (size_t i = 0; i < avatar_menu->GetNumberOfItems(); ++i) {
+ const AvatarMenu::Item& item = avatar_menu->GetItemAt(i);
+ ProfileItemView* item_view = new ProfileItemView(item,
+ this,
+ avatar_menu_.get());
item_view->SetAccessibleName(l10n_util::GetStringFUTF16(
IDS_PROFILES_SWITCH_TO_PROFILE_ACCESSIBLE_NAME, item.name));
item_view->set_focusable(true);
@@ -722,7 +731,7 @@
AddChildView(separator_);
buttons_view_ = new ActionButtonView(this, browser_->profile());
AddChildView(buttons_view_);
- } else if (avatar_menu_model_->ShouldShowAddNewProfileLink()) {
+ } else if (avatar_menu_->ShouldShowAddNewProfileLink()) {
views::Link* add_profile_link = new views::Link(
l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK));
add_profile_link->set_listener(this);
@@ -736,12 +745,14 @@
}
void AvatarMenuBubbleView::InitManagedUserContents(
- AvatarMenuModel* avatar_menu_model) {
+ AvatarMenu* avatar_menu) {
// Show the profile of the managed user.
- size_t active_index = avatar_menu_model->GetActiveProfileIndex();
- const AvatarMenuModel::Item& item =
- avatar_menu_model->GetItemAt(active_index);
- ProfileItemView* item_view = new ProfileItemView(item, this);
+ size_t active_index = avatar_menu->GetActiveProfileIndex();
+ const AvatarMenu::Item& item =
+ avatar_menu->GetItemAt(active_index);
+ ProfileItemView* item_view = new ProfileItemView(item,
+ this,
+ avatar_menu_.get());
item_view->SetAccessibleName(l10n_util::GetStringFUTF16(
IDS_PROFILES_SWITCH_TO_PROFILE_ACCESSIBLE_NAME, item.name));
item_views_.push_back(item_view);
@@ -751,7 +762,7 @@
// Add information about managed users.
managed_user_info_ =
- new views::Label(avatar_menu_model_->GetManagedUserInformation(),
+ new views::Label(avatar_menu_->GetManagedUserInformation(),
ui::ResourceBundle::GetSharedInstance().GetFont(
ui::ResourceBundle::SmallFont));
managed_user_info_->SetMultiLine(true);
@@ -761,7 +772,7 @@
// Add the managed user icon.
icon_view_ = new views::ImageView();
- icon_view_->SetImage(avatar_menu_model_->GetManagedUserIcon().ToImageSkia());
+ icon_view_->SetImage(avatar_menu_->GetManagedUserIcon().ToImageSkia());
AddChildView(icon_view_);
// Add a link for switching profiles.
@@ -775,8 +786,8 @@
AddChildView(switch_profile_link_);
}
-void AvatarMenuBubbleView::OnAvatarMenuModelChanged(
- AvatarMenuModel* avatar_menu_model) {
+void AvatarMenuBubbleView::OnAvatarMenuChanged(
+ AvatarMenu* avatar_menu) {
// Unset all our child view references and call RemoveAllChildViews() which
// will actually delete them.
buttons_view_ = NULL;
@@ -784,10 +795,10 @@
item_views_.clear();
RemoveAllChildViews(true);
- if (avatar_menu_model_->GetManagedUserInformation().empty() || expanded_)
- InitMenuContents(avatar_menu_model);
+ if (avatar_menu_->GetManagedUserInformation().empty() || expanded_)
+ InitMenuContents(avatar_menu);
else
- InitManagedUserContents(avatar_menu_model);
+ InitManagedUserContents(avatar_menu);
// If the bubble has already been shown then resize and reposition the bubble.
Layout();
diff --git a/chrome/browser/ui/views/avatar_menu_bubble_view.h b/chrome/browser/ui/views/avatar_menu_bubble_view.h
index 39d4f6f..781e6be 100644
--- a/chrome/browser/ui/views/avatar_menu_bubble_view.h
+++ b/chrome/browser/ui/views/avatar_menu_bubble_view.h
@@ -10,12 +10,12 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
-#include "chrome/browser/profiles/avatar_menu_model_observer.h"
+#include "chrome/browser/profiles/avatar_menu_observer.h"
#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/link_listener.h"
-class AvatarMenuModel;
+class AvatarMenu;
class Browser;
class ProfileItemView;
@@ -36,7 +36,7 @@
class AvatarMenuBubbleView : public views::BubbleDelegateView,
public views::ButtonListener,
public views::LinkListener,
- public AvatarMenuModelObserver {
+ public AvatarMenuObserver {
public:
// Helper function to show the bubble and ensure that it doesn't reshow.
// Normally this bubble is shown when there's a mouse down event on a button.
@@ -75,9 +75,9 @@
virtual void Init() OVERRIDE;
virtual void WindowClosing() OVERRIDE;
- // AvatarMenuModelObserver implementation.
- virtual void OnAvatarMenuModelChanged(
- AvatarMenuModel* avatar_menu_model) OVERRIDE;
+ // AvatarMenuObserver implementation.
+ virtual void OnAvatarMenuChanged(
+ AvatarMenu* avatar_menu) OVERRIDE;
// We normally close the bubble any time it becomes inactive but this can lead
// to flaky tests where unexpected UI events are triggering this behavior.
@@ -98,12 +98,12 @@
void SetBackgroundColors();
// Create the menu contents for a normal profile.
- void InitMenuContents(AvatarMenuModel* avatar_menu_model);
+ void InitMenuContents(AvatarMenu* avatar_menu);
// Create the managed user specific contents of the menu.
- void InitManagedUserContents(AvatarMenuModel* avatar_menu_model);
+ void InitManagedUserContents(AvatarMenu* avatar_menu);
- scoped_ptr<AvatarMenuModel> avatar_menu_model_;
+ scoped_ptr<AvatarMenu> avatar_menu_;
gfx::Rect anchor_rect_;
Browser* browser_;
std::vector<ProfileItemView*> item_views_;
@@ -112,13 +112,13 @@
views::Separator* separator_;
// This will be non-NULL if and only if
- // avatar_menu_model_->ShouldShowAddNewProfileLink() returns true. See
- // OnAvatarMenuModelChanged().
+ // avatar_menu_->ShouldShowAddNewProfileLink() returns true. See
+ // OnAvatarMenuChanged().
views::View* buttons_view_;
// This will be non-NULL if and only if |expanded_| is false and
- // avatar_menu_model_->GetManagedUserInformation() returns a non-empty string.
- // See OnAvatarMenuModelChanged().
+ // avatar_menu_->GetManagedUserInformation() returns a non-empty string.
+ // See OnAvatarMenuChanged().
views::Label* managed_user_info_;
views::ImageView* icon_view_;
views::Separator* separator_switch_users_;
diff --git a/chrome/browser/ui/views/avatar_menu_button.cc b/chrome/browser/ui/views/avatar_menu_button.cc
index 5cdb78f..530716c 100644
--- a/chrome/browser/ui/views/avatar_menu_button.cc
+++ b/chrome/browser/ui/views/avatar_menu_button.cc
@@ -8,7 +8,7 @@
#include "base/prefs/pref_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile_info_util.h"
#include "chrome/browser/profiles/profile_metrics.h"
#include "chrome/browser/profiles/profiles_state.h"
@@ -29,7 +29,7 @@
: MenuButton(NULL, string16(), this, false),
browser_(browser),
disabled_(disabled),
- is_gaia_picture_(false),
+ is_rectangle_(false),
old_height_(0) {
// In RTL mode, the avatar icon should be looking the opposite direction.
EnableCanvasFlippingForRTLUI(true);
@@ -45,7 +45,7 @@
if (old_height_ != height() || button_icon_.isNull()) {
old_height_ = height();
button_icon_ = *profiles::GetAvatarIconForTitleBar(
- *icon_, is_gaia_picture_, width(), height()).ToImageSkia();
+ *icon_, is_rectangle_, width(), height()).ToImageSkia();
}
// Scale the image to fit the width of the button.
@@ -76,10 +76,10 @@
}
void AvatarMenuButton::SetAvatarIcon(const gfx::Image& icon,
- bool is_gaia_picture) {
+ bool is_rectangle) {
icon_.reset(new gfx::Image(icon));
button_icon_ = gfx::ImageSkia();
- is_gaia_picture_ = is_gaia_picture;
+ is_rectangle_ = is_rectangle;
SchedulePaint();
}
diff --git a/chrome/browser/ui/views/avatar_menu_button.h b/chrome/browser/ui/views/avatar_menu_button.h
index 2555c5a..e7142b7 100644
--- a/chrome/browser/ui/views/avatar_menu_button.h
+++ b/chrome/browser/ui/views/avatar_menu_button.h
@@ -36,7 +36,9 @@
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE;
- virtual void SetAvatarIcon(const gfx::Image& icon, bool is_gaia_picture);
+ // Sets the image for the avatar button. Rectangular images, as opposed
+ // to Chrome avatar icons, will be resized and modified for the title bar.
+ virtual void SetAvatarIcon(const gfx::Image& icon, bool is_rectangle);
void ShowAvatarBubble();
@@ -52,7 +54,7 @@
// Use a scoped ptr because gfx::Image doesn't have a default constructor.
scoped_ptr<gfx::Image> icon_;
gfx::ImageSkia button_icon_;
- bool is_gaia_picture_;
+ bool is_rectangle_;
int old_height_;
DISALLOW_COPY_AND_ASSIGN(AvatarMenuButton);
diff --git a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
index 757108d..a3c0125 100644
--- a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
+++ b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
@@ -8,7 +8,7 @@
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/ui/browser_list.h"
@@ -150,21 +150,21 @@
chrome::NOTIFICATION_BROWSER_CLOSED,
content::Source<Browser>(browser()));
- AvatarMenuModel* model =
- ProfileChooserView::profile_bubble_->avatar_menu_model_.get();
- const AvatarMenuModel::Item& model_item_before =
- model->GetItemAt(model->GetActiveProfileIndex());
- EXPECT_FALSE(model_item_before.signin_required);
+ AvatarMenu* menu =
+ ProfileChooserView::profile_bubble_->avatar_menu_.get();
+ const AvatarMenu::Item& menu_item_before =
+ menu->GetItemAt(menu->GetActiveProfileIndex());
+ EXPECT_FALSE(menu_item_before.signin_required);
ui::MouseEvent mouse_ev(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0);
- model->SetLogoutURL("about:blank");
+ menu->SetLogoutURL("about:blank");
ProfileChooserView::profile_bubble_->LinkClicked(
static_cast<views::Link*>(
ProfileChooserView::profile_bubble_->signout_current_profile_link_),
0);
- EXPECT_TRUE(model->GetItemAt(model->GetActiveProfileIndex()).signin_required);
+ EXPECT_TRUE(menu->GetItemAt(menu->GetActiveProfileIndex()).signin_required);
window_close_observer.Wait(); // Rely on test timeout for failure indication.
EXPECT_TRUE(browser_list->empty());
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 455c659..fa3dbf1 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -18,7 +18,6 @@
#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_utils.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
@@ -1169,7 +1168,7 @@
node = model_->bookmark_bar_node()->GetChild(button_index);
}
- bookmark_utils::RecordBookmarkFolderOpen(GetBookmarkLaunchLocation());
+ RecordBookmarkFolderOpen(GetBookmarkLaunchLocation());
bookmark_menu_ = new BookmarkMenuController(
browser_, page_navigator_, GetWidget(), node, start_index);
bookmark_menu_->set_observer(this);
@@ -1188,7 +1187,7 @@
content::PAGE_TRANSITION_AUTO_BOOKMARK,
false);
page_navigator_->OpenURL(params);
- bookmark_utils::RecordAppsPageOpen(GetBookmarkLaunchLocation());
+ RecordBookmarkAppsPageOpen(GetBookmarkLaunchLocation());
return;
}
@@ -1213,7 +1212,7 @@
disposition_from_event_flags, browser_->profile());
}
- bookmark_utils::RecordBookmarkLaunch(GetBookmarkLaunchLocation());
+ RecordBookmarkLaunch(GetBookmarkLaunchLocation());
}
void BookmarkBarView::ShowContextMenuForView(views::View* source,
@@ -1315,10 +1314,9 @@
return static_cast<views::TextButton*>(child_at(index));
}
-bookmark_utils::BookmarkLaunchLocation
- BookmarkBarView::GetBookmarkLaunchLocation() const {
- return IsDetached() ? bookmark_utils::LAUNCH_DETACHED_BAR :
- bookmark_utils::LAUNCH_ATTACHED_BAR;
+BookmarkLaunchLocation BookmarkBarView::GetBookmarkLaunchLocation() const {
+ return IsDetached() ? BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR :
+ BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR;
}
int BookmarkBarView::GetFirstHiddenNodeIndex() {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
index 0db4aa3..031fcaf 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
@@ -15,7 +15,7 @@
#include "base/prefs/pref_change_registrar.h"
#include "chrome/browser/bookmarks/bookmark_model_observer.h"
#include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/ui/bookmarks/bookmark_bar.h"
#include "chrome/browser/ui/bookmarks/bookmark_bar_instructions_delegate.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view_observer.h"
@@ -283,8 +283,9 @@
// Returns the button at the specified index.
views::TextButton* GetBookmarkButton(int index);
- // Returns LAUNCH_DETACHED_BAR or LAUNCH_ATTACHED_BAR based on detached state.
- bookmark_utils::BookmarkLaunchLocation GetBookmarkLaunchLocation() const;
+ // Returns BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR or
+ // BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR based on detached state.
+ BookmarkLaunchLocation GetBookmarkLaunchLocation() const;
// Returns the index of the first hidden bookmark button. If all buttons are
// visible, this returns GetBookmarkButtonCount().
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_controller_win.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_controller_win.cc
index ce6338a..ab115c6 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_controller_win.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_controller_win.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h"
#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
#include "chrome/browser/ui/browser.h"
@@ -124,8 +124,7 @@
chrome::OpenAll(parent_window_, navigator, selection_,
NEW_FOREGROUND_TAB, profile_to_use);
- bookmark_utils::RecordBookmarkLaunch(
- bookmark_utils::LAUNCH_CONTEXT_MENU);
+ RecordBookmarkLaunch(BOOKMARK_LAUNCH_LOCATION_CONTEXT_MENU);
return true;
}
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.cc
index d3a4614..66c5c9d 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.cc
@@ -8,7 +8,7 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_observer.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h"
@@ -41,7 +41,7 @@
bookmark_bar_(NULL) {
menu_delegate_->Init(this, NULL, node, start_child_index,
BookmarkMenuDelegate::HIDE_PERMANENT_FOLDERS,
- bookmark_utils::LAUNCH_BAR_SUBFOLDER);
+ BOOKMARK_LAUNCH_LOCATION_BAR_SUBFOLDER);
menu_runner_.reset(new views::MenuRunner(menu_delegate_->menu()));
}
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
index 41f5dac..f7cb252 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
@@ -8,7 +8,6 @@
#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_node_data.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
@@ -53,20 +52,18 @@
next_menu_id_(first_menu_id),
real_delegate_(NULL),
is_mutating_model_(false),
- location_(bookmark_utils::LAUNCH_NONE){
-}
+ location_(BOOKMARK_LAUNCH_LOCATION_NONE) {}
BookmarkMenuDelegate::~BookmarkMenuDelegate() {
GetBookmarkModel()->RemoveObserver(this);
}
-void BookmarkMenuDelegate::Init(
- views::MenuDelegate* real_delegate,
- MenuItemView* parent,
- const BookmarkNode* node,
- int start_child_index,
- ShowOptions show_options,
- bookmark_utils::BookmarkLaunchLocation location) {
+void BookmarkMenuDelegate::Init(views::MenuDelegate* real_delegate,
+ MenuItemView* parent,
+ const BookmarkNode* node,
+ int start_child_index,
+ ShowOptions show_options,
+ BookmarkLaunchLocation location) {
GetBookmarkModel()->AddObserver(this);
real_delegate_ = real_delegate;
if (parent) {
@@ -141,11 +138,12 @@
chrome::OpenAll(parent_->GetNativeWindow(), page_navigator_, selection,
ui::DispositionFromEventFlags(mouse_event_flags),
profile_);
- bookmark_utils::RecordBookmarkLaunch(location_);
+ RecordBookmarkLaunch(location_);
}
bool BookmarkMenuDelegate::ShouldExecuteCommandWithoutClosingMenu(
- int id, const ui::Event& event) {
+ int id,
+ const ui::Event& event) {
return (event.flags() & ui::EF_LEFT_MOUSE_BUTTON) &&
ui::DispositionFromEventFlags(event.flags()) == NEW_BACKGROUND_TAB;
}
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h
index 6bed146..e88fde1 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h
@@ -11,7 +11,7 @@
#include "base/compiler_specific.h"
#include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
#include "chrome/browser/bookmarks/bookmark_node_data.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_context_menu.h"
#include "ui/views/controls/menu/menu_delegate.h"
@@ -62,7 +62,7 @@
const BookmarkNode* node,
int start_child_index,
ShowOptions show_options,
- bookmark_utils::BookmarkLaunchLocation location);
+ BookmarkLaunchLocation location);
// Sets the PageNavigator.
void SetPageNavigator(content::PageNavigator* navigator);
@@ -196,7 +196,7 @@
bool is_mutating_model_;
// The location where this bookmark menu will be displayed (for UMA).
- bookmark_utils::BookmarkLaunchLocation location_;
+ BookmarkLaunchLocation location_;
DISALLOW_COPY_AND_ASSIGN(BookmarkMenuDelegate);
};
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc
index 97c565e..fb51c40 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc
@@ -7,6 +7,7 @@
#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_stats.h"
#include "chrome/browser/bookmarks/bookmark_test_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/test/base/browser_with_test_window_test.h"
@@ -88,7 +89,7 @@
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);
+ BOOKMARK_LAUNCH_LOCATION_NONE);
std::vector<const BookmarkNode*> nodes_to_remove;
nodes_to_remove.push_back(node->GetChild(1));
bookmark_menu_delegate_->WillRemoveBookmarks(nodes_to_remove);
diff --git a/chrome/browser/ui/views/collected_cookies_views.cc b/chrome/browser/ui/views/collected_cookies_views.cc
index fab9e65..910ee3a 100644
--- a/chrome/browser/ui/views/collected_cookies_views.cc
+++ b/chrome/browser/ui/views/collected_cookies_views.cc
@@ -302,6 +302,11 @@
///////////////////////////////////////////////////////////////////////////////
// CollectedCookiesViews, views::View overrides:
+gfx::Size CollectedCookiesViews::GetMinimumSize() {
+ // Allow UpdateWebContentsModalDialogPosition to clamp the dialog width.
+ return gfx::Size(0, View::GetMinimumSize().height());
+}
+
void CollectedCookiesViews::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
if (details.is_add && details.child == this)
diff --git a/chrome/browser/ui/views/collected_cookies_views.h b/chrome/browser/ui/views/collected_cookies_views.h
index 2d91554..14ed7ae 100644
--- a/chrome/browser/ui/views/collected_cookies_views.h
+++ b/chrome/browser/ui/views/collected_cookies_views.h
@@ -65,6 +65,7 @@
virtual void OnTreeViewSelectionChanged(views::TreeView* tree_view) OVERRIDE;
// views::View:
+ virtual gfx::Size GetMinimumSize() OVERRIDE;
virtual void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) OVERRIDE;
diff --git a/chrome/browser/ui/views/constrained_window_views_browsertest.cc b/chrome/browser/ui/views/constrained_window_views_browsertest.cc
index 4421cd6..eb08335 100644
--- a/chrome/browser/ui/views/constrained_window_views_browsertest.cc
+++ b/chrome/browser/ui/views/constrained_window_views_browsertest.cc
@@ -34,7 +34,7 @@
#if defined(USE_AURA) && defined(USE_X11)
#include <X11/Xlib.h>
-#include "ui/base/x/x11_util.h"
+#include "ui/events/x/events_x_utils.h"
#endif
using web_modal::WebContentsModalDialogManager;
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc
index 3d6639a..93d2808 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents.cc
+++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -18,6 +18,7 @@
#include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
#include "chrome/browser/ui/content_settings/content_setting_media_menu_model.h"
#include "chrome/browser/ui/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/password_menu_model.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/plugin_service.h"
@@ -135,7 +136,6 @@
ContentSettingBubbleContents::MediaMenuParts::~MediaMenuParts() {}
-
// ContentSettingBubbleContents -----------------------------------------------
ContentSettingBubbleContents::ContentSettingBubbleContents(
@@ -324,13 +324,18 @@
media_menus_[menu_button] = menu_view;
if (!menu_view->menu_model->GetItemCount()) {
- // Show a "None available" title and grey out the menu when there is no
- // available device.
+ // Show a "None available" title and grey out the menu when there are
+ // no available devices.
menu_button->SetText(
l10n_util::GetStringUTF16(IDS_MEDIA_MENU_NO_DEVICE_TITLE));
menu_button->SetEnabled(false);
}
+ // Disable the device selection when the website is managing the devices
+ // itself.
+ if (i->second.disabled)
+ menu_button->SetEnabled(false);
+
// Use the longest width of the menus as the width of the menu buttons.
menu_width = std::max(menu_width,
GetPreferredMediaMenuWidth(
@@ -386,10 +391,13 @@
const int kDoubleColumnSetId = 1;
views::ColumnSet* double_column_set =
layout->AddColumnSet(kDoubleColumnSetId);
+
if (content_setting_bubble_model_->content_type() ==
CONTENT_SETTINGS_TYPE_SAVE_PASSWORD) {
double_column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 1,
GridLayout::USE_PREF, 0, 0);
+ double_column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
double_column_set->AddPaddingColumn(
0, views::kRelatedControlSmallVerticalSpacing);
double_column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
@@ -402,11 +410,13 @@
GridLayout::USE_PREF, 0, 0);
cancel_button_ = new views::LabelButton(
- this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON));
- cancel_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
+ this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CANCEL_DROP_DOWN));
+ cancel_button_->set_border(
+ new views::TextButtonNativeThemeBorder(cancel_button_));
save_button_ = new views::LabelButton(
this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON));
- save_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
+ save_button_->set_border(
+ new views::TextButtonNativeThemeBorder(save_button_));
manage_link_ = new views::Link(UTF8ToUTF16(bubble_content.manage_link));
manage_link_->set_listener(this);
@@ -414,6 +424,18 @@
layout->StartRow(0, kDoubleColumnSetId);
layout->AddView(cancel_button_);
+
+ views::MenuButton* menu_button =
+ new views::MenuButton(NULL, UTF8ToUTF16(" "), this, true);
+ menu_button->set_alignment(views::TextButton::ALIGN_LEFT);
+ menu_button->set_border(
+ new views::TextButtonNativeThemeBorder(menu_button));
+
+ password_menu_model_.reset(
+ new PasswordMenuModel(content_setting_bubble_model_.get(), this));
+ layout->AddView(menu_button);
+ menu_button->set_max_width(15);
+
layout->AddView(save_button_);
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
@@ -463,9 +485,7 @@
if (sender == save_button_)
content_setting_bubble_model_->OnSaveClicked();
- else if (sender == cancel_button_)
- content_setting_bubble_model_->OnCancelClicked();
- else if (sender == close_button_)
+ else if (sender == cancel_button_ || sender == close_button_)
content_setting_bubble_model_->OnDoneClicked();
else
NOTREACHED();
@@ -495,21 +515,36 @@
void ContentSettingBubbleContents::OnMenuButtonClicked(
views::View* source,
const gfx::Point& point) {
- MediaMenuPartsMap::iterator i(media_menus_.find(
- static_cast<views::MenuButton*>(source)));
- DCHECK(i != media_menus_.end());
+ if (password_menu_model_) {
+ menu_runner_.reset(new views::MenuRunner(password_menu_model_.get()));
- menu_runner_.reset(new views::MenuRunner(i->second->menu_model.get()));
+ gfx::Point screen_location;
+ views::View::ConvertPointToScreen(static_cast<views::MenuButton*>(source),
+ &screen_location);
+ ignore_result(menu_runner_->RunMenuAt(
+ source->GetWidget(),
+ static_cast<views::MenuButton*>(source),
+ gfx::Rect(screen_location,
+ static_cast<views::MenuButton*>(source)->size()),
+ views::MenuItemView::TOPRIGHT,
+ ui::MENU_SOURCE_NONE,
+ views::MenuRunner::HAS_MNEMONICS));
+ } else {
+ MediaMenuPartsMap::iterator j(media_menus_.find(
+ static_cast<views::MenuButton*>(source)));
+ DCHECK(j != media_menus_.end());
+ menu_runner_.reset(new views::MenuRunner(j->second->menu_model.get()));
- gfx::Point screen_location;
- views::View::ConvertPointToScreen(i->first, &screen_location);
- ignore_result(menu_runner_->RunMenuAt(
- source->GetWidget(),
- i->first,
- gfx::Rect(screen_location, i->first->size()),
- views::MenuItemView::TOPLEFT,
- ui::MENU_SOURCE_NONE,
- views::MenuRunner::HAS_MNEMONICS));
+ gfx::Point screen_location;
+ views::View::ConvertPointToScreen(j->first, &screen_location);
+ ignore_result(menu_runner_->RunMenuAt(
+ source->GetWidget(),
+ j->first,
+ gfx::Rect(screen_location, j->first->size()),
+ views::MenuItemView::TOPLEFT,
+ ui::MENU_SOURCE_NONE,
+ views::MenuRunner::HAS_MNEMONICS));
+ }
}
void ContentSettingBubbleContents::Observe(
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.h b/chrome/browser/ui/views/content_setting_bubble_contents.h
index de7b0e9..9fc8de7 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents.h
+++ b/chrome/browser/ui/views/content_setting_bubble_contents.h
@@ -117,6 +117,7 @@
views::LabelButton* close_button_;
scoped_ptr<views::MenuRunner> menu_runner_;
MediaMenuPartsMap media_menus_;
+ scoped_ptr<ui::SimpleMenuModel> password_menu_model_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ContentSettingBubbleContents);
};
diff --git a/chrome/browser/ui/views/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_media_picker_views.cc
index 507ce4e..782b736 100644
--- a/chrome/browser/ui/views/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_media_picker_views.cc
@@ -23,6 +23,14 @@
#include "ui/views/window/dialog_client_view.h"
#include "ui/views/window/dialog_delegate.h"
+#if defined(USE_AURA)
+#include "ui/aura/root_window.h"
+#endif
+
+#if defined(OS_WIN)
+#include "ui/views/win/hwnd_util.h"
+#endif
+
using content::DesktopMediaID;
namespace {
@@ -100,6 +108,8 @@
scoped_ptr<DesktopMediaPickerModel> model);
virtual ~DesktopMediaListView();
+ void StartUpdating(content::DesktopMediaID::Id dialog_window_id);
+
// Called by DesktopMediaSourceView when selection has changed.
void OnSelectionChanged();
@@ -292,10 +302,14 @@
: parent_(parent),
model_(model.Pass()) {
model_->SetThumbnailSize(gfx::Size(kThumbnailWidth, kThumbnailHeight));
- model_->StartUpdating(this);
}
-DesktopMediaListView::~DesktopMediaListView() {
+DesktopMediaListView::~DesktopMediaListView() {}
+
+void DesktopMediaListView::StartUpdating(
+ content::DesktopMediaID::Id dialog_window_id) {
+ model_->SetViewDialogWindowId(dialog_window_id);
+ model_->StartUpdating(this);
}
void DesktopMediaListView::OnSelectionChanged() {
@@ -447,6 +461,29 @@
AddChildView(scroll_view_);
DialogDelegate::CreateDialogWidget(this, context, parent_window);
+
+ // DesktopMediaPickerModel needs to know the ID of the picker window which
+ // matches the ID it gets from the OS. Depending on the OS and configuration
+ // we get this ID differently.
+ //
+ // TODO(sergeyu): Update this code when Ash-specific window capturer is
+ // implemented. Currently this code will always get native windows ID
+ // which is not what we need in Ash. http://crbug.com/295102
+ content::DesktopMediaID::Id dialog_window_id;
+
+#if defined(OS_WIN)
+ dialog_window_id = reinterpret_cast<content::DesktopMediaID::Id>(
+ views::HWNDForWidget(GetWidget()));
+#elif defined(USE_AURA)
+ dialog_window_id = static_cast<content::DesktopMediaID::Id>(
+ GetWidget()->GetNativeWindow()->GetRootWindow()->GetAcceleratedWidget());
+#else
+ dialog_window_id = 0;
+ NOTIMPLEMENTED();
+#endif
+
+ list_view_->StartUpdating(dialog_window_id);
+
GetWidget()->Show();
}
diff --git a/chrome/browser/ui/views/dropdown_bar_view.cc b/chrome/browser/ui/views/dropdown_bar_view.cc
index eece8aa..235bbef 100644
--- a/chrome/browser/ui/views/dropdown_bar_view.cc
+++ b/chrome/browser/ui/views/dropdown_bar_view.cc
@@ -112,7 +112,7 @@
if (animation_offset() > 0) {
gfx::Canvas animating_edges(
gfx::Size(bounds().width(), kAnimatingEdgeHeight),
- canvas->scale_factor(),
+ canvas->image_scale(),
false);
canvas->Translate(bounds().OffsetFromOrigin());
OnPaintBackground(&animating_edges);
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
index 081e36c..e52edaf 100644
--- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
@@ -42,19 +42,9 @@
}
// Returns parent window for extension uninstall dialog.
-// For platforms with an app list, use the app list window if it is visible.
-// For other platforms or when app list is not visible, use the given browser
-// window.
-// Note this function could return NULL if the app list is not visible and
-// there is no browser window.
gfx::NativeWindow GetParent(Browser* browser) {
- gfx::NativeWindow window = AppListService::Get()->GetAppListWindow();
- if (window)
- return window;
-
if (browser && browser->window())
return browser->window()->GetNativeWindow();
-
return NULL;
}
@@ -76,6 +66,7 @@
virtual void Show() OVERRIDE;
ExtensionUninstallDialogDelegateView* view_;
+ bool show_in_app_list_;
DISALLOW_COPY_AND_ASSIGN(ExtensionUninstallDialogViews);
};
@@ -126,7 +117,8 @@
Browser* browser,
ExtensionUninstallDialog::Delegate* delegate)
: ExtensionUninstallDialog(profile, browser, delegate),
- view_(NULL) {
+ view_(NULL),
+ show_in_app_list_(!browser) {
}
ExtensionUninstallDialogViews::~ExtensionUninstallDialogViews() {
@@ -138,7 +130,9 @@
}
void ExtensionUninstallDialogViews::Show() {
- gfx::NativeWindow parent = GetParent(browser_);
+ gfx::NativeWindow parent = show_in_app_list_ ?
+ AppListService::Get()->GetAppListWindow() :
+ GetParent(browser_);
if (browser_ && !parent) {
delegate_->ExtensionUninstallCanceled();
return;
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 64f81cd..568356c 100644
--- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
+++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
@@ -158,30 +158,33 @@
spacing);
}
- // Separator line.
- views::Separator* separator = new views::Separator(
- views::Separator::HORIZONTAL);
- scroll_container->AddChildView(separator);
-
- // Unattached locations section.
- views::Label* unattached_text = new views::Label(
- controller_->GetUnattachedLocationsHeader());
- unattached_text->SetMultiLine(true);
- unattached_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- unattached_text->set_border(views::Border::CreateEmptyBorder(
- views::kRelatedControlVerticalSpacing,
- views::kPanelHorizMargin,
- views::kRelatedControlVerticalSpacing,
- 0));
- scroll_container->AddChildView(unattached_text);
-
- // Add unattached galleries checkboxes.
GalleryPermissionsVector unattached_permissions =
controller_->UnattachedPermissions();
- for (GalleryPermissionsVector::const_iterator iter =
- unattached_permissions.begin();
- iter != unattached_permissions.end(); ++iter) {
- AddOrUpdateGallery(iter->pref_info, iter->allowed, scroll_container, 0);
+
+ if (!unattached_permissions.empty()) {
+ // Separator line.
+ views::Separator* separator = new views::Separator(
+ views::Separator::HORIZONTAL);
+ scroll_container->AddChildView(separator);
+
+ // Unattached locations section.
+ views::Label* unattached_text = new views::Label(
+ controller_->GetUnattachedLocationsHeader());
+ unattached_text->SetMultiLine(true);
+ unattached_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ unattached_text->set_border(views::Border::CreateEmptyBorder(
+ views::kRelatedControlVerticalSpacing,
+ views::kPanelHorizMargin,
+ views::kRelatedControlVerticalSpacing,
+ 0));
+ scroll_container->AddChildView(unattached_text);
+
+ // Add unattached galleries checkboxes.
+ for (GalleryPermissionsVector::const_iterator iter =
+ unattached_permissions.begin();
+ iter != unattached_permissions.end(); ++iter) {
+ AddOrUpdateGallery(iter->pref_info, iter->allowed, scroll_container, 0);
+ }
}
confirm_available_ = controller_->HasPermittedGalleries();
@@ -224,6 +227,7 @@
views::Checkbox* checkbox = iter->second;
checkbox->SetChecked(permitted);
checkbox->SetText(label);
+ checkbox->SetElideBehavior(views::Label::ELIDE_IN_MIDDLE);
checkbox->SetTooltipText(tooltip_text);
// Replace the details string.
views::View* checkbox_view = checkbox->parent();
diff --git a/chrome/browser/ui/views/frame/browser_frame_aura.cc b/chrome/browser/ui/views/frame/browser_frame_aura.cc
index c49fab2..c27da2a 100644
--- a/chrome/browser/ui/views/frame/browser_frame_aura.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_aura.cc
@@ -18,7 +18,7 @@
#include "ui/views/view.h"
#if defined(USE_ASH)
-#include "ash/wm/window_settings.h"
+#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#endif
@@ -168,7 +168,7 @@
#if defined(USE_ASH)
if (browser_view_->browser()->type() != Browser::TYPE_POPUP ||
browser_view_->browser()->is_app()) {
- ash::wm::GetWindowSettings(GetNativeWindow())->
+ ash::wm::GetWindowState(GetNativeWindow())->
set_window_position_managed(true);
}
#endif
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 ef8c258..367aae1 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
@@ -5,7 +5,7 @@
#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -81,26 +81,26 @@
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
gfx::Image avatar;
string16 text;
- bool is_gaia_picture = false;
+ bool is_rectangle = false;
if (browser_view_->IsGuestSession()) {
avatar = rb.GetImageNamed(browser_view_->GetGuestIconResourceID());
} else if (browser_view_->IsOffTheRecord()) {
avatar = rb.GetImageNamed(browser_view_->GetOTRIconResourceID());
- } else if (AvatarMenuModel::ShouldShowAvatarMenu()) {
+ } else if (AvatarMenu::ShouldShowAvatarMenu()) {
ProfileInfoCache& cache =
g_browser_process->profile_manager()->GetProfileInfoCache();
Profile* profile = browser_view_->browser()->profile();
size_t index = cache.GetIndexOfProfileWithPath(profile->GetPath());
if (index == std::string::npos)
return;
- is_gaia_picture =
- cache.IsUsingGAIAPictureOfProfileAtIndex(index) &&
- cache.GetGAIAPictureOfProfileAtIndex(index);
- avatar = cache.GetAvatarIconOfProfileAtIndex(index);
text = cache.GetNameOfProfileAtIndex(index);
+
+ AvatarMenu::GetImageForMenuButton(browser_view_->browser()->profile(),
+ &avatar,
+ &is_rectangle);
}
if (avatar_button_) {
- avatar_button_->SetAvatarIcon(avatar, is_gaia_picture);
+ avatar_button_->SetAvatarIcon(avatar, is_rectangle);
if (!text.empty())
avatar_button_->SetText(text);
}
@@ -109,5 +109,5 @@
// need to draw the taskbar decoration.
chrome::DrawTaskbarDecoration(
frame_->GetNativeWindow(),
- AvatarMenuModel::ShouldShowAvatarMenu() ? &avatar : NULL);
+ AvatarMenu::ShouldShowAvatarMenu() ? &avatar : NULL);
}
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 3c48696..330cf1e 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -17,14 +17,14 @@
#include "chrome/app/chrome_command_ids.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/native_window_notification_source.h"
#include "chrome/browser/password_manager/password_manager.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -209,7 +209,7 @@
// Calculate thickness of bottom border as per current scale factor to
// determine where to draw the 1-px thick border.
float thickness = views::NonClientFrameView::kClientEdgeThickness /
- ui::GetScaleFactorScale(canvas->scale_factor());
+ canvas->image_scale();
SkScalar y = SkIntToScalar(view->height()) - SkFloatToScalar(thickness);
canvas->sk_canvas()->drawLine(SkIntToScalar(0), y,
SkIntToScalar(view->width()), y, paint);
@@ -591,7 +591,7 @@
return false;
}
- return AvatarMenuModel::ShouldShowAvatarMenu();
+ return AvatarMenu::ShouldShowAvatarMenu();
}
bool BrowserView::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) {
@@ -775,6 +775,54 @@
GetLocationBarView()->SetStarToggled(is_starred);
}
+void BrowserView::OnActiveTabChanged(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason) {
+ DCHECK(new_contents);
+
+ // If |contents_container_| already has the correct WebContents, we can save
+ // some work. This also prevents extra events from being reported by the
+ // Visibility API under Windows, as ChangeWebContents will briefly hide
+ // the WebContents window.
+ bool change_tab_contents =
+ contents_web_view_->web_contents() != new_contents;
+
+ // Update various elements that are interested in knowing the current
+ // WebContents.
+
+ // When we toggle the NTP floating bookmarks bar and/or the info bar,
+ // we don't want any WebContents to be attached, so that we
+ // avoid an unnecessary resize and re-layout of a WebContents.
+ if (change_tab_contents)
+ contents_web_view_->SetWebContents(NULL);
+ infobar_container_->ChangeInfoBarService(
+ InfoBarService::FromWebContents(new_contents));
+ if (bookmark_bar_view_.get()) {
+ bookmark_bar_view_->SetBookmarkBarState(
+ browser_->bookmark_bar_state(),
+ BookmarkBar::DONT_ANIMATE_STATE_CHANGE);
+ }
+ UpdateUIForContents(new_contents);
+
+ // Layout for DevTools _before_ setting the main WebContents to avoid
+ // toggling the size of the main WebContents.
+ UpdateDevToolsForContents(new_contents);
+
+ if (change_tab_contents)
+ contents_web_view_->SetWebContents(new_contents);
+
+ if (!browser_->tab_strip_model()->closing_all() && GetWidget()->IsActive() &&
+ GetWidget()->IsVisible()) {
+ // We only restore focus if our window is visible, to avoid invoking blur
+ // handlers when we are eventually shown.
+ new_contents->GetView()->RestoreFocus();
+ }
+
+ // Update all the UI bits.
+ UpdateTitleBar();
+}
+
void BrowserView::ZoomChangedForActiveTab(bool can_show_bubble) {
GetLocationBarView()->ZoomChangedForActiveTab(
can_show_bubble && !toolbar_->IsWrenchMenuShowing());
@@ -1397,57 +1445,6 @@
contents->GetView()->StoreFocus();
}
-void BrowserView::ActiveTabChanged(content::WebContents* old_contents,
- content::WebContents* new_contents,
- int index,
- int reason) {
- DCHECK(new_contents);
-
- // If |contents_container_| already has the correct WebContents, we can save
- // some work. This also prevents extra events from being reported by the
- // Visibility API under Windows, as ChangeWebContents will briefly hide
- // the WebContents window.
- bool change_tab_contents =
- contents_web_view_->web_contents() != new_contents;
-
- // Update various elements that are interested in knowing the current
- // WebContents.
-
- // When we toggle the NTP floating bookmarks bar and/or the info bar,
- // we don't want any WebContents to be attached, so that we
- // avoid an unnecessary resize and re-layout of a WebContents.
- if (change_tab_contents)
- contents_web_view_->SetWebContents(NULL);
- infobar_container_->ChangeInfoBarService(
- InfoBarService::FromWebContents(new_contents));
- if (bookmark_bar_view_.get()) {
- bookmark_bar_view_->SetBookmarkBarState(
- browser_->bookmark_bar_state(),
- BookmarkBar::DONT_ANIMATE_STATE_CHANGE);
- }
- UpdateUIForContents(new_contents);
-
- // Layout for DevTools _before_ setting the main WebContents to avoid
- // toggling the size of the main WebContents.
- UpdateDevToolsForContents(new_contents);
-
- if (change_tab_contents)
- contents_web_view_->SetWebContents(new_contents);
-
- if (!browser_->tab_strip_model()->closing_all() && GetWidget()->IsActive() &&
- GetWidget()->IsVisible()) {
- // We only restore focus if our window is visible, to avoid invoking blur
- // handlers when we are eventually shown.
- new_contents->GetView()->RestoreFocus();
- }
-
- // Update all the UI bits.
- UpdateTitleBar();
-
- // No need to update Toolbar because it's already updated in
- // browser.cc.
-}
-
void BrowserView::TabStripEmpty() {
// Make sure all optional UI is removed before we are destroyed, otherwise
// there will be consequences (since our view hierarchy will still have
@@ -2464,16 +2461,16 @@
#endif
}
-void BrowserView::UpdateAcceleratorMetrics(
- const ui::Accelerator& accelerator, int command_id) {
+void BrowserView::UpdateAcceleratorMetrics(const ui::Accelerator& accelerator,
+ int command_id) {
const ui::KeyboardCode key_code = accelerator.key_code();
if (command_id == IDC_HELP_PAGE_VIA_KEYBOARD && key_code == ui::VKEY_F1)
content::RecordAction(UserMetricsAction("ShowHelpTabViaF1"));
if (command_id == IDC_BOOKMARK_PAGE)
UMA_HISTOGRAM_ENUMERATION("Bookmarks.EntryPoint",
- bookmark_utils::ENTRY_POINT_ACCELERATOR,
- bookmark_utils::ENTRY_POINT_LIMIT);
+ BOOKMARK_ENTRY_POINT_ACCELERATOR,
+ BOOKMARK_ENTRY_POINT_LIMIT);
#if defined(OS_CHROMEOS)
// Collect information about the relative popularity of various accelerators
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 9bb5219..a7a3421 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -272,6 +272,10 @@
virtual void UpdateDevTools() OVERRIDE;
virtual void UpdateLoadingAnimations(bool should_animate) OVERRIDE;
virtual void SetStarredState(bool is_starred) OVERRIDE;
+ virtual void OnActiveTabChanged(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason) OVERRIDE;
virtual void ZoomChangedForActiveTab(bool can_show_bubble) OVERRIDE;
virtual gfx::Rect GetRestoredBounds() const OVERRIDE;
virtual ui::WindowShowState GetRestoredState() const OVERRIDE;
@@ -376,10 +380,6 @@
virtual void TabDetachedAt(content::WebContents* contents,
int index) OVERRIDE;
virtual void TabDeactivated(content::WebContents* contents) OVERRIDE;
- virtual void ActiveTabChanged(content::WebContents* old_contents,
- content::WebContents* new_contents,
- int index,
- int reason) OVERRIDE;
virtual void TabStripEmpty() OVERRIDE;
// Overridden from ui::AcceleratorProvider:
diff --git a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
index d0320cd..77db189 100644
--- a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
+++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
@@ -248,6 +248,8 @@
void* dbusmenu_lib = dlopen("libdbusmenu-glib.so", RTLD_LAZY);
if (!dbusmenu_lib)
+ dbusmenu_lib = dlopen("libdbusmenu-glib.so.4", RTLD_LAZY);
+ if (!dbusmenu_lib)
return;
// DbusmenuMenuItem methods.
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
index 2916c5f..5962fb0 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -84,7 +84,7 @@
// The calculations depend on the size of the OTR resource, and chromeos
// uses a different sized image, so hard code the size of the current
// windows/linux one.
- gfx::ImageSkiaRep rep(gfx::Size(40, 29), ui::SCALE_FACTOR_100P);
+ gfx::ImageSkiaRep rep(gfx::Size(40, 29), 1.0f);
gfx::ImageSkia image(rep);
return image;
}
@@ -173,7 +173,7 @@
views::ImageButton* InitWindowCaptionButton(ViewID view_id,
const gfx::Size& size) {
views::ImageButton* button = new views::ImageButton(NULL);
- gfx::ImageSkiaRep rep(size, ui::SCALE_FACTOR_100P);
+ gfx::ImageSkiaRep rep(size, 1.0f);
gfx::ImageSkia image(rep);
button->SetImage(views::CustomButton::STATE_NORMAL, &image);
button->set_id(view_id);
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 9e38e7a..6734411 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
@@ -65,8 +65,7 @@
// sit atop.
const SkBitmap& bitmap(
ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
- kBackgroundImages[4])->GetRepresentation(
- ui::SCALE_FACTOR_100P).sk_bitmap());
+ kBackgroundImages[4])->GetRepresentation(1.0f).sk_bitmap());
SkAutoLockPixels pixel_lock(bitmap);
SkColor background_image_color =
bitmap.getColor(bitmap.width() / 2, bitmap.height() / 2);
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
index 6a49136..f279f24 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -54,8 +54,7 @@
// sit atop.
const SkBitmap& bitmap(
ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
- background_images[4])->GetRepresentation(
- ui::SCALE_FACTOR_100P).sk_bitmap());
+ background_images[4])->GetRepresentation(1.0f).sk_bitmap());
SkAutoLockPixels pixel_lock(bitmap);
SkColor background_image_color =
bitmap.getColor(bitmap.width() / 2, bitmap.height() / 2);
diff --git a/chrome/browser/ui/views/location_bar/star_view.cc b/chrome/browser/ui/views/location_bar/star_view.cc
index e952661..7a3c955 100644
--- a/chrome/browser/ui/views/location_bar/star_view.cc
+++ b/chrome/browser/ui/views/location_bar/star_view.cc
@@ -7,7 +7,7 @@
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h"
@@ -28,8 +28,7 @@
LocationBarView::InitTouchableLocationBarChildView(this);
}
-StarView::~StarView() {
-}
+StarView::~StarView() {}
void StarView::SetToggled(bool on) {
SetTooltipText(l10n_util::GetStringUTF16(
@@ -72,8 +71,8 @@
if (event.IsOnlyLeftMouseButton() && HitTestPoint(event.location())) {
UMA_HISTOGRAM_ENUMERATION("Bookmarks.EntryPoint",
- bookmark_utils::ENTRY_POINT_STAR_MOUSE,
- bookmark_utils::ENTRY_POINT_LIMIT);
+ BOOKMARK_ENTRY_POINT_STAR_MOUSE,
+ BOOKMARK_ENTRY_POINT_LIMIT);
command_updater_->ExecuteCommand(IDC_BOOKMARK_PAGE_FROM_STAR);
}
}
@@ -82,8 +81,8 @@
if (event.key_code() == ui::VKEY_SPACE ||
event.key_code() == ui::VKEY_RETURN) {
UMA_HISTOGRAM_ENUMERATION("Bookmarks.EntryPoint",
- bookmark_utils::ENTRY_POINT_STAR_KEY,
- bookmark_utils::ENTRY_POINT_LIMIT);
+ BOOKMARK_ENTRY_POINT_STAR_KEY,
+ BOOKMARK_ENTRY_POINT_LIMIT);
command_updater_->ExecuteCommand(IDC_BOOKMARK_PAGE_FROM_STAR);
return true;
}
@@ -93,8 +92,8 @@
void StarView::OnGestureEvent(ui::GestureEvent* event) {
if (event->type() == ui::ET_GESTURE_TAP) {
UMA_HISTOGRAM_ENUMERATION("Bookmarks.EntryPoint",
- bookmark_utils::ENTRY_POINT_STAR_GESTURE,
- bookmark_utils::ENTRY_POINT_LIMIT);
+ BOOKMARK_ENTRY_POINT_STAR_GESTURE,
+ BOOKMARK_ENTRY_POINT_LIMIT);
command_updater_->ExecuteCommand(IDC_BOOKMARK_PAGE_FROM_STAR);
event->SetHandled();
}
diff --git a/chrome/browser/ui/views/message_center/message_center_widget_delegate.cc b/chrome/browser/ui/views/message_center/message_center_widget_delegate.cc
index 8ebb3c3..b273c44 100644
--- a/chrome/browser/ui/views/message_center/message_center_widget_delegate.cc
+++ b/chrome/browser/ui/views/message_center/message_center_widget_delegate.cc
@@ -150,7 +150,7 @@
widget->SetAlwaysOnTop(true);
const NotificationList::Notifications& notifications =
- tray_->message_center()->GetNotifications();
+ tray_->message_center()->GetVisibleNotifications();
SetNotifications(notifications);
widget->SetBounds(GetMessageCenterBounds());
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 bdd3977..12193bb 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -82,8 +82,7 @@
size_animation_(this),
left_margin_(0),
right_margin_(0),
- outside_vertical_padding_(0),
- in_popup_init_(false) {
+ outside_vertical_padding_(0) {
// The contents is owned by the LocationBarView.
set_owned_by_client();
@@ -106,7 +105,6 @@
// We don't need to do anything with |popup_| here. The OS either has already
// closed the window, in which case it's been deleted, or it will soon, in
// which case there's nothing we need to do.
- CHECK(!in_popup_init_);
}
gfx::Rect OmniboxPopupContentsView::GetPopupBounds() const {
@@ -167,8 +165,6 @@
// No matches or the IME is showing a popup window which may overlap
// the omnibox popup window. Close any existing popup.
if (popup_ != NULL) {
- CHECK(!in_popup_init_);
-
size_animation_.Stop();
// NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack
@@ -219,9 +215,14 @@
params.parent = popup_parent;
params.bounds = GetPopupBounds();
params.context = popup_parent;
- in_popup_init_ = true;
popup_->Init(params);
- in_popup_init_ = false;
+ // Third-party software such as DigitalPersona identity verification can
+ // hook the underlying window creation methods and use SendMessage to
+ // synchronously change focus/activation, resulting in the popup being
+ // destroyed by the time control returns here. Bail out in this case to
+ // avoid a NULL dereference.
+ if (!popup_.get())
+ return;
#if defined(USE_AURA)
views::corewm::SetWindowVisibilityAnimationType(
popup_->GetNativeView(),
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
index 5dd88a2..76849a5 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
@@ -169,9 +169,6 @@
// Amount of extra padding to add to the popup on the top and bottom.
int outside_vertical_padding_;
- // TODO(sky): nuke. Used for debugging 275794.
- bool in_popup_init_;
-
DISALLOW_COPY_AND_ASSIGN(OmniboxPopupContentsView);
};
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index bf56ecc..faa17d8 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -68,20 +68,29 @@
static const char kKey[];
OmniboxState(const OmniboxEditModel::State& model_state,
- const gfx::SelectionModel& selection_model);
+ const gfx::Range& selection,
+ const gfx::Range& saved_selection_for_focus_change);
virtual ~OmniboxState();
const OmniboxEditModel::State model_state;
- const gfx::SelectionModel selection_model;
+
+ // We store both the actual selection and any saved selection (for when the
+ // omnibox is not focused). This allows us to properly handle cases like
+ // selecting text, tabbing out of the omnibox, switching tabs away and back,
+ // and tabbing back into the omnibox.
+ const gfx::Range selection;
+ const gfx::Range saved_selection_for_focus_change;
};
// static
const char OmniboxState::kKey[] = "OmniboxState";
OmniboxState::OmniboxState(const OmniboxEditModel::State& model_state,
- const gfx::SelectionModel& selection_model)
+ const gfx::Range& selection,
+ const gfx::Range& saved_selection_for_focus_change)
: model_state(model_state),
- selection_model(selection_model) {
+ selection(selection),
+ saved_selection_for_focus_change(saved_selection_for_focus_change) {
}
OmniboxState::~OmniboxState() {}
@@ -129,6 +138,7 @@
: OmniboxView(profile, controller, command_updater),
popup_window_mode_(popup_window_mode),
security_level_(ToolbarModel::NONE),
+ saved_selection_for_focus_change_(gfx::Range::InvalidRange()),
ime_composing_before_change_(false),
delete_at_end_pressed_(false),
location_bar_view_(location_bar),
@@ -186,6 +196,10 @@
views::Textfield::OnGestureEvent(event);
if (!HasFocus() && event->type() == ui::ET_GESTURE_TAP_DOWN) {
select_all_on_gesture_tap_ = true;
+
+ // If we're trying to select all on tap, invalidate any saved selection lest
+ // restoring it fights with the "select all" action.
+ saved_selection_for_focus_change_ = gfx::Range::InvalidRange();
return;
}
if (select_all_on_gesture_tap_ && event->type() == ui::ET_GESTURE_TAP)
@@ -202,12 +216,20 @@
select_all_on_mouse_release_ =
(event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) &&
(!HasFocus() || (model()->focus_state() == OMNIBOX_FOCUS_INVISIBLE));
- // Restore caret visibility whenever the user clicks in the omnibox in a way
- // that would give it focus. We must handle this case separately here because
- // if the omnibox currently has invisible focus, the mouse event won't trigger
- // either SetFocus() or OmniboxEditModel::OnSetFocus().
- if (select_all_on_mouse_release_)
+ if (select_all_on_mouse_release_) {
+ // Restore caret visibility whenever the user clicks in the omnibox in a way
+ // that would give it focus. We must handle this case separately here
+ // because if the omnibox currently has invisible focus, the mouse event
+ // won't trigger either SetFocus() or OmniboxEditModel::OnSetFocus().
model()->SetCaretVisibility(true);
+
+ // When we're going to select all on mouse release, invalidate any saved
+ // selection lest restoring it fights with the "select all" action. It's
+ // possible to later set select_all_on_mouse_release_ back to false, but
+ // that happens for things like dragging, which are cases where having
+ // invalidated this saved selection is still OK.
+ saved_selection_for_focus_change_ = gfx::Range::InvalidRange();
+ }
return views::Textfield::OnMousePressed(event);
}
@@ -329,19 +351,16 @@
model()->OnSetFocus(false);
// Don't call controller()->OnSetFocus, this view has already acquired focus.
- // Restore a valid saved selection on tab-to-focus.
- if (location_bar_view_->GetWebContents() && !select_all_on_mouse_release_) {
- const OmniboxState* state = static_cast<OmniboxState*>(
- location_bar_view_->GetWebContents()->GetUserData(&OmniboxState::kKey));
- if (state)
- SelectSelectionModel(state->selection_model);
+ // Restore the selection we saved in OnBlur() if it's still valid.
+ if (saved_selection_for_focus_change_.IsValid()) {
+ SelectRange(saved_selection_for_focus_change_);
+ saved_selection_for_focus_change_ = gfx::Range::InvalidRange();
}
}
void OmniboxViewViews::OnBlur() {
- // Save the selection to restore on tab-to-focus.
- if (location_bar_view_->GetWebContents())
- SaveStateToTab(location_bar_view_->GetWebContents());
+ // Save the user's existing selection to restore it later.
+ saved_selection_for_focus_change_ = GetSelectedRange();
views::Textfield::OnBlur();
gfx::NativeView native_view = NULL;
@@ -357,6 +376,7 @@
model()->OnWillKillFocus(native_view);
// Close the popup.
CloseOmniboxPopup();
+
// Tell the model to reset itself.
model()->OnKillFocus();
controller()->OnKillFocus();
@@ -379,10 +399,11 @@
GetInputMethod()->CancelComposition(this);
}
- // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important.
+ // NOTE: GetStateForTabSwitch() may affect GetSelectedRange(), so order is
+ // important.
OmniboxEditModel::State state = model()->GetStateForTabSwitch();
- const gfx::SelectionModel selection = GetSelectionModel();
- tab->SetUserData(OmniboxState::kKey, new OmniboxState(state, selection));
+ tab->SetUserData(OmniboxState::kKey, new OmniboxState(
+ state, GetSelectedRange(), saved_selection_for_focus_change_));
}
void OmniboxViewViews::OnTabChanged(const content::WebContents* web_contents) {
@@ -391,8 +412,14 @@
const OmniboxState* state = static_cast<OmniboxState*>(
web_contents->GetUserData(&OmniboxState::kKey));
model()->RestoreState(state ? &state->model_state : NULL);
- if (state)
- SelectSelectionModel(state->selection_model);
+ if (state) {
+ // This assumes that the omnibox has already been focused or blurred as
+ // appropriate; otherwise, a subsequent OnFocus() or OnBlur() call could
+ // goof up the selection. See comments at the end of
+ // BrowserView::ActiveTabChanged().
+ SelectRange(state->selection);
+ saved_selection_for_focus_change_ = state->saved_selection_for_focus_change;
+ }
// TODO(msw|oshima): Consider saving/restoring edit history.
ClearEditHistory();
@@ -436,6 +463,13 @@
return text();
}
+void OmniboxViewViews::SetUserText(const string16& text,
+ const string16& display_text,
+ bool update_popup) {
+ saved_selection_for_focus_change_ = gfx::Range::InvalidRange();
+ OmniboxView::SetUserText(text, display_text, update_popup);
+}
+
void OmniboxViewViews::SetWindowTextAndCaretPos(const string16& text,
size_t caret_pos,
bool update_popup,
@@ -454,7 +488,7 @@
const string16 current_text(text());
const size_t start = current_text.find_first_not_of(kWhitespaceUTF16);
if (start == string16::npos || (current_text[start] != '?'))
- SetUserText(ASCIIToUTF16("?"));
+ OmniboxView::SetUserText(ASCIIToUTF16("?"));
else
SelectRange(gfx::Range(current_text.size(), start + 1));
}
@@ -479,6 +513,11 @@
views::Textfield::SelectAll(reversed);
}
+void OmniboxViewViews::RevertAll() {
+ saved_selection_for_focus_change_ = gfx::Range::InvalidRange();
+ OmniboxView::RevertAll();
+}
+
void OmniboxViewViews::UpdatePopup() {
model()->SetInputInProgress(true);
if (!model()->has_focus())
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
index dda2c84..af991f0 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -75,6 +75,9 @@
virtual void OnTabChanged(const content::WebContents* web_contents) OVERRIDE;
virtual void Update() OVERRIDE;
virtual string16 GetText() const OVERRIDE;
+ virtual void SetUserText(const string16& text,
+ const string16& display_text,
+ bool update_popup) OVERRIDE;
virtual void SetWindowTextAndCaretPos(const string16& text,
size_t caret_pos,
bool update_popup,
@@ -85,6 +88,7 @@
virtual void GetSelectionBounds(string16::size_type* start,
string16::size_type* end) const OVERRIDE;
virtual void SelectAll(bool reversed) OVERRIDE;
+ virtual void RevertAll() OVERRIDE;
virtual void UpdatePopup() OVERRIDE;
virtual void SetFocus() OVERRIDE;
virtual void ApplyCaretVisibility() OVERRIDE;
@@ -170,6 +174,10 @@
// Selection persisted across temporary text changes, like popup suggestions.
gfx::Range saved_temporary_selection_;
+ // Holds the user's selection across focus changes. There is only a saved
+ // selection if this range IsValid().
+ gfx::Range saved_selection_for_focus_change_;
+
// Tracking state before and after a possible change.
string16 text_before_change_;
gfx::Range sel_before_change_;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_win.cc b/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
index 43bf0c7..e2c98ce 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
@@ -2514,7 +2514,7 @@
// it to fully transparent so any antialiasing will look nice when painted
// atop the edit.
gfx::Canvas canvas(gfx::Size(scheme_rect.Width(), scheme_rect.Height()),
- ui::SCALE_FACTOR_100P, false);
+ 1.0f, false);
SkCanvas* sk_canvas = canvas.sk_canvas();
sk_canvas->getDevice()->accessBitmap(true).eraseARGB(0, 0, 0, 0);
diff --git a/chrome/browser/ui/views/panels/panel_frame_view.cc b/chrome/browser/ui/views/panels/panel_frame_view.cc
index 5359e72..7b9ed29 100644
--- a/chrome/browser/ui/views/panels/panel_frame_view.cc
+++ b/chrome/browser/ui/views/panels/panel_frame_view.cc
@@ -64,7 +64,7 @@
const SkColor kTitleTextDefaultColor = SkColorSetRGB(0xf9, 0xf9, 0xf9);
gfx::ImageSkia* CreateImageForColor(SkColor color) {
- gfx::Canvas canvas(gfx::Size(1, 1), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(1, 1), 1.0f, true);
canvas.DrawColor(color);
return new gfx::ImageSkia(canvas.ExtractImageRep());
}
diff --git a/chrome/browser/ui/views/panels/panel_stack_view.cc b/chrome/browser/ui/views/panels/panel_stack_view.cc
index 2514f26..b534da8 100644
--- a/chrome/browser/ui/views/panels/panel_stack_view.cc
+++ b/chrome/browser/ui/views/panels/panel_stack_view.cc
@@ -156,6 +156,14 @@
}
void PanelStackView::RemovePanel(Panel* panel) {
+ if (IsAnimatingPanelBounds()) {
+ // This panel is gone.
+ bounds_updates_.erase(panel);
+
+ // Abort the ongoing animation.
+ bounds_animator_->Stop();
+ }
+
panels_.remove(panel);
MakeStackWindowOwnPanelWindow(panel, NULL);
@@ -362,6 +370,14 @@
NotifyBoundsUpdateCompleted();
}
+void PanelStackView::AnimationCanceled(const gfx::Animation* animation) {
+ // When the animation is aborted due to something like one of panels is gone,
+ // update panels to their taget bounds immediately.
+ UpdatePanelsBounds();
+
+ AnimationEnded(animation);
+}
+
void PanelStackView::AnimationProgressed(const gfx::Animation* animation) {
UpdatePanelsBounds();
}
diff --git a/chrome/browser/ui/views/panels/panel_stack_view.h b/chrome/browser/ui/views/panels/panel_stack_view.h
index 52a298e..c04e0c7 100644
--- a/chrome/browser/ui/views/panels/panel_stack_view.h
+++ b/chrome/browser/ui/views/panels/panel_stack_view.h
@@ -72,6 +72,7 @@
// Overridden from AnimationDelegate:
virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
+ virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
// Updates the bounds of panels as specified in batch update data.
void UpdatePanelsBounds();
diff --git a/chrome/browser/ui/views/panels/panel_view.cc b/chrome/browser/ui/views/panels/panel_view.cc
index 77455c5..aef7111 100644
--- a/chrome/browser/ui/views/panels/panel_view.cc
+++ b/chrome/browser/ui/views/panels/panel_view.cc
@@ -103,6 +103,7 @@
virtual bool VerifyActiveState(bool is_active) OVERRIDE;
virtual bool VerifyAppIcon() const OVERRIDE;
virtual bool VerifySystemMinimizeState() const OVERRIDE;
+ virtual bool IsWindowVisible() const OVERRIDE;
virtual bool IsWindowSizeKnown() const OVERRIDE;
virtual bool IsAnimatingBounds() const OVERRIDE;
virtual bool IsButtonVisible(
@@ -195,6 +196,15 @@
#endif
}
+bool NativePanelTestingWin::IsWindowVisible() const {
+#if defined(OS_WIN)
+ HWND native_window = views::HWNDForWidget(panel_view_->window());
+ return ::IsWindowVisible(native_window) == TRUE;
+#else
+ return panel_view_->visible();
+#endif
+}
+
bool NativePanelTestingWin::IsWindowSizeKnown() const {
return true;
}
@@ -568,20 +578,22 @@
void PanelView::FullScreenModeChanged(bool is_full_screen) {
if (is_full_screen) {
- if (window_->IsVisible())
+ if (window_->IsVisible() && always_on_top_)
window_->Hide();
} else {
- ShowPanelInactive();
+ if (!window_->IsVisible()) {
+ 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);
+ // 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 e6946bb..29c2a5f 100644
--- a/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.cc
+++ b/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.cc
@@ -188,7 +188,7 @@
if (!width || !height)
return NULL;
- gfx::Canvas canvas(gfx::Size(width, height), ui::SCALE_FACTOR_100P, false);
+ gfx::Canvas canvas(gfx::Size(width, height), 1.0f, false);
{
skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
HDC target_dc = scoped_platform_paint.GetPlatformSurface();
diff --git a/chrome/browser/ui/views/password_menu_model.cc b/chrome/browser/ui/views/password_menu_model.cc
new file mode 100644
index 0000000..6b21ccb
--- /dev/null
+++ b/chrome/browser/ui/views/password_menu_model.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/ui/views/password_menu_model.h"
+
+#include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
+#include "chrome/browser/ui/views/content_setting_bubble_contents.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+PasswordMenuModel::PasswordMenuModel(
+ ContentSettingBubbleModel* bubble_model,
+ ContentSettingBubbleContents* bubble_contents)
+ : ui::SimpleMenuModel(this),
+ media_bubble_model_(bubble_model),
+ media_bubble_contents_(bubble_contents) {
+ AddItem(COMMAND_ID_NOPE,
+ l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CANCEL_DROP_DOWN));
+ AddItem(COMMAND_ID_NEVER_FOR_THIS_SITE,
+ l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_BLACKLIST_DROP_DOWN));
+}
+
+PasswordMenuModel::~PasswordMenuModel() {}
+
+bool PasswordMenuModel::IsCommandIdChecked(int command_id) const {
+ return false;
+}
+
+bool PasswordMenuModel::IsCommandIdEnabled(int command_id) const {
+ return true;
+}
+
+bool PasswordMenuModel::GetAcceleratorForCommandId(
+ int command_id,
+ ui::Accelerator* accelerator) {
+ return false;
+}
+
+void PasswordMenuModel::ExecuteCommand(int command_id,
+ int event_flags) {
+ switch (static_cast<CommandID>(command_id)) {
+ case COMMAND_ID_NOPE:
+ media_bubble_model_->OnDoneClicked();
+ media_bubble_contents_->StartFade(false);
+ break;
+ case COMMAND_ID_NEVER_FOR_THIS_SITE: {
+ media_bubble_model_->OnCancelClicked();
+ media_bubble_contents_->StartFade(false);
+ break;
+ }
+ }
+}
diff --git a/chrome/browser/ui/views/password_menu_model.h b/chrome/browser/ui/views/password_menu_model.h
new file mode 100644
index 0000000..19b6e20
--- /dev/null
+++ b/chrome/browser/ui/views/password_menu_model.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_VIEWS_PASSWORD_MENU_MODEL_H_
+#define CHROME_BROWSER_UI_VIEWS_PASSWORD_MENU_MODEL_H_
+
+#include <map>
+#include <string>
+
+#include "ui/base/models/simple_menu_model.h"
+
+class ContentSettingBubbleModel;
+class ContentSettingBubbleContents;
+
+// A menu model that builds the contents of the password menu in the content
+// setting bubble.
+class PasswordMenuModel : public ui::SimpleMenuModel,
+ public ui::SimpleMenuModel::Delegate {
+ public:
+ PasswordMenuModel(
+ ContentSettingBubbleModel* bubble_model,
+ ContentSettingBubbleContents* bubble_contents);
+ virtual ~PasswordMenuModel();
+
+ // ui::SimpleMenuModel::Delegate:
+ virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
+ virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
+ virtual bool GetAcceleratorForCommandId(
+ int command_id,
+ ui::Accelerator* accelerator) OVERRIDE;
+ virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
+
+ private:
+ enum CommandID {
+ COMMAND_ID_NOPE,
+ COMMAND_ID_NEVER_FOR_THIS_SITE,
+ };
+
+ ContentSettingBubbleModel* media_bubble_model_; // Weak.
+ ContentSettingBubbleContents* media_bubble_contents_; // Weak.
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordMenuModel);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_PASSWORD_MENU_MODEL_H_
diff --git a/chrome/browser/ui/views/profile_chooser_view.cc b/chrome/browser/ui/views/profile_chooser_view.cc
index 64e81ca..5e34a6f 100644
--- a/chrome/browser/ui/views/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profile_chooser_view.cc
@@ -5,16 +5,17 @@
#include "chrome/browser/ui/views/profile_chooser_view.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
#include "chrome/browser/profiles/profile_info_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_window.h"
#include "chrome/browser/signin/signin_promo.h"
+#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/views/user_manager_view.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
@@ -31,14 +32,18 @@
#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"
-
-// Helpers --------------------------------------------------------------------
+#if defined(USE_AURA)
+#include "ui/native_theme/native_theme_aura.h"
+#endif
namespace {
+// Helpers --------------------------------------------------------------------
+
const int kLargeImageSide = 64;
const int kSmallImageSide = 32;
const int kMinMenuWidth = 250;
+const int kButtonHeight = 29;
// Current profile avatar image.
views::View* CreateProfileImageView(const gfx::Image& icon) {
@@ -73,13 +78,13 @@
views::ColumnSet* columns = layout->AddColumnSet(0);
columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
views::GridLayout::USE_PREF, 0, 0);
- columns->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
+ columns->AddPaddingColumn(0, views::kUnrelatedControlLargeHorizontalSpacing);
columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::TRAILING, 1,
views::GridLayout::USE_PREF, 0, 0);
return layout;
}
-views::Link* CreateLink(const string16 link_text,
+views::Link* CreateLink(const string16& link_text,
views::LinkListener* listener) {
views::Link* link_button = new views::Link(link_text);
link_button->SetHorizontalAlignment(gfx::ALIGN_LEFT);
@@ -88,6 +93,82 @@
return link_button;
}
+
+// HorizontalPaddingButtonBorder ----------------------------------------------
+
+// A button border that adds padding before the icon and after the text. This
+// is needed so that the button looks like it is spanning the entire parent
+// view (especially when hovered over), but has the icon indented and aligned
+// with the other items in the parent view.
+class HorizontalPaddingButtonBorder : public views::TextButtonBorder {
+ public:
+ HorizontalPaddingButtonBorder() : views::TextButtonBorder() {
+ SetInsets(gfx::Insets(0, views::kButtonHEdgeMarginNew,
+ 0, views::kButtonHEdgeMarginNew));
+ };
+
+ virtual ~HorizontalPaddingButtonBorder() {
+ };
+
+ private:
+ // This function is pure virtual in the parent, so we must provide an
+ // implementation.
+ virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE {
+ };
+
+ DISALLOW_COPY_AND_ASSIGN(HorizontalPaddingButtonBorder);
+};
+
+
+// BackgroundColorHoverButton -------------------------------------------------
+
+// A custom button that allows for setting a background color when hovered over.
+class BackgroundColorHoverButton : public views::TextButton {
+ public:
+ BackgroundColorHoverButton(views::ButtonListener* listener,
+ const string16& text,
+ const gfx::ImageSkia& normal_icon,
+ const gfx::ImageSkia& hover_icon)
+ : views::TextButton(listener, text) {
+ set_border(new HorizontalPaddingButtonBorder);
+ set_min_height(kButtonHeight);
+ set_icon_text_spacing(views::kItemLabelSpacing);
+ SetIcon(normal_icon);
+ SetHoverIcon(hover_icon);
+ SetPushedIcon(hover_icon);
+ SetHoverColor(GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor));
+ OnHighlightStateChanged();
+ };
+
+ virtual ~BackgroundColorHoverButton(){
+ };
+
+ private:
+ virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
+ views::TextButton::OnMouseEntered(event);
+ OnHighlightStateChanged();
+ };
+
+ virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE {
+ views::TextButton::OnMouseExited(event);
+ OnHighlightStateChanged();
+ };
+
+ void OnHighlightStateChanged() {
+ bool is_highlighted = (state() == views::TextButton::STATE_PRESSED) ||
+ (state() == views::TextButton::STATE_HOVERED) || HasFocus();
+ ui::NativeTheme::ColorId color_id = is_highlighted ?
+ ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor :
+ ui::NativeTheme::kColorId_MenuBackgroundColor;
+ set_background(views::Background::CreateSolidBackground(
+ GetNativeTheme()->GetSystemColor(color_id)));
+ SchedulePaint();
+ };
+
+ DISALLOW_COPY_AND_ASSIGN(BackgroundColorHoverButton);
+};
+
} // namespace
@@ -137,9 +218,12 @@
set_margins(gfx::Insets());
ResetLinksAndButtons();
- avatar_menu_model_.reset(new AvatarMenuModel(
+
+ avatar_menu_.reset(new AvatarMenu(
&g_browser_process->profile_manager()->GetProfileInfoCache(),
- this, browser_));
+ this,
+ browser_));
+ avatar_menu_->RebuildMenu();
}
ProfileChooserView::~ProfileChooserView() {
@@ -153,28 +237,29 @@
guest_button_ = NULL;
end_guest_button_ = NULL;
users_button_ = NULL;
+ add_user_button_ = NULL;
open_other_profile_indexes_map_.clear();
}
void ProfileChooserView::Init() {
- ShowView(PROFILE_CHOOSER_VIEW, avatar_menu_model_.get());
+ ShowView(PROFILE_CHOOSER_VIEW, avatar_menu_.get());
}
-void ProfileChooserView::OnAvatarMenuModelChanged(
- AvatarMenuModel* avatar_menu_model) {
- // Refresh the view with the new model. We can't just update the local copy
+void ProfileChooserView::OnAvatarMenuChanged(
+ AvatarMenu* avatar_menu) {
+ // Refresh the view with the new menu. We can't just update the local copy
// as this may have been triggered by a sign out action, in which case
// the view is being destroyed.
- ShowView(PROFILE_CHOOSER_VIEW, avatar_menu_model);
+ ShowView(PROFILE_CHOOSER_VIEW, avatar_menu);
}
void ProfileChooserView::ShowView(BubbleViewMode view_to_display,
- AvatarMenuModel* avatar_menu_model) {
+ AvatarMenu* avatar_menu) {
// The account management view should only be displayed if the active profile
// is signed in.
if (view_to_display == ACCOUNT_MANAGEMENT_VIEW) {
- const AvatarMenuModel::Item& active_item = avatar_menu_model->GetItemAt(
- avatar_menu_model->GetActiveProfileIndex());
+ const AvatarMenu::Item& active_item = avatar_menu->GetItemAt(
+ avatar_menu->GetActiveProfileIndex());
DCHECK(active_item.signed_in);
}
@@ -189,8 +274,8 @@
bool is_guest_view = true;
views::View* current_profile_view = NULL;
views::View* current_profile_accounts = NULL;
- for (size_t i = 0; i < avatar_menu_model->GetNumberOfItems(); ++i) {
- const AvatarMenuModel::Item& item = avatar_menu_model->GetItemAt(i);
+ for (size_t i = 0; i < avatar_menu->GetNumberOfItems(); ++i) {
+ const AvatarMenu::Item& item = avatar_menu->GetItemAt(i);
if (item.active) {
if (view_to_display == PROFILE_CHOOSER_VIEW) {
current_profile_view = CreateCurrentProfileView(item, false);
@@ -246,17 +331,19 @@
sender->SetEnabled(false);
if (sender == guest_button_) {
- avatar_menu_model_->SwitchToGuestProfileWindow(browser_);
+ avatar_menu_->SwitchToGuestProfileWindow(browser_);
} else if (sender == end_guest_button_) {
profiles::CloseGuestProfileWindows();
} else if (sender == users_button_) {
UserManagerView::Show(browser_);
+ } else if (sender == add_user_button_) {
+ profiles::CreateAndSwitchToNewProfile(browser_->host_desktop_type());
} else {
// One of the "other profiles" buttons was pressed.
ButtonIndexes::const_iterator match =
open_other_profile_indexes_map_.find(sender);
DCHECK(match != open_other_profile_indexes_map_.end());
- avatar_menu_model_->SwitchToProfile(
+ avatar_menu_->SwitchToProfile(
match->second,
ui::DispositionFromEventFlags(event.flags()) == NEW_WINDOW);
}
@@ -265,29 +352,29 @@
void ProfileChooserView::LinkClicked(views::Link* sender, int event_flags) {
if (sender == manage_accounts_link_) {
// ShowView() will DCHECK if this view is displayed for non signed-in users.
- ShowView(ACCOUNT_MANAGEMENT_VIEW, avatar_menu_model_.get());
+ ShowView(ACCOUNT_MANAGEMENT_VIEW, avatar_menu_.get());
SizeToContents(); // The account list changes the height of the bubble.
} else if (sender == signout_current_profile_link_) {
- avatar_menu_model_->BeginSignOut();
+ avatar_menu_->BeginSignOut();
} else if (sender == signin_current_profile_link_) {
GURL page = signin::GetPromoURL(signin::SOURCE_MENU, false);
chrome::ShowSingletonTab(browser_, page);
} else {
DCHECK(sender == change_photo_link_);
- avatar_menu_model_->EditProfile(
- avatar_menu_model_->GetActiveProfileIndex());
+ avatar_menu_->EditProfile(
+ avatar_menu_->GetActiveProfileIndex());
}
}
views::View* ProfileChooserView::CreateCurrentProfileView(
- const AvatarMenuModel::Item& avatar_item,
+ const AvatarMenu::Item& avatar_item,
bool is_guest) {
views::View* view = new views::View();
views::GridLayout* layout = CreateDoubleColumnLayout(view);
- layout->SetInsets(views::kButtonHEdgeMarginNew,
- views::kButtonVEdgeMarginNew,
+ layout->SetInsets(views::kButtonVEdgeMarginNew,
views::kButtonHEdgeMarginNew,
- views::kButtonVEdgeMarginNew);
+ views::kButtonVEdgeMarginNew,
+ views::kButtonHEdgeMarginNew);
views::View* photo_image = CreateProfileImageView(avatar_item.icon);
view->SetBoundsRect(photo_image->bounds());
@@ -316,10 +403,10 @@
l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_SIGNOUT_BUTTON), this);
layout->StartRow(1, 0);
layout->SkipColumns(1);
- layout->AddView(manage_accounts_link_);
+ layout->AddView(signout_current_profile_link_);
layout->StartRow(1, 0);
layout->SkipColumns(1);
- layout->AddView(signout_current_profile_link_);
+ layout->AddView(manage_accounts_link_);
} else {
signin_current_profile_link_ = CreateLink(
l10n_util::GetStringFUTF16(
@@ -337,14 +424,14 @@
}
views::View* ProfileChooserView::CreateCurrentProfileEditableView(
- const AvatarMenuModel::Item& avatar_item) {
+ const AvatarMenu::Item& avatar_item) {
DCHECK(avatar_item.signed_in);
views::View* view = new views::View();
views::GridLayout* layout = CreateDoubleColumnLayout(view);
- layout->SetInsets(views::kButtonHEdgeMarginNew,
- views::kButtonVEdgeMarginNew,
+ layout->SetInsets(views::kButtonVEdgeMarginNew,
views::kButtonHEdgeMarginNew,
- views::kButtonVEdgeMarginNew);
+ views::kButtonVEdgeMarginNew,
+ views::kButtonHEdgeMarginNew);
views::View* photo_image = CreateProfileImageView(avatar_item.icon);
view->SetBoundsRect(photo_image->bounds());
@@ -377,7 +464,7 @@
views::View* ProfileChooserView::CreateGuestProfileView() {
gfx::Image guest_icon =
ui::ResourceBundle::GetSharedInstance().GetImageNamed(IDR_GUEST_ICON);
- AvatarMenuModel::Item guest_avatar_item(0, guest_icon);
+ AvatarMenu::Item guest_avatar_item(0, 0, guest_icon);
guest_avatar_item.active = true;
guest_avatar_item.name = l10n_util::GetStringUTF16(
IDS_PROFILES_GUEST_PROFILE_NAME);
@@ -390,16 +477,12 @@
const Indexes& avatars_to_show) {
views::View* view = new views::View();
views::GridLayout* layout = CreateSingleColumnLayout(view);
- layout->SetInsets(0 - views::kRelatedControlHorizontalSpacing,
- views::kButtonVEdgeMarginNew,
- views::kButtonHEdgeMarginNew,
- views::kButtonVEdgeMarginNew);
-
- for (Indexes::const_iterator iter = avatars_to_show.begin();
- iter != avatars_to_show.end();
- ++iter) {
- const size_t index = *iter;
- const AvatarMenuModel::Item& item = avatar_menu_model_->GetItemAt(index);
+ layout->SetInsets(0, views::kButtonHEdgeMarginNew,
+ views::kButtonVEdgeMarginNew, views::kButtonHEdgeMarginNew);
+ int num_avatars_to_show = avatars_to_show.size();
+ for (int i = 0; i < num_avatars_to_show; ++i) {
+ const size_t index = avatars_to_show[i];
+ const AvatarMenu::Item& item = avatar_menu_->GetItemAt(index);
gfx::Image image = profiles::GetSizedAvatarIconWithBorder(
item.icon, true,
@@ -409,13 +492,17 @@
views::TextButton* button = new views::TextButton(this, item.name);
open_other_profile_indexes_map_[button] = index;
button->SetIcon(*image.ToImageSkia());
+ button->set_icon_text_spacing(views::kItemLabelSpacing);
button->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
- ui::ResourceBundle::BaseFont));
+ ui::ResourceBundle::MediumFont));
button->set_border(NULL);
- layout->AddPaddingRow(0, views::kRelatedControlHorizontalSpacing);
layout->StartRow(1, 0);
layout->AddView(button);
+
+ // The last avatar in the list does not need any bottom padding.
+ if (i < num_avatars_to_show - 1)
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
}
return view;
@@ -424,35 +511,43 @@
views::View* ProfileChooserView::CreateOptionsView(bool is_guest_view) {
views::View* view = new views::View();
views::GridLayout* layout = CreateSingleColumnLayout(view);
- layout->SetInsets(views::kRelatedControlHorizontalSpacing,
- views::kButtonVEdgeMarginNew,
- views::kButtonHEdgeMarginNew,
- views::kButtonVEdgeMarginNew);
+ // The horizontal padding will be set by each button individually, so that
+ // in the hovered state the button spans the entire parent view.
+ layout->SetInsets(views::kRelatedControlVerticalSpacing, 0,
+ views::kRelatedControlVerticalSpacing, 0);
ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
layout->StartRow(1, 0);
if (is_guest_view) {
- end_guest_button_ = new views::TextButton(this,
- l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_EXIT_GUEST_BUTTON));
- end_guest_button_->SetIcon(
- *rb->GetImageSkiaNamed(IDR_ICON_GUEST_WHITE));
- end_guest_button_->set_border(NULL);
+ end_guest_button_ = new BackgroundColorHoverButton(
+ this,
+ l10n_util::GetStringUTF16(IDS_PROFILES_EXIT_GUEST_BUTTON),
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_BROWSE_GUEST),
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_BROWSE_GUEST_WHITE));
layout->AddView(end_guest_button_);
} else {
- guest_button_ = new views::TextButton(this,
- l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_GUEST_BUTTON));
- guest_button_->SetIcon(*rb->GetImageSkiaNamed(IDR_ICON_GUEST_WHITE));
- guest_button_->set_border(NULL);
+ guest_button_ = new BackgroundColorHoverButton(
+ this,
+ l10n_util::GetStringUTF16(IDS_PROFILES_GUEST_BUTTON),
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_BROWSE_GUEST),
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_BROWSE_GUEST_WHITE));
layout->AddView(guest_button_);
}
- users_button_ = new views::TextButton(this,
- l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_USERS_BUTTON));
- users_button_->SetIcon(*rb->GetImageSkiaNamed(IDR_ICON_ADD_USER_WHITE));
- users_button_->set_border(NULL);
+ add_user_button_ = new BackgroundColorHoverButton(
+ this,
+ l10n_util::GetStringUTF16(IDS_PROFILES_ADD_PERSON_BUTTON),
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_ADD_USER),
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_ADD_USER_WHITE));
+ layout->StartRow(1, 0);
+ layout->AddView(add_user_button_);
- layout->AddPaddingRow(0, views::kRelatedControlHorizontalSpacing);
+ users_button_ = new BackgroundColorHoverButton(
+ this,
+ l10n_util::GetStringUTF16(IDS_PROFILES_ALL_PEOPLE_BUTTON),
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_ADD_USER),
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_ADD_USER_WHITE));
layout->StartRow(1, 0);
layout->AddView(users_button_);
@@ -460,14 +555,14 @@
}
views::View* ProfileChooserView::CreateCurrentProfileAccountsView(
- const AvatarMenuModel::Item& avatar_item) {
+ const AvatarMenu::Item& avatar_item) {
DCHECK(avatar_item.signed_in);
views::View* view = new views::View();
views::GridLayout* layout = CreateSingleColumnLayout(view);
- layout->SetInsets(views::kButtonHEdgeMarginNew,
- views::kButtonVEdgeMarginNew,
+ layout->SetInsets(views::kButtonVEdgeMarginNew,
views::kButtonHEdgeMarginNew,
- views::kButtonVEdgeMarginNew);
+ views::kButtonVEdgeMarginNew,
+ views::kButtonHEdgeMarginNew);
views::Label* email_label = new views::Label(avatar_item.sync_state);
email_label->SetElideBehavior(views::Label::ELIDE_AS_EMAIL);
@@ -477,7 +572,7 @@
layout->StartRow(1, 0);
layout->AddView(email_label);
- layout->AddPaddingRow(0, views::kUnrelatedControlHorizontalSpacing);
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
views::BlueButton* add_account_button = new views::BlueButton(
NULL,
diff --git a/chrome/browser/ui/views/profile_chooser_view.h b/chrome/browser/ui/views/profile_chooser_view.h
index a1d99d2..d045be3 100644
--- a/chrome/browser/ui/views/profile_chooser_view.h
+++ b/chrome/browser/ui/views/profile_chooser_view.h
@@ -8,8 +8,8 @@
#include <map>
#include <vector>
-#include "chrome/browser/profiles/avatar_menu_model.h"
-#include "chrome/browser/profiles/avatar_menu_model_observer.h"
+#include "chrome/browser/profiles/avatar_menu.h"
+#include "chrome/browser/profiles/avatar_menu_observer.h"
#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/link_listener.h"
@@ -32,7 +32,7 @@
class ProfileChooserView : public views::BubbleDelegateView,
public views::ButtonListener,
public views::LinkListener,
- public AvatarMenuModelObserver {
+ public AvatarMenuObserver {
public:
// Shows the bubble if one is not already showing. This allows us to easily
// make a button toggle the bubble on and off when clicked: we unconditionally
@@ -63,7 +63,7 @@
typedef std::map<views::Button*, int> ButtonIndexes;
// Different views that can be displayed in the bubble.
- enum BubbleViewMode{
+ enum BubbleViewMode {
PROFILE_CHOOSER_VIEW, // Displays a "fast profile switcher" view.
ACCOUNT_MANAGEMENT_VIEW // Displays a list of accounts for the active user.
};
@@ -85,9 +85,8 @@
// LinkListener:
virtual void LinkClicked(views::Link* sender, int event_flags) OVERRIDE;
- // AvatarMenuModelObserver:
- virtual void OnAvatarMenuModelChanged(
- AvatarMenuModel* avatar_menu_model) OVERRIDE;
+ // AvatarMenuObserver:
+ virtual void OnAvatarMenuChanged(AvatarMenu* avatar_menu) OVERRIDE;
static ProfileChooserView* profile_bubble_;
static bool close_on_deactivate_;
@@ -96,13 +95,13 @@
// Shows either the profile chooser or the account management views.
void ShowView(BubbleViewMode view_to_display,
- AvatarMenuModel* avatar_menu_model);
+ AvatarMenu* avatar_menu);
// Creates the main profile card for the profile |avatar_item|. |is_guest|
// is used to determine whether to show any Sign in/Sign out/Manage accounts
// links.
views::View* CreateCurrentProfileView(
- const AvatarMenuModel::Item& avatar_item,
+ const AvatarMenu::Item& avatar_item,
bool is_guest);
views::View* CreateGuestProfileView();
views::View* CreateOtherProfilesView(const Indexes& avatars_to_show);
@@ -110,11 +109,11 @@
// Account Management view for the profile |avatar_item|.
views::View* CreateCurrentProfileEditableView(
- const AvatarMenuModel::Item& avatar_item);
+ const AvatarMenu::Item& avatar_item);
views::View* CreateCurrentProfileAccountsView(
- const AvatarMenuModel::Item& avatar_item);
+ const AvatarMenu::Item& avatar_item);
- scoped_ptr<AvatarMenuModel> avatar_menu_model_;
+ scoped_ptr<AvatarMenu> avatar_menu_;
Browser* browser_;
// Other profiles used in the "fast profile switcher" view.
@@ -129,6 +128,7 @@
// Action buttons.
views::TextButton* guest_button_;
views::TextButton* end_guest_button_;
+ views::TextButton* add_user_button_;
views::TextButton* users_button_;
DISALLOW_COPY_AND_ASSIGN(ProfileChooserView);
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc
index 26a0cff..6e89dec 100644
--- a/chrome/browser/ui/views/status_bubble_views.cc
+++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -35,7 +35,7 @@
#include "url/gurl.h"
#if defined(USE_ASH)
-#include "ash/wm/window_settings.h"
+#include "ash/wm/window_state.h"
#endif
// The alpha and color of the bubble's shadow.
@@ -583,7 +583,7 @@
popup_->SetOpacity(0x00);
popup_->SetContentsView(view_);
#if defined(USE_ASH)
- ash::wm::GetWindowSettings(popup_->GetNativeWindow())->
+ ash::wm::GetWindowState(popup_->GetNativeWindow())->
set_ignored_by_shelf(true);
#endif
Reposition();
diff --git a/chrome/browser/ui/views/tab_icon_view.cc b/chrome/browser/ui/views/tab_icon_view.cc
index 433e36f..ab13cd6 100644
--- a/chrome/browser/ui/views/tab_icon_view.cc
+++ b/chrome/browser/ui/views/tab_icon_view.cc
@@ -39,8 +39,7 @@
HICON app_icon = GetAppIcon();
scoped_ptr<SkBitmap> bitmap(
IconUtil::CreateSkBitmapFromHICON(app_icon, gfx::Size(16, 16)));
- g_default_favicon = new gfx::ImageSkia(
- gfx::ImageSkiaRep(*bitmap, ui::SCALE_FACTOR_100P));
+ g_default_favicon = new gfx::ImageSkia(gfx::ImageSkiaRep(*bitmap, 1.0f));
DestroyIcon(app_icon);
#else
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
diff --git a/chrome/browser/ui/views/tabs/dragged_tab_view.cc b/chrome/browser/ui/views/tabs/dragged_tab_view.cc
index bb3b8a6..d7b8cf8 100644
--- a/chrome/browser/ui/views/tabs/dragged_tab_view.cc
+++ b/chrome/browser/ui/views/tabs/dragged_tab_view.cc
@@ -138,7 +138,7 @@
void DraggedTabView::PaintDetachedView(gfx::Canvas* canvas) {
gfx::Size ps = GetPreferredSize();
// TODO(pkotwicz): DIP enable this class.
- gfx::Canvas scale_canvas(ps, ui::SCALE_FACTOR_100P, false);
+ gfx::Canvas scale_canvas(ps, 1.0f, false);
SkBitmap& bitmap_device = const_cast<SkBitmap&>(
skia::GetTopDevice(*scale_canvas.sk_canvas())->accessBitmap(true));
bitmap_device.eraseARGB(0, 0, 0, 0);
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index b7871eb..be34f25 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
#include "chrome/browser/ui/tabs/tab_resources.h"
+#include "chrome/browser/ui/tabs/tab_utils.h"
#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"
@@ -31,7 +32,6 @@
#include "ui/base/theme_provider.h"
#include "ui/gfx/animation/animation_container.h"
#include "ui/gfx/animation/multi_animation.h"
-#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_analysis.h"
@@ -164,9 +164,6 @@
// How long the pulse throb takes.
const int kPulseDurationMs = 200;
-// How long the recording button takes to fade in/out.
-const int kRecordingDurationMs = 1000;
-
// Width of touch tabs.
static const int kTouchWidth = 120;
@@ -465,6 +462,7 @@
tab_activated_with_last_gesture_begin_(false),
hover_controller_(this),
showing_icon_(false),
+ showing_audio_indicator_(false),
showing_close_button_(false),
close_button_color_(0) {
InitTabResources();
@@ -492,8 +490,6 @@
AddChildView(close_button_);
set_context_menu_controller(this);
-
- tab_audio_indicator_.reset(new TabAudioIndicator(this));
}
Tab::~Tab() {
@@ -502,7 +498,6 @@
void Tab::set_animation_container(gfx::AnimationContainer* container) {
animation_container_ = container;
hover_controller_.SetAnimationContainer(container);
- tab_audio_indicator_->SetAnimationContainer(container);
}
bool Tab::IsActive() const {
@@ -556,8 +551,6 @@
}
}
- tab_audio_indicator_->SetIsPlayingAudio(data_.AudioActive());
-
DataChanged(old);
Layout();
@@ -679,16 +672,6 @@
}
////////////////////////////////////////////////////////////////////////////////
-// Tab, TabAudioIndicator::Delegate overrides:
-
-void Tab::ScheduleAudioIndicatorPaint() {
- // No need to schedule a paint if another animation is active. The other
- // animation will do its own scheduling.
- if (!icon_animation_)
- ScheduleIconPaint();
-}
-
-////////////////////////////////////////////////////////////////////////////////
// Tab, AnimationDelegate overrides:
void Tab::AnimationProgressed(const gfx::Animation* animation) {
@@ -781,20 +764,7 @@
int favicon_left = lb.x();
favicon_bounds_.SetRect(favicon_left, favicon_top,
tab_icon_size(), tab_icon_size());
- if (data().mini && width() < kMiniTabRendererAsNormalTabWidth) {
- // Adjust the location of the favicon when transitioning from a normal
- // tab to a mini-tab.
- int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth();
- int ideal_delta = width() - GetMiniWidth();
- if (ideal_delta < mini_delta) {
- int ideal_x = (GetMiniWidth() - tab_icon_size()) / 2;
- int x = favicon_bounds_.x() + static_cast<int>(
- (1 - static_cast<float>(ideal_delta) /
- static_cast<float>(mini_delta)) *
- (ideal_x - favicon_bounds_.x()));
- favicon_bounds_.set_x(x);
- }
- }
+ MaybeAdjustLeftForMiniTab(&favicon_bounds_);
} else {
favicon_bounds_.SetRect(lb.x(), lb.y(), 0, 0);
}
@@ -831,6 +801,23 @@
close_button_->SetVisible(false);
}
+ showing_audio_indicator_ = ShouldShowAudioIndicator();
+ if (showing_audio_indicator_) {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ gfx::ImageSkia audio_indicator_image(
+ *rb.GetImageSkiaNamed(IDR_TAB_AUDIO_INDICATOR));
+ const int top =
+ top_padding() + (content_height - audio_indicator_image.height()) / 2;
+ const int right = showing_close_button_ ?
+ close_button_->x() + close_button_->GetInsets().left() : lb.right();
+ const int left = std::max(lb.x(), right - audio_indicator_image.width());
+ audio_indicator_bounds_.SetRect(left, top,
+ tab_icon_size(), tab_icon_size());
+ MaybeAdjustLeftForMiniTab(&audio_indicator_bounds_);
+ } else {
+ audio_indicator_bounds_.SetRect(lb.x(), lb.y(), 0, 0);
+ }
+
const int title_text_offset = is_host_desktop_type_ash ?
kTitleTextOffsetYAsh : kTitleTextOffsetY;
int title_left = favicon_bounds_.right() + kFaviconTitleSpacing;
@@ -847,16 +834,19 @@
title_top -= (text_height - minimum_size.height()) / 2;
int title_width;
- if (close_button_->visible()) {
+ if (showing_audio_indicator_) {
+ title_width = audio_indicator_bounds_.x() - kTitleCloseButtonSpacing -
+ title_left;
+ } else if (close_button_->visible()) {
// The close button has an empty border with some padding (see details
// above where the close-button's bounds is set). Allow the title to
// overlap the empty padding.
- title_width = std::max(close_button_->x() +
- close_button_->GetInsets().left() -
- kTitleCloseButtonSpacing - title_left, 0);
+ title_width = close_button_->x() + close_button_->GetInsets().left() -
+ kTitleCloseButtonSpacing - title_left;
} else {
- title_width = std::max(lb.width() - title_left, 0);
+ title_width = lb.width() - title_left;
}
+ title_width = std::max(title_width, 0);
title_bounds_.SetRect(title_left, title_top, title_width, font_height_);
} else {
title_bounds_.SetRect(title_left, title_top, 0, 0);
@@ -1077,6 +1067,17 @@
return favicon_bounds_;
}
+void Tab::MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const {
+ if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth)
+ return;
+ const int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth();
+ const int ideal_delta = width() - GetMiniWidth();
+ const int ideal_x = (GetMiniWidth() - bounds->width()) / 2;
+ bounds->set_x(bounds->x() + static_cast<int>(
+ (1 - static_cast<float>(ideal_delta) / static_cast<float>(mini_delta)) *
+ (ideal_x - bounds->x())));
+}
+
void Tab::DataChanged(const TabRendererData& old) {
if (data().blocked == old.blocked)
return;
@@ -1090,9 +1091,13 @@
void Tab::PaintTab(gfx::Canvas* canvas) {
// See if the model changes whether the icons should be painted.
const bool show_icon = ShouldShowIcon();
+ const bool show_audio_indicator = ShouldShowAudioIndicator();
const bool show_close_button = ShouldShowCloseBox();
- if (show_icon != showing_icon_ || show_close_button != showing_close_button_)
+ if (show_icon != showing_icon_ ||
+ show_audio_indicator != showing_audio_indicator_ ||
+ show_close_button != showing_close_button_) {
Layout();
+ }
PaintTabBackground(canvas);
@@ -1107,6 +1112,9 @@
if (show_icon)
PaintIcon(canvas);
+ if (show_audio_indicator)
+ PaintAudioIndicator(canvas);
+
// If the close button color has changed, generate a new one.
if (!close_button_color_ || title_color != close_button_color_) {
close_button_color_ = title_color;
@@ -1191,13 +1199,13 @@
gfx::Canvas* canvas,
gfx::MultiAnimation* animation) {
// Render the inactive tab background. We'll use this for clipping.
- gfx::Canvas background_canvas(size(), canvas->scale_factor(), false);
+ gfx::Canvas background_canvas(size(), canvas->image_scale(), false);
PaintInactiveTabBackground(&background_canvas);
gfx::ImageSkia background_image(background_canvas.ExtractImageRep());
// Draw a radial gradient to hover_canvas.
- gfx::Canvas hover_canvas(size(), canvas->scale_factor(), false);
+ gfx::Canvas hover_canvas(size(), canvas->image_scale(), false);
int radius = kMiniTitleChangeGradientRadius;
int x0 = width() + radius - kMiniTitleChangeInitialXOffset;
int x1 = radius;
@@ -1260,13 +1268,14 @@
!hover_controller_.ShouldDraw();
if (can_cache) {
- gfx::ImageSkia cached_image(
- GetCachedImage(tab_id, size(), canvas->scale_factor()));
+ ui::ScaleFactor scale_factor =
+ ui::GetSupportedScaleFactor(canvas->image_scale());
+ gfx::ImageSkia cached_image(GetCachedImage(tab_id, size(), scale_factor));
if (cached_image.width() == 0) {
- gfx::Canvas tmp_canvas(size(), canvas->scale_factor(), false);
+ gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false);
PaintInactiveTabBackgroundUsingResourceId(&tmp_canvas, tab_id);
cached_image = gfx::ImageSkia(tmp_canvas.ExtractImageRep());
- SetCachedImage(tab_id, canvas->scale_factor(), cached_image);
+ SetCachedImage(tab_id, scale_factor, cached_image);
}
canvas->DrawImageInt(cached_image, 0, 0);
} else {
@@ -1299,7 +1308,7 @@
// We need a gfx::Canvas object to be able to extract the image from.
// We draw everything to this canvas and then output it to the canvas
// parameter in addition to using it to mask the hover glow if needed.
- gfx::Canvas background_canvas(size(), canvas->scale_factor(), false);
+ gfx::Canvas background_canvas(size(), canvas->image_scale(), false);
// Draw left edge. Don't draw over the toolbar, as we're not the foreground
// tab.
@@ -1457,13 +1466,6 @@
data().favicon.width(),
data().favicon.height(),
bounds, true, SkPaint());
- } else if (!icon_animation_ && tab_audio_indicator_->IsAnimating()) {
- // Draw the audio indicator UI only if no other icon animation is
- // active.
- if (!icon_animation_ && tab_audio_indicator_->IsAnimating()) {
- tab_audio_indicator_->set_favicon(data().favicon);
- tab_audio_indicator_->Paint(canvas, bounds);
- }
} else {
DrawIconCenter(canvas, data().favicon, 0,
data().favicon.width(),
@@ -1482,8 +1484,8 @@
void Tab::PaintCaptureState(gfx::Canvas* canvas, gfx::Rect bounds) {
SkPaint paint;
paint.setAntiAlias(true);
- U8CPU alpha = icon_animation_->GetCurrentValue() * 0xff;
- paint.setAlpha(alpha);
+ DCHECK(capture_icon_animation_.get());
+ paint.setAlpha(capture_icon_animation_->GetCurrentValue() * SK_AlphaOPAQUE);
ui::ThemeProvider* tp = GetThemeProvider();
if (data().capture_state == TabRendererData::CAPTURE_STATE_PROJECTING) {
@@ -1573,6 +1575,21 @@
}
}
+void Tab::PaintAudioIndicator(gfx::Canvas* canvas) {
+ if (audio_indicator_bounds_.IsEmpty())
+ return;
+
+ gfx::Rect bounds = audio_indicator_bounds_;
+ bounds.set_x(GetMirroredXForRect(bounds));
+
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ const gfx::ImageSkia audio_indicator_image(
+ *rb.GetImageSkiaNamed(IDR_TAB_AUDIO_INDICATOR));
+ DrawIconAtLocation(canvas, audio_indicator_image, 0,
+ bounds.x(), bounds.y(), audio_indicator_image.width(),
+ audio_indicator_image.height(), true, SkPaint());
+}
+
void Tab::PaintTitle(gfx::Canvas* canvas, SkColor title_color) {
// Paint the Title.
const gfx::Rect& title_bounds = GetTitleBounds();
@@ -1652,19 +1669,44 @@
int Tab::IconCapacity() const {
if (height() < GetMinimumUnselectedSize().height())
return 0;
- return (width() - left_padding() - right_padding()) / tab_icon_size();
+ const int kPaddingBetweenIcons = 2;
+ return (width() - left_padding() - right_padding()) /
+ (tab_icon_size() + kPaddingBetweenIcons);
}
bool Tab::ShouldShowIcon() const {
+ if (!data().show_icon)
+ return false;
+ const bool should_show_audio_indicator = ShouldShowAudioIndicator();
+ if (data().mini && height() >= GetMinimumUnselectedSize().height()) {
+ // Audio indicator always takes precendence over the favicon for mini tabs.
+ return !should_show_audio_indicator;
+ }
+ int required_capacity = should_show_audio_indicator ? 2 : 1;
+ if (IsActive()) {
+ // Active tabs give priority to the close button, then the audio indicator,
+ // then the favicon.
+ ++required_capacity;
+ } else {
+ // Non-active tabs give priority to the audio indicator, then the favicon,
+ // and finally the close button.
+ }
+ return IconCapacity() >= required_capacity;
+}
+
+bool Tab::ShouldShowAudioIndicator() const {
+ // Note: If the capture indicator is active, then do not show the audio
+ // indicator. This allows the favicon "throbber" animation to be shown in
+ // small-width situations.
+ if (!data().AudioActive() || data().CaptureActive())
+ return false;
if (data().mini && height() >= GetMinimumUnselectedSize().height())
return true;
- if (!data().show_icon) {
- return false;
- } else if (IsActive()) {
- // The active tab clips favicon before close button.
+ if (IsActive()) {
+ // The active tab clips the audio indicator before the close button.
return IconCapacity() >= 2;
}
- // Non-selected tabs clip close button before favicon.
+ // Non-active tabs clip close button before the audio indicator.
return IconCapacity() >= 1;
}
@@ -1705,27 +1747,25 @@
}
void Tab::StopIconAnimation() {
- if (!icon_animation_.get())
- return;
- icon_animation_->Stop();
- icon_animation_.reset();
+ crash_icon_animation_.reset();
+ capture_icon_animation_.reset();
}
void Tab::StartCrashAnimation() {
- icon_animation_.reset(new FaviconCrashAnimation(this));
- icon_animation_->Start();
+ capture_icon_animation_.reset();
+ crash_icon_animation_.reset(new FaviconCrashAnimation(this));
+ crash_icon_animation_->Start();
}
void Tab::StartRecordingAnimation() {
- gfx::ThrobAnimation* animation = new gfx::ThrobAnimation(this);
- animation->SetTweenType(gfx::Tween::EASE_IN_OUT);
- animation->SetThrobDuration(kRecordingDurationMs);
- animation->StartThrobbing(-1);
- icon_animation_.reset(animation);
+ crash_icon_animation_.reset();
+ capture_icon_animation_ = chrome::CreateTabRecordingIndicatorAnimation();
+ capture_icon_animation_->set_delegate(this);
+ capture_icon_animation_->Start();
}
bool Tab::IsPerformingCrashAnimation() const {
- return icon_animation_.get() && data_.IsCrashed();
+ return crash_icon_animation_.get() && data_.IsCrashed();
}
void Tab::ScheduleIconPaint() {
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index 0c43230..4ef7567 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -10,7 +10,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/ui/tabs/tab_audio_indicator.h"
#include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
#include "ui/base/layout.h"
#include "ui/gfx/animation/animation_delegate.h"
@@ -38,8 +37,7 @@
// A View that renders a Tab, either in a TabStrip or in a DraggedTabView.
//
///////////////////////////////////////////////////////////////////////////////
-class Tab : public TabAudioIndicator::Delegate,
- public gfx::AnimationDelegate,
+class Tab : public gfx::AnimationDelegate,
public views::ButtonListener,
public views::ContextMenuController,
public views::View {
@@ -153,9 +151,6 @@
typedef std::list<ImageCacheEntry> ImageCache;
- // Overridden from TabAudioIndicator::Delegate:
- virtual void ScheduleAudioIndicatorPaint() OVERRIDE;
-
// Overridden from gfx::AnimationDelegate:
virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
@@ -198,6 +193,10 @@
const gfx::Rect& GetTitleBounds() const;
const gfx::Rect& GetIconBounds() const;
+ // Invoked from Layout to adjust the position of the favicon or audio
+ // indicator for mini tabs.
+ void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const;
+
// Invoked from SetData after |data_| has been updated to the new data.
void DataChanged(const TabRendererData& old);
@@ -217,9 +216,10 @@
int tab_id);
void PaintActiveTabBackground(gfx::Canvas* canvas);
- // Paints the icon at the specified coordinates, mirrored for RTL if needed.
+ // Paints the icon, audio indicator icon, etc., mirrored for RTL if needed.
void PaintIcon(gfx::Canvas* canvas);
void PaintCaptureState(gfx::Canvas* canvas, gfx::Rect bounds);
+ void PaintAudioIndicator(gfx::Canvas* canvas);
void PaintTitle(gfx::Canvas* canvas, SkColor title_color);
// Invoked if data_.network_state changes, or the network_state is not none.
@@ -233,6 +233,9 @@
// Returns whether the Tab should display a favicon.
bool ShouldShowIcon() const;
+ // Returns whether the Tab should display the audio indicator.
+ bool ShouldShowAudioIndicator() const;
+
// Returns whether the Tab should display a close button.
bool ShouldShowCloseBox() const;
@@ -317,12 +320,10 @@
// recording, projecting, etc. Note that the icon animation related to network
// state does not have an animation associated with it.
scoped_ptr<gfx::Animation> tab_animation_;
- scoped_ptr<gfx::LinearAnimation> icon_animation_;
-
+ scoped_ptr<gfx::LinearAnimation> crash_icon_animation_;
+ scoped_ptr<gfx::Animation> capture_icon_animation_;
scoped_refptr<gfx::AnimationContainer> animation_container_;
- scoped_ptr<TabAudioIndicator> tab_audio_indicator_;
-
views::ImageButton* close_button_;
ui::ThemeProvider* theme_provider_;
@@ -334,6 +335,7 @@
// The bounds of various sections of the display.
gfx::Rect favicon_bounds_;
gfx::Rect title_bounds_;
+ gfx::Rect audio_indicator_bounds_;
// The offset used to paint the inactive background image.
gfx::Point background_offset_;
@@ -353,6 +355,10 @@
// changes and layout appropriately.
bool showing_icon_;
+ // Whether we're showing the audio indicator. It is cached so that we can
+ // detect when it changes and layout appropriately.
+ bool showing_audio_indicator_;
+
// Whether we are showing the close button. It is cached so that we can
// detect when it changes and layout appropriately.
bool showing_close_button_;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index 69d15ed..a5dd831 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -51,11 +51,12 @@
#if defined(USE_ASH)
#include "ash/shell.h"
+#include "ash/shell_delegate.h"
#include "ash/wm/coordinate_conversion.h"
-#include "ash/wm/window_settings.h"
+#include "ash/wm/window_state.h"
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
-#include "ui/base/gestures/gesture_recognizer.h"
+#include "ui/events/gestures/gesture_recognizer.h"
#endif
using content::OpenURLParams;
@@ -193,13 +194,13 @@
void SetTrackedByWorkspace(gfx::NativeWindow window, bool value) {
#if defined(USE_ASH)
- ash::wm::GetWindowSettings(window)->SetTrackedByWorkspace(value);
+ ash::wm::GetWindowState(window)->SetTrackedByWorkspace(value);
#endif
}
void SetWindowPositionManaged(gfx::NativeWindow window, bool value) {
#if defined(USE_ASH)
- ash::wm::GetWindowSettings(window)->set_window_position_managed(value);
+ ash::wm::GetWindowState(window)->set_window_position_managed(value);
#endif
}
@@ -373,6 +374,9 @@
move_behavior_(REORDER),
mouse_move_direction_(0),
is_dragging_window_(false),
+ is_dragging_new_browser_(false),
+ was_source_maximized_(false),
+ was_source_fullscreen_(false),
end_run_loop_behavior_(END_RUN_LOOP_STOP_DRAGGING),
waiting_for_run_loop_to_exit_(false),
tab_strip_to_attach_to_after_exit_(NULL),
@@ -424,6 +428,8 @@
DCHECK(!tabs.empty());
DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end());
source_tabstrip_ = source_tabstrip;
+ was_source_maximized_ = source_tabstrip->GetWidget()->IsMaximized();
+ was_source_fullscreen_ = source_tabstrip->GetWidget()->IsFullscreen();
screen_ = gfx::Screen::GetScreenFor(
source_tabstrip->GetWidget()->GetNativeView());
host_desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
@@ -812,6 +818,7 @@
last_point_in_screen_ = point_in_screen;
if (tab_strip_changed) {
+ is_dragging_new_browser_ = false;
if (detach_into_browser_ &&
DragBrowserToNewTabStrip(target_tabstrip, point_in_screen) ==
DRAG_BROWSER_RESULT_STOP) {
@@ -1443,8 +1450,13 @@
event_source_ == EVENT_SOURCE_MOUSE ?
views::Widget::MOVE_LOOP_SOURCE_MOUSE :
views::Widget::MOVE_LOOP_SOURCE_TOUCH;
+ const views::Widget::MoveLoopEscapeBehavior escape_behavior =
+ is_dragging_new_browser_ ?
+ views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE :
+ views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_DONT_HIDE;
views::Widget::MoveLoopResult result =
- move_loop_widget_->RunMoveLoop(drag_offset, move_loop_source);
+ move_loop_widget_->RunMoveLoop(
+ drag_offset, move_loop_source, escape_behavior);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE,
content::NotificationService::AllBrowserContextsAndSources(),
@@ -1831,6 +1843,19 @@
initial_tab_positions_,
move_behavior_ == MOVE_VISIBILE_TABS,
true);
+ if (is_dragging_new_browser_) {
+ // If source window was maximized - maximize the new window as well.
+ if (was_source_maximized_)
+ attached_tabstrip_->GetWidget()->Maximize();
+#if defined(USE_ASH)
+ if (was_source_fullscreen_ &&
+ host_desktop_type_ == chrome::HOST_DESKTOP_TYPE_ASH) {
+ // In fullscreen mode it is only possible to get here if the source
+ // was in "immersive fullscreen" mode, so toggle it back on.
+ ash::Shell::GetInstance()->delegate()->ToggleFullscreen();
+ }
+#endif
+ }
} else {
if (dock_info_.type() != DockInfo::NONE) {
switch (dock_info_.type()) {
@@ -2122,6 +2147,17 @@
gfx::Point center(0, source->height() / 2);
views::View::ConvertPointToWidget(source, ¢er);
gfx::Rect new_bounds(source->GetWidget()->GetRestoredBounds());
+ if (source->GetWidget()->IsMaximized()) {
+ // If the restore bounds is really small, we don't want to honor it
+ // (dragging a really small window looks wrong), instead make sure the new
+ // window is at least 50% the size of the old.
+ const gfx::Size max_size(
+ source->GetWidget()->GetWindowBoundsInScreen().size());
+ new_bounds.set_width(
+ std::max(max_size.width() / 2, new_bounds.width()));
+ new_bounds.set_height(
+ std::max(max_size.height() / 2, new_bounds.width()));
+ }
new_bounds.set_y(point_in_screen.y() - center.y());
switch (GetDetachPosition(point_in_screen)) {
case DETACH_BEFORE:
@@ -2151,6 +2187,7 @@
host_desktop_type_);
create_params.initial_bounds = new_bounds;
Browser* browser = new Browser(create_params);
+ is_dragging_new_browser_ = true;
SetTrackedByWorkspace(browser->window()->GetNativeWindow(), false);
SetWindowPositionManaged(browser->window()->GetNativeWindow(), false);
// If the window is created maximized then the bounds we supplied are ignored.
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.h b/chrome/browser/ui/views/tabs/tab_drag_controller.h
index eb7defd..4dd86ed 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.h
@@ -606,6 +606,16 @@
// See description above getter.
bool is_dragging_window_;
+ // True if |attached_tabstrip_| is in a browser specifically created for
+ // the drag.
+ bool is_dragging_new_browser_;
+
+ // True if |source_tabstrip_| was maximized before the drag.
+ bool was_source_maximized_;
+
+ // True if |source_tabstrip_| was in immersive fullscreen before the drag.
+ bool was_source_fullscreen_;
+
EndRunLoopBehavior end_run_loop_behavior_;
// If true, we're waiting for a move loop to complete.
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 6b0e545..bd7183a 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
@@ -4,7 +4,7 @@
#include "chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h"
-#include "ash/wm/window_settings.h"
+#include "ash/wm/window_state.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
@@ -213,7 +213,7 @@
#if !defined(USE_ASH) || defined(OS_WIN) // TODO(win_ash)
return true;
#else
- return ash::wm::GetWindowSettings(browser->window()->GetNativeWindow())->
+ return ash::wm::GetWindowState(browser->window()->GetNativeWindow())->
tracked_by_workspace();
#endif
}
@@ -559,10 +559,10 @@
#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
bool IsWindowPositionManaged(aura::Window* window) {
- return ash::wm::GetWindowSettings(window)->window_position_managed();
+ return ash::wm::GetWindowState(window)->window_position_managed();
}
bool HasUserChangedWindowPositionOrSize(aura::Window* window) {
- return ash::wm::GetWindowSettings(window)->bounds_changed_by_user();
+ return ash::wm::GetWindowState(window)->bounds_changed_by_user();
}
#else
bool IsWindowPositionManaged(gfx::NativeWindow window) {
@@ -678,8 +678,8 @@
EXPECT_TRUE(IsWindowPositionManaged(
new_browser->window()->GetNativeWindow()));
- // The new window should not be maximized.
- EXPECT_FALSE(new_browser->window()->IsMaximized());
+ // The new window should be maximized.
+ EXPECT_TRUE(new_browser->window()->IsMaximized());
}
// Deletes a tab being dragged before the user moved enough to start a drag.
@@ -1243,10 +1243,10 @@
EXPECT_TRUE(GetTrackedByWorkspace(browser()));
EXPECT_TRUE(GetTrackedByWorkspace(new_browser));
- // The source window should be maximized, but the new window should now
- // be restored.
+ // The source window should be maximized.
EXPECT_TRUE(browser()->window()->IsMaximized());
- EXPECT_FALSE(new_browser->window()->IsMaximized());
+ // The new window should be maximized.
+ EXPECT_TRUE(new_browser->window()->IsMaximized());
}
// Subclass of DetachToBrowserInSeparateDisplayTabDragControllerTest that
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 17e1579..5e40997 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -39,6 +39,7 @@
#include "ui/gfx/animation/animation_container.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/display.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/path.h"
@@ -393,7 +394,8 @@
#endif
void NewTabButton::OnPaint(gfx::Canvas* canvas) {
- gfx::ImageSkia image = GetImageForScale(canvas->scale_factor());
+ gfx::ImageSkia image =
+ GetImageForScale(ui::GetSupportedScaleFactor(canvas->image_scale()));
canvas->DrawImageInt(image, 0, height() - image.height());
}
@@ -443,12 +445,12 @@
GetThemeProvider()->GetImageSkiaNamed(IDR_NEWTAB_BUTTON_MASK);
int height = mask->height();
int width = mask->width();
-
+ float scale = ui::GetImageScale(scale_factor);
// The canvas and mask has to use the same scale factor.
- if (!mask->HasRepresentation(scale_factor))
+ if (!mask->HasRepresentation(scale))
scale_factor = ui::SCALE_FACTOR_100P;
- gfx::Canvas canvas(gfx::Size(width, height), scale_factor, false);
+ gfx::Canvas canvas(gfx::Size(width, height), scale, false);
// For custom images the background starts at the top of the tab strip.
// Otherwise the background starts at the top of the frame.
@@ -494,7 +496,9 @@
gfx::ImageSkia* overlay = GetThemeProvider()->GetImageSkiaNamed(overlay_id);
gfx::Canvas canvas(
- gfx::Size(overlay->width(), overlay->height()), scale_factor, false);
+ gfx::Size(overlay->width(), overlay->height()),
+ ui::GetImageScale(scale_factor),
+ false);
canvas.DrawImageInt(GetBackgroundImage(state, scale_factor), 0, 0);
// Draw the button border with a slight alpha.
@@ -2304,14 +2308,9 @@
drop_indicator_height);
// If the rect doesn't fit on the monitor, push the arrow to the bottom.
-#if defined(OS_WIN) && !defined(USE_AURA)
- gfx::Rect monitor_bounds = views::GetMonitorBoundsForRect(drop_bounds);
- *is_beneath = (monitor_bounds.IsEmpty() ||
- !monitor_bounds.Contains(drop_bounds));
-#else
- *is_beneath = false;
- NOTIMPLEMENTED();
-#endif
+ gfx::Screen* screen = gfx::Screen::GetScreenFor(GetWidget()->GetNativeView());
+ gfx::Display display = screen->GetDisplayMatching(drop_bounds);
+ *is_beneath = !display.bounds().Contains(drop_bounds);
if (*is_beneath)
drop_bounds.Offset(0, drop_bounds.height() + height());
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc
index 6a175fa..16ab690 100644
--- a/chrome/browser/ui/views/tabs/tab_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -16,11 +16,12 @@
class FakeTabController : public TabController {
public:
- FakeTabController() : immersive_style_(false) {
+ FakeTabController() : immersive_style_(false), active_tab_(false) {
}
virtual ~FakeTabController() {}
void set_immersive_style(bool value) { immersive_style_ = value; }
+ void set_active_tab(bool value) { active_tab_ = value; }
virtual const ui::ListSelectionModel& GetSelectionModel() OVERRIDE {
return selection_model_;
@@ -34,7 +35,9 @@
virtual void ShowContextMenuForTab(Tab* tab,
const gfx::Point& p,
ui::MenuSourceType source_type) OVERRIDE {}
- virtual bool IsActiveTab(const Tab* tab) const OVERRIDE { return false; }
+ virtual bool IsActiveTab(const Tab* tab) const OVERRIDE {
+ return active_tab_;
+ }
virtual bool IsTabSelected(const Tab* tab) const OVERRIDE {
return false;
}
@@ -60,6 +63,7 @@
private:
ui::ListSelectionModel selection_model_;
bool immersive_style_;
+ bool active_tab_;
DISALLOW_COPY_AND_ASSIGN(FakeTabController);
};
@@ -70,11 +74,108 @@
virtual ~TabTest() {}
static bool IconAnimationInvariant(const Tab& tab) {
- bool capture_invariant =
- tab.data().CaptureActive() == (tab.icon_animation_.get() != NULL);
- bool audio_invariant =
- !tab.data().AudioActive() || tab.tab_audio_indicator_->IsAnimating();
- return capture_invariant && audio_invariant;
+ return tab.data().CaptureActive() == !!tab.capture_icon_animation_.get();
+ }
+
+ static void CheckForExpectedLayoutAndVisibilityOfElements(const Tab& tab) {
+ // Check whether elements are visible when they are supposed to be, given
+ // Tab size and TabRendererData state.
+ if (tab.data_.mini) {
+ if (tab.data_.CaptureActive())
+ EXPECT_TRUE(tab.ShouldShowIcon());
+ else
+ EXPECT_TRUE(tab.ShouldShowIcon() != tab.ShouldShowAudioIndicator());
+ EXPECT_FALSE(tab.ShouldShowCloseBox());
+ } else if (tab.IsActive()) {
+ EXPECT_TRUE(tab.ShouldShowCloseBox());
+ switch (tab.IconCapacity()) {
+ case 0:
+ case 1:
+ EXPECT_FALSE(tab.ShouldShowIcon());
+ EXPECT_FALSE(tab.ShouldShowAudioIndicator());
+ break;
+ case 2:
+ if (tab.data_.CaptureActive())
+ EXPECT_TRUE(tab.ShouldShowIcon());
+ else
+ EXPECT_TRUE(tab.ShouldShowIcon() != tab.ShouldShowAudioIndicator());
+ break;
+ default:
+ EXPECT_LE(3, tab.IconCapacity());
+ EXPECT_TRUE(tab.ShouldShowIcon());
+ if (tab.data_.CaptureActive()) {
+ EXPECT_FALSE(tab.ShouldShowAudioIndicator());
+ } else {
+ EXPECT_TRUE(tab.data_.AudioActive() ==
+ tab.ShouldShowAudioIndicator());
+ }
+ break;
+ }
+ } else { // Tab not active and not mini tab.
+ switch (tab.IconCapacity()) {
+ case 0:
+ EXPECT_FALSE(tab.ShouldShowCloseBox());
+ EXPECT_FALSE(tab.ShouldShowIcon());
+ EXPECT_FALSE(tab.ShouldShowAudioIndicator());
+ break;
+ case 1:
+ EXPECT_FALSE(tab.ShouldShowCloseBox());
+ if (tab.data_.CaptureActive())
+ EXPECT_TRUE(tab.ShouldShowIcon());
+ else
+ EXPECT_TRUE(tab.ShouldShowIcon() != tab.ShouldShowAudioIndicator());
+ break;
+ default:
+ EXPECT_LE(2, tab.IconCapacity());
+ EXPECT_TRUE(tab.ShouldShowIcon());
+ if (tab.data_.CaptureActive()) {
+ EXPECT_FALSE(tab.ShouldShowAudioIndicator());
+ } else {
+ EXPECT_TRUE(tab.data_.AudioActive() ==
+ tab.ShouldShowAudioIndicator());
+ }
+ break;
+ }
+ }
+
+ // Check positioning of elements with respect to each other, and that they
+ // are fully within the contents bounds.
+ const gfx::Rect contents_bounds = tab.GetContentsBounds();
+ if (tab.ShouldShowIcon()) {
+ EXPECT_LE(contents_bounds.x(), tab.favicon_bounds_.x());
+ if (tab.title_bounds_.width() > 0)
+ EXPECT_LE(tab.favicon_bounds_.right(), tab.title_bounds_.x());
+ EXPECT_LE(contents_bounds.y(), tab.favicon_bounds_.y());
+ EXPECT_LE(tab.favicon_bounds_.bottom(), contents_bounds.bottom());
+ }
+ if (tab.ShouldShowIcon() && tab.ShouldShowAudioIndicator())
+ EXPECT_LE(tab.favicon_bounds_.right(), tab.audio_indicator_bounds_.x());
+ if (tab.ShouldShowAudioIndicator()) {
+ if (tab.title_bounds_.width() > 0)
+ EXPECT_LE(tab.title_bounds_.right(), tab.audio_indicator_bounds_.x());
+ EXPECT_LE(tab.audio_indicator_bounds_.right(), contents_bounds.right());
+ EXPECT_LE(contents_bounds.y(), tab.audio_indicator_bounds_.y());
+ EXPECT_LE(tab.audio_indicator_bounds_.bottom(), contents_bounds.bottom());
+ }
+ if (tab.ShouldShowAudioIndicator() && tab.ShouldShowCloseBox()) {
+ // Note: The audio indicator can overlap the left-insets of the close box,
+ // but should otherwise be to the left of the close button.
+ EXPECT_LE(tab.audio_indicator_bounds_.right(),
+ tab.close_button_->bounds().x() +
+ tab.close_button_->GetInsets().left());
+ }
+ if (tab.ShouldShowCloseBox()) {
+ // Note: The title bounds can overlap the left-insets of the close box,
+ // but should otherwise be to the left of the close button.
+ if (tab.title_bounds_.width() > 0) {
+ EXPECT_LE(tab.title_bounds_.right(),
+ tab.close_button_->bounds().x() +
+ tab.close_button_->GetInsets().left());
+ }
+ EXPECT_LE(tab.close_button_->bounds().right(), contents_bounds.right());
+ EXPECT_LE(contents_bounds.y(), tab.close_button_->bounds().y());
+ EXPECT_LE(tab.close_button_->bounds().bottom(), contents_bounds.bottom());
+ }
}
};
@@ -108,6 +209,61 @@
EXPECT_FALSE(tab.HitTestPoint(gfx::Point(tab.width() - 1, 0)));
}
+TEST_F(TabTest, LayoutAndVisibilityOfElements) {
+ FakeTabController controller;
+ Tab tab(&controller);
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16);
+ bitmap.allocPixels();
+ TabRendererData data;
+ data.favicon = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
+
+ // Perform layout over all possible combinations, checking for correct
+ // results.
+ for (int is_mini_tab = 0; is_mini_tab < 2; ++is_mini_tab) {
+ for (int is_active_tab = 0; is_active_tab < 2; ++is_active_tab) {
+ for (int audio_state = TabRendererData::AUDIO_STATE_NONE;
+ audio_state <= TabRendererData::AUDIO_STATE_PLAYING; ++audio_state) {
+ for (int capture_state = TabRendererData::CAPTURE_STATE_NONE;
+ capture_state <= TabRendererData::CAPTURE_STATE_PROJECTING;
+ ++capture_state) {
+ SCOPED_TRACE(::testing::Message()
+ << (is_active_tab ? "Active" : "Inactive") << ' '
+ << (is_mini_tab ? "Mini " : "")
+ << "Tab with audio_state=" << audio_state
+ << " and capture_state=" << capture_state);
+ data.mini = !!is_mini_tab;
+ controller.set_active_tab(!!is_active_tab);
+ data.audio_state =
+ static_cast<TabRendererData::AudioState>(audio_state);
+ data.capture_state =
+ static_cast<TabRendererData::CaptureState>(capture_state);
+ tab.SetData(data);
+
+ // Test layout for every width from standard to minimum.
+ gfx::Rect bounds(gfx::Point(0, 0), Tab::GetStandardSize());
+ int min_width;
+ if (is_mini_tab) {
+ bounds.set_width(Tab::GetMiniWidth());
+ min_width = Tab::GetMiniWidth();
+ } else {
+ min_width = is_active_tab ? Tab::GetMinimumSelectedSize().width() :
+ Tab::GetMinimumUnselectedSize().width();
+ }
+ while (bounds.width() >= min_width) {
+ SCOPED_TRACE(::testing::Message()
+ << "bounds=" << bounds.ToString());
+ tab.SetBoundsRect(bounds); // Invokes Tab::Layout().
+ CheckForExpectedLayoutAndVisibilityOfElements(tab);
+ bounds.set_width(bounds.width() - 1);
+ }
+ }
+ }
+ }
+ }
+}
+
// Regression test for http://crbug.com/226253. Calling Layout() more than once
// shouldn't change the insets of the close button.
TEST_F(TabTest, CloseButtonLayout) {
@@ -127,9 +283,10 @@
EXPECT_EQ(50, tab.close_button_->bounds().height());
}
-TEST_F(TabTest, ActivityIndicators) {
+TEST_F(TabTest, RecordingAndProjectingActivityIndicators) {
FakeTabController controller;
Tab tab(&controller);
+ tab.SetBoundsRect(gfx::Rect(gfx::Point(0, 0), Tab::GetStandardSize()));
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16);
@@ -139,77 +296,45 @@
data.favicon = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
tab.SetData(data);
- // Audio starts and stops.
- data.audio_state = TabRendererData::AUDIO_STATE_PLAYING;
- tab.SetData(data);
- EXPECT_TRUE(IconAnimationInvariant(tab));
- EXPECT_EQ(TabRendererData::AUDIO_STATE_PLAYING, tab.data().audio_state);
- EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state);
- data.audio_state = TabRendererData::AUDIO_STATE_NONE;
- tab.SetData(data);
- EXPECT_TRUE(IconAnimationInvariant(tab));
- EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state);
- EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state);
- EXPECT_TRUE(IconAnimationInvariant(tab));
-
- // Capture starts and stops.
+ // Recording starts and stops.
data.capture_state = TabRendererData::CAPTURE_STATE_RECORDING;
tab.SetData(data);
EXPECT_TRUE(IconAnimationInvariant(tab));
- EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state);
EXPECT_EQ(TabRendererData::CAPTURE_STATE_RECORDING, tab.data().capture_state);
data.capture_state = TabRendererData::CAPTURE_STATE_NONE;
tab.SetData(data);
EXPECT_TRUE(IconAnimationInvariant(tab));
- EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state);
EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state);
EXPECT_TRUE(IconAnimationInvariant(tab));
- // Audio starts then capture starts, then audio stops then capture stops.
- data.audio_state = TabRendererData::AUDIO_STATE_PLAYING;
- tab.SetData(data);
+ // Recording starts then tab capture starts, then back to just recording, then
+ // recording stops.
data.capture_state = TabRendererData::CAPTURE_STATE_RECORDING;
tab.SetData(data);
EXPECT_TRUE(IconAnimationInvariant(tab));
- EXPECT_EQ(TabRendererData::AUDIO_STATE_PLAYING, tab.data().audio_state);
EXPECT_EQ(TabRendererData::CAPTURE_STATE_RECORDING, tab.data().capture_state);
data.title = ASCIIToUTF16("test X");
tab.SetData(data);
EXPECT_TRUE(IconAnimationInvariant(tab));
- data.audio_state = TabRendererData::AUDIO_STATE_NONE;
+ data.capture_state = TabRendererData::CAPTURE_STATE_PROJECTING;
tab.SetData(data);
EXPECT_TRUE(IconAnimationInvariant(tab));
- EXPECT_EQ(TabRendererData::CAPTURE_STATE_RECORDING, tab.data().capture_state);
- data.capture_state = TabRendererData::CAPTURE_STATE_NONE;
- tab.SetData(data);
- EXPECT_TRUE(IconAnimationInvariant(tab));
- EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state);
- EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state);
-
- // Audio starts then capture starts, then capture stops then audio stops.
- data.audio_state = TabRendererData::AUDIO_STATE_PLAYING;
- tab.SetData(data);
- data.capture_state = TabRendererData::CAPTURE_STATE_RECORDING;
- tab.SetData(data);
- EXPECT_TRUE(IconAnimationInvariant(tab));
- EXPECT_EQ(TabRendererData::AUDIO_STATE_PLAYING, tab.data().audio_state);
- EXPECT_EQ(TabRendererData::CAPTURE_STATE_RECORDING, tab.data().capture_state);
+ EXPECT_EQ(TabRendererData::CAPTURE_STATE_PROJECTING,
+ tab.data().capture_state);
data.title = ASCIIToUTF16("test Y");
tab.SetData(data);
EXPECT_TRUE(IconAnimationInvariant(tab));
+ data.capture_state = TabRendererData::CAPTURE_STATE_RECORDING;
+ tab.SetData(data);
+ EXPECT_TRUE(IconAnimationInvariant(tab));
+ EXPECT_EQ(TabRendererData::CAPTURE_STATE_RECORDING, tab.data().capture_state);
+
data.capture_state = TabRendererData::CAPTURE_STATE_NONE;
tab.SetData(data);
EXPECT_TRUE(IconAnimationInvariant(tab));
EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state);
-
- data.audio_state = TabRendererData::AUDIO_STATE_NONE;
- tab.SetData(data);
- EXPECT_TRUE(IconAnimationInvariant(tab));
- EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state);
- EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state);
- EXPECT_TRUE(IconAnimationInvariant(tab));
}
diff --git a/chrome/browser/ui/views/validation_message_bubble_view.cc b/chrome/browser/ui/views/validation_message_bubble_view.cc
index bb3262e..4d4a0da 100644
--- a/chrome/browser/ui/views/validation_message_bubble_view.cc
+++ b/chrome/browser/ui/views/validation_message_bubble_view.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/ui/validation_message_bubble.h"
+#include "chrome/browser/platform_util.h"
#include "chrome/browser/ui/views/validation_message_bubble_delegate.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
@@ -16,7 +17,8 @@
: public chrome::ValidationMessageBubble,
public ValidationMessageBubbleDelegate::Observer {
public:
- ValidationMessageBubbleImpl(const gfx::Rect& anchor_in_screen,
+ ValidationMessageBubbleImpl(content::RenderWidgetHost* widget_host,
+ const gfx::Rect& anchor_in_screen,
const string16& main_text,
const string16& sub_text);
@@ -46,11 +48,14 @@
};
ValidationMessageBubbleImpl::ValidationMessageBubbleImpl(
+ content::RenderWidgetHost* widget_host,
const gfx::Rect& anchor_in_screen,
const string16& main_text,
const string16& sub_text) {
delegate_ = new ValidationMessageBubbleDelegate(
anchor_in_screen, main_text, sub_text, this);
+ delegate_->set_parent_window(platform_util::GetTopLevel(
+ widget_host->GetView()->GetNativeView()));
views::BubbleDelegateView::CreateBubble(delegate_);
delegate_->GetWidget()->ShowInactive();
}
@@ -66,8 +71,8 @@
const string16& sub_text) {
const gfx::Rect anchor_in_screen = anchor_in_root_view
+ widget_host->GetView()->GetViewBounds().origin().OffsetFromOrigin();
- scoped_ptr<ValidationMessageBubble> bubble(
- new ValidationMessageBubbleImpl(anchor_in_screen, main_text, sub_text));
+ scoped_ptr<ValidationMessageBubble> bubble(new ValidationMessageBubbleImpl(
+ widget_host, anchor_in_screen, main_text, sub_text));
return bubble.Pass();
}
diff --git a/chrome/browser/ui/views/wrench_menu.cc b/chrome/browser/ui/views/wrench_menu.cc
index f8f8c54..79eaf78 100644
--- a/chrome/browser/ui/views/wrench_menu.cc
+++ b/chrome/browser/ui/views/wrench_menu.cc
@@ -13,6 +13,7 @@
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/search.h"
@@ -1264,8 +1265,10 @@
browser_,
parent,
first_bookmark_command_id_));
- bookmark_menu_delegate_->Init(
- this, bookmark_menu_, model->bookmark_bar_node(), 0,
- BookmarkMenuDelegate::SHOW_PERMANENT_FOLDERS,
- bookmark_utils::LAUNCH_WRENCH_MENU);
+ bookmark_menu_delegate_->Init(this,
+ bookmark_menu_,
+ model->bookmark_bar_node(),
+ 0,
+ BookmarkMenuDelegate::SHOW_PERMANENT_FOLDERS,
+ BOOKMARK_LAUNCH_LOCATION_WRENCH_MENU);
}
diff --git a/chrome/browser/ui/web_applications/web_app_ui.cc b/chrome/browser/ui/web_applications/web_app_ui.cc
index 4834b3f..2e7b6c4 100644
--- a/chrome/browser/ui/web_applications/web_app_ui.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui.cc
@@ -364,7 +364,7 @@
// the icons, hackily put into a single ImageSkia. Separate them out into
// individual ImageSkias and insert them into the icon family.
const gfx::ImageSkia& multires_image_skia = image.AsImageSkia();
- // NOTE: We do not call ImageSkia::EnsureRepsForSupportedScaleFactors here.
+ // NOTE: We do not call ImageSkia::EnsureRepsForSupportedScales here.
// The image reps here are not really for different scale factors (ImageSkia
// is just being used as a handy container for multiple images).
std::vector<gfx::ImageSkiaRep> image_reps =
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc
index cd9f7cf..9704386 100644
--- a/chrome/browser/ui/webui/about_ui.cc
+++ b/chrome/browser/ui/webui/about_ui.cc
@@ -95,8 +95,11 @@
const char kMemoryCssPath[] = "about_memory.css";
const char kStatsJsPath[] = "stats.js";
const char kStringsJsPath[] = "strings.js";
+
+#if defined(OS_CHROMEOS)
// chrome://terms falls back to offline page after kOnlineTermsTimeoutSec.
const int kOnlineTermsTimeoutSec = 7;
+#endif // defined(OS_CHROMEOS)
// When you type about:memory, it actually loads this intermediate URL that
// redirects you to the final page. This avoids the problem where typing
diff --git a/chrome/browser/ui/webui/app_launcher_page_ui.cc b/chrome/browser/ui/webui/app_launcher_page_ui.cc
index c1fb8ae..e83c8af 100644
--- a/chrome/browser/ui/webui/app_launcher_page_ui.cc
+++ b/chrome/browser/ui/webui/app_launcher_page_ui.cc
@@ -30,12 +30,6 @@
using content::BrowserThread;
-namespace {
-
-const char kUmaPaintTimesLabel[] = "AppLauncherPageUI load";
-
-} // namespace
-
///////////////////////////////////////////////////////////////////////////////
// AppLauncherPageUI
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 e7257aa..4003e73 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -548,7 +548,7 @@
// Assume that |bitmap| is |gfx::kFaviconSize| x |gfx::kFaviconSize|
// DIP.
- float scale = ui::GetScaleFactorScale(scale_factors[i]);
+ float scale = ui::GetImageScale(scale_factors[i]);
int edge_pixel_size =
static_cast<int>(gfx::kFaviconSize * scale + 0.5f);
bitmap_result.pixel_size = gfx::Size(edge_pixel_size, edge_pixel_size);
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 589564b..70536f7 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -146,8 +146,6 @@
if (browsing_data_remover_ || refresh_token_revoker_ || access_token_revoker_)
return;
- auth_reset_callbacks_.push_back(callback);
-
if (oauth_fetcher_) {
if (!oauth_fetcher_->oauth2_access_token().empty()) {
access_token_revoker_.reset(new TokenRevoker(this));
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 8541188..da1c73d 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
@@ -16,6 +16,7 @@
#include "google_apis/gaia/gaia_auth_util.h"
#include "grit/generated_resources.h"
#include "net/base/data_url.h"
+#include "net/base/escape.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
@@ -37,7 +38,10 @@
}
LocallyManagedUserCreationScreenHandler::
- ~LocallyManagedUserCreationScreenHandler() {}
+ ~LocallyManagedUserCreationScreenHandler() {
+ if (delegate_)
+ delegate_->OnActorDestroyed(this);
+}
void LocallyManagedUserCreationScreenHandler::DeclareLocalizedValues(
LocalizedValuesBuilder* builder) {
@@ -244,6 +248,10 @@
CallJS("managedUserNameError", name,
l10n_util::GetStringUTF16(
IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_USERNAME_ALREADY_EXISTS));
+ } else if (net::EscapeForHTML(name) != name) {
+ CallJS("managedUserNameError", name,
+ l10n_util::GetStringUTF16(
+ IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ILLEGAL_USERNAME));
} else {
CallJS("managedUserNameOk", name);
}
@@ -262,8 +270,13 @@
new_user_name));
return;
}
+ if (net::EscapeForHTML(new_user_name) != new_user_name) {
+ CallJS("managedUserNameError", new_user_name,
+ l10n_util::GetStringUTF16(
+ IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ILLEGAL_USERNAME));
+ return;
+ }
- // TODO(antrim): Any other password checks here?
if (new_user_password.length() == 0) {
CallJS("showPasswordError",
l10n_util::GetStringUTF16(
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 1ec027a..2fb77c9 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
@@ -25,9 +25,6 @@
public:
virtual ~Delegate() {}
- // Called when screen is exited.
- virtual void OnExit() = 0;
-
// This method is called, when actor is being destroyed. Note, if Delegate
// is destroyed earlier then it has to call SetDelegate(NULL).
virtual void OnActorDestroyed(
diff --git a/chrome/browser/ui/webui/chromeos/login/network_dropdown.cc b/chrome/browser/ui/webui/chromeos/login/network_dropdown.cc
index 57af9b5..b220e31 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_dropdown.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_dropdown.cc
@@ -90,7 +90,8 @@
gfx::Image icon;
if (model->GetIconAt(i, &icon)) {
SkBitmap icon_bitmap = icon.ToImageSkia()->GetRepresentation(
- web_ui_->GetDeviceScaleFactor()).sk_bitmap();
+ ui::GetImageScale(
+ web_ui_->GetDeviceScaleFactor())).sk_bitmap();
item->SetString("icon", webui::GetBitmapDataUrl(icon_bitmap));
}
if (id >= 0) {
@@ -192,7 +193,7 @@
RemoveObserver(this);
}
SkBitmap icon_bitmap = icon_image.GetRepresentation(
- web_ui_->GetDeviceScaleFactor()).sk_bitmap();
+ ui::GetImageScale(web_ui_->GetDeviceScaleFactor())).sk_bitmap();
std::string icon_str;
if (!icon_image.isNull())
icon_str = webui::GetBitmapDataUrl(icon_bitmap);
diff --git a/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc b/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
index a88afa7..3f42982 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
@@ -146,7 +146,7 @@
if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE ||
(status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
!IsProxyConfigured(network) &&
- network->connection_state() == flimflam::kStateOnline)) {
+ network->connection_state() == shill::kStateOnline)) {
return ONLINE;
}
if (status ==
@@ -156,14 +156,14 @@
}
if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL ||
(status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
- network->connection_state() == flimflam::kStatePortal))
+ network->connection_state() == shill::kStatePortal))
return CAPTIVE_PORTAL;
} else {
if (NetworkState::StateIsConnecting(network->connection_state()))
return CONNECTING;
- if (network->connection_state() == flimflam::kStateOnline)
+ if (network->connection_state() == shill::kStateOnline)
return ONLINE;
- if (network->connection_state() == flimflam::kStatePortal)
+ if (network->connection_state() == shill::kStatePortal)
return CAPTIVE_PORTAL;
}
return OFFLINE;
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 56614f2..c927742 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -252,12 +252,12 @@
void RecordDiscrepancyWithShill(
const NetworkState* network,
const NetworkPortalDetector::CaptivePortalStatus status) {
- if (network->connection_state() == flimflam::kStateOnline) {
+ if (network->connection_state() == shill::kStateOnline) {
UMA_HISTOGRAM_ENUMERATION(
"CaptivePortal.OOBE.DiscrepancyWithShill_Online",
status,
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
- } else if (network->connection_state() == flimflam::kStatePortal) {
+ } else if (network->connection_state() == shill::kStatePortal) {
UMA_HISTOGRAM_ENUMERATION(
"CaptivePortal.OOBE.DiscrepancyWithShill_RestrictedPool",
status,
@@ -292,20 +292,20 @@
NOTREACHED();
break;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
- if (network->connection_state() == flimflam::kStateOnline ||
- network->connection_state() == flimflam::kStatePortal)
+ if (network->connection_state() == shill::kStateOnline ||
+ network->connection_state() == shill::kStatePortal)
RecordDiscrepancyWithShill(network, state.status);
break;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
- if (network->connection_state() != flimflam::kStateOnline)
+ if (network->connection_state() != shill::kStateOnline)
RecordDiscrepancyWithShill(network, state.status);
break;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
- if (network->connection_state() != flimflam::kStatePortal)
+ if (network->connection_state() != shill::kStatePortal)
RecordDiscrepancyWithShill(network, state.status);
break;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
- if (network->connection_state() != flimflam::kStateOnline)
+ if (network->connection_state() != shill::kStateOnline)
RecordDiscrepancyWithShill(network, state.status);
break;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
@@ -403,8 +403,14 @@
DCHECK(error_screen_actor_);
DCHECK(core_oobe_actor_);
network_state_informer_->AddObserver(this);
- CrosSettings::Get()->AddSettingsObserver(kAccountsPrefAllowNewUser, this);
- CrosSettings::Get()->AddSettingsObserver(kAccountsPrefAllowGuest, this);
+ allow_new_user_subscription_ = CrosSettings::Get()->AddSettingsObserver(
+ kAccountsPrefAllowNewUser,
+ base::Bind(&SigninScreenHandler::UserSettingsChanged,
+ base::Unretained(this)));
+ allow_guest_subscription_ = CrosSettings::Get()->AddSettingsObserver(
+ kAccountsPrefAllowGuest,
+ base::Bind(&SigninScreenHandler::UserSettingsChanged,
+ base::Unretained(this)));
registrar_.Add(this,
chrome::NOTIFICATION_AUTH_NEEDED,
@@ -426,8 +432,6 @@
if (delegate_)
delegate_->SetWebUIHandler(NULL);
network_state_informer_->RemoveObserver(this);
- CrosSettings::Get()->RemoveSettingsObserver(kAccountsPrefAllowNewUser, this);
- CrosSettings::Get()->RemoveSettingsObserver(kAccountsPrefAllowGuest, this);
}
void SigninScreenHandler::DeclareLocalizedValues(
@@ -993,11 +997,6 @@
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
- case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED: {
- UpdateAuthExtension();
- UpdateAddButtonStatus();
- break;
- }
case chrome::NOTIFICATION_AUTH_NEEDED: {
has_pending_auth_ui_ = true;
break;
@@ -1181,6 +1180,11 @@
CallJS("login.GaiaSigninScreen.loadAuthExtension", params);
}
+void SigninScreenHandler::UserSettingsChanged() {
+ UpdateAuthExtension();
+ UpdateAddButtonStatus();
+}
+
void SigninScreenHandler::UpdateAuthExtension() {
DictionaryValue params;
UpdateAuthParams(¶ms);
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 df9bf26..6f977d1 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -11,12 +11,14 @@
#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/login/help_app_launcher.h"
#include "chrome/browser/chromeos/login/login_display.h"
#include "chrome/browser/chromeos/login/screens/error_screen_actor.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/net/network_portal_detector.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/system_key_event_listener.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
@@ -278,6 +280,7 @@
// Updates authentication extension. Called when device settings that affect
// sign-in (allow BWSI and allow whitelist) are changed.
+ void UserSettingsChanged();
void UpdateAuthExtension();
void UpdateAddButtonStatus();
@@ -468,6 +471,9 @@
// NOTIFICATION_AUTH_CANCELLED.
bool has_pending_auth_ui_;
+ scoped_ptr<CrosSettings::ObserverSubscription> allow_new_user_subscription_;
+ scoped_ptr<CrosSettings::ObserverSubscription> allow_guest_subscription_;
+
DISALLOW_COPY_AND_ASSIGN(SigninScreenHandler);
};
diff --git a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
index 75b3152..5e47756 100644
--- a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
@@ -93,6 +93,7 @@
IDS_OPTIONS_PHOTO_CAPTURE_ACCESSIBLE_TEXT);
builder->Add("photoDiscardAccessibleText",
IDS_OPTIONS_PHOTO_DISCARD_ACCESSIBLE_TEXT);
+ builder->Add("syncingPreferences", IDS_IMAGE_SCREEN_SYNCING_PREFERENCES);
}
void UserImageScreenHandler::RegisterMessages() {
diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
index 6dd9c65..a081821 100644
--- a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
@@ -88,8 +88,7 @@
// Converts the network properties into a JS object.
void GetDeviceInfo(const DictionaryValue& properties, DictionaryValue* value) {
std::string name;
- properties.GetStringWithoutPathExpansion(
- flimflam::kNameProperty, &name);
+ properties.GetStringWithoutPathExpansion(shill::kNameProperty, &name);
bool activate_over_non_cellular_networks = false;
properties.GetBooleanWithoutPathExpansion(
shill::kActivateOverNonCellularNetworkProperty,
@@ -97,13 +96,13 @@
const DictionaryValue* payment_dict;
std::string payment_url, post_method, post_data;
if (properties.GetDictionaryWithoutPathExpansion(
- flimflam::kPaymentPortalProperty, &payment_dict)) {
+ shill::kPaymentPortalProperty, &payment_dict)) {
payment_dict->GetStringWithoutPathExpansion(
- flimflam::kPaymentPortalURL, &payment_url);
+ shill::kPaymentPortalURL, &payment_url);
payment_dict->GetStringWithoutPathExpansion(
- flimflam::kPaymentPortalMethod, &post_method);
+ shill::kPaymentPortalMethod, &post_method);
payment_dict->GetStringWithoutPathExpansion(
- flimflam::kPaymentPortalPostData, &post_data);
+ shill::kPaymentPortalPostData, &post_data);
}
value->SetBoolean("activate_over_non_cellular_network",
@@ -116,7 +115,7 @@
// Use the cached DeviceState properties.
std::string device_path;
if (!properties.GetStringWithoutPathExpansion(
- flimflam::kDeviceProperty, &device_path) ||
+ shill::kDeviceProperty, &device_path) ||
device_path.empty()) {
return;
}
@@ -329,21 +328,21 @@
const DictionaryValue* payment_dict;
std::string name, usage_url, activation_state, payment_url;
if (!properties.GetStringWithoutPathExpansion(
- flimflam::kNameProperty, &name) ||
+ shill::kNameProperty, &name) ||
!properties.GetStringWithoutPathExpansion(
- flimflam::kUsageURLProperty, &usage_url) ||
+ shill::kUsageURLProperty, &usage_url) ||
!properties.GetStringWithoutPathExpansion(
- flimflam::kActivationStateProperty, &activation_state) ||
+ shill::kActivationStateProperty, &activation_state) ||
!properties.GetDictionaryWithoutPathExpansion(
- flimflam::kPaymentPortalProperty, &payment_dict) ||
+ shill::kPaymentPortalProperty, &payment_dict) ||
!payment_dict->GetStringWithoutPathExpansion(
- flimflam::kPaymentPortalURL, &payment_url)) {
+ shill::kPaymentPortalURL, &payment_url)) {
DataRequestFailed(service_path, callback);
return;
}
if (payment_url.empty() && usage_url.empty() &&
- activation_state != flimflam::kActivationStateActivated) {
+ activation_state != shill::kActivationStateActivated) {
DataRequestFailed(service_path, callback);
return;
}
@@ -381,7 +380,7 @@
// network is activated, the webui goes straight to portal. Otherwise the
// webui is used for activation flow.
std::string full_html;
- if (activation_state == flimflam::kActivationStateActivated) {
+ if (activation_state == shill::kActivationStateActivated) {
static const base::StringPiece html_for_activated(
ResourceBundle::GetSharedInstance().GetRawDataResource(
IDR_MOBILE_SETUP_PORTAL_PAGE_HTML));
@@ -547,9 +546,8 @@
// network changes, but only for LTE networks. The other networks should
// ignore network status.
if (type_ == TYPE_UNDETERMINED) {
- if (network->network_technology() == flimflam::kNetworkTechnologyLte ||
- network->network_technology() ==
- flimflam::kNetworkTechnologyLteAdvanced) {
+ if (network->network_technology() == shill::kNetworkTechnologyLte ||
+ network->network_technology() == shill::kNetworkTechnologyLteAdvanced) {
type_ = TYPE_PORTAL_LTE;
nsh->AddObserver(this, FROM_HERE);
// Update the network status and notify the webui. This is the initial
@@ -639,7 +637,7 @@
bool portal_reachable =
(network->IsConnectedState() ||
(nsh->DefaultNetwork() &&
- nsh->DefaultNetwork()->connection_state() == flimflam::kStateOnline));
+ nsh->DefaultNetwork()->connection_state() == shill::kStateOnline));
if (force_notification || portal_reachable != lte_portal_reachable_) {
web_ui()->CallJavascriptFunction(kJsConnectivityChangedCallback,
diff --git a/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc b/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc
index 835d502..2354816 100644
--- a/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc
@@ -732,9 +732,9 @@
<< " retries: " << retries_left;
switch (state_) {
case SIM_UNLOCK_LOADING:
- if (sim_lock_type_ == flimflam::kSIMLockPin) {
+ if (sim_lock_type_ == shill::kSIMLockPin) {
state_ = SIM_LOCKED_PIN;
- } else if (sim_lock_type_ == flimflam::kSIMLockPuk) {
+ } else if (sim_lock_type_ == shill::kSIMLockPuk) {
if (retries_left > 0)
state_ = SIM_LOCKED_PUK;
else
@@ -765,7 +765,7 @@
// that means entered PIN was incorrect.
if (sim_lock_type_.empty()) {
error_msg = kErrorPin;
- } else if (sim_lock_type_ == flimflam::kSIMLockPuk) {
+ } else if (sim_lock_type_ == shill::kSIMLockPuk) {
state_ = SIM_LOCKED_NO_PIN_TRIES_LEFT;
} else {
NOTREACHED()
@@ -774,9 +774,9 @@
}
break;
case SIM_LOCKED_PIN:
- if (sim_lock_type_ == flimflam::kSIMLockPuk) {
+ if (sim_lock_type_ == shill::kSIMLockPuk) {
state_ = SIM_LOCKED_NO_PIN_TRIES_LEFT;
- } else if (sim_lock_type_ == flimflam::kSIMLockPin) {
+ } else if (sim_lock_type_ == shill::kSIMLockPin) {
// Still locked with PIN.
error_msg = kErrorPin;
} else {
@@ -788,8 +788,8 @@
state_ = SIM_LOCKED_PUK;
break;
case SIM_LOCKED_PUK:
- if (sim_lock_type_ != flimflam::kSIMLockPin &&
- sim_lock_type_ != flimflam::kSIMLockPuk) {
+ if (sim_lock_type_ != shill::kSIMLockPin &&
+ sim_lock_type_ != shill::kSIMLockPuk) {
state_ = SIM_ABSENT_NOT_LOCKED;
} else if (retries_left == 0) {
state_ = SIM_LOCKED_NO_PUK_TRIES_LEFT;
diff --git a/chrome/browser/ui/webui/chromeos/system_info_ui.cc b/chrome/browser/ui/webui/chromeos/system_info_ui.cc
index 3040b9d..45a41a0 100644
--- a/chrome/browser/ui/webui/chromeos/system_info_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/system_info_ui.cc
@@ -127,16 +127,21 @@
strings.SetString("title", l10n_util::GetStringUTF16(IDS_ABOUT_SYS_TITLE));
strings.SetString("description",
l10n_util::GetStringUTF16(IDS_ABOUT_SYS_DESC));
- strings.SetString("table_title",
+ strings.SetString("tableTitle",
l10n_util::GetStringUTF16(IDS_ABOUT_SYS_TABLE_TITLE));
- strings.SetString("expand_all_btn",
+ strings.SetString(
+ "logFileTableTitle",
+ l10n_util::GetStringUTF16(IDS_ABOUT_SYS_LOG_FILE_TABLE_TITLE));
+ strings.SetString("expandAllBtn",
l10n_util::GetStringUTF16(IDS_ABOUT_SYS_EXPAND_ALL));
- strings.SetString("collapse_all_btn",
+ strings.SetString("collapseAllBtn",
l10n_util::GetStringUTF16(IDS_ABOUT_SYS_COLLAPSE_ALL));
- strings.SetString("expand_btn",
+ strings.SetString("expandBtn",
l10n_util::GetStringUTF16(IDS_ABOUT_SYS_EXPAND));
- strings.SetString("collapse_btn",
+ strings.SetString("collapseBtn",
l10n_util::GetStringUTF16(IDS_ABOUT_SYS_COLLAPSE));
+ strings.SetString("parseError",
+ l10n_util::GetStringUTF16(IDS_ABOUT_SYS_PARSE_ERROR));
webui::SetFontAndTextDirection(&strings);
if (response_.get()) {
ListValue* details = new ListValue();
@@ -145,11 +150,10 @@
it != response_->end();
++it) {
DictionaryValue* val = new DictionaryValue;
- val->SetString("stat_name", it->first);
- val->SetString("stat_value", it->second);
+ val->SetString("statName", it->first);
+ val->SetString("statValue", it->second);
details->Append(val);
}
- strings.SetString("anchor", path_);
}
static const base::StringPiece systeminfo_html(
ResourceBundle::GetSharedInstance().GetRawDataResource(
diff --git a/chrome/browser/ui/webui/cookies_tree_model_util.cc b/chrome/browser/ui/webui/cookies_tree_model_util.cc
index bb1ac1a..520e799 100644
--- a/chrome/browser/ui/webui/cookies_tree_model_util.cc
+++ b/chrome/browser/ui/webui/cookies_tree_model_util.cc
@@ -54,7 +54,6 @@
const char kKeyTotalUsage[] = "totalUsage";
const char kKeyTemporaryUsage[] = "temporaryUsage";
const char kKeyPersistentUsage[] = "persistentUsage";
-const char kKeyPersistentQuota[] = "persistentQuota";
const char kKeyCertType[] = "certType";
diff --git a/chrome/browser/ui/webui/extensions/extension_basic_info.cc b/chrome/browser/ui/webui/extensions/extension_basic_info.cc
index 606ee2b..0e6b3e5 100644
--- a/chrome/browser/ui/webui/extensions/extension_basic_info.cc
+++ b/chrome/browser/ui/webui/extensions/extension_basic_info.cc
@@ -6,7 +6,7 @@
#include "base/values.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h"
+#include "chrome/common/extensions/manifest_handlers/kiosk_mode_info.h"
#include "chrome/common/extensions/manifest_handlers/offline_enabled_info.h"
#include "chrome/common/extensions/manifest_url_handler.h"
@@ -19,6 +19,7 @@
const char kIdKey[] = "id";
const char kNameKey[] = "name";
const char kKioskEnabledKey[] = "kioskEnabled";
+const char kKioskOnlyKey[] = "kioskOnly";
const char kOfflineEnabledKey[] = "offlineEnabled";
const char kOptionsUrlKey[] = "optionsUrl";
const char kDetailsUrlKey[] = "detailsUrl";
@@ -36,7 +37,9 @@
info->SetString(kNameKey, extension->name());
info->SetBoolean(kEnabledKey, enabled);
info->SetBoolean(kKioskEnabledKey,
- KioskEnabledInfo::IsKioskEnabled(extension));
+ KioskModeInfo::IsKioskEnabled(extension));
+ info->SetBoolean(kKioskOnlyKey,
+ KioskModeInfo::IsKioskOnly(extension));
info->SetBoolean(kOfflineEnabledKey,
OfflineEnabledInfo::IsOfflineEnabled(extension));
info->SetString(kVersionKey, extension->VersionString());
diff --git a/chrome/browser/ui/webui/extensions/extension_error_handler.cc b/chrome/browser/ui/webui/extensions/extension_error_handler.cc
index f89feb4..c537365 100644
--- a/chrome/browser/ui/webui/extensions/extension_error_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_error_handler.cc
@@ -26,17 +26,10 @@
namespace extensions {
-namespace {
-
// Keys for objects passed to and from extension error UI.
-const char kFileTypeKey[] = "fileType";
-const char kManifestFileType[] = "manifest";
const char kPathSuffixKey[] = "pathSuffix";
-const char kSourceFileType[] = "source";
const char kTitleKey[] = "title";
-} // namespace
-
ExtensionErrorHandler::ExtensionErrorHandler(Profile* profile)
: profile_(profile) {
}
diff --git a/chrome/browser/ui/webui/fileicon_source.cc b/chrome/browser/ui/webui/fileicon_source.cc
index ee0cb11..1705c41 100644
--- a/chrome/browser/ui/webui/fileicon_source.cc
+++ b/chrome/browser/ui/webui/fileicon_source.cc
@@ -103,7 +103,8 @@
if (icon) {
scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
gfx::PNGCodec::EncodeBGRASkBitmap(
- icon->ToImageSkia()->GetRepresentation(scale_factor).sk_bitmap(),
+ icon->ToImageSkia()->GetRepresentation(
+ ui::GetImageScale(scale_factor)).sk_bitmap(),
false, &icon_data->data());
callback.Run(icon_data.get());
@@ -150,8 +151,8 @@
if (icon) {
scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
gfx::PNGCodec::EncodeBGRASkBitmap(
- icon->ToImageSkia()->GetRepresentation(details.scale_factor)
- .sk_bitmap(),
+ icon->ToImageSkia()->GetRepresentation(
+ ui::GetImageScale(details.scale_factor)).sk_bitmap(),
false,
&icon_data->data());
diff --git a/chrome/browser/ui/webui/help/help_utils_chromeos.cc b/chrome/browser/ui/webui/help/help_utils_chromeos.cc
index 376fecd..a986a97 100644
--- a/chrome/browser/ui/webui/help/help_utils_chromeos.cc
+++ b/chrome/browser/ui/webui/help/help_utils_chromeos.cc
@@ -50,15 +50,15 @@
string16 GetConnectionTypeAsUTF16(const std::string& type) {
if (chromeos::NetworkTypePattern::Ethernet().MatchesType(type))
return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_ETHERNET);
- if (type == flimflam::kTypeWifi)
+ if (type == shill::kTypeWifi)
return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_WIFI);
- if (type == flimflam::kTypeWimax)
+ if (type == shill::kTypeWimax)
return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_WIMAX);
- if (type == flimflam::kTypeBluetooth)
+ if (type == shill::kTypeBluetooth)
return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_BLUETOOTH);
- if (type == flimflam::kTypeCellular)
+ if (type == shill::kTypeCellular)
return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_CELLULAR);
- if (type == flimflam::kTypeVPN)
+ if (type == shill::kTypeVPN)
return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_VPN);
NOTREACHED();
return string16();
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
index cf4c1cb..d27c304 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -52,9 +52,9 @@
// The connection type checking strategy must be the same as the one
// used in update engine.
- if (network->type() == flimflam::kTypeBluetooth)
+ if (network->type() == shill::kTypeBluetooth)
return NETWORK_STATUS_DISALLOWED;
- if (network->type() == flimflam::kTypeCellular &&
+ if (network->type() == shill::kTypeCellular &&
!help_utils_chromeos::IsUpdateOverCellularAllowed()) {
return NETWORK_STATUS_DISALLOWED;
}
diff --git a/chrome/browser/ui/webui/history_ui.cc b/chrome/browser/ui/webui/history_ui.cc
index 99c82d0..2dcaf3f 100644
--- a/chrome/browser/ui/webui/history_ui.cc
+++ b/chrome/browser/ui/webui/history_ui.cc
@@ -624,6 +624,7 @@
base::Unretained(this)));
}
+#if defined(ENABLE_EXTENSIONS)
// If the profile has activity logging enabled also clean up any URLs from
// the extension activity log. The extension activity log contains URLS
// which websites an extension has activity on so it will indirectly
@@ -634,6 +635,7 @@
expire_list.begin(); it != expire_list.end(); ++it) {
activity_log->RemoveURLs(it->urls);
}
+#endif
}
void BrowsingHistoryHandler::HandleClearBrowsingData(const ListValue* args) {
diff --git a/chrome/browser/ui/webui/inspect_ui.cc b/chrome/browser/ui/webui/inspect_ui.cc
index 4461ddb..4a5db1c 100644
--- a/chrome/browser/ui/webui/inspect_ui.cc
+++ b/chrome/browser/ui/webui/inspect_ui.cc
@@ -65,50 +65,47 @@
namespace {
-static const char kDataFile[] = "targets-data.json";
-static const char kAdbPages[] = "adb-pages";
+const char kAppTargetType[] = "app";
+const char kExtensionTargetType[] = "extension";
+const char kPageTargetType[] = "page";
+const char kWorkerTargetType[] = "worker";
+const char kAdbTargetType[] = "adb_page";
-static const char kAppTargetType[] = "app";
-static const char kExtensionTargetType[] = "extension";
-static const char kPageTargetType[] = "page";
-static const char kWorkerTargetType[] = "worker";
-static const char kAdbTargetType[] = "adb_page";
+const char kInitUICommand[] = "init-ui";
+const char kInspectCommand[] = "inspect";
+const char kActivateCommand[] = "activate";
+const char kTerminateCommand[] = "terminate";
+const char kReloadCommand[] = "reload";
+const char kOpenCommand[] = "open";
-static const char kInitUICommand[] = "init-ui";
-static const char kInspectCommand[] = "inspect";
-static const char kActivateCommand[] = "activate";
-static const char kTerminateCommand[] = "terminate";
-static const char kReloadCommand[] = "reload";
-static const char kOpenCommand[] = "open";
-
-static const char kPortForwardingEnabledCommand[] =
+const char kPortForwardingEnabledCommand[] =
"set-port-forwarding-enabled";
-static const char kPortForwardingConfigCommand[] = "set-port-forwarding-config";
+const char kPortForwardingConfigCommand[] = "set-port-forwarding-config";
-static const char kPortForwardingDefaultPort[] = "8080";
-static const char kPortForwardingDefaultLocation[] = "localhost:8080";
+const char kPortForwardingDefaultPort[] = "8080";
+const char kPortForwardingDefaultLocation[] = "localhost:8080";
-static const char kTargetTypeField[] = "type";
-static const char kAttachedField[] = "attached";
-static const char kProcessIdField[] = "processId";
-static const char kRouteIdField[] = "routeId";
-static const char kUrlField[] = "url";
-static const char kNameField[] = "name";
-static const char kFaviconUrlField[] = "faviconUrl";
-static const char kDescription[] = "description";
-static const char kPidField[] = "pid";
-static const char kAdbSerialField[] = "adbSerial";
-static const char kAdbModelField[] = "adbModel";
-static const char kAdbBrowserProductField[] = "adbBrowserProduct";
-static const char kAdbBrowserPackageField[] = "adbBrowserPackage";
-static const char kAdbBrowserVersionField[] = "adbBrowserVersion";
-static const char kAdbGlobalIdField[] = "adbGlobalId";
-static const char kAdbBrowsersField[] = "browsers";
-static const char kAdbPagesField[] = "pages";
-static const char kAdbPortStatus[] = "adbPortStatus";
-static const char kAdbScreenWidthField[] = "adbScreenWidth";
-static const char kAdbScreenHeightField[] = "adbScreenHeight";
-static const char kGuestList[] = "guests";
+const char kTargetTypeField[] = "type";
+const char kAttachedField[] = "attached";
+const char kProcessIdField[] = "processId";
+const char kRouteIdField[] = "routeId";
+const char kUrlField[] = "url";
+const char kNameField[] = "name";
+const char kFaviconUrlField[] = "faviconUrl";
+const char kDescription[] = "description";
+const char kPidField[] = "pid";
+const char kAdbSerialField[] = "adbSerial";
+const char kAdbModelField[] = "adbModel";
+const char kAdbBrowserProductField[] = "adbBrowserProduct";
+const char kAdbBrowserPackageField[] = "adbBrowserPackage";
+const char kAdbBrowserVersionField[] = "adbBrowserVersion";
+const char kAdbGlobalIdField[] = "adbGlobalId";
+const char kAdbBrowsersField[] = "browsers";
+const char kAdbPagesField[] = "pages";
+const char kAdbPortStatus[] = "adbPortStatus";
+const char kAdbScreenWidthField[] = "adbScreenWidth";
+const char kAdbScreenHeightField[] = "adbScreenHeight";
+const char kGuestList[] = "guests";
DictionaryValue* BuildTargetDescriptor(
const std::string& target_type,
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui.cc
index 9a98758..819ec7f 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui.cc
@@ -7,6 +7,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h"
#include "chrome/browser/ui/webui/metrics_handler.h"
+#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
@@ -71,6 +72,25 @@
IDS_LOCAL_DISCOVERY_CLOUD_DEVICES_LOGIN);
source->AddLocalizedString("registerNeedLogin",
IDS_LOCAL_DISCOVERY_REGISTER_NEED_LOGIN);
+ source->AddLocalizedString("availableDevicesTitle",
+ IDS_LOCAL_DISCOVERY_AVAILABLE_DEVICES);
+ source->AddLocalizedString("myDevicesTitle",
+ IDS_LOCAL_DISCOVERY_MY_DEVICES);
+
+
+ // Cloud print connector-related strings.
+#if defined(ENABLE_FULL_PRINTING) && !defined(OS_CHROMEOS)
+ source->AddLocalizedString("cloudPrintConnectorEnablingButton",
+ IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_ENABLING_BUTTON);
+ source->AddLocalizedString("cloudPrintConnectorDisabledButton",
+ IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_DISABLED_BUTTON);
+ source->AddLocalizedString("cloudPrintConnectorEnabledButton",
+ IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_ENABLED_BUTTON);
+ source->AddLocalizedString("cloudPrintName",
+ IDS_GOOGLE_CLOUD_PRINT);
+ source->AddLocalizedString("titleConnector",
+ IDS_LOCAL_DISCOVERY_CONNECTOR_SECTION);
+#endif
source->SetJsonPath("strings.js");
@@ -92,3 +112,15 @@
web_ui->AddMessageHandler(local_discovery::LocalDiscoveryUIHandler::Create());
web_ui->AddMessageHandler(new MetricsHandler());
}
+
+void LocalDiscoveryUI::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterBooleanPref(
+ prefs::kLocalDiscoveryNotificationsEnabled,
+#if defined(OS_WIN)
+ false,
+#else
+ true,
+#endif
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+}
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui.h b/chrome/browser/ui/webui/local_discovery/local_discovery_ui.h
index 692ab52..d2619df 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui.h
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui.h
@@ -5,12 +5,14 @@
#ifndef CHROME_BROWSER_UI_WEBUI_LOCAL_DISCOVERY_LOCAL_DISCOVERY_UI_H_
#define CHROME_BROWSER_UI_WEBUI_LOCAL_DISCOVERY_LOCAL_DISCOVERY_UI_H_
+#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/web_ui_controller.h"
class LocalDiscoveryUI : public content::WebUIController {
public:
explicit LocalDiscoveryUI(content::WebUI* web_ui);
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
private:
DISALLOW_COPY_AND_ASSIGN(LocalDiscoveryUI);
};
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
index f31e105..d5fa32b 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
@@ -7,17 +7,21 @@
#include <set>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
+#include "base/prefs/pref_service.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/local_discovery/cloud_print_account_manager.h"
#include "chrome/browser/local_discovery/privet_confirm_api_flow.h"
#include "chrome/browser/local_discovery/privet_constants.h"
#include "chrome/browser/local_discovery/privet_device_lister_impl.h"
#include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h"
-#include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h"
#include "chrome/browser/local_discovery/privet_http_impl.h"
-#include "chrome/browser/local_discovery/service_discovery_host_client.h"
+#include "chrome/browser/local_discovery/service_discovery_shared_client.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_url.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_oauth2_token_service.h"
@@ -28,12 +32,22 @@
#include "chrome/browser/signin/signin_promo.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/user_metrics.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/page_transition_types.h"
+#include "grit/generated_resources.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_util.h"
#include "net/http/http_status_code.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if defined(ENABLE_FULL_PRINTING) && !defined(OS_CHROMEOS) && \
+ !defined(OS_MACOSX)
+#define CLOUD_PRINT_CONNECTOR_UI_AVAILABLE
+#endif
namespace local_discovery {
@@ -47,6 +61,20 @@
} // namespace
LocalDiscoveryUIHandler::LocalDiscoveryUIHandler() : is_visible_(false) {
+#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
+#if !defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN)
+ // On Windows, we need the PDF plugin which is only guaranteed to exist on
+ // Google Chrome builds. Use a command-line switch for Windows non-Google
+ // Chrome builds.
+ cloud_print_connector_ui_enabled_ =
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableCloudPrintProxy);
+#elif !defined(OS_CHROMEOS)
+ // Always enabled for Linux and Google Chrome Windows builds.
+ // Never enabled for Chrome OS, we don't even need to indicate it.
+ cloud_print_connector_ui_enabled_ = true;
+#endif
+#endif // !defined(OS_MACOSX)
}
LocalDiscoveryUIHandler::LocalDiscoveryUIHandler(
@@ -97,6 +125,21 @@
web_ui()->RegisterMessageCallback("showSyncUI", base::Bind(
&LocalDiscoveryUIHandler::HandleShowSyncUI,
base::Unretained(this)));
+
+ // Cloud print connector related messages
+#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
+ if (cloud_print_connector_ui_enabled_) {
+ web_ui()->RegisterMessageCallback(
+ "showCloudPrintSetupDialog",
+ base::Bind(&LocalDiscoveryUIHandler::ShowCloudPrintSetupDialog,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "disableCloudPrintConnector",
+ base::Bind(&LocalDiscoveryUIHandler::HandleDisableCloudPrintConnector,
+ base::Unretained(this)));
+ }
+#endif // defined(ENABLE_FULL_PRINTING)
+
}
void LocalDiscoveryUIHandler::HandleStart(const base::ListValue* args) {
@@ -116,6 +159,10 @@
privet_lister_->Start();
privet_lister_->DiscoverNewDevices(false);
+#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
+ StartCloudPrintConnector();
+#endif
+
CheckUserLoggedIn();
}
@@ -149,13 +196,14 @@
void LocalDiscoveryUIHandler::HandleRequestPrinterList(
const base::ListValue* args) {
Profile* profile = Profile::FromWebUI(web_ui());
- OAuth2TokenService* token_service =
+ ProfileOAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
cloud_print_printer_list_.reset(new CloudPrintPrinterList(
profile->GetRequestContext(),
GetCloudPrintBaseUrl(),
token_service,
+ token_service->GetPrimaryAccountId(),
this));
cloud_print_printer_list_->Start();
}
@@ -229,7 +277,7 @@
Profile* profile = Profile::FromWebUI(web_ui());
- OAuth2TokenService* token_service =
+ ProfileOAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
if (!token_service) {
@@ -240,6 +288,7 @@
confirm_api_call_flow_.reset(new PrivetConfirmApiCallFlow(
profile->GetRequestContext(),
token_service,
+ token_service->GetPrimaryAccountId(),
automated_claim_url,
base::Bind(&LocalDiscoveryUIHandler::OnConfirmDone,
base::Unretained(this))));
@@ -440,4 +489,107 @@
logged_in_value);
}
+#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
+void LocalDiscoveryUIHandler::StartCloudPrintConnector() {
+ Profile* profile = Profile::FromWebUI(web_ui());
+
+ base::Closure cloud_print_callback = base::Bind(
+ &LocalDiscoveryUIHandler::OnCloudPrintPrefsChanged,
+ base::Unretained(this));
+
+ if (cloud_print_connector_email_.GetPrefName().empty()) {
+ cloud_print_connector_email_.Init(
+ prefs::kCloudPrintEmail, profile->GetPrefs(), cloud_print_callback);
+ }
+
+ if (cloud_print_connector_enabled_.GetPrefName().empty()) {
+ cloud_print_connector_enabled_.Init(
+ prefs::kCloudPrintProxyEnabled, profile->GetPrefs(),
+ cloud_print_callback);
+ }
+
+ if (cloud_print_connector_ui_enabled_) {
+ SetupCloudPrintConnectorSection();
+ RefreshCloudPrintStatusFromService();
+ } else {
+ RemoveCloudPrintConnectorSection();
+ }
+}
+
+void LocalDiscoveryUIHandler::OnCloudPrintPrefsChanged() {
+ if (cloud_print_connector_ui_enabled_)
+ SetupCloudPrintConnectorSection();
+}
+
+void LocalDiscoveryUIHandler::ShowCloudPrintSetupDialog(const ListValue* args) {
+ content::RecordAction(
+ content::UserMetricsAction("Options_EnableCloudPrintProxy"));
+ // Open the connector enable page in the current tab.
+ Profile* profile = Profile::FromWebUI(web_ui());
+ content::OpenURLParams params(
+ CloudPrintURL(profile).GetCloudPrintServiceEnableURL(
+ CloudPrintProxyServiceFactory::GetForProfile(profile)->proxy_id()),
+ content::Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_LINK, false);
+ web_ui()->GetWebContents()->OpenURL(params);
+}
+
+void LocalDiscoveryUIHandler::HandleDisableCloudPrintConnector(
+ const ListValue* args) {
+ content::RecordAction(
+ content::UserMetricsAction("Options_DisableCloudPrintProxy"));
+ CloudPrintProxyServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()))->
+ DisableForUser();
+}
+
+void LocalDiscoveryUIHandler::SetupCloudPrintConnectorSection() {
+ Profile* profile = Profile::FromWebUI(web_ui());
+
+ if (!CloudPrintProxyServiceFactory::GetForProfile(profile)) {
+ cloud_print_connector_ui_enabled_ = false;
+ RemoveCloudPrintConnectorSection();
+ return;
+ }
+
+ bool cloud_print_connector_allowed =
+ !cloud_print_connector_enabled_.IsManaged() ||
+ cloud_print_connector_enabled_.GetValue();
+ base::FundamentalValue allowed(cloud_print_connector_allowed);
+
+ std::string email;
+ if (profile->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
+ cloud_print_connector_allowed) {
+ email = profile->GetPrefs()->GetString(prefs::kCloudPrintEmail);
+ }
+ base::FundamentalValue disabled(email.empty());
+
+ string16 label_str;
+ if (email.empty()) {
+ label_str = l10n_util::GetStringFUTF16(
+ IDS_LOCAL_DISCOVERY_CLOUD_PRINT_CONNECTOR_DISABLED_LABEL,
+ l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT));
+ } else {
+ label_str = l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_ENABLED_LABEL,
+ l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT),
+ UTF8ToUTF16(email));
+ }
+ StringValue label(label_str);
+
+ web_ui()->CallJavascriptFunction(
+ "local_discovery.setupCloudPrintConnectorSection", disabled, label,
+ allowed);
+}
+
+void LocalDiscoveryUIHandler::RemoveCloudPrintConnectorSection() {
+ web_ui()->CallJavascriptFunction(
+ "local_discovery.removeCloudPrintConnectorSection");
+}
+
+void LocalDiscoveryUIHandler::RefreshCloudPrintStatusFromService() {
+ if (cloud_print_connector_ui_enabled_)
+ CloudPrintProxyServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()))->
+ RefreshStatusFromService();
+}
+#endif // cloud print connector option stuff
+
} // namespace local_discovery
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
index 5505a1b..bb91a29 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
@@ -10,11 +10,17 @@
#include <vector>
#include "base/cancelable_callback.h"
+#include "base/prefs/pref_member.h"
#include "chrome/browser/local_discovery/cloud_print_printer_list.h"
#include "chrome/browser/local_discovery/privet_device_lister.h"
#include "chrome/browser/local_discovery/privet_http.h"
#include "content/public/browser/web_ui_message_handler.h"
+#if defined(ENABLE_FULL_PRINTING) && !defined(OS_CHROMEOS) && \
+ !defined(OS_MACOSX)
+#define CLOUD_PRINT_CONNECTOR_UI_AVAILABLE
+#endif
+
// TODO(noamsml): Factor out full registration flow into single class
namespace local_discovery {
@@ -144,6 +150,16 @@
void CheckUserLoggedIn();
+#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
+ void StartCloudPrintConnector();
+ void OnCloudPrintPrefsChanged();
+ void ShowCloudPrintSetupDialog(const ListValue* args);
+ void HandleDisableCloudPrintConnector(const ListValue* args);
+ void SetupCloudPrintConnectorSection();
+ void RemoveCloudPrintConnectorSection();
+ void RefreshCloudPrintStatusFromService();
+#endif
+
// The current HTTP client (used for the current operation).
scoped_ptr<PrivetHTTPClient> current_http_client_;
@@ -181,8 +197,16 @@
// Announcement timeout for registration.
base::CancelableCallback<void()> registration_announce_timeout_;
+#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
+ StringPrefMember cloud_print_connector_email_;
+ BooleanPrefMember cloud_print_connector_enabled_;
+ bool cloud_print_connector_ui_enabled_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(LocalDiscoveryUIHandler);
};
+#undef CLOUD_PRINT_CONNECTOR_UI_AVAILABLE
+
} // namespace local_discovery
#endif // CHROME_BROWSER_UI_WEBUI_LOCAL_DISCOVERY_LOCAL_DISCOVERY_UI_HANDLER_H_
diff --git a/chrome/browser/ui/webui/ntp/new_tab_page_sync_handler.cc b/chrome/browser/ui/webui/ntp/new_tab_page_sync_handler.cc
index 35dee3a..74ab381 100644
--- a/chrome/browser/ui/webui/ntp/new_tab_page_sync_handler.cc
+++ b/chrome/browser/ui/webui/ntp/new_tab_page_sync_handler.cc
@@ -33,13 +33,6 @@
#include "net/url_request/url_request_context.h"
#include "ui/base/l10n/l10n_util.h"
-// Default URL for the sync web interface.
-//
-// TODO(idana): when we figure out how we are going to allow third parties to
-// plug in their own sync engine, we should allow this value to be
-// configurable.
-static const char kSyncDefaultViewOnlineUrl[] = "http://docs.google.com";
-
NewTabPageSyncHandler::NewTabPageSyncHandler() : sync_service_(NULL),
waiting_for_initial_page_load_(true) {
}
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui.cc b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
index 677da66..6370e8a 100644
--- a/chrome/browser/ui/webui/ntp/new_tab_ui.cc
+++ b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
@@ -123,7 +123,7 @@
// Android doesn't have a sync promo/username on NTP.
web_ui->AddMessageHandler(new NewTabPageSyncHandler());
- if (ShouldShowApps()) {
+ if (MightShowApps()) {
ExtensionService* service = GetProfile()->GetExtensionService();
// We might not have an ExtensionService (on ChromeOS when not logged in
// for example).
@@ -276,6 +276,16 @@
}
// static
+bool NewTabUI::MightShowApps() {
+// Android does not have apps.
+#if defined(OS_ANDROID)
+ return false;
+#else
+ return true;
+#endif
+}
+
+// static
bool NewTabUI::ShouldShowApps() {
// Ash shows apps in app list thus should not show apps page in NTP4.
// Android does not have apps.
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui.h b/chrome/browser/ui/webui/ntp/new_tab_ui.h
index dcbdbc8..5bdf752 100644
--- a/chrome/browser/ui/webui/ntp/new_tab_ui.h
+++ b/chrome/browser/ui/webui/ntp/new_tab_ui.h
@@ -37,6 +37,14 @@
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+ // Returns whether or not this browser process might ever need to show apps
+ // on the NTP. With Win8 running in immersive mode, for example, apps are
+ // displayed on a ChromeOS-style apps bar and not on the NTP. In desktop,
+ // however, apps are displayed on the NTP. Since they both share the same
+ // browser process instance, a different decision is necessary for whether
+ // or not to register app message handlers versus whether to show it on NTP.
+ static bool MightShowApps();
+
// Returns whether or not to show apps pages.
static bool ShouldShowApps();
diff --git a/chrome/browser/ui/webui/ntp/ntp_login_handler.cc b/chrome/browser/ui/webui/ntp/ntp_login_handler.cc
index db212ec..dbe8373 100644
--- a/chrome/browser/ui/webui/ntp/ntp_login_handler.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_login_handler.cc
@@ -58,8 +58,7 @@
SkBitmap bmp = skia::ImageOperations::Resize(*image.ToSkBitmap(),
skia::ImageOperations::RESIZE_BEST, kLength, kLength);
- gfx::Canvas canvas(gfx::Size(kLength, kLength), ui::SCALE_FACTOR_100P,
- false);
+ gfx::Canvas canvas(gfx::Size(kLength, kLength), 1.0f, false);
canvas.DrawImageInt(gfx::ImageSkia::CreateFrom1xBitmap(bmp), 0, 0);
// Draw a gray border on the inside of the icon.
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index 7594cbf..80d46dc 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -82,14 +82,6 @@
const char kLearnMoreGuestSessionUrl[] =
"https://www.google.com/support/chromeos/bin/answer.py?answer=1057090";
-// The URL for bookmark sync service help.
-const char kSyncServiceHelpUrl[] =
- "https://www.google.com/support/chrome/bin/answer.py?answer=165139";
-
-// The URL to be loaded to display Help.
-const char kHelpContentUrl[] =
- "https://www.google.com/support/chrome/";
-
string16 GetUrlWithLang(const GURL& url) {
return ASCIIToUTF16(google_util::AppendGoogleLocaleParam(url).spec());
}
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc
index ab35fae..1d3e9c3 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.cc
+++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -30,11 +30,6 @@
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/gpu/gpu_mode_manager.h"
#include "chrome/browser/lifetime/application_lifetime.h"
-#include "chrome/browser/managed_mode/managed_user_registration_utility.h"
-#include "chrome/browser/managed_mode/managed_user_service.h"
-#include "chrome/browser/managed_mode/managed_user_service_factory.h"
-#include "chrome/browser/managed_mode/managed_user_sync_service.h"
-#include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
@@ -43,6 +38,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_info_util.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_metrics.h"
#include "chrome/browser/profiles/profile_shortcut_manager.h"
#include "chrome/browser/profiles/profile_window.h"
@@ -64,6 +60,7 @@
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/options/options_util.h"
#include "chrome/browser/ui/webui/favicon_source.h"
+#include "chrome/browser/ui/webui/options/options_handlers_helper.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
@@ -136,46 +133,12 @@
#endif
}
-void CreateDesktopShortcutForProfile(Profile* profile,
- Profile::CreateStatus status) {
- ProfileShortcutManager* shortcut_manager =
- g_browser_process->profile_manager()->profile_shortcut_manager();
- if (shortcut_manager)
- shortcut_manager->CreateProfileShortcut(profile->GetPath());
-}
-
-void RunProfileCreationCallbacks(
- const std::vector<ProfileManager::CreateCallback>& callbacks,
- Profile* profile,
- Profile::CreateStatus status) {
- std::vector<ProfileManager::CreateCallback>::const_iterator it;
- for (it = callbacks.begin(); it != callbacks.end(); ++it) {
- it->Run(profile, status);
- }
-}
-
-void OpenNewWindowForProfile(
- chrome::HostDesktopType desktop_type,
- Profile* profile,
- Profile::CreateStatus status) {
- if (status != Profile::CREATE_STATUS_INITIALIZED)
- return;
-
- profiles::FindOrCreateNewWindowForProfile(
- profile,
- chrome::startup::IS_PROCESS_STARTUP,
- chrome::startup::IS_FIRST_RUN,
- desktop_type,
- false);
-}
-
} // namespace
BrowserOptionsHandler::BrowserOptionsHandler()
: page_initialized_(false),
template_url_service_(NULL),
- weak_ptr_factory_(this),
- importing_existing_managed_user_(false) {
+ weak_ptr_factory_(this) {
#if !defined(OS_MACOSX)
default_browser_worker_ = new ShellIntegration::DefaultBrowserWorker(this);
#endif
@@ -197,7 +160,6 @@
}
BrowserOptionsHandler::~BrowserOptionsHandler() {
- CancelProfileRegistration(false);
ProfileSyncService* sync_service(ProfileSyncServiceFactory::
GetInstance()->GetForProfile(Profile::FromWebUI(web_ui())));
if (sync_service)
@@ -398,7 +360,7 @@
{ "timezone", IDS_OPTIONS_SETTINGS_TIMEZONE_DESCRIPTION },
{ "use24HourClock", IDS_OPTIONS_SETTINGS_USE_24HOUR_CLOCK_DESCRIPTION },
#else
- { "cloudPrintConnectorEnabledManageButton",
+ { "cloudPrintManageButton",
IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_ENABLED_MANAGE_BUTTON},
{ "cloudPrintConnectorEnablingButton",
IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_ENABLING_BUTTON },
@@ -436,6 +398,11 @@
#endif
{ "languageSectionLabel", IDS_OPTIONS_ADVANCED_LANGUAGE_LABEL,
IDS_SHORT_PRODUCT_NAME },
+#if defined(ENABLE_MDNS)
+ { "cloudPrintDevicesPageButton", IDS_LOCAL_DISCOVERY_DEVICES_PAGE_BUTTON },
+ { "cloudPrintEnableNotificationsLabel",
+ IDS_LOCAL_DISCOVERY_NOTIFICATIONS_ENABLE_CHECKBOX_LABEL },
+#endif
};
#if defined(ENABLE_SETTINGS_APP)
@@ -482,8 +449,6 @@
values->SetString("doNotTrackLearnMoreURL", chrome::kDoNotTrackLearnMoreURL);
#if defined(OS_CHROMEOS)
- values->SetString("cloudPrintLearnMoreURL", chrome::kCloudPrintLearnMoreURL);
-
// TODO(pastarmovj): replace this with a call to the CrosSettings list
// handling functionality to come.
values->Set("timezoneList", GetTimezoneList().release());
@@ -520,7 +485,7 @@
g_browser_process->profile_manager()->GetNumberOfProfiles() > 1);
#endif
- if (ShouldShowMultiProfilesUserList(GetDesktopType()))
+ if (ShouldShowMultiProfilesUserList(helper::GetDesktopType(web_ui())))
values->Set("profilesInfo", GetProfilesInfoList().release());
values->SetBoolean("profileIsManaged",
@@ -531,20 +496,37 @@
"gpuEnabledAtStart",
g_browser_process->gpu_mode_manager()->initial_gpu_mode_pref());
#endif
+
+#if defined(ENABLE_MDNS)
+bool cloud_print_mdns_options_shown =
+ !CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableDeviceDiscovery);
+#else
+bool cloud_print_mdns_options_shown = false;
+#endif
+
+values->SetBoolean("cloudPrintShowMDnsOptions",
+ cloud_print_mdns_options_shown);
+
+values->SetString("cloudPrintLearnMoreURL", chrome::kCloudPrintLearnMoreURL);
+
}
#if defined(ENABLE_FULL_PRINTING)
void BrowserOptionsHandler::RegisterCloudPrintValues(DictionaryValue* values) {
+ values->SetString("cloudPrintOptionLabel",
+ l10n_util::GetStringFUTF16(
+ IDS_CLOUD_PRINT_CHROMEOS_OPTION_LABEL,
+ l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT)));
+
#if defined(OS_CHROMEOS)
- values->SetString("cloudPrintChromeosOptionLabel",
- l10n_util::GetStringFUTF16(
- IDS_CLOUD_PRINT_CHROMEOS_OPTION_LABEL,
- l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT)));
- values->SetString("cloudPrintChromeosOptionButton",
+ values->SetString("cloudPrintManageButton",
l10n_util::GetStringFUTF16(
IDS_CLOUD_PRINT_CHROMEOS_OPTION_BUTTON,
l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT)));
#else
+ // TODO(noamsml): Remove all cloud print connector related code from the
+ // settings page as soon as the devices page is supported on all platforms.
values->SetString("cloudPrintConnectorDisabledLabel",
l10n_util::GetStringFUTF16(
IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_DISABLED_LABEL,
@@ -569,18 +551,10 @@
base::Bind(&BrowserOptionsHandler::SetDefaultSearchEngine,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
- "createProfile",
- base::Bind(&BrowserOptionsHandler::CreateProfile,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
"deleteProfile",
base::Bind(&BrowserOptionsHandler::DeleteProfile,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
- "cancelCreateProfile",
- base::Bind(&BrowserOptionsHandler::HandleCancelProfileCreation,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
"themesReset",
base::Bind(&BrowserOptionsHandler::ThemesReset,
base::Unretained(this)));
@@ -657,6 +631,16 @@
base::Bind(&BrowserOptionsHandler::ShowNetworkProxySettings,
base::Unretained(this)));
#endif // defined(OS_CHROMEOS)
+
+#if defined(ENABLE_MDNS)
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableDeviceDiscovery)) {
+ web_ui()->RegisterMessageCallback(
+ "showCloudPrintDevicesPage",
+ base::Bind(&BrowserOptionsHandler::ShowCloudPrintDevicesPage,
+ base::Unretained(this)));
+ }
+#endif
}
void BrowserOptionsHandler::OnStateChanged() {
@@ -1080,244 +1064,12 @@
}
void BrowserOptionsHandler::SendProfilesInfo() {
- if (!ShouldShowMultiProfilesUserList(GetDesktopType()))
+ if (!ShouldShowMultiProfilesUserList(helper::GetDesktopType(web_ui())))
return;
web_ui()->CallJavascriptFunction("BrowserOptions.setProfilesInfo",
*GetProfilesInfoList());
}
-chrome::HostDesktopType BrowserOptionsHandler::GetDesktopType() {
- content::WebContents* web_contents = web_ui()->GetWebContents();
- Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
- if (browser)
- return browser->host_desktop_type();
-
- apps::ShellWindow* shell_window =
- apps::ShellWindowRegistry::Get(Profile::FromWebUI(web_ui()))->
- GetShellWindowForRenderViewHost(web_contents->GetRenderViewHost());
- if (shell_window) {
- return chrome::GetHostDesktopTypeForNativeWindow(
- shell_window->GetNativeWindow());
- }
-
- return chrome::GetActiveDesktop();
-}
-
-void BrowserOptionsHandler::CreateProfile(const ListValue* args) {
- // This handler could have been called in managed mode, for example because
- // the user fiddled with the web inspector. Silently return in this case.
- Profile* current_profile = Profile::FromWebUI(web_ui());
- if (current_profile->IsManaged())
- return;
-
- if (!profiles::IsMultipleProfilesEnabled())
- return;
-
- DCHECK(profile_path_being_created_.empty());
- profile_creation_start_time_ = base::TimeTicks::Now();
- importing_existing_managed_user_ = false;
-
- string16 name;
- string16 icon;
- std::string managed_user_id;
- bool create_shortcut = false;
- bool managed_user = false;
- if (args->GetString(0, &name) && args->GetString(1, &icon)) {
- if (args->GetBoolean(2, &create_shortcut)) {
- bool success = args->GetBoolean(3, &managed_user);
- DCHECK(success);
- success = args->GetString(4, &managed_user_id);
- DCHECK(success);
- }
- }
-
- std::vector<ProfileManager::CreateCallback> callbacks;
- if (create_shortcut)
- callbacks.push_back(base::Bind(&CreateDesktopShortcutForProfile));
-
- if (managed_user && ManagedUserService::AreManagedUsersEnabled()) {
- if (!IsValidExistingManagedUserId(managed_user_id))
- return;
-
- if (managed_user_id.empty()) {
- managed_user_id =
- ManagedUserRegistrationUtility::GenerateNewManagedUserId();
-
- // If sync is not yet fully initialized, the creation may take extra time,
- // so show a message. Import doesn't wait for an acknowledgement, so it
- // won't have the same potential delay.
- ProfileSyncService* sync_service =
- ProfileSyncServiceFactory::GetInstance()->GetForProfile(
- current_profile);
- ProfileSyncService::SyncStatusSummary status =
- sync_service->QuerySyncStatusSummary();
- if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED) {
- ShowProfileCreationWarning(l10n_util::GetStringUTF16(
- IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
- }
- } else {
- importing_existing_managed_user_ = true;
- }
-
- callbacks.push_back(
- base::Bind(&BrowserOptionsHandler::RegisterManagedUser,
- weak_ptr_factory_.GetWeakPtr(),
- GetDesktopType(),
- managed_user_id));
- } else {
- callbacks.push_back(
- base::Bind(&BrowserOptionsHandler::ShowProfileCreationFeedback,
- weak_ptr_factory_.GetWeakPtr(),
- GetDesktopType()));
- }
-
- ProfileMetrics::LogProfileAddNewUser(ProfileMetrics::ADD_NEW_USER_DIALOG);
-
- profile_path_being_created_ = ProfileManager::CreateMultiProfileAsync(
- name, icon, base::Bind(&RunProfileCreationCallbacks, callbacks),
- managed_user_id);
-}
-
-void BrowserOptionsHandler::RegisterManagedUser(
- chrome::HostDesktopType desktop_type,
- const std::string& managed_user_id,
- Profile* new_profile,
- Profile::CreateStatus status) {
- DCHECK_EQ(profile_path_being_created_.value(),
- new_profile->GetPath().value());
- if (status != Profile::CREATE_STATUS_INITIALIZED) {
- ShowProfileCreationFeedback(desktop_type, new_profile, status);
- return;
- }
-
- ManagedUserService* managed_user_service =
- ManagedUserServiceFactory::GetForProfile(new_profile);
-
- // Register the managed user using the profile of the custodian.
- managed_user_registration_utility_ =
- ManagedUserRegistrationUtility::Create(Profile::FromWebUI(web_ui()));
- managed_user_service->RegisterAndInitSync(
- managed_user_registration_utility_.get(),
- Profile::FromWebUI(web_ui()),
- managed_user_id,
- base::Bind(&BrowserOptionsHandler::OnManagedUserRegistered,
- weak_ptr_factory_.GetWeakPtr(),
- desktop_type,
- new_profile));
-}
-
-void BrowserOptionsHandler::RecordProfileCreationMetrics(
- Profile::CreateStatus status) {
- UMA_HISTOGRAM_ENUMERATION("Profile.CreateResult",
- status,
- Profile::MAX_CREATE_STATUS);
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Profile.CreateTimeNoTimeout",
- base::TimeTicks::Now() - profile_creation_start_time_);
-}
-
-void BrowserOptionsHandler::OnManagedUserRegistered(
- chrome::HostDesktopType desktop_type,
- Profile* profile,
- const GoogleServiceAuthError& error) {
- GoogleServiceAuthError::State state = error.state();
- if (state == GoogleServiceAuthError::NONE) {
- ShowProfileCreationSuccess(profile, desktop_type, true);
- return;
- }
-
- string16 error_msg;
- if (state == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
- state == GoogleServiceAuthError::USER_NOT_SIGNED_UP ||
- state == GoogleServiceAuthError::ACCOUNT_DELETED ||
- state == GoogleServiceAuthError::ACCOUNT_DISABLED) {
- error_msg = GetProfileCreationErrorMessage(SIGNIN_ERROR);
- } else {
- error_msg = GetProfileCreationErrorMessage(REMOTE_ERROR);
- }
- ShowProfileCreationError(profile, error_msg);
-}
-
-void BrowserOptionsHandler::ShowProfileCreationFeedback(
- chrome::HostDesktopType desktop_type,
- Profile* profile,
- Profile::CreateStatus status) {
- if (status != Profile::CREATE_STATUS_CREATED)
- RecordProfileCreationMetrics(status);
-
- switch (status) {
- case Profile::CREATE_STATUS_LOCAL_FAIL: {
- ShowProfileCreationError(profile,
- GetProfileCreationErrorMessage(LOCAL_ERROR));
- break;
- }
- case Profile::CREATE_STATUS_CREATED: {
- // Do nothing for an intermediate status.
- break;
- }
- case Profile::CREATE_STATUS_INITIALIZED: {
- // Managed user registration success is handled in
- // OnManagedUserRegistered().
- ShowProfileCreationSuccess(profile, desktop_type, false);
- break;
- }
- // User-initiated cancellation is handled in CancelProfileRegistration and
- // does not call this callback.
- case Profile::CREATE_STATUS_CANCELED:
- // Managed user registration errors are handled in
- // OnManagedUserRegistered().
- case Profile::CREATE_STATUS_REMOTE_FAIL:
- case Profile::MAX_CREATE_STATUS: {
- NOTREACHED();
- break;
- }
- }
-}
-
-void BrowserOptionsHandler::ShowProfileCreationError(Profile* profile,
- const string16& error) {
- profile_path_being_created_.clear();
- web_ui()->CallJavascriptFunction(
- GetJavascriptMethodName(PROFILE_CREATION_ERROR),
- base::StringValue(error));
- DeleteProfileAtPath(profile->GetPath());
-}
-
-void BrowserOptionsHandler::ShowProfileCreationWarning(
- const string16& warning) {
- DCHECK(!importing_existing_managed_user_);
- web_ui()->CallJavascriptFunction("BrowserOptions.showCreateProfileWarning",
- base::StringValue(warning));
-}
-
-void BrowserOptionsHandler::ShowProfileCreationSuccess(
- Profile* profile,
- chrome::HostDesktopType desktop_type,
- bool is_managed) {
- DCHECK_EQ(profile_path_being_created_.value(), profile->GetPath().value());
- profile_path_being_created_.clear();
- DictionaryValue dict;
- dict.SetString("name",
- profile->GetPrefs()->GetString(prefs::kProfileName));
- dict.Set("filePath", base::CreateFilePathValue(profile->GetPath()));
- dict.SetBoolean("isManaged", is_managed);
- web_ui()->CallJavascriptFunction(
- GetJavascriptMethodName(PROFILE_CREATION_SUCCESS), dict);
-
- // If the new profile is a managed user, instead of opening a new window
- // right away, a confirmation overlay will be shown from the creation
- // dialog. However, if we are importing an existing managed user we
- // open the new window directly.
- if (is_managed && !importing_existing_managed_user_)
- return;
-
- // Opening the new window must be the last action, after all callbacks
- // have been run, to give them a chance to initialize the profile.
- OpenNewWindowForProfile(desktop_type,
- profile,
- Profile::CREATE_STATUS_INITIALIZED);
-}
-
void BrowserOptionsHandler::DeleteProfile(const ListValue* args) {
DCHECK(args);
const Value* file_path_value;
@@ -1327,58 +1079,7 @@
base::FilePath file_path;
if (!base::GetValueAsFilePath(*file_path_value, &file_path))
return;
- DeleteProfileAtPath(file_path);
-}
-
-void BrowserOptionsHandler::DeleteProfileAtPath(base::FilePath file_path) {
- // This handler could have been called in managed mode, for example because
- // the user fiddled with the web inspector. Silently return in this case.
- if (Profile::FromWebUI(web_ui())->IsManaged())
- return;
-
- if (!profiles::IsMultipleProfilesEnabled())
- return;
-
- ProfileMetrics::LogProfileDeleteUser(ProfileMetrics::PROFILE_DELETED);
-
- g_browser_process->profile_manager()->ScheduleProfileForDeletion(
- file_path,
- base::Bind(&OpenNewWindowForProfile, GetDesktopType()));
-}
-
-void BrowserOptionsHandler::HandleCancelProfileCreation(const ListValue* args) {
- CancelProfileRegistration(true);
-}
-
-void BrowserOptionsHandler::CancelProfileRegistration(bool user_initiated) {
- if (profile_path_being_created_.empty())
- return;
-
- ProfileManager* manager = g_browser_process->profile_manager();
- Profile* new_profile = manager->GetProfileByPath(profile_path_being_created_);
- if (!new_profile)
- return;
-
- // Non-managed user creation cannot be canceled. (Creating a non-managed
- // profile shouldn't take significant time, and it can easily be deleted
- // afterward.)
- if (!new_profile->IsManaged())
- return;
-
- if (user_initiated) {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Profile.CreateTimeCanceledNoTimeout",
- base::TimeTicks::Now() - profile_creation_start_time_);
- RecordProfileCreationMetrics(Profile::CREATE_STATUS_CANCELED);
- }
-
- DCHECK(managed_user_registration_utility_.get());
- managed_user_registration_utility_.reset();
-
- // Cancelling registration means the callback passed into
- // RegisterAndInitSync() won't be called, so the cleanup must be done here.
- profile_path_being_created_.clear();
- DeleteProfileAtPath(new_profile->GetPath());
+ helper::DeleteProfileAtPath(file_path, web_ui());
}
void BrowserOptionsHandler::ObserveThemeChanged() {
@@ -1583,6 +1284,19 @@
}
#endif
+#if defined(ENABLE_MDNS)
+
+void BrowserOptionsHandler::ShowCloudPrintDevicesPage(const ListValue* args) {
+ content::RecordAction(UserMetricsAction("Options_CloudPrintDevicesPage"));
+ // Navigate in current tab to devices page.
+ OpenURLParams params(
+ GURL(chrome::kChromeUIDevicesURL), Referrer(),
+ CURRENT_TAB, content::PAGE_TRANSITION_LINK, false);
+ web_ui()->GetWebContents()->OpenURL(params);
+}
+
+#endif
+
#if defined(ENABLE_FULL_PRINTING)
void BrowserOptionsHandler::ShowCloudPrintManagePage(const ListValue* args) {
content::RecordAction(UserMetricsAction("Options_ManageCloudPrinters"));
@@ -1824,74 +1538,4 @@
#endif // !defined(OS_CHROMEOS)
}
-string16 BrowserOptionsHandler::GetProfileCreationErrorMessage(
- ProfileCreationErrorType error) const {
- int message_id = -1;
- switch (error) {
- case SIGNIN_ERROR:
- message_id =
- importing_existing_managed_user_ ?
- IDS_MANAGED_USER_IMPORT_SIGN_IN_ERROR :
- IDS_PROFILES_CREATE_SIGN_IN_ERROR;
- break;
- case REMOTE_ERROR:
- message_id =
- importing_existing_managed_user_ ?
- IDS_MANAGED_USER_IMPORT_REMOTE_ERROR :
- IDS_PROFILES_CREATE_REMOTE_ERROR;
- break;
- case LOCAL_ERROR:
- message_id =
- importing_existing_managed_user_ ?
- IDS_MANAGED_USER_IMPORT_LOCAL_ERROR :
- IDS_PROFILES_CREATE_LOCAL_ERROR;
- break;
- }
-
- return l10n_util::GetStringUTF16(message_id);
-}
-
-std::string BrowserOptionsHandler::GetJavascriptMethodName(
- ProfileCreationStatus status) const {
- switch (status) {
- case PROFILE_CREATION_SUCCESS:
- return importing_existing_managed_user_ ?
- "BrowserOptions.showManagedUserImportSuccess" :
- "BrowserOptions.showCreateProfileSuccess";
- case PROFILE_CREATION_ERROR:
- return importing_existing_managed_user_ ?
- "BrowserOptions.showManagedUserImportError" :
- "BrowserOptions.showCreateProfileError";
- }
-
- NOTREACHED();
- return std::string();
-}
-
-bool BrowserOptionsHandler::IsValidExistingManagedUserId(
- const std::string& existing_managed_user_id) const {
- if (existing_managed_user_id.empty())
- return true;
-
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAllowCreateExistingManagedUsers)) {
- return false;
- }
-
- Profile* profile = Profile::FromWebUI(web_ui());
- const DictionaryValue* dict =
- ManagedUserSyncServiceFactory::GetForProfile(profile)->GetManagedUsers();
- if (!dict->HasKey(existing_managed_user_id))
- return false;
-
- // Check if this managed user already exists on this machine.
- const ProfileInfoCache& cache =
- g_browser_process->profile_manager()->GetProfileInfoCache();
- for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
- if (existing_managed_user_id == cache.GetManagedUserIdOfProfileAtIndex(i))
- return false;
- }
- return true;
-}
-
} // namespace options
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.h b/chrome/browser/ui/webui/options/browser_options_handler.h
index f63f6a6..04018be 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.h
+++ b/chrome/browser/ui/webui/options/browser_options_handler.h
@@ -12,13 +12,13 @@
#include "base/memory/weak_ptr.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/prefs/pref_member.h"
-#include "base/time/time.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url_service_observer.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/sync/profile_sync_service_observer.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/webui/options/options_ui.h"
+#include "google_apis/gaia/google_service_auth_error.h"
#include "ui/base/models/table_model_observer.h"
#include "ui/shell_dialogs/select_file_dialog.h"
@@ -29,8 +29,6 @@
class AutocompleteController;
class CloudPrintSetupHandler;
class CustomHomePagesTableModel;
-class GoogleServiceAuthError;
-class ManagedUserRegistrationUtility;
class TemplateURLService;
namespace options {
@@ -68,22 +66,6 @@
virtual void OnTemplateURLServiceChanged() OVERRIDE;
private:
- // Represents the final profile creation status. It is used to map
- // the status to the javascript method to be called.
- enum ProfileCreationStatus {
- PROFILE_CREATION_SUCCESS,
- PROFILE_CREATION_ERROR,
- };
-
- // Represents errors that could occur during a profile creation.
- // It is used to map error types to messages that will be displayed
- // to the user.
- enum ProfileCreationErrorType {
- REMOTE_ERROR,
- LOCAL_ERROR,
- SIGNIN_ERROR
- };
-
// content::NotificationObserver implementation.
virtual void Observe(int type,
const content::NotificationSource& source,
@@ -157,71 +139,10 @@
// Sends an array of Profile objects to javascript.
void SendProfilesInfo();
- // Returns the current desktop type.
- chrome::HostDesktopType GetDesktopType();
-
- // Asynchronously creates and initializes a new profile.
- // The arguments are as follows:
- // 0: name (string)
- // 1: icon (string)
- // 2: a flag stating whether we should create a profile desktop shortcut
- // (optional, boolean)
- // 3: a flag stating whether the user should be managed (optional, boolean)
- void CreateProfile(const base::ListValue* args);
-
- // After a new managed-user profile has been created, registers the user with
- // the management server.
- void RegisterManagedUser(chrome::HostDesktopType desktop_type,
- const std::string& managed_user_id,
- Profile* new_profile,
- Profile::CreateStatus status);
-
- // Called back with the result of the managed user registration.
- void OnManagedUserRegistered(chrome::HostDesktopType desktop_type,
- Profile* profile,
- const GoogleServiceAuthError& error);
-
- // Records UMA histograms relevant to profile creation.
- void RecordProfileCreationMetrics(Profile::CreateStatus status);
-
- // Updates the UI as the final task after a new profile has been created.
- void ShowProfileCreationFeedback(
- chrome::HostDesktopType desktop_type,
- Profile* profile,
- Profile::CreateStatus status);
-
- // Updates the UI to show an error when creating a profile.
- void ShowProfileCreationError(Profile* profile, const string16& error);
-
- // Updates the UI to show a non-fatal warning when creating a profile.
- void ShowProfileCreationWarning(const string16& warning);
-
- // Updates the UI to indicate success when creating a profile.
- void ShowProfileCreationSuccess(Profile* profile,
- chrome::HostDesktopType desktop_type,
- bool is_managed);
-
// Deletes the given profile. Expects one argument:
// 0: profile file path (string)
void DeleteProfile(const base::ListValue* args);
- // Deletes the profile at the given |file_path|.
- void DeleteProfileAtPath(base::FilePath file_path);
-
- // Cancels creation of a managed-user profile currently in progress, as
- // indicated by profile_path_being_created_, removing the object and files
- // and canceling managed-user registration. This is the handler for the
- // "cancelCreateProfile" message. |args| is not used.
- // TODO(pamg): Move all the profile-handling methods into a more appropriate
- // class.
- void HandleCancelProfileCreation(const base::ListValue* args);
-
- // Internal implementation. This may safely be called whether profile creation
- // or registration is in progress or not. |user_initiated| should be true if
- // the cancellation was deliberately requested by the user, and false if it
- // was caused implicitly, e.g. by shutting down the browser.
- void CancelProfileRegistration(bool user_initiated);
-
void ObserveThemeChanged();
void ThemesReset(const base::ListValue* args);
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
@@ -276,6 +197,10 @@
void ShowManageSSLCertificates(const ListValue* args);
#endif
+#if defined(ENABLE_MDNS)
+ void ShowCloudPrintDevicesPage(const ListValue* args);
+#endif
+
#if defined(ENABLE_FULL_PRINTING)
// Callback for the Cloud Print manage button. This will open a new
// tab pointed at the management URL.
@@ -343,13 +268,6 @@
void SetupAccessibilityFeatures();
#endif
- string16 GetProfileCreationErrorMessage(
- ProfileCreationErrorType error) const;
- std::string GetJavascriptMethodName(ProfileCreationStatus status) const;
-
- bool IsValidExistingManagedUserId(
- const std::string& existing_managed_user_id) const;
-
// Returns a newly created dictionary with a number of properties that
// correspond to the status of sync.
scoped_ptr<DictionaryValue> GetSyncStateDictionary();
@@ -363,14 +281,6 @@
TemplateURLService* template_url_service_; // Weak.
- // Used to allow cancelling a profile creation (particularly a managed-user
- // registration) in progress. Set when profile creation is begun, and
- // cleared when all the callbacks have been run and creation is complete.
- base::FilePath profile_path_being_created_;
-
- // Used to track how long profile creation takes.
- base::TimeTicks profile_creation_start_time_;
-
// Used to get WeakPtr to self for use on the UI thread.
base::WeakPtrFactory<BrowserOptionsHandler> weak_ptr_factory_;
@@ -387,14 +297,6 @@
PrefChangeRegistrar profile_pref_registrar_;
- scoped_ptr<ManagedUserRegistrationUtility> managed_user_registration_utility_;
-
- // Indicates if the in progress user creation operation is an import operation
- // for an existing managed user or a new user (either a new managed user or
- // a new normal user) creation one.
- // The value is only relevant while we are creating/importing a user.
- bool importing_existing_managed_user_;
-
DISALLOW_COPY_AND_ASSIGN(BrowserOptionsHandler);
};
diff --git a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
index 3932a5b..1a1b9b5 100644
--- a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
+++ b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
@@ -21,8 +21,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_CHROMEOS)
-#include "base/files/scoped_temp_dir.h"
-#include "chrome/browser/chromeos/policy/cros_enterprise_test_utils.h"
+#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
#include "chrome/browser/chromeos/policy/network_configuration_updater.h"
#include "chromeos/network/onc/onc_test_utils.h"
#include "crypto/nss_util.h"
@@ -40,10 +39,7 @@
protected:
virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
#if defined(OS_CHROMEOS)
- const char kFakeUsername[] = "fake_username@example.com";
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- policy::test_utils::MarkAsEnterpriseOwned(kFakeUsername,
- temp_dir_.path());
+ device_policy_test_helper_.MarkAsEnterpriseOwned();
#endif
// Setup the policy provider for injecting certs through ONC policy.
EXPECT_CALL(provider_, IsInitializationComplete(_))
@@ -91,7 +87,7 @@
policy::MockConfigurationPolicyProvider provider_;
#if defined(OS_CHROMEOS)
- base::ScopedTempDir temp_dir_;
+ policy::DevicePolicyCrosTestHelper device_policy_test_helper_;
crypto::ScopedTestNSSDB test_nssdb_;
#endif
};
diff --git a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc
index 7ef79d1..583312a 100644
--- a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc
@@ -12,7 +12,6 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/proxy_cros_settings_parser.h"
@@ -22,9 +21,6 @@
#include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h"
#include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.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"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_ui.h"
@@ -167,7 +163,14 @@
}
if (!CrosSettings::IsCrosSettings(pref_name))
return ::options::CoreOptionsHandler::ObservePref(pref_name);
- CrosSettings::Get()->AddSettingsObserver(pref_name.c_str(), this);
+
+ linked_ptr<CrosSettings::ObserverSubscription> subscription(
+ CrosSettings::Get()->AddSettingsObserver(
+ pref_name.c_str(),
+ base::Bind(&CoreChromeOSOptionsHandler::NotifySettingsChanged,
+ base::Unretained(this),
+ pref_name)).release());
+ pref_subscription_map_.insert(make_pair(pref_name, subscription));
}
void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name,
@@ -195,7 +198,7 @@
return; // We unregister those in the destructor.
// Unregister this instance from observing prefs of chrome os settings.
if (CrosSettings::IsCrosSettings(path))
- CrosSettings::Get()->RemoveSettingsObserver(path.c_str(), this);
+ pref_subscription_map_.erase(path);
else // Call base class to handle regular preferences.
::options::CoreOptionsHandler::StopObservingPref(path);
}
@@ -208,17 +211,6 @@
AddAccountUITweaksLocalizedValues(localized_strings);
}
-void CoreChromeOSOptionsHandler::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED) {
- NotifySettingsChanged(content::Details<std::string>(details).ptr());
- return;
- }
- ::options::CoreOptionsHandler::Observe(type, source, details);
-}
-
void CoreChromeOSOptionsHandler::SelectNetworkCallback(
const base::ListValue* args) {
std::string service_path;
@@ -252,12 +244,12 @@
}
void CoreChromeOSOptionsHandler::NotifySettingsChanged(
- const std::string* setting_name) {
- DCHECK(CrosSettings::Get()->IsCrosSettings(*setting_name));
- scoped_ptr<base::Value> value(FetchPref(*setting_name));
+ const std::string& setting_name) {
+ DCHECK(CrosSettings::Get()->IsCrosSettings(setting_name));
+ scoped_ptr<base::Value> value(FetchPref(setting_name));
if (!value.get())
NOTREACHED();
- DispatchPrefChangeNotification(*setting_name, value.Pass());
+ DispatchPrefChangeNotification(setting_name, value.Pass());
}
void CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged() {
diff --git a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h
index d73db1b..4b823b4 100644
--- a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h
+++ b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h
@@ -5,7 +5,11 @@
#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS_CHROMEOS_CORE_CHROMEOS_OPTIONS_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_OPTIONS_CHROMEOS_CORE_CHROMEOS_OPTIONS_HANDLER_H_
+#include <map>
+
#include "base/compiler_specific.h"
+#include "base/memory/linked_ptr.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/ui_proxy_config_service.h"
#include "chrome/browser/ui/webui/options/core_options_handler.h"
@@ -32,11 +36,6 @@
virtual void GetLocalizedValues(
base::DictionaryValue* localized_strings) OVERRIDE;
- // content::NotificationObserver implementation.
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
-
private:
virtual void OnPreferenceChanged(PrefService* service,
const std::string& pref_name) OVERRIDE;
@@ -46,9 +45,13 @@
void SelectNetworkCallback(const base::ListValue* args);
// Notifies registered JS callbacks on ChromeOS setting change.
- void NotifySettingsChanged(const std::string* setting_name);
+ void NotifySettingsChanged(const std::string& setting_name);
void NotifyProxyPrefsChanged();
+ typedef std::map<std::string, linked_ptr<CrosSettings::ObserverSubscription> >
+ SubscriptionMap;
+ SubscriptionMap pref_subscription_map_;
+
UIProxyConfigService proxy_config_service_;
};
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 504cf23..06e37dc 100644
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -192,7 +192,7 @@
std::vector<float> ui_scales;
if (display.IsInternal()) {
ui_scales = DisplayManager::GetScalesForDisplay(display_info);
- gfx::SizeF base_size = display_info.bounds_in_pixel().size();
+ gfx::SizeF base_size = display_info.bounds_in_native().size();
base_size.Scale(1.0f / display.device_scale_factor());
if (display_info.rotation() == gfx::Display::ROTATE_90 ||
display_info.rotation() == gfx::Display::ROTATE_270) {
@@ -213,7 +213,7 @@
std::sort(resolutions.begin(), resolutions.end(), CompareResolution);
base::ListValue* js_resolutions = new base::ListValue();
- gfx::Size current_size = display_info.bounds_in_pixel().size();
+ gfx::Size current_size = display_info.bounds_in_native().size();
gfx::Insets current_overscan = display_info.GetOverscanInsetsInPixel();
for (size_t i = 0; i < resolutions.size(); ++i) {
base::DictionaryValue* resolution_info = new base::DictionaryValue();
@@ -350,7 +350,7 @@
gfx::Insets current_overscan = display_info.GetOverscanInsetsInPixel();
gfx::Size new_resolution = gfx::ToFlooredSize(gfx::SizeF(width, height));
new_resolution.Enlarge(current_overscan.width(), current_overscan.height());
- gfx::Size old_resolution = display_info.bounds_in_pixel().size();
+ gfx::Size old_resolution = display_info.bounds_in_native().size();
bool has_new_resolution = false;
bool has_old_resolution = false;
for (size_t i = 0; i < display_info.resolutions().size(); ++i) {
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 bc82a94..773374e 100644
--- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
@@ -288,13 +288,13 @@
std::string ActivationStateString(const std::string& activation_state) {
int id;
- if (activation_state == flimflam::kActivationStateActivated)
+ if (activation_state == shill::kActivationStateActivated)
id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATED;
- else if (activation_state == flimflam::kActivationStateActivating)
+ else if (activation_state == shill::kActivationStateActivating)
id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATING;
- else if (activation_state == flimflam::kActivationStateNotActivated)
+ else if (activation_state == shill::kActivationStateNotActivated)
id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_NOT_ACTIVATED;
- else if (activation_state == flimflam::kActivationStatePartiallyActivated)
+ else if (activation_state == shill::kActivationStatePartiallyActivated)
id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_PARTIALLY_ACTIVATED;
else
id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_UNKNOWN;
@@ -303,9 +303,9 @@
std::string RoamingStateString(const std::string& roaming_state) {
int id;
- if (roaming_state == flimflam::kRoamingStateHome)
+ if (roaming_state == shill::kRoamingStateHome)
id = IDS_CHROMEOS_NETWORK_ROAMING_STATE_HOME;
- else if (roaming_state == flimflam::kRoamingStateRoaming)
+ else if (roaming_state == shill::kRoamingStateRoaming)
id = IDS_CHROMEOS_NETWORK_ROAMING_STATE_ROAMING;
else
id = IDS_CHROMEOS_NETWORK_ROAMING_STATE_UNKNOWN;
@@ -314,27 +314,27 @@
std::string ConnectionStateString(const std::string& state) {
int id;
- if (state == flimflam::kUnknownString)
+ if (state == shill::kUnknownString)
id = IDS_CHROMEOS_NETWORK_STATE_UNKNOWN;
- else if (state == flimflam::kStateIdle)
+ else if (state == shill::kStateIdle)
id = IDS_CHROMEOS_NETWORK_STATE_IDLE;
- else if (state == flimflam::kStateCarrier)
+ else if (state == shill::kStateCarrier)
id = IDS_CHROMEOS_NETWORK_STATE_CARRIER;
- else if (state == flimflam::kStateAssociation)
+ else if (state == shill::kStateAssociation)
id = IDS_CHROMEOS_NETWORK_STATE_ASSOCIATION;
- else if (state == flimflam::kStateConfiguration)
+ else if (state == shill::kStateConfiguration)
id = IDS_CHROMEOS_NETWORK_STATE_CONFIGURATION;
- else if (state == flimflam::kStateReady)
+ else if (state == shill::kStateReady)
id = IDS_CHROMEOS_NETWORK_STATE_READY;
- else if (state == flimflam::kStateDisconnect)
+ else if (state == shill::kStateDisconnect)
id = IDS_CHROMEOS_NETWORK_STATE_DISCONNECT;
- else if (state == flimflam::kStateFailure)
+ else if (state == shill::kStateFailure)
id = IDS_CHROMEOS_NETWORK_STATE_FAILURE;
- else if (state == flimflam::kStateActivationFailure)
+ else if (state == shill::kStateActivationFailure)
id = IDS_CHROMEOS_NETWORK_STATE_ACTIVATION_FAILURE;
- else if (state == flimflam::kStatePortal)
+ else if (state == shill::kStatePortal)
id = IDS_CHROMEOS_NETWORK_STATE_PORTAL;
- else if (state == flimflam::kStateOnline)
+ else if (state == shill::kStateOnline)
id = IDS_CHROMEOS_NETWORK_STATE_ONLINE;
else
id = IDS_CHROMEOS_NETWORK_STATE_UNRECOGNIZED;
@@ -367,25 +367,25 @@
std::string EncryptionString(const std::string& security,
const std::string& eap_method) {
- if (security == flimflam::kSecurityNone)
+ if (security == shill::kSecurityNone)
return "";
- if (security == flimflam::kSecurityWpa)
+ if (security == shill::kSecurityWpa)
return "WPA";
- if (security == flimflam::kSecurityWep)
+ if (security == shill::kSecurityWep)
return "WEP";
- if (security == flimflam::kSecurityRsn)
+ if (security == shill::kSecurityRsn)
return "RSN";
- if (security == flimflam::kSecurityPsk)
+ if (security == shill::kSecurityPsk)
return "PSK";
- if (security == flimflam::kSecurity8021x) {
+ if (security == shill::kSecurity8021x) {
std::string result = "8021X";
- if (eap_method == flimflam::kEapMethodPEAP)
+ if (eap_method == shill::kEapMethodPEAP)
result += "PEAP";
- else if (eap_method == flimflam::kEapMethodTLS)
+ else if (eap_method == shill::kEapMethodTLS)
result += "TLS";
- else if (eap_method == flimflam::kEapMethodTTLS)
+ else if (eap_method == shill::kEapMethodTTLS)
result += "TTLS";
- else if (eap_method == flimflam::kEapMethodLEAP)
+ else if (eap_method == shill::kEapMethodLEAP)
result += "LEAP";
return result;
}
@@ -396,15 +396,15 @@
const std::string& provider_type,
const base::DictionaryValue& provider_properties) {
int id;
- if (provider_type == flimflam::kProviderL2tpIpsec) {
+ if (provider_type == shill::kProviderL2tpIpsec) {
std::string client_cert_id;
provider_properties.GetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecClientCertIdProperty, &client_cert_id);
+ shill::kL2tpIpsecClientCertIdProperty, &client_cert_id);
if (client_cert_id.empty())
id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK;
else
id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT;
- } else if (provider_type == flimflam::kProviderOpenVpn) {
+ } else if (provider_type == shill::kProviderOpenVpn) {
id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN;
} else {
id = IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN;
@@ -416,7 +416,8 @@
const gfx::ImageSkia& icon,
ui::ScaleFactor icon_scale_factor,
base::DictionaryValue* network_info) {
- gfx::ImageSkiaRep image_rep = icon.GetRepresentation(icon_scale_factor);
+ gfx::ImageSkiaRep image_rep =
+ icon.GetRepresentation(ui::GetImageScale(icon_scale_factor));
std::string icon_url =
icon.isNull() ? "" : webui::GetBitmapDataUrl(image_rep.sk_bitmap());
network_info->SetString(kNetworkInfoKeyIconURL, icon_url);
@@ -527,15 +528,15 @@
}
static bool CanForgetNetworkType(const std::string& type) {
- return type == flimflam::kTypeWifi ||
- type == flimflam::kTypeWimax ||
- type == flimflam::kTypeVPN;
+ return type == shill::kTypeWifi ||
+ type == shill::kTypeWimax ||
+ type == shill::kTypeVPN;
}
static bool CanAddNetworkType(const std::string& type) {
- return type == flimflam::kTypeWifi ||
- type == flimflam::kTypeVPN ||
- type == flimflam::kTypeCellular;
+ return type == shill::kTypeWifi ||
+ type == shill::kTypeVPN ||
+ type == shill::kTypeCellular;
}
// Decorate pref value as CoreOptionsHandler::CreateValueForPref() does and
@@ -593,24 +594,24 @@
// Provider properties are stored in the "Provider" dictionary.
const base::DictionaryValue* provider_properties = NULL;
if (!shill_properties.GetDictionaryWithoutPathExpansion(
- flimflam::kProviderProperty, &provider_properties)) {
+ shill::kProviderProperty, &provider_properties)) {
LOG(ERROR) << "No provider properties for VPN: " << vpn->path();
return;
}
std::string provider_type;
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kTypeProperty, &provider_type);
+ shill::kTypeProperty, &provider_type);
dictionary->SetString(kTagProviderType,
ProviderTypeString(provider_type,
*provider_properties));
std::string username;
- if (provider_type == flimflam::kProviderOpenVpn) {
+ if (provider_type == shill::kProviderOpenVpn) {
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kOpenVPNUserProperty, &username);
+ shill::kOpenVPNUserProperty, &username);
} else {
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecUserProperty, &username);
+ shill::kL2tpIpsecUserProperty, &username);
}
dictionary->SetString(kTagUsername, username);
@@ -625,7 +626,7 @@
base::StringPrintf("%s.%s", onc::network_config::kVPN, onc::vpn::kHost));
std::string provider_host;
provider_properties->GetStringWithoutPathExpansion(
- flimflam::kHostProperty, &provider_host);
+ shill::kHostProperty, &provider_host);
SetValueDictionary(dictionary, kTagServerHostname,
new base::StringValue(provider_host),
hostname_ui_data);
@@ -643,7 +644,7 @@
const DeviceState* device) {
DCHECK(carriers);
DCHECK(device);
- bool gsm = (device->technology_family() == flimflam::kTechnologyFamilyGsm);
+ bool gsm = (device->technology_family() == shill::kTechnologyFamilyGsm);
int index = 0;
for (base::ListValue::const_iterator it = carriers->begin();
it != carriers->end(); ++it, ++index) {
@@ -1114,7 +1115,7 @@
if (apn.empty()) {
std::vector<std::string> properties_to_clear;
- properties_to_clear.push_back(flimflam::kCellularApnProperty);
+ properties_to_clear.push_back(shill::kCellularApnProperty);
NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
service_path, properties_to_clear,
base::Bind(&base::DoNothing),
@@ -1125,20 +1126,20 @@
const base::DictionaryValue* shill_apn_dict = NULL;
std::string network_id;
if (shill_properties.GetDictionaryWithoutPathExpansion(
- flimflam::kCellularApnProperty, &shill_apn_dict)) {
+ shill::kCellularApnProperty, &shill_apn_dict)) {
shill_apn_dict->GetStringWithoutPathExpansion(
- flimflam::kApnNetworkIdProperty, &network_id);
+ shill::kApnNetworkIdProperty, &network_id);
}
base::DictionaryValue properties;
base::DictionaryValue* apn_dict = new base::DictionaryValue;
- apn_dict->SetStringWithoutPathExpansion(flimflam::kApnProperty, apn);
- apn_dict->SetStringWithoutPathExpansion(flimflam::kApnNetworkIdProperty,
+ apn_dict->SetStringWithoutPathExpansion(shill::kApnProperty, apn);
+ apn_dict->SetStringWithoutPathExpansion(shill::kApnNetworkIdProperty,
network_id);
- apn_dict->SetStringWithoutPathExpansion(flimflam::kApnUsernameProperty,
+ apn_dict->SetStringWithoutPathExpansion(shill::kApnUsernameProperty,
username);
- apn_dict->SetStringWithoutPathExpansion(flimflam::kApnPasswordProperty,
+ apn_dict->SetStringWithoutPathExpansion(shill::kApnPasswordProperty,
password);
- properties.SetWithoutPathExpansion(flimflam::kCellularApnProperty, apn_dict);
+ properties.SetWithoutPathExpansion(shill::kCellularApnProperty, apn_dict);
NetworkHandler::Get()->network_configuration_handler()->SetProperties(
service_path, properties,
base::Bind(&base::DoNothing),
@@ -1217,7 +1218,7 @@
gfx::ImageSkia* icon =
ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
gfx::ImageSkiaRep image_rep = icon->GetRepresentation(
- web_ui()->GetDeviceScaleFactor());
+ ui::GetImageScale(web_ui()->GetDeviceScaleFactor()));
return webui::GetBitmapDataUrl(image_rep.sk_bitmap());
}
@@ -1325,7 +1326,7 @@
NOTREACHED();
return;
}
- SetNetworkProperty(service_path, flimflam::kProviderHostProperty,
+ SetNetworkProperty(service_path, shill::kProviderHostProperty,
base::Value::CreateStringValue(server_hostname));
}
@@ -1339,7 +1340,7 @@
return;
}
int priority = (prefer_network_str == kTagTrue) ? kPreferredPriority : 0;
- SetNetworkProperty(service_path, flimflam::kPriorityProperty,
+ SetNetworkProperty(service_path, shill::kPriorityProperty,
base::Value::CreateIntegerValue(priority));
}
@@ -1353,7 +1354,7 @@
return;
}
bool auto_connect = auto_connect_str == kTagTrue;
- SetNetworkProperty(service_path, flimflam::kAutoConnectProperty,
+ SetNetworkProperty(service_path, shill::kAutoConnectProperty,
base::Value::CreateBooleanValue(auto_connect));
}
@@ -1443,7 +1444,7 @@
}
std::string device_path;
shill_properties.GetStringWithoutPathExpansion(
- flimflam::kDeviceProperty, &device_path);
+ shill::kDeviceProperty, &device_path);
if (!device_path.empty()) {
base::Closure callback = base::Bind(&base::DoNothing);
// If auto config or a static IP property changed, we need to reconnect
@@ -1534,7 +1535,7 @@
// Enable static ip config for ethernet. For wifi, enable if flag is set.
bool staticIPConfig = network->Matches(NetworkTypePattern::Ethernet()) ||
- (type == flimflam::kTypeWifi &&
+ (type == shill::kTypeWifi &&
CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kEnableStaticIPConfig));
dictionary.SetBoolean(kTagShowStaticIPConfig, staticIPConfig);
@@ -1542,7 +1543,7 @@
dictionary.SetBoolean(kTagShowPreferred, !network->profile_path().empty());
int priority = 0;
shill_properties.GetIntegerWithoutPathExpansion(
- flimflam::kPriorityProperty, &priority);
+ shill::kPriorityProperty, &priority);
bool preferred = priority > 0;
SetValueDictionary(&dictionary, kTagPreferred,
new base::FundamentalValue(preferred),
@@ -1550,12 +1551,12 @@
NetworkPropertyUIData auto_connect_ui_data(onc_source);
std::string onc_path_to_auto_connect;
- if (type == flimflam::kTypeWifi) {
+ if (type == shill::kTypeWifi) {
onc_path_to_auto_connect = base::StringPrintf(
"%s.%s",
onc::network_config::kWiFi,
onc::wifi::kAutoConnect);
- } else if (type == flimflam::kTypeVPN) {
+ } else if (type == shill::kTypeVPN) {
onc_path_to_auto_connect = base::StringPrintf(
"%s.%s",
onc::network_config::kVPN,
@@ -1567,7 +1568,7 @@
}
bool auto_connect = false;
shill_properties.GetBooleanWithoutPathExpansion(
- flimflam::kAutoConnectProperty, &auto_connect);
+ shill::kAutoConnectProperty, &auto_connect);
SetValueDictionary(&dictionary, kTagAutoConnect,
new base::FundamentalValue(auto_connect),
auto_connect_ui_data);
@@ -1604,13 +1605,13 @@
dictionary->SetBoolean(kTagDeviceConnected, connected_network != NULL);
- if (type == flimflam::kTypeWifi)
+ if (type == shill::kTypeWifi)
PopulateWifiDetails(network, shill_properties, dictionary);
- else if (type == flimflam::kTypeWimax)
+ else if (type == shill::kTypeWimax)
PopulateWimaxDetails(network, shill_properties, dictionary);
- else if (type == flimflam::kTypeCellular)
+ else if (type == shill::kTypeCellular)
PopulateCellularDetails(network, shill_properties, dictionary);
- else if (type == flimflam::kTypeVPN)
+ else if (type == shill::kTypeVPN)
PopulateVPNDetails(network, shill_properties, dictionary);
}
@@ -1622,13 +1623,13 @@
std::string security, eap_method;
shill_properties.GetStringWithoutPathExpansion(
- flimflam::kSecurityProperty, &security);
+ shill::kSecurityProperty, &security);
shill_properties.GetStringWithoutPathExpansion(
- flimflam::kEapMethodProperty, &eap_method);
+ shill::kEapMethodProperty, &eap_method);
dictionary->SetString(kTagEncryption, EncryptionString(security, eap_method));
- CopyStringFromDictionary(shill_properties, flimflam::kWifiBSsid,
+ CopyStringFromDictionary(shill_properties, shill::kWifiBSsid,
kTagBssid, dictionary);
- CopyIntegerFromDictionary(shill_properties, flimflam::kWifiFrequency,
+ CopyIntegerFromDictionary(shill_properties, shill::kWifiFrequency,
kTagFrequency, false, dictionary);
}
@@ -1636,25 +1637,25 @@
const base::DictionaryValue& shill_properties,
base::DictionaryValue* dictionary) {
dictionary->SetInteger(kTagStrength, wimax->signal_strength());
- CopyStringFromDictionary(shill_properties, flimflam::kEapIdentityProperty,
+ CopyStringFromDictionary(shill_properties, shill::kEapIdentityProperty,
kTagIdentity, dictionary);
}
void CreateDictionaryFromCellularApn(const base::DictionaryValue* apn,
base::DictionaryValue* dictionary) {
- CopyStringFromDictionary(*apn, flimflam::kApnProperty,
+ CopyStringFromDictionary(*apn, shill::kApnProperty,
kTagApn, dictionary);
- CopyStringFromDictionary(*apn, flimflam::kApnNetworkIdProperty,
+ CopyStringFromDictionary(*apn, shill::kApnNetworkIdProperty,
kTagNetworkId, dictionary);
- CopyStringFromDictionary(*apn, flimflam::kApnUsernameProperty,
+ CopyStringFromDictionary(*apn, shill::kApnUsernameProperty,
kTagUsername, dictionary);
- CopyStringFromDictionary(*apn, flimflam::kApnPasswordProperty,
+ CopyStringFromDictionary(*apn, shill::kApnPasswordProperty,
kTagPassword, dictionary);
- CopyStringFromDictionary(*apn, flimflam::kApnNameProperty,
+ CopyStringFromDictionary(*apn, shill::kApnNameProperty,
kTagName, dictionary);
- CopyStringFromDictionary(*apn, flimflam::kApnLocalizedNameProperty,
+ CopyStringFromDictionary(*apn, shill::kApnLocalizedNameProperty,
kTagLocalizedName, dictionary);
- CopyStringFromDictionary(*apn, flimflam::kApnLanguageProperty,
+ CopyStringFromDictionary(*apn, shill::kApnLanguageProperty,
kTagLanguage, dictionary);
}
@@ -1670,7 +1671,7 @@
ActivationStateString(cellular->activation_state()));
dictionary->SetString(kTagRoamingState,
RoamingStateString(cellular->roaming()));
- bool restricted = cellular->connection_state() == flimflam::kStatePortal;
+ bool restricted = cellular->connection_state() == shill::kStatePortal;
dictionary->SetString(kTagRestrictedPool,
restricted ?
l10n_util::GetStringUTF8(
@@ -1680,32 +1681,32 @@
const base::DictionaryValue* serving_operator = NULL;
if (shill_properties.GetDictionaryWithoutPathExpansion(
- flimflam::kServingOperatorProperty, &serving_operator)) {
- CopyStringFromDictionary(*serving_operator, flimflam::kOperatorNameKey,
+ shill::kServingOperatorProperty, &serving_operator)) {
+ CopyStringFromDictionary(*serving_operator, shill::kOperatorNameKey,
kTagOperatorName, dictionary);
- CopyStringFromDictionary(*serving_operator, flimflam::kOperatorCodeKey,
+ CopyStringFromDictionary(*serving_operator, shill::kOperatorCodeKey,
kTagOperatorCode, dictionary);
}
const base::DictionaryValue* olp = NULL;
if (shill_properties.GetDictionaryWithoutPathExpansion(
- flimflam::kPaymentPortalProperty, &olp)) {
+ shill::kPaymentPortalProperty, &olp)) {
std::string url;
- olp->GetStringWithoutPathExpansion(flimflam::kPaymentPortalURL, &url);
+ olp->GetStringWithoutPathExpansion(shill::kPaymentPortalURL, &url);
dictionary->SetString(kTagSupportUrl, url);
}
base::DictionaryValue* apn = new base::DictionaryValue;
const base::DictionaryValue* source_apn = NULL;
if (shill_properties.GetDictionaryWithoutPathExpansion(
- flimflam::kCellularApnProperty, &source_apn)) {
+ shill::kCellularApnProperty, &source_apn)) {
CreateDictionaryFromCellularApn(source_apn, apn);
}
dictionary->Set(kTagApn, apn);
base::DictionaryValue* last_good_apn = new base::DictionaryValue;
if (shill_properties.GetDictionaryWithoutPathExpansion(
- flimflam::kCellularLastGoodApnProperty, &source_apn)) {
+ shill::kCellularLastGoodApnProperty, &source_apn)) {
CreateDictionaryFromCellularApn(source_apn, last_good_apn);
}
dictionary->Set(kTagLastGoodApn, last_good_apn);
@@ -1724,36 +1725,36 @@
const base::DictionaryValue& device_properties = device->properties();
const NetworkPropertyUIData cellular_property_ui_data(
cellular->ui_data().onc_source());
- CopyStringFromDictionary(device_properties, flimflam::kManufacturerProperty,
+ CopyStringFromDictionary(device_properties, shill::kManufacturerProperty,
kTagManufacturer, dictionary);
- CopyStringFromDictionary(device_properties, flimflam::kModelIDProperty,
+ CopyStringFromDictionary(device_properties, shill::kModelIDProperty,
kTagModelId, dictionary);
CopyStringFromDictionary(device_properties,
- flimflam::kFirmwareRevisionProperty,
+ shill::kFirmwareRevisionProperty,
kTagFirmwareRevision, dictionary);
CopyStringFromDictionary(device_properties,
- flimflam::kHardwareRevisionProperty,
+ shill::kHardwareRevisionProperty,
kTagHardwareRevision, dictionary);
- CopyIntegerFromDictionary(device_properties, flimflam::kPRLVersionProperty,
+ CopyIntegerFromDictionary(device_properties, shill::kPRLVersionProperty,
kTagPrlVersion, true, dictionary);
- CopyStringFromDictionary(device_properties, flimflam::kMeidProperty,
+ CopyStringFromDictionary(device_properties, shill::kMeidProperty,
kTagMeid, dictionary);
- CopyStringFromDictionary(device_properties, flimflam::kIccidProperty,
+ CopyStringFromDictionary(device_properties, shill::kIccidProperty,
kTagIccid, dictionary);
- CopyStringFromDictionary(device_properties, flimflam::kImeiProperty,
+ CopyStringFromDictionary(device_properties, shill::kImeiProperty,
kTagImei, dictionary);
- mdn = CopyStringFromDictionary(device_properties, flimflam::kMdnProperty,
+ mdn = CopyStringFromDictionary(device_properties, shill::kMdnProperty,
kTagMdn, dictionary);
- CopyStringFromDictionary(device_properties, flimflam::kImsiProperty,
+ CopyStringFromDictionary(device_properties, shill::kImsiProperty,
kTagImsi, dictionary);
- CopyStringFromDictionary(device_properties, flimflam::kEsnProperty,
+ CopyStringFromDictionary(device_properties, shill::kEsnProperty,
kTagEsn, dictionary);
- CopyStringFromDictionary(device_properties, flimflam::kMinProperty,
+ CopyStringFromDictionary(device_properties, shill::kMinProperty,
kTagMin, dictionary);
std::string family;
device_properties.GetStringWithoutPathExpansion(
- flimflam::kTechnologyFamilyProperty, &family);
- dictionary->SetBoolean(kTagGsm, family == flimflam::kNetworkTechnologyGsm);
+ shill::kTechnologyFamilyProperty, &family);
+ dictionary->SetBoolean(kTagGsm, family == shill::kNetworkTechnologyGsm);
SetValueDictionary(
dictionary, kTagSimCardLockEnabled,
@@ -1772,7 +1773,7 @@
base::ListValue* apn_list_value = new base::ListValue();
const base::ListValue* apn_list;
if (device_properties.GetListWithoutPathExpansion(
- flimflam::kCellularApnListProperty, &apn_list)) {
+ shill::kCellularApnListProperty, &apn_list)) {
for (base::ListValue::const_iterator iter = apn_list->begin();
iter != apn_list->end(); ++iter) {
const base::DictionaryValue* dict;
@@ -1805,21 +1806,21 @@
// Set Cellular Buttons Visibility
dictionary->SetBoolean(
kTagDisableConnectButton,
- cellular->activation_state() == flimflam::kActivationStateActivating ||
+ cellular->activation_state() == shill::kActivationStateActivating ||
cellular->IsConnectingState());
// Don't show any account management related buttons if the activation
// state is unknown or no payment portal URL is available.
std::string support_url;
- if (cellular->activation_state() == flimflam::kActivationStateUnknown ||
+ if (cellular->activation_state() == shill::kActivationStateUnknown ||
!dictionary->GetString(kTagSupportUrl, &support_url) ||
support_url.empty()) {
VLOG(2) << "No support URL is available. Don't display buttons.";
return;
}
- if (cellular->activation_state() != flimflam::kActivationStateActivating &&
- cellular->activation_state() != flimflam::kActivationStateActivated) {
+ if (cellular->activation_state() != shill::kActivationStateActivating &&
+ cellular->activation_state() != shill::kActivationStateActivated) {
dictionary->SetBoolean(kTagShowActivateButton, true);
} else {
const MobileConfig::Carrier* carrier =
@@ -1834,8 +1835,8 @@
NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
const std::string& technology = cellular->network_technology();
bool force_show_view_account_button =
- (technology == flimflam::kNetworkTechnologyLte ||
- technology == flimflam::kNetworkTechnologyLteAdvanced) &&
+ (technology == shill::kNetworkTechnologyLte ||
+ technology == shill::kNetworkTechnologyLteAdvanced) &&
default_network &&
!mdn.empty();
@@ -1899,7 +1900,7 @@
base::Bind(&ShillError, "NetworkCommand: " + command));
} else if (command == kTagConfigure) {
NetworkConfigView::Show(service_path, GetNativeWindow());
- } else if (command == kTagActivate && type == flimflam::kTypeCellular) {
+ } else if (command == kTagActivate && type == shill::kTypeCellular) {
ash::network_connect::ActivateCellular(service_path);
// Activation may update network properties (e.g. ActivationState), so
// request them here in case they change.
@@ -1911,11 +1912,11 @@
}
void InternetOptionsHandler::AddConnection(const std::string& type) {
- if (type == flimflam::kTypeWifi)
- NetworkConfigView::ShowForType(flimflam::kTypeWifi, GetNativeWindow());
- else if (type == flimflam::kTypeVPN)
- NetworkConfigView::ShowForType(flimflam::kTypeVPN, GetNativeWindow());
- else if (type == flimflam::kTypeCellular)
+ if (type == shill::kTypeWifi)
+ NetworkConfigView::ShowForType(shill::kTypeWifi, GetNativeWindow());
+ else if (type == shill::kTypeVPN)
+ NetworkConfigView::ShowForType(shill::kTypeVPN, GetNativeWindow());
+ else if (type == shill::kTypeCellular)
ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow());
else
NOTREACHED();
@@ -1970,8 +1971,8 @@
for (NetworkStateHandler::FavoriteStateList::const_iterator iter =
favorites.begin(); iter != favorites.end(); ++iter) {
const FavoriteState* favorite = *iter;
- if (favorite->type() != flimflam::kTypeWifi &&
- favorite->type() != flimflam::kTypeVPN)
+ if (favorite->type() != shill::kTypeWifi &&
+ favorite->type() != shill::kTypeVPN)
continue;
list->Append(
BuildFavoriteDictionary(favorite, web_ui()->GetDeviceScaleFactor()));
diff --git a/chrome/browser/ui/webui/options/create_profile_handler.cc b/chrome/browser/ui/webui/options/create_profile_handler.cc
new file mode 100644
index 0000000..f88bacc
--- /dev/null
+++ b/chrome/browser/ui/webui/options/create_profile_handler.cc
@@ -0,0 +1,434 @@
+// Copyright 2013 The Chromium 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/options/create_profile_handler.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
+#include "base/value_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/managed_mode/managed_user_registration_utility.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/managed_mode/managed_user_service_factory.h"
+#include "chrome/browser/managed_mode/managed_user_sync_service.h"
+#include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_metrics.h"
+#include "chrome/browser/profiles/profiles_state.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/ui/webui/options/options_handlers_helper.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace options {
+
+CreateProfileHandler::CreateProfileHandler()
+ : profile_creation_type_(NO_CREATION_IN_PROGRESS),
+ weak_ptr_factory_(this) {
+}
+
+CreateProfileHandler::~CreateProfileHandler() {
+ CancelProfileRegistration(false);
+}
+
+void CreateProfileHandler::GetLocalizedValues(
+ base::DictionaryValue* localized_strings) {
+}
+
+void CreateProfileHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "cancelCreateProfile",
+ base::Bind(&CreateProfileHandler::HandleCancelProfileCreation,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "createProfile",
+ base::Bind(&CreateProfileHandler::CreateProfile,
+ base::Unretained(this)));
+}
+
+void CreateProfileHandler::CreateProfile(const ListValue* args) {
+ // This handler could have been called in managed mode, for example because
+ // the user fiddled with the web inspector. Silently return in this case.
+ Profile* current_profile = Profile::FromWebUI(web_ui());
+ if (current_profile->IsManaged())
+ return;
+
+ if (!profiles::IsMultipleProfilesEnabled())
+ return;
+
+ // We can have only one in progress profile creation
+ // at any given moment, if new ones are initiated just
+ // ignore them until we are done with the old one.
+ if (profile_creation_type_ != NO_CREATION_IN_PROGRESS)
+ return;
+
+ profile_creation_type_ = NON_SUPERVISED_PROFILE_CREATION;
+
+ DCHECK(profile_path_being_created_.empty());
+ profile_creation_start_time_ = base::TimeTicks::Now();
+
+ string16 name;
+ string16 icon;
+ std::string managed_user_id;
+ bool create_shortcut = false;
+ bool managed_user = false;
+ if (args->GetString(0, &name) && args->GetString(1, &icon)) {
+ if (args->GetBoolean(2, &create_shortcut)) {
+ bool success = args->GetBoolean(3, &managed_user);
+ DCHECK(success);
+ success = args->GetString(4, &managed_user_id);
+ DCHECK(success);
+ }
+ }
+
+ if (managed_user && ManagedUserService::AreManagedUsersEnabled()) {
+ if (!IsValidExistingManagedUserId(managed_user_id))
+ return;
+
+ profile_creation_type_ = SUPERVISED_PROFILE_IMPORT;
+ if (managed_user_id.empty()) {
+ profile_creation_type_ = SUPERVISED_PROFILE_CREATION;
+ managed_user_id =
+ ManagedUserRegistrationUtility::GenerateNewManagedUserId();
+
+ // If sync is not yet fully initialized, the creation may take extra time,
+ // so show a message. Import doesn't wait for an acknowledgement, so it
+ // won't have the same potential delay.
+ ProfileSyncService* sync_service =
+ ProfileSyncServiceFactory::GetInstance()->GetForProfile(
+ current_profile);
+ ProfileSyncService::SyncStatusSummary status =
+ sync_service->QuerySyncStatusSummary();
+ if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED) {
+ ShowProfileCreationWarning(l10n_util::GetStringUTF16(
+ IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
+ }
+ }
+ }
+
+ ProfileMetrics::LogProfileAddNewUser(ProfileMetrics::ADD_NEW_USER_DIALOG);
+
+ profile_path_being_created_ = ProfileManager::CreateMultiProfileAsync(
+ name, icon,
+ base::Bind(&CreateProfileHandler::OnProfileCreated,
+ weak_ptr_factory_.GetWeakPtr(),
+ create_shortcut,
+ helper::GetDesktopType(web_ui()),
+ managed_user_id),
+ managed_user_id);
+}
+
+void CreateProfileHandler::OnProfileCreated(
+ bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ const std::string& managed_user_id,
+ Profile* profile,
+ Profile::CreateStatus status) {
+ if (status != Profile::CREATE_STATUS_CREATED)
+ RecordProfileCreationMetrics(status);
+
+ switch (status) {
+ case Profile::CREATE_STATUS_LOCAL_FAIL: {
+ ShowProfileCreationError(profile,
+ GetProfileCreationErrorMessage(LOCAL_ERROR));
+ break;
+ }
+ case Profile::CREATE_STATUS_CREATED: {
+ // Do nothing for an intermediate status.
+ break;
+ }
+ case Profile::CREATE_STATUS_INITIALIZED: {
+ HandleProfileCreationSuccess(create_shortcut, desktop_type,
+ managed_user_id, profile);
+ break;
+ }
+ // User-initiated cancellation is handled in CancelProfileRegistration and
+ // does not call this callback.
+ case Profile::CREATE_STATUS_CANCELED:
+ // Managed user registration errors are handled in
+ // OnManagedUserRegistered().
+ case Profile::CREATE_STATUS_REMOTE_FAIL:
+ case Profile::MAX_CREATE_STATUS: {
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
+void CreateProfileHandler::HandleProfileCreationSuccess(
+ bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ const std::string& managed_user_id,
+ Profile* profile) {
+ switch (profile_creation_type_) {
+ case NON_SUPERVISED_PROFILE_CREATION: {
+ DCHECK(managed_user_id.empty());
+ CreateShortcutAndShowSuccess(create_shortcut, desktop_type, profile);
+ break;
+ }
+ case SUPERVISED_PROFILE_CREATION:
+ case SUPERVISED_PROFILE_IMPORT:
+ RegisterManagedUser(create_shortcut, desktop_type,
+ managed_user_id, profile);
+ break;
+ case NO_CREATION_IN_PROGRESS:
+ NOTREACHED();
+ break;
+ }
+}
+
+void CreateProfileHandler::RegisterManagedUser(
+ bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ const std::string& managed_user_id,
+ Profile* new_profile) {
+ DCHECK_EQ(profile_path_being_created_.value(),
+ new_profile->GetPath().value());
+
+ ManagedUserService* managed_user_service =
+ ManagedUserServiceFactory::GetForProfile(new_profile);
+
+ // Register the managed user using the profile of the custodian.
+ managed_user_registration_utility_ =
+ ManagedUserRegistrationUtility::Create(Profile::FromWebUI(web_ui()));
+ managed_user_service->RegisterAndInitSync(
+ managed_user_registration_utility_.get(),
+ Profile::FromWebUI(web_ui()),
+ managed_user_id,
+ base::Bind(&CreateProfileHandler::OnManagedUserRegistered,
+ weak_ptr_factory_.GetWeakPtr(),
+ create_shortcut,
+ desktop_type,
+ new_profile));
+}
+
+void CreateProfileHandler::OnManagedUserRegistered(
+ bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ Profile* profile,
+ const GoogleServiceAuthError& error) {
+ GoogleServiceAuthError::State state = error.state();
+ RecordSupervisedProfileCreationMetrics(state);
+ if (state == GoogleServiceAuthError::NONE) {
+ CreateShortcutAndShowSuccess(create_shortcut, desktop_type, profile);
+ return;
+ }
+
+ string16 error_msg;
+ if (state == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
+ state == GoogleServiceAuthError::USER_NOT_SIGNED_UP ||
+ state == GoogleServiceAuthError::ACCOUNT_DELETED ||
+ state == GoogleServiceAuthError::ACCOUNT_DISABLED) {
+ error_msg = GetProfileCreationErrorMessage(SIGNIN_ERROR);
+ } else {
+ error_msg = GetProfileCreationErrorMessage(REMOTE_ERROR);
+ }
+ ShowProfileCreationError(profile, error_msg);
+}
+
+void CreateProfileHandler::CreateShortcutAndShowSuccess(
+ bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ Profile* profile) {
+ if (create_shortcut) {
+ ProfileShortcutManager* shortcut_manager =
+ g_browser_process->profile_manager()->profile_shortcut_manager();
+
+ if (shortcut_manager)
+ shortcut_manager->CreateProfileShortcut(profile->GetPath());
+ }
+
+ DCHECK_EQ(profile_path_being_created_.value(), profile->GetPath().value());
+ profile_path_being_created_.clear();
+ DCHECK_NE(NO_CREATION_IN_PROGRESS, profile_creation_type_);
+ DictionaryValue dict;
+ dict.SetString("name",
+ profile->GetPrefs()->GetString(prefs::kProfileName));
+ dict.Set("filePath", base::CreateFilePathValue(profile->GetPath()));
+ bool is_managed =
+ profile_creation_type_ == SUPERVISED_PROFILE_CREATION ||
+ profile_creation_type_ == SUPERVISED_PROFILE_IMPORT;
+ dict.SetBoolean("isManaged", is_managed);
+ web_ui()->CallJavascriptFunction(
+ GetJavascriptMethodName(PROFILE_CREATION_SUCCESS), dict);
+
+ // If the new profile is a supervised user, instead of opening a new window
+ // right away, a confirmation overlay will be shown by JS from the creation
+ // dialog. If we are importing an existing supervised profile or creating a
+ // new non-supervised user profile we don't show any confirmation, so open
+ // the new window now.
+ if (profile_creation_type_ != SUPERVISED_PROFILE_CREATION) {
+ // Opening the new window must be the last action, after all callbacks
+ // have been run, to give them a chance to initialize the profile.
+ helper::OpenNewWindowForProfile(desktop_type,
+ profile,
+ Profile::CREATE_STATUS_INITIALIZED);
+ }
+ profile_creation_type_ = NO_CREATION_IN_PROGRESS;
+}
+
+void CreateProfileHandler::ShowProfileCreationError(Profile* profile,
+ const string16& error) {
+ DCHECK_NE(NO_CREATION_IN_PROGRESS, profile_creation_type_);
+ profile_creation_type_ = NO_CREATION_IN_PROGRESS;
+ profile_path_being_created_.clear();
+ web_ui()->CallJavascriptFunction(
+ GetJavascriptMethodName(PROFILE_CREATION_ERROR),
+ base::StringValue(error));
+ helper::DeleteProfileAtPath(profile->GetPath(), web_ui());
+}
+
+void CreateProfileHandler::ShowProfileCreationWarning(
+ const string16& warning) {
+ DCHECK_EQ(SUPERVISED_PROFILE_CREATION, profile_creation_type_);
+ web_ui()->CallJavascriptFunction("BrowserOptions.showCreateProfileWarning",
+ base::StringValue(warning));
+}
+
+void CreateProfileHandler::HandleCancelProfileCreation(const ListValue* args) {
+ CancelProfileRegistration(true);
+}
+
+void CreateProfileHandler::CancelProfileRegistration(bool user_initiated) {
+ if (profile_path_being_created_.empty())
+ return;
+
+ ProfileManager* manager = g_browser_process->profile_manager();
+ Profile* new_profile = manager->GetProfileByPath(profile_path_being_created_);
+ if (!new_profile)
+ return;
+
+ // Non-managed user creation cannot be canceled. (Creating a non-managed
+ // profile shouldn't take significant time, and it can easily be deleted
+ // afterward.)
+ if (!new_profile->IsManaged())
+ return;
+
+ if (user_initiated) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Profile.CreateTimeCanceledNoTimeout",
+ base::TimeTicks::Now() - profile_creation_start_time_);
+ RecordProfileCreationMetrics(Profile::CREATE_STATUS_CANCELED);
+ }
+
+ DCHECK(managed_user_registration_utility_.get());
+ managed_user_registration_utility_.reset();
+
+ DCHECK_NE(NO_CREATION_IN_PROGRESS, profile_creation_type_);
+ profile_creation_type_ = NO_CREATION_IN_PROGRESS;
+
+ // Cancelling registration means the callback passed into
+ // RegisterAndInitSync() won't be called, so the cleanup must be done here.
+ profile_path_being_created_.clear();
+ helper::DeleteProfileAtPath(new_profile->GetPath(), web_ui());
+}
+
+void CreateProfileHandler::RecordProfileCreationMetrics(
+ Profile::CreateStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("Profile.CreateResult",
+ status,
+ Profile::MAX_CREATE_STATUS);
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Profile.CreateTimeNoTimeout",
+ base::TimeTicks::Now() - profile_creation_start_time_);
+}
+
+void CreateProfileHandler::RecordSupervisedProfileCreationMetrics(
+ GoogleServiceAuthError::State error_state) {
+ if (profile_creation_type_ == SUPERVISED_PROFILE_CREATION) {
+ UMA_HISTOGRAM_ENUMERATION("Profile.SupervisedProfileCreateError",
+ error_state,
+ GoogleServiceAuthError::NUM_STATES);
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Profile.SupervisedProfileTotalCreateTime",
+ base::TimeTicks::Now() - profile_creation_start_time_);
+ } else {
+ DCHECK_EQ(SUPERVISED_PROFILE_IMPORT, profile_creation_type_);
+ UMA_HISTOGRAM_ENUMERATION("Profile.SupervisedProfileImportError",
+ error_state,
+ GoogleServiceAuthError::NUM_STATES);
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Profile.SupervisedProfileTotalImportTime",
+ base::TimeTicks::Now() - profile_creation_start_time_);
+ }
+}
+
+string16 CreateProfileHandler::GetProfileCreationErrorMessage(
+ ProfileCreationErrorType error) const {
+ int message_id = -1;
+ switch (error) {
+ case SIGNIN_ERROR:
+ message_id =
+ profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
+ IDS_MANAGED_USER_IMPORT_SIGN_IN_ERROR :
+ IDS_PROFILES_CREATE_SIGN_IN_ERROR;
+ break;
+ case REMOTE_ERROR:
+ message_id =
+ profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
+ IDS_MANAGED_USER_IMPORT_REMOTE_ERROR :
+ IDS_PROFILES_CREATE_REMOTE_ERROR;
+ break;
+ case LOCAL_ERROR:
+ message_id =
+ profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
+ IDS_MANAGED_USER_IMPORT_LOCAL_ERROR :
+ IDS_PROFILES_CREATE_LOCAL_ERROR;
+ break;
+ }
+
+ return l10n_util::GetStringUTF16(message_id);
+}
+
+std::string CreateProfileHandler::GetJavascriptMethodName(
+ ProfileCreationStatus status) const {
+ switch (status) {
+ case PROFILE_CREATION_SUCCESS:
+ return profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
+ "BrowserOptions.showManagedUserImportSuccess" :
+ "BrowserOptions.showCreateProfileSuccess";
+ case PROFILE_CREATION_ERROR:
+ return profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
+ "BrowserOptions.showManagedUserImportError" :
+ "BrowserOptions.showCreateProfileError";
+ }
+
+ NOTREACHED();
+ return std::string();
+}
+
+bool CreateProfileHandler::IsValidExistingManagedUserId(
+ const std::string& existing_managed_user_id) const {
+ if (existing_managed_user_id.empty())
+ return true;
+
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAllowCreateExistingManagedUsers)) {
+ return false;
+ }
+
+ Profile* profile = Profile::FromWebUI(web_ui());
+ const DictionaryValue* dict =
+ ManagedUserSyncServiceFactory::GetForProfile(profile)->GetManagedUsers();
+ if (!dict->HasKey(existing_managed_user_id))
+ return false;
+
+ // Check if this managed user already exists on this machine.
+ const ProfileInfoCache& cache =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
+ if (existing_managed_user_id == cache.GetManagedUserIdOfProfileAtIndex(i))
+ return false;
+ }
+ return true;
+}
+
+} // namespace options
diff --git a/chrome/browser/ui/webui/options/create_profile_handler.h b/chrome/browser/ui/webui/options/create_profile_handler.h
new file mode 100644
index 0000000..d443df9
--- /dev/null
+++ b/chrome/browser/ui/webui/options/create_profile_handler.h
@@ -0,0 +1,164 @@
+// Copyright 2013 The Chromium 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_OPTIONS_CREATE_PROFILE_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS_CREATE_PROFILE_HANDLER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_window.h"
+#include "chrome/browser/ui/host_desktop.h"
+#include "chrome/browser/ui/webui/options/options_ui.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+class ManagedUserRegistrationUtility;
+
+namespace options {
+
+// Handler for the 'create profile' overlay.
+class CreateProfileHandler: public OptionsPageUIHandler {
+ public:
+ CreateProfileHandler();
+ virtual ~CreateProfileHandler();
+
+ // OptionsPageUIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ // Represents the final profile creation status. It is used to map
+ // the status to the javascript method to be called.
+ enum ProfileCreationStatus {
+ PROFILE_CREATION_SUCCESS,
+ PROFILE_CREATION_ERROR,
+ };
+
+ // Represents errors that could occur during a profile creation.
+ // It is used to map error types to messages that will be displayed
+ // to the user.
+ enum ProfileCreationErrorType {
+ REMOTE_ERROR,
+ LOCAL_ERROR,
+ SIGNIN_ERROR
+ };
+
+ // Represents the type of the in progress profile creation operation.
+ // It is used to map the type of the profile creation operation to the
+ // correct UMA metric name.
+ enum ProfileCreationOperationType {
+ SUPERVISED_PROFILE_CREATION,
+ SUPERVISED_PROFILE_IMPORT,
+ NON_SUPERVISED_PROFILE_CREATION,
+ NO_CREATION_IN_PROGRESS
+ };
+
+ // Asynchronously creates and initializes a new profile.
+ // The arguments are as follows:
+ // 0: name (string)
+ // 1: icon (string)
+ // 2: a flag stating whether we should create a profile desktop shortcut
+ // (optional, boolean)
+ // 3: a flag stating whether the user should be managed (optional, boolean)
+ // 4: a string representing the managed user ID.
+ void CreateProfile(const base::ListValue* args);
+
+ // If a local error occurs during profile creation, then show an appropriate
+ // error message. However, if profile creation succeeded and the
+ // profile being created/imported is a supervised user profile,
+ // then proceed with the registration step. Otherwise, update the UI
+ // as the final task after a new profile has been created.
+ void OnProfileCreated(bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ const std::string& managed_user_id,
+ Profile* profile,
+ Profile::CreateStatus status);
+
+ void HandleProfileCreationSuccess(bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ const std::string& managed_user_id,
+ Profile* profile);
+
+ // After a new managed-user profile has been created, registers the user with
+ // the management server.
+ void RegisterManagedUser(bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ const std::string& managed_user_id,
+ Profile* new_profile);
+
+ // Called back with the result of the managed user registration.
+ void OnManagedUserRegistered(bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ Profile* profile,
+ const GoogleServiceAuthError& error);
+
+ // Creates desktop shortcut and updates the UI to indicate success
+ // when creating a profile.
+ void CreateShortcutAndShowSuccess(bool create_shortcut,
+ chrome::HostDesktopType desktop_type,
+ Profile* profile);
+
+ // Updates the UI to show an error when creating a profile.
+ void ShowProfileCreationError(Profile* profile, const string16& error);
+
+ // Updates the UI to show a non-fatal warning when creating a profile.
+ void ShowProfileCreationWarning(const string16& warning);
+
+ // Cancels creation of a managed-user profile currently in progress, as
+ // indicated by profile_path_being_created_, removing the object and files
+ // and canceling managed-user registration. This is the handler for the
+ // "cancelCreateProfile" message. |args| is not used.
+ void HandleCancelProfileCreation(const base::ListValue* args);
+
+ // Internal implementation. This may safely be called whether profile creation
+ // or registration is in progress or not. |user_initiated| should be true if
+ // the cancellation was deliberately requested by the user, and false if it
+ // was caused implicitly, e.g. by shutting down the browser.
+ void CancelProfileRegistration(bool user_initiated);
+
+ // Records UMA histograms relevant to profile creation.
+ void RecordProfileCreationMetrics(Profile::CreateStatus status);
+
+ // Records UMA histograms relevant to supervised user profiles
+ // creation and registration.
+ void RecordSupervisedProfileCreationMetrics(
+ GoogleServiceAuthError::State error_state);
+
+ string16 GetProfileCreationErrorMessage(ProfileCreationErrorType error) const;
+ std::string GetJavascriptMethodName(ProfileCreationStatus status) const;
+
+ bool IsValidExistingManagedUserId(
+ const std::string& existing_managed_user_id) const;
+
+ // Used to allow cancelling a profile creation (particularly a managed-user
+ // registration) in progress. Set when profile creation is begun, and
+ // cleared when all the callbacks have been run and creation is complete.
+ base::FilePath profile_path_being_created_;
+
+ // Used to track how long profile creation takes.
+ base::TimeTicks profile_creation_start_time_;
+
+ scoped_ptr<ManagedUserRegistrationUtility> managed_user_registration_utility_;
+
+ // Indicates the type of the in progress profile creation operation.
+ // The value is only relevant while we are creating/importing a profile.
+ ProfileCreationOperationType profile_creation_type_;
+
+ base::WeakPtrFactory<CreateProfileHandler> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CreateProfileHandler);
+};
+
+} // namespace options
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS_CREATE_PROFILE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options/media_galleries_handler.cc b/chrome/browser/ui/webui/options/media_galleries_handler.cc
index 982aaeb..d42c3c9 100644
--- a/chrome/browser/ui/webui/options/media_galleries_handler.cc
+++ b/chrome/browser/ui/webui/options/media_galleries_handler.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/media_galleries/media_file_system_registry.h"
+#include "chrome/browser/media_galleries/media_galleries_histograms.h"
#include "chrome/browser/media_galleries/media_galleries_preferences.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/storage_monitor/storage_monitor.h"
@@ -134,6 +135,7 @@
return;
}
+ media_galleries::UsageCount(media_galleries::WEBUI_FORGET_GALLERY);
DCHECK(StorageMonitor::GetInstance()->IsInitialized());
MediaGalleriesPreferences* preferences =
g_browser_process->media_file_system_registry()->GetPreferences(
@@ -144,6 +146,7 @@
void MediaGalleriesHandler::FileSelected(const base::FilePath& path,
int index,
void* params) {
+ media_galleries::UsageCount(media_galleries::WEBUI_ADD_GALLERY);
DCHECK(StorageMonitor::GetInstance()->IsInitialized());
MediaGalleriesPreferences* preferences =
g_browser_process->media_file_system_registry()->GetPreferences(
diff --git a/chrome/browser/ui/webui/options/options_handlers_helper.cc b/chrome/browser/ui/webui/options/options_handlers_helper.cc
new file mode 100644
index 0000000..f754eac
--- /dev/null
+++ b/chrome/browser/ui/webui/options/options_handlers_helper.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 "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
+#include "base/bind.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_metrics.h"
+#include "chrome/browser/profiles/profile_window.h"
+#include "chrome/browser/profiles/profiles_state.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+
+namespace options {
+namespace helper {
+
+chrome::HostDesktopType GetDesktopType(content::WebUI* web_ui) {
+ DCHECK(web_ui);
+ content::WebContents* web_contents = web_ui->GetWebContents();
+ Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
+ if (browser)
+ return browser->host_desktop_type();
+
+ apps::ShellWindow* shell_window =
+ apps::ShellWindowRegistry::Get(Profile::FromWebUI(web_ui))->
+ GetShellWindowForRenderViewHost(web_contents->GetRenderViewHost());
+ if (shell_window) {
+ return chrome::GetHostDesktopTypeForNativeWindow(
+ shell_window->GetNativeWindow());
+ }
+
+ return chrome::GetActiveDesktop();
+}
+
+void OpenNewWindowForProfile(chrome::HostDesktopType desktop_type,
+ Profile* profile,
+ Profile::CreateStatus status) {
+ if (status != Profile::CREATE_STATUS_INITIALIZED)
+ return;
+
+ profiles::FindOrCreateNewWindowForProfile(
+ profile,
+ chrome::startup::IS_PROCESS_STARTUP,
+ chrome::startup::IS_FIRST_RUN,
+ desktop_type,
+ false);
+}
+
+void DeleteProfileAtPath(base::FilePath file_path, content::WebUI* web_ui) {
+ DCHECK(web_ui);
+ // This handler could have been called in managed mode, for example because
+ // the user fiddled with the web inspector. Silently return in this case.
+ if (Profile::FromWebUI(web_ui)->IsManaged())
+ return;
+
+ if (!profiles::IsMultipleProfilesEnabled())
+ return;
+
+ ProfileMetrics::LogProfileDeleteUser(ProfileMetrics::PROFILE_DELETED);
+
+ g_browser_process->profile_manager()->ScheduleProfileForDeletion(
+ file_path,
+ base::Bind(&OpenNewWindowForProfile, GetDesktopType(web_ui)));
+}
+
+} // namespace helper
+} // namespace options
+
+
diff --git a/chrome/browser/ui/webui/options/options_handlers_helper.h b/chrome/browser/ui/webui/options/options_handlers_helper.h
new file mode 100644
index 0000000..493db5e
--- /dev/null
+++ b/chrome/browser/ui/webui/options/options_handlers_helper.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_UI_WEBUI_OPTIONS_OPTIONS_HANDLERS_HELPER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS_OPTIONS_HANDLERS_HELPER_H_
+
+#include "base/files/file_path.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/host_desktop.h"
+
+namespace content {
+class WebUI;
+}
+
+namespace options {
+namespace helper {
+
+// Returns the current desktop type.
+chrome::HostDesktopType GetDesktopType(content::WebUI* web_ui);
+
+void OpenNewWindowForProfile(chrome::HostDesktopType desktop_type,
+ Profile* profile,
+ Profile::CreateStatus status);
+
+// Deletes the profile at the given |file_path|.
+void DeleteProfileAtPath(base::FilePath file_path, content::WebUI* web_ui);
+
+} // namespace helper
+} // namespace options
+
+
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS_OPTIONS_HANDLERS_HELPER_H_
diff --git a/chrome/browser/ui/webui/options/options_ui.cc b/chrome/browser/ui/webui/options/options_ui.cc
index 2eff54f..3d7b8ae 100644
--- a/chrome/browser/ui/webui/options/options_ui.cc
+++ b/chrome/browser/ui/webui/options/options_ui.cc
@@ -28,6 +28,7 @@
#include "chrome/browser/ui/webui/options/content_settings_handler.h"
#include "chrome/browser/ui/webui/options/cookies_view_handler.h"
#include "chrome/browser/ui/webui/options/core_options_handler.h"
+#include "chrome/browser/ui/webui/options/create_profile_handler.h"
#include "chrome/browser/ui/webui/options/font_settings_handler.h"
#include "chrome/browser/ui/webui/options/handler_options_handler.h"
#include "chrome/browser/ui/webui/options/home_page_overlay_handler.h"
@@ -256,6 +257,7 @@
AddOptionsPageUIHandler(localized_strings, new ClearBrowserDataHandler());
AddOptionsPageUIHandler(localized_strings, new ContentSettingsHandler());
AddOptionsPageUIHandler(localized_strings, new CookiesViewHandler());
+ AddOptionsPageUIHandler(localized_strings, new CreateProfileHandler());
AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler());
#if defined(ENABLE_GOOGLE_NOW)
AddOptionsPageUIHandler(localized_strings, new GeolocationOptionsHandler());
diff --git a/chrome/browser/ui/webui/options/preferences_browsertest.cc b/chrome/browser/ui/webui/options/preferences_browsertest.cc
index 365e211..6533a0c 100644
--- a/chrome/browser/ui/webui/options/preferences_browsertest.cc
+++ b/chrome/browser/ui/webui/options/preferences_browsertest.cc
@@ -761,15 +761,15 @@
service_test->ClearServices();
service_test->AddService("stub_ethernet",
"eth0",
- flimflam::kTypeEthernet,
- flimflam::kStateOnline,
+ shill::kTypeEthernet,
+ shill::kStateOnline,
true, // add to visible
true); // add to watchlist
service_test->SetServiceProperty("stub_ethernet",
- flimflam::kGuidProperty,
+ shill::kGuidProperty,
base::StringValue("stub_ethernet"));
service_test->SetServiceProperty("stub_ethernet",
- flimflam::kProfileProperty,
+ shill::kProfileProperty,
base::StringValue(kUserProfilePath));
profile_test->AddService(kUserProfilePath, "stub_wifi2");
}
diff --git a/chrome/browser/ui/webui/policy_ui.cc b/chrome/browser/ui/webui/policy_ui.cc
index fa9ed74..7e00861 100644
--- a/chrome/browser/ui/webui/policy_ui.cc
+++ b/chrome/browser/ui/webui/policy_ui.cc
@@ -64,7 +64,7 @@
#include "chrome/browser/policy/policy_domain_descriptor.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_set.h"
-#include "components/policy/core/common/policy_schema.h"
+#include "components/policy/core/common/schema.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#endif
@@ -579,11 +579,11 @@
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);
+ policy::Schema policy_schema = schema->second;
+ for (policy::Schema::Iterator it_policies =
+ policy_schema.GetPropertiesIterator();
+ !it_policies.IsAtEnd(); it_policies.Advance()) {
+ policy_names->SetBoolean(it_policies.key(), true);
}
}
extension_value->Set("policyNames", policy_names);
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index c1f15cd..dda5668 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -259,13 +259,21 @@
return; // Already in progress.
OAuth2TokenService* service = NULL;
+ std::string account_id;
if (type == "profile") {
Profile* profile = Profile::FromWebUI(handler_->web_ui());
- if (profile)
- service = ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+ if (profile) {
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+ account_id = token_service->GetPrimaryAccountId();
+ service = token_service;
+ }
} else if (type == "device") {
#if defined(OS_CHROMEOS)
- service = chromeos::DeviceOAuth2TokenServiceFactory::Get();
+ chromeos::DeviceOAuth2TokenService* token_service =
+ chromeos::DeviceOAuth2TokenServiceFactory::Get();
+ account_id = token_service->GetRobotAccountId();
+ service = token_service;
#endif
}
@@ -273,7 +281,7 @@
OAuth2TokenService::ScopeSet oauth_scopes;
oauth_scopes.insert(cloud_print::kCloudPrintAuth);
scoped_ptr<OAuth2TokenService::Request> request(
- service->StartRequest(oauth_scopes, this));
+ service->StartRequest(account_id, oauth_scopes, this));
requests_[type].reset(request.release());
} else {
handler_->SendAccessToken(type, std::string()); // Unknown type.
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index 5460bdb..35b89cb 100644
--- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -8,7 +8,7 @@
#include "base/value_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_info_cache_observer.h"
@@ -47,14 +47,6 @@
const char kKeyIsDesktop[] = "isDesktopUser";
const char kKeyAvatarUrl[] = "userImage";
const char kKeyNeedsSignin[] = "needsSignin";
-const char kGAIAPictureFileNameKey[] = "gaia_picture_file_name";
-
-// Max number of users to show.
-const size_t kMaxUsers = 18;
-
-// Type of the login screen UI that is currently presented to user.
-const char kSourceGaiaSignin[] = "gaia-signin";
-const char kSourceAccountPicker[] = "account-picker";
// JS API callback names.
const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
@@ -173,16 +165,10 @@
}
void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
- // TODO(noms): Should display the addUser page here, not do a redirect.
Browser* browser = chrome::FindOrCreateTabbedBrowser(
ProfileManager::GetLastUsedProfileAllowedByPolicy(), desktop_type_);
DCHECK(browser);
- chrome::NavigateParams params(browser,
- GURL("chrome://settings/createProfile"),
- content::PAGE_TRANSITION_LINK);
- params.disposition = NEW_FOREGROUND_TAB;
- params.window_action = chrome::NavigateParams::SHOW_WINDOW;
- chrome::Navigate(¶ms);
+ profiles::CreateAndSwitchToNewProfile(desktop_type_);
}
void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
@@ -211,7 +197,7 @@
void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
Browser* browser = chrome::FindOrCreateTabbedBrowser(
ProfileManager::GetLastUsedProfileAllowedByPolicy(), desktop_type_);
- AvatarMenuModel::SwitchToGuestProfileWindow(browser);
+ AvatarMenu::SwitchToGuestProfileWindow(browser);
}
void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/signin/user_manager_ui.cc b/chrome/browser/ui/webui/signin/user_manager_ui.cc
index 67e8ed5..c26423f 100644
--- a/chrome/browser/ui/webui/signin/user_manager_ui.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_ui.cc
@@ -15,13 +15,9 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/webui/web_ui_util.h"
-namespace {
- // JS file names.
- const char kStringsJSPath[] = "strings.js";
- const char kUserManagerJSPath[] = "user_manager.js";
- const char kHeaderBarJSPath[] = "header_bar.js";
- const char kAccountPickerJSPath[] = "screen_account_picker.js";
-}
+// JS file names.
+const char kStringsJSPath[] = "strings.js";
+const char kUserManagerJSPath[] = "user_manager.js";
UserManagerUI::UserManagerUI(content::WebUI* web_ui)
: WebUIController(web_ui) {
diff --git a/chrome/browser/ui/webui/sync_setup_handler_unittest.cc b/chrome/browser/ui/webui/sync_setup_handler_unittest.cc
index 22b2d28..a56c675 100644
--- a/chrome/browser/ui/webui/sync_setup_handler_unittest.cc
+++ b/chrome/browser/ui/webui/sync_setup_handler_unittest.cc
@@ -48,7 +48,6 @@
MATCHER_P(ModelTypeSetMatches, value, "") { return arg.Equals(value); }
const char kTestUser[] = "chrome.p13n.test@gmail.com";
-const char kTestPassword[] = "passwd";
// Returns a ModelTypeSet with all user selectable types set.
syncer::ModelTypeSet GetAllTypes() {
diff --git a/chrome/browser/ui/webui/version_handler.cc b/chrome/browser/ui/webui/version_handler.cc
index 8c54037..638ff0b 100644
--- a/chrome/browser/ui/webui/version_handler.cc
+++ b/chrome/browser/ui/webui/version_handler.cc
@@ -101,10 +101,7 @@
}
#else
// In release mode, display the hashes only.
- std::vector<string16> active_groups;
- chrome_variations::GetFieldTrialActiveGroupIdsAsStrings(&active_groups);
- for (size_t i = 0; i < active_groups.size(); ++i)
- variations.push_back(UTF16ToASCII(active_groups[i]));
+ chrome_variations::GetFieldTrialActiveGroupIdsAsStrings(&variations);
#endif
ListValue variations_list;
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash.cc b/chrome/browser/ui/window_sizer/window_sizer_ash.cc
index f962fd6..6f41a86 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_ash.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash.cc
@@ -7,6 +7,7 @@
#include "ash/ash_switches.h"
#include "ash/shell.h"
#include "ash/wm/mru_window_tracker.h"
+#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/auto_window_management.h"
#include "base/command_line.h"
@@ -135,7 +136,7 @@
*show_state = ui::SHOW_STATE_MAXIMIZED;
return;
}
- bool maximized = ash::wm::IsWindowMaximized(top_window);
+ bool maximized = ash::wm::GetWindowState(top_window)->IsMaximized();
// We ignore the saved show state, but look instead for the top level
// window's show state.
if (passed_show_state == ui::SHOW_STATE_DEFAULT) {
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
index c5e1f5e..9874fba 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
@@ -7,7 +7,7 @@
#include "ash/test/ash_test_base.h"
#include "ash/test/test_shell_delegate.h"
#include "ash/wm/window_resizer.h"
-#include "ash/wm/window_settings.h"
+#include "ash/wm/window_state.h"
#include "base/compiler_specific.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/window_sizer/window_sizer_common_unittest.h"
@@ -62,7 +62,7 @@
create_params.window = this;
browser_.reset(new Browser(create_params));
if (browser_->is_type_tabbed() || browser_->is_app()) {
- ash::wm::GetWindowSettings(native_window_.get())->
+ ash::wm::GetWindowState(native_window_.get())->
set_window_position_managed(true);
}
}
diff --git a/chrome/browser/user_style_sheet_watcher.cc b/chrome/browser/user_style_sheet_watcher.cc
index a034f50..f52a705 100644
--- a/chrome/browser/user_style_sheet_watcher.cc
+++ b/chrome/browser/user_style_sheet_watcher.cc
@@ -57,7 +57,7 @@
void LoadStyleSheet(const base::FilePath& style_sheet_file);
// Register a callback to be called whenever the stylesheet gets updated.
- scoped_ptr<base::CallbackRegistry<void>::Subscription>
+ scoped_ptr<base::CallbackRegistry<void(void)>::Subscription>
RegisterOnStyleSheetUpdatedCallback(const base::Closure& callback);
// Send out a notification if the stylesheet has already been loaded.
@@ -79,7 +79,7 @@
// Whether the stylesheet has been loaded.
bool has_loaded_;
- base::CallbackRegistry<void> style_sheet_updated_callbacks_;
+ base::CallbackRegistry<void(void)> style_sheet_updated_callbacks_;
DISALLOW_COPY_AND_ASSIGN(UserStyleSheetLoader);
};
@@ -91,7 +91,7 @@
UserStyleSheetLoader::~UserStyleSheetLoader() {
}
-scoped_ptr<base::CallbackRegistry<void>::Subscription>
+scoped_ptr<base::CallbackRegistry<void(void)>::Subscription>
UserStyleSheetLoader::RegisterOnStyleSheetUpdatedCallback(
const base::Closure& callback) {
return style_sheet_updated_callbacks_.Add(callback);
@@ -192,7 +192,7 @@
return loader_->user_style_sheet();
}
-scoped_ptr<base::CallbackRegistry<void>::Subscription>
+scoped_ptr<base::CallbackRegistry<void(void)>::Subscription>
UserStyleSheetWatcher::RegisterOnStyleSheetUpdatedCallback(
const base::Closure& callback) {
return loader_->RegisterOnStyleSheetUpdatedCallback(callback);
diff --git a/chrome/browser/user_style_sheet_watcher.h b/chrome/browser/user_style_sheet_watcher.h
index 5929c37..b2d4dfb 100644
--- a/chrome/browser/user_style_sheet_watcher.h
+++ b/chrome/browser/user_style_sheet_watcher.h
@@ -32,7 +32,7 @@
GURL user_style_sheet() const;
// Register a callback to be called whenever the stylesheet gets updated.
- scoped_ptr<base::CallbackRegistry<void>::Subscription>
+ scoped_ptr<base::CallbackRegistry<void(void)>::Subscription>
RegisterOnStyleSheetUpdatedCallback(const base::Closure& callback);
// content::NotificationObserver interface
diff --git a/chrome/browser/web_resource/promo_resource_service.cc b/chrome/browser/web_resource/promo_resource_service.cc
index f4b35fe..5963568 100644
--- a/chrome/browser/web_resource/promo_resource_service.cc
+++ b/chrome/browser/web_resource/promo_resource_service.cc
@@ -30,10 +30,6 @@
const int kCacheUpdateDelay = 6 * 60 * 60 * 1000;
const int kTestCacheUpdateDelay = 3 * 60 * 1000;
-// The version of the service (used to expire the cache when upgrading Chrome
-// to versions with different types of promos).
-const int kPromoServiceVersion = 7;
-
// The promotion type used for Unpack() and ScheduleNotificationOnInit().
const NotificationPromo::PromoType kValidPromoTypes[] = {
#if defined(OS_ANDROID) || defined(OS_IOS)
diff --git a/chrome/browser_tests.isolate b/chrome/browser_tests.isolate
index a43a861..ed2a3f8 100644
--- a/chrome/browser_tests.isolate
+++ b/chrome/browser_tests.isolate
@@ -44,6 +44,7 @@
'../ppapi/tests/test_case.html',
'../ppapi/tests/test_page.css',
'../testing/test_env.py',
+ '../third_party/accessibility-audit/axs_testing.js',
'<(PRODUCT_DIR)/browser_tests<(EXECUTABLE_SUFFIX)',
'<(PRODUCT_DIR)/ppapi_nacl_tests_glibc.nmf',
'<(PRODUCT_DIR)/ppapi_nacl_tests_newlib.nmf',
@@ -64,7 +65,6 @@
'../net/data/',
'../net/tools/testserver/',
'../third_party/WebKit/Tools/Scripts/',
- '../third_party/accessibility-developer-tools/gen/',
'../third_party/pyftpdlib/',
'../third_party/pywebsocket/',
'../third_party/safe_browsing/',
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 0d556b7..7179824 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -636,8 +636,8 @@
'conditions': [
['component=="shared_library"', {
'dependencies': [
- '../webkit/support/webkit_support.gyp:glue',
'../content/content.gyp:content_plugin',
+ '../webkit/glue/webkit_glue.gyp:glue',
],
'xcode_settings': {
'LD_RUNPATH_SEARCH_PATHS': [
@@ -784,8 +784,6 @@
{
'action_name': 'strip_reliability_tests',
'inputs': [
- '<(PRODUCT_DIR)/automated_ui_tests',
- '<(PRODUCT_DIR)/reliability_tests',
'<(PRODUCT_DIR)/_pyautolib.so',
],
'outputs': [
@@ -797,10 +795,6 @@
'message': 'Stripping reliability tests',
},
],
- 'dependencies': [
- 'automated_ui_tests',
- 'reliability_tests',
- ],
}],
],
},
@@ -938,17 +932,12 @@
'sources': [
'test/automation/automation_handle_tracker.cc',
'test/automation/automation_handle_tracker.h',
- 'test/automation/automation_json_requests.cc',
- 'test/automation/automation_json_requests.h',
'test/automation/automation_proxy.cc',
'test/automation/automation_proxy.h',
'test/automation/browser_proxy.cc',
'test/automation/browser_proxy.h',
'test/automation/tab_proxy.cc',
'test/automation/tab_proxy.h',
- 'test/automation/value_conversion_traits.cc',
- 'test/automation/value_conversion_traits.h',
- 'test/automation/value_conversion_util.h',
'test/automation/window_proxy.cc',
'test/automation/window_proxy.h',
],
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index a076fcb..2e7657f 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -279,6 +279,8 @@
'browser/bookmarks/bookmark_prompt_prefs.h',
'browser/bookmarks/bookmark_service.cc',
'browser/bookmarks/bookmark_service.h',
+ 'browser/bookmarks/bookmark_stats.cc',
+ 'browser/bookmarks/bookmark_stats.h',
'browser/bookmarks/bookmark_storage.cc',
'browser/bookmarks/bookmark_storage.h',
'browser/bookmarks/bookmark_title_match.cc',
@@ -789,6 +791,8 @@
'browser/history/in_memory_url_index_types.h',
'browser/history/most_visited_tiles_experiment.cc',
'browser/history/most_visited_tiles_experiment.h',
+ 'browser/history/page_collector.cc',
+ 'browser/history/page_collector.h',
'browser/history/page_usage_data.cc',
'browser/history/page_usage_data.h',
'browser/history/query_parser.cc',
@@ -936,17 +940,27 @@
'browser/local_discovery/cloud_print_account_manager.h',
'browser/local_discovery/cloud_print_base_api_flow.cc',
'browser/local_discovery/cloud_print_base_api_flow.h',
- 'browser/local_discovery/cloud_print_printer_list.h',
'browser/local_discovery/cloud_print_printer_list.cc',
+ 'browser/local_discovery/cloud_print_printer_list.h',
'browser/local_discovery/privet_confirm_api_flow.cc',
'browser/local_discovery/privet_confirm_api_flow.h',
- 'browser/local_discovery/privet_constants.h',
'browser/local_discovery/privet_constants.cc',
+ 'browser/local_discovery/privet_constants.h',
+ 'browser/local_discovery/privet_device_lister.cc',
+ 'browser/local_discovery/privet_device_lister.h',
+ 'browser/local_discovery/privet_device_lister_impl.cc',
+ 'browser/local_discovery/privet_device_lister_impl.h',
+ 'browser/local_discovery/privet_http.h',
+ 'browser/local_discovery/privet_http_impl.cc',
+ 'browser/local_discovery/privet_http_impl.h',
'browser/local_discovery/privet_url_fetcher.cc',
'browser/local_discovery/privet_url_fetcher.h',
- 'browser/local_discovery/privet_http.h',
- 'browser/local_discovery/privet_http_impl.h',
- 'browser/local_discovery/privet_http_impl.cc',
+ 'browser/local_discovery/service_discovery_client_mac.h',
+ 'browser/local_discovery/service_discovery_client_mac.mm',
+ 'browser/local_discovery/service_discovery_client_mac_factory.h',
+ 'browser/local_discovery/service_discovery_client_mac_factory.mm',
+ 'browser/local_discovery/service_discovery_shared_client.cc',
+ 'browser/local_discovery/service_discovery_shared_client.h',
'browser/mac/dock.h',
'browser/mac/dock.mm',
'browser/mac/install_from_dmg.h',
@@ -1083,6 +1097,8 @@
'browser/media_galleries/media_file_system_registry.h',
'browser/media_galleries/media_galleries_dialog_controller.cc',
'browser/media_galleries/media_galleries_dialog_controller.h',
+ 'browser/media_galleries/media_galleries_histograms.cc',
+ 'browser/media_galleries/media_galleries_histograms.h',
'browser/media_galleries/media_galleries_preferences.cc',
'browser/media_galleries/media_galleries_preferences.h',
'browser/media_galleries/media_galleries_preferences_factory.cc',
@@ -1162,6 +1178,8 @@
'browser/net/chrome_http_user_agent_settings.h',
'browser/net/chrome_net_log.cc',
'browser/net/chrome_net_log.h',
+ 'browser/net/chrome_network_data_saving_metrics.cc',
+ 'browser/net/chrome_network_data_saving_metrics.h',
'browser/net/chrome_network_delegate.cc',
'browser/net/chrome_network_delegate.h',
'browser/net/chrome_url_request_context.cc',
@@ -1259,6 +1277,8 @@
'browser/notifications/message_center_notification_manager_win.cc',
'browser/notifications/message_center_settings_controller.cc',
'browser/notifications/message_center_settings_controller.h',
+ 'browser/notifications/message_center_stats_collector.cc',
+ 'browser/notifications/message_center_stats_collector.h',
'browser/notifications/notification.cc',
'browser/notifications/notification.h',
'browser/notifications/screen_lock_notification_blocker.cc',
@@ -1325,7 +1345,7 @@
'browser/password_manager/password_manager_delegate_impl.cc',
'browser/password_manager/password_manager_delegate_impl.h',
'browser/password_manager/password_manager_metrics_util.cc',
- 'browser/password_manager/password_manager_metrics_util.h',
+ 'browser/password_manager/password_manager_metrics_util.h',
'browser/password_manager/password_store.cc',
'browser/password_manager/password_store.h',
'browser/password_manager/password_store_consumer.cc',
@@ -1671,17 +1691,28 @@
'browser/profile_resetter/brandcode_config_fetcher.cc',
'browser/profile_resetter/profile_resetter.h',
'browser/profile_resetter/profile_resetter.cc',
+ 'browser/profile_resetter/jtl_foundation.h',
+ 'browser/profile_resetter/jtl_foundation.cc',
+ 'browser/profile_resetter/jtl_instructions.h',
+ 'browser/profile_resetter/jtl_interpreter.h',
+ 'browser/profile_resetter/jtl_interpreter.cc',
'browser/profile_resetter/resettable_settings_snapshot.h',
'browser/profile_resetter/resettable_settings_snapshot.cc',
- 'browser/profiles/avatar_menu_model.cc',
- 'browser/profiles/avatar_menu_model.h',
- 'browser/profiles/avatar_menu_model_observer.h',
+ 'browser/profiles/avatar_menu.cc',
+ 'browser/profiles/avatar_menu.h',
+ 'browser/profiles/avatar_menu_actions.h',
+ 'browser/profiles/avatar_menu_actions_desktop.h',
+ 'browser/profiles/avatar_menu_actions_desktop.cc',
+ 'browser/profiles/avatar_menu_desktop.cc',
+ 'browser/profiles/avatar_menu_observer.h',
'browser/profiles/bookmark_model_loaded_observer.cc',
'browser/profiles/bookmark_model_loaded_observer.h',
'browser/profiles/chrome_browser_main_extra_parts_profiles.cc',
'browser/profiles/chrome_browser_main_extra_parts_profiles.h',
'browser/profiles/chrome_version_service.cc',
'browser/profiles/chrome_version_service.h',
+ 'browser/profiles/file_path_verifier_win.cc',
+ 'browser/profiles/file_path_verifier_win.h',
'browser/profiles/gaia_info_update_service.cc',
'browser/profiles/gaia_info_update_service.h',
'browser/profiles/gaia_info_update_service_factory.cc',
@@ -1713,6 +1744,9 @@
'browser/profiles/profile_info_util.h',
'browser/profiles/profile_io_data.cc',
'browser/profiles/profile_io_data.h',
+ 'browser/profiles/profile_list.h',
+ 'browser/profiles/profile_list_desktop.cc',
+ 'browser/profiles/profile_list_desktop.h',
'browser/profiles/profile_loader.cc',
'browser/profiles/profile_loader.h',
'browser/profiles/profile_manager.cc',
@@ -1849,6 +1883,7 @@
'browser/search/instant_service.h',
'browser/search/instant_service_factory.cc',
'browser/search/instant_service_factory.h',
+ 'browser/search/instant_service_observer.cc',
'browser/search/instant_service_observer.h',
'browser/search/local_ntp_source.cc',
'browser/search/local_ntp_source.h',
@@ -2227,6 +2262,8 @@
'browser/sync_file_system/conflict_resolution_policy.h',
'browser/sync_file_system/conflict_resolution_resolver.cc',
'browser/sync_file_system/conflict_resolution_resolver.h',
+ 'browser/sync_file_system/drive_backend/drive_backend_constants.cc',
+ 'browser/sync_file_system/drive_backend/drive_backend_constants.h',
'browser/sync_file_system/drive_backend/local_to_remote_syncer.cc',
'browser/sync_file_system/drive_backend/local_to_remote_syncer.h',
'browser/sync_file_system/drive_backend/metadata_database.cc',
@@ -2857,6 +2894,11 @@
'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/profiles/avatar_menu_desktop.cc',
+ 'browser/profiles/avatar_menu_actions_desktop.cc',
+ 'browser/profiles/avatar_menu_actions_desktop.h',
+ 'browser/profiles/profile_list_desktop.cc',
+ 'browser/profiles/profile_list_desktop.h',
'browser/screensaver_window_finder_x11.cc',
'browser/screensaver_window_finder_x11.h',
'browser/shell_integration_linux.cc',
@@ -3085,6 +3127,12 @@
'browser/ssl/ssl_add_certificate_android.cc',
'browser/web_resource/notification_promo_mobile_ntp.cc',
'browser/web_resource/notification_promo_mobile_ntp.h',
+ 'browser/media/protected_media_identifier_infobar_delegate.cc',
+ 'browser/media/protected_media_identifier_infobar_delegate.h',
+ 'browser/media/protected_media_identifier_permission_context.cc',
+ 'browser/media/protected_media_identifier_permission_context.h',
+ 'browser/media/protected_media_identifier_permission_context_factory.cc',
+ 'browser/media/protected_media_identifier_permission_context_factory.h',
],
'sources!': [
# Bookmark export/import are handled via the BookmarkColumns
@@ -3378,10 +3426,6 @@
}],
['enable_mdns==1', {
'sources' : [
- 'browser/local_discovery/privet_device_lister.cc',
- 'browser/local_discovery/privet_device_lister.h',
- 'browser/local_discovery/privet_device_lister_impl.cc',
- 'browser/local_discovery/privet_device_lister_impl.h',
'browser/local_discovery/privet_http_asynchronous_factory.cc',
'browser/local_discovery/privet_http_asynchronous_factory.h',
'browser/local_discovery/privet_notifications.cc',
@@ -3390,6 +3434,8 @@
'browser/local_discovery/privet_notifications_factory.h',
'browser/local_discovery/privet_traffic_detector.cc',
'browser/local_discovery/privet_traffic_detector.h',
+ 'browser/local_discovery/service_discovery_client_mdns.cc',
+ 'browser/local_discovery/service_discovery_client_mdns.h',
'browser/local_discovery/service_discovery_host_client.cc',
'browser/local_discovery/service_discovery_host_client.h',
]
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index 9592392..ebed695 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -92,9 +92,9 @@
'../v8/tools/gyp/v8.gyp:v8',
'../ui/views/controls/webview/webview.gyp:webview',
'../webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
+ '../webkit/glue/webkit_glue.gyp:glue',
'../webkit/storage_browser.gyp:webkit_storage_browser',
'../webkit/storage_common.gyp:webkit_storage_common',
- '../webkit/support/webkit_support.gyp:glue',
'../webkit/webkit_resources.gyp:webkit_resources',
'chrome_resources.gyp:chrome_strings',
],
@@ -493,6 +493,11 @@
'browser/chromeos/login/merge_session_throttle.h',
'browser/chromeos/login/mount_manager.cc',
'browser/chromeos/login/mount_manager.h',
+ 'browser/chromeos/login/multi_profile_first_run_notification.cc',
+ 'browser/chromeos/login/multi_profile_first_run_notification.h',
+ 'browser/chromeos/login/multi_profile_user_controller.cc',
+ 'browser/chromeos/login/multi_profile_user_controller.h',
+ 'browser/chromeos/login/multi_profile_user_controller_delegate.h',
'browser/chromeos/login/oauth2_login_manager.cc',
'browser/chromeos/login/oauth2_login_manager.h',
'browser/chromeos/login/oauth2_login_manager_factory.cc',
@@ -731,8 +736,13 @@
'browser/chromeos/preferences.h',
'browser/chromeos/prerender_condition_network.cc',
'browser/chromeos/prerender_condition_network.h',
+ 'browser/chromeos/profiles/avatar_menu_actions_chromeos.cc',
+ 'browser/chromeos/profiles/avatar_menu_actions_chromeos.h',
+ 'browser/chromeos/profiles/avatar_menu_chromeos.cc',
'browser/chromeos/profiles/profile_helper.cc',
'browser/chromeos/profiles/profile_helper.h',
+ 'browser/chromeos/profiles/profile_list_chromeos.cc',
+ 'browser/chromeos/profiles/profile_list_chromeos.h',
'browser/chromeos/profiles/profile_util.cc',
'browser/chromeos/profiles/profile_util.h',
'browser/chromeos/proxy_config_service_impl.cc',
@@ -897,7 +907,7 @@
['use_cras==1', {
'defines': [
'USE_CRAS',
- ],
+ ],
}],
['use_ash==1', {
'dependencies': [
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index 706ecaa..02e8e89 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -28,6 +28,7 @@
'../content/content.gyp:content_browser',
'../crypto/crypto.gyp:crypto',
'../device/bluetooth/bluetooth.gyp:device_bluetooth',
+ '../extensions/extensions.gyp:extensions_browser',
'../net/net.gyp:net',
'../skia/skia.gyp:skia',
'../sync/sync.gyp:sync',
@@ -54,17 +55,6 @@
'sources': [
# All .cc, .h, .m, and .mm files under browser/extensions except for
# tests and mocks.
- '../extensions/browser/extension_prefs_scope.h',
- '../extensions/browser/extension_error.cc',
- '../extensions/browser/extension_error.h',
- '../extensions/browser/file_highlighter.cc',
- '../extensions/browser/file_highlighter.h',
- '../extensions/browser/file_reader.cc',
- '../extensions/browser/file_reader.h',
- '../extensions/browser/pref_names.cc',
- '../extensions/browser/pref_names.h',
- '../extensions/browser/view_type_utils.cc',
- '../extensions/browser/view_type_utils.h',
'browser/apps/app_url_redirector.cc',
'browser/apps/app_url_redirector.h',
'browser/apps/chrome_apps_client.cc',
@@ -91,6 +81,8 @@
'browser/extensions/activity_log/database_string_table.h',
'browser/extensions/activity_log/fullstream_ui_policy.cc',
'browser/extensions/activity_log/fullstream_ui_policy.h',
+ 'browser/extensions/activity_log/uma_policy.cc',
+ 'browser/extensions/activity_log/uma_policy.h',
'browser/extensions/activity_log/web_request_constants.cc',
'browser/extensions/activity_log/web_request_constants.h',
'browser/extensions/admin_policy.cc',
@@ -592,6 +584,8 @@
'browser/extensions/api/web_request/web_request_permissions.h',
'browser/extensions/api/web_request/web_request_time_tracker.cc',
'browser/extensions/api/web_request/web_request_time_tracker.h',
+ 'browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc',
+ 'browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h',
'browser/extensions/api/webstore_private/webstore_private_api.cc',
'browser/extensions/api/webstore_private/webstore_private_api.h',
'browser/extensions/api/webview/webview_api.cc',
@@ -781,6 +775,8 @@
'browser/extensions/pack_extension_job.h',
'browser/extensions/page_action_controller.cc',
'browser/extensions/page_action_controller.h',
+ 'browser/extensions/pending_enables.cc',
+ 'browser/extensions/pending_enables.h',
'browser/extensions/pending_extension_info.cc',
'browser/extensions/pending_extension_info.h',
'browser/extensions/pending_extension_manager.cc',
@@ -809,6 +805,7 @@
'browser/extensions/state_store.h',
'browser/extensions/suggest_permission_util.h',
'browser/extensions/suggest_permission_util.cc',
+ 'browser/extensions/sync_bundle.h',
'browser/extensions/tab_helper.cc',
'browser/extensions/tab_helper.h',
'browser/extensions/theme_installed_infobar_delegate.cc',
@@ -876,8 +873,6 @@
'browser/extensions/api/input_ime/input_ime_api.cc',
'browser/extensions/api/input_ime/input_ime_api.h',
'browser/extensions/api/log_private/log_private_api_chromeos.cc',
- 'browser/extensions/api/rtc_private/rtc_private_api.cc',
- 'browser/extensions/api/rtc_private/rtc_private_api.h',
'browser/extensions/api/terminal/terminal_extension_helper.cc',
'browser/extensions/api/terminal/terminal_extension_helper.h',
'browser/extensions/api/terminal/terminal_private_api.cc',
@@ -1046,6 +1041,7 @@
'sources!': [
'browser/apps/shortcut_manager.cc',
'browser/apps/shortcut_manager_factory.cc',
+ 'browser/extensions/activity_log/uma_policy.cc',
'browser/extensions/api/declarative/rules_registry_with_cache.cc',
'browser/extensions/api/processes/processes_api_constants.cc',
'browser/extensions/api/web_navigation/frame_navigation_state.cc',
@@ -1070,7 +1066,7 @@
}],
['chrome_multiple_dll!=1', {
'dependencies': [
- '../webkit/support/webkit_support.gyp:glue',
+ '../webkit/glue/webkit_glue.gyp:glue',
],
}],
['use_brlapi==1', {
@@ -1089,6 +1085,14 @@
'browser/extensions/api/braille_display_private/brlapi_connection.cc',
],
}],
+ ['enable_webrtc==0', {
+ 'sources!': [
+ 'browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc',
+ ],
+ 'sources': [
+ 'browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc',
+ ],
+ }],
],
},
],
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index a0df3c0..a30fa5e 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -75,13 +75,14 @@
'browser/ui/android/autofill/autofill_dialog_result.h',
'browser/ui/android/autofill/autofill_popup_view_android.cc',
'browser/ui/android/autofill/autofill_popup_view_android.h',
- 'browser/ui/android/infobar/auto_login_infobar_delegate_android.cc',
- 'browser/ui/android/infobar/confirm_infobar.cc',
- 'browser/ui/android/infobar/confirm_infobar.h',
- 'browser/ui/android/infobar/infobar_android.cc',
- 'browser/ui/android/infobar/infobar_android.h',
- 'browser/ui/android/infobar/infobar_container_android.cc',
- 'browser/ui/android/infobar/infobar_container_android.h',
+ 'browser/ui/android/infobars/auto_login_infobar_delegate_android.cc',
+ 'browser/ui/android/infobars/auto_login_infobar_delegate_android.h',
+ 'browser/ui/android/infobars/confirm_infobar.cc',
+ 'browser/ui/android/infobars/confirm_infobar.h',
+ 'browser/ui/android/infobars/infobar_android.cc',
+ 'browser/ui/android/infobars/infobar_android.h',
+ 'browser/ui/android/infobars/infobar_container_android.cc',
+ 'browser/ui/android/infobars/infobar_container_android.h',
'browser/ui/android/certificate_viewer_android.cc',
'browser/ui/android/chrome_http_auth_handler.cc',
'browser/ui/android/chrome_http_auth_handler.h',
@@ -113,6 +114,8 @@
'browser/ui/android/website_settings_popup_android.h',
'browser/ui/android/window_android_helper.cc',
'browser/ui/android/window_android_helper.h',
+ 'browser/ui/app_list/fast_show_pickler.cc',
+ 'browser/ui/app_list/fast_show_pickler.h',
'browser/ui/app_list/app_context_menu.cc',
'browser/ui/app_list/app_context_menu.h',
'browser/ui/app_list/app_context_menu_delegate.h',
@@ -329,7 +332,6 @@
'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_window_params.cc',
@@ -821,8 +823,6 @@
'browser/ui/cocoa/multi_key_equivalent_button.mm',
'browser/ui/cocoa/new_tab_button.h',
'browser/ui/cocoa/new_tab_button.mm',
- 'browser/ui/cocoa/nine_part_button_cell.h',
- 'browser/ui/cocoa/nine_part_button_cell.mm',
'browser/ui/cocoa/notifications/balloon_collection_cocoa.mm',
'browser/ui/cocoa/notifications/balloon_controller.h',
'browser/ui/cocoa/notifications/balloon_controller.mm',
@@ -921,8 +921,6 @@
'browser/ui/cocoa/tabpose_window.h',
'browser/ui/cocoa/tabpose_window.mm',
'browser/ui/cocoa/tabs/dock_info_mac.cc',
- 'browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.h',
- 'browser/ui/cocoa/tabs/tab_audio_indicator_view_mac.mm',
'browser/ui/cocoa/tabs/tab_controller.h',
'browser/ui/cocoa/tabs/tab_controller.mm',
'browser/ui/cocoa/tabs/tab_projecting_image_view.h',
@@ -1513,8 +1511,6 @@
'browser/ui/tabs/pinned_tab_service.h',
'browser/ui/tabs/pinned_tab_service_factory.cc',
'browser/ui/tabs/pinned_tab_service_factory.h',
- 'browser/ui/tabs/tab_audio_indicator.cc',
- 'browser/ui/tabs/tab_audio_indicator.h',
'browser/ui/tabs/tab_menu_model.cc',
'browser/ui/tabs/tab_menu_model.h',
'browser/ui/tabs/tab_resources.cc',
@@ -1913,6 +1909,8 @@
'browser/ui/views/panels/taskbar_window_thumbnailer_win.h',
'browser/ui/views/password_generation_bubble_view.cc',
'browser/ui/views/password_generation_bubble_view.h',
+ 'browser/ui/views/password_menu_model.cc',
+ 'browser/ui/views/password_menu_model.h',
'browser/ui/views/pdf_password_dialog.cc',
'browser/ui/views/profile_chooser_view.cc',
'browser/ui/views/profile_chooser_view.h',
@@ -2298,6 +2296,8 @@
'browser/ui/webui/options/cookies_view_handler.h',
'browser/ui/webui/options/core_options_handler.cc',
'browser/ui/webui/options/core_options_handler.h',
+ 'browser/ui/webui/options/create_profile_handler.cc',
+ 'browser/ui/webui/options/create_profile_handler.h',
'browser/ui/webui/options/font_settings_handler.cc',
'browser/ui/webui/options/font_settings_handler.h',
'browser/ui/webui/options/font_settings_utils.h',
@@ -2330,6 +2330,8 @@
'browser/ui/webui/options/media_devices_selection_handler.h',
'browser/ui/webui/options/media_galleries_handler.cc',
'browser/ui/webui/options/media_galleries_handler.h',
+ 'browser/ui/webui/options/options_handlers_helper.cc',
+ 'browser/ui/webui/options/options_handlers_helper.h',
'browser/ui/webui/options/options_ui.cc',
'browser/ui/webui/options/options_ui.h',
'browser/ui/webui/options/password_manager_handler.cc',
@@ -2506,7 +2508,7 @@
}],
['OS!="ios" and chrome_multiple_dll!=1', {
'dependencies': [
- '../webkit/support/webkit_support.gyp:glue',
+ '../webkit/glue/webkit_glue.gyp:glue',
],
}],
['OS == "android"', {
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index c0ef0f3..e050471 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -41,6 +41,7 @@
'<(DEPTH)/components/components.gyp:variations',
'<(DEPTH)/components/components.gyp:visitedlink_common',
'<(DEPTH)/content/content.gyp:content_common',
+ '<(DEPTH)/extensions/extensions.gyp:extensions_common',
'<(DEPTH)/net/net.gyp:net',
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/third_party/icu/icu.gyp:icui18n',
@@ -55,67 +56,6 @@
'sources': [
'../apps/app_shim/app_shim_launch.h',
'../apps/app_shim/app_shim_messages.h',
- '../extensions/common/crx_file.cc',
- '../extensions/common/crx_file.h',
- '../extensions/common/draggable_region.cc',
- '../extensions/common/draggable_region.h',
- '../extensions/common/error_utils.cc',
- '../extensions/common/error_utils.h',
- '../extensions/common/event_filter.cc',
- '../extensions/common/event_filter.h',
- '../extensions/common/event_filtering_info.cc',
- '../extensions/common/event_filtering_info.h',
- '../extensions/common/event_matcher.cc',
- '../extensions/common/event_matcher.h',
- '../extensions/common/extension_paths.cc',
- '../extensions/common/extension_paths.h',
- '../extensions/common/extension_resource.cc',
- '../extensions/common/extension_resource.h',
- '../extensions/common/extension_urls.cc',
- '../extensions/common/extension_urls.h',
- '../extensions/common/extensions_client.cc',
- '../extensions/common/extensions_client.h',
- '../extensions/common/features/feature.cc',
- '../extensions/common/features/feature.h',
- '../extensions/common/features/feature_provider.cc',
- '../extensions/common/features/feature_provider.h',
- '../extensions/common/id_util.cc',
- '../extensions/common/id_util.h',
- '../extensions/common/install_warning.cc',
- '../extensions/common/install_warning.h',
- '../extensions/common/manifest.cc',
- '../extensions/common/manifest.h',
- '../extensions/common/manifest_constants.cc',
- '../extensions/common/manifest_constants.h',
- '../extensions/common/matcher/regex_set_matcher.cc',
- '../extensions/common/matcher/regex_set_matcher.h',
- '../extensions/common/matcher/string_pattern.cc',
- '../extensions/common/matcher/string_pattern.h',
- '../extensions/common/matcher/substring_set_matcher.cc',
- '../extensions/common/matcher/substring_set_matcher.h',
- '../extensions/common/matcher/url_matcher.cc',
- '../extensions/common/matcher/url_matcher.h',
- '../extensions/common/matcher/url_matcher_constants.cc',
- '../extensions/common/matcher/url_matcher_constants.h',
- '../extensions/common/matcher/url_matcher_factory.cc',
- '../extensions/common/matcher/url_matcher_factory.h',
- '../extensions/common/matcher/url_matcher_helpers.cc',
- '../extensions/common/matcher/url_matcher_helpers.h',
- '../extensions/common/one_shot_event.cc',
- '../extensions/common/one_shot_event.h',
- '../extensions/common/permissions/permissions_provider.h',
- '../extensions/common/stack_frame.cc',
- '../extensions/common/stack_frame.h',
- '../extensions/common/switches.cc',
- '../extensions/common/switches.h',
- '../extensions/common/url_pattern.cc',
- '../extensions/common/url_pattern.h',
- '../extensions/common/url_pattern_set.cc',
- '../extensions/common/url_pattern_set.h',
- '../extensions/common/user_script.cc',
- '../extensions/common/user_script.h',
- '../extensions/common/view_type.cc',
- '../extensions/common/view_type.h',
'common/all_messages.h',
'common/attrition_experiments.h',
'common/auto_start_linux.cc',
@@ -124,8 +64,6 @@
'common/autocomplete_match_type.h',
'common/automation_constants.cc',
'common/automation_constants.h',
- 'common/automation_id.cc',
- 'common/automation_id.h',
'common/automation_messages.cc',
'common/automation_messages.h',
'common/automation_messages_internal.h',
@@ -180,7 +118,6 @@
'common/descriptors_android.h',
'common/dump_without_crashing.cc',
'common/dump_without_crashing.h',
- 'common/encrypted_media_messages_android.cc',
'common/encrypted_media_messages_android.h',
'common/extensions/api/commands/commands_handler.cc',
'common/extensions/api/commands/commands_handler.h',
@@ -213,6 +150,8 @@
'common/extensions/api/omnibox/omnibox_handler.h',
'common/extensions/api/plugins/plugins_handler.cc',
'common/extensions/api/plugins/plugins_handler.h',
+ 'common/extensions/api/sockets/sockets_handler.cc',
+ 'common/extensions/api/sockets/sockets_handler.h',
'common/extensions/api/speech/tts_engine_manifest_handler.cc',
'common/extensions/api/speech/tts_engine_manifest_handler.h',
'common/extensions/api/spellcheck/spellcheck_handler.cc',
@@ -284,8 +223,8 @@
'common/extensions/manifest_handlers/externally_connectable.h',
'common/extensions/manifest_handlers/icons_handler.cc',
'common/extensions/manifest_handlers/icons_handler.h',
- 'common/extensions/manifest_handlers/kiosk_enabled_info.cc',
- 'common/extensions/manifest_handlers/kiosk_enabled_info.h',
+ 'common/extensions/manifest_handlers/kiosk_mode_info.cc',
+ 'common/extensions/manifest_handlers/kiosk_mode_info.h',
'common/extensions/manifest_handlers/minimum_chrome_version_checker.cc',
'common/extensions/manifest_handlers/minimum_chrome_version_checker.h',
'common/extensions/manifest_handlers/nacl_modules_handler.cc',
@@ -335,6 +274,8 @@
'common/extensions/permissions/socket_permission.h',
'common/extensions/permissions/socket_permission_data.cc',
'common/extensions/permissions/socket_permission_data.h',
+ 'common/extensions/permissions/socket_permission_entry.cc',
+ 'common/extensions/permissions/socket_permission_entry.h',
'common/extensions/permissions/usb_device_permission.cc',
'common/extensions/permissions/usb_device_permission.h',
'common/extensions/permissions/usb_device_permission_data.cc',
@@ -384,6 +325,8 @@
'common/instant_types.h',
'common/localized_error.cc',
'common/localized_error.h',
+ 'common/local_discovery/service_discovery_client.cc',
+ 'common/local_discovery/service_discovery_client.h',
'common/logging_chrome.cc',
'common/logging_chrome.h',
'common/mac/app_mode_common.h',
@@ -567,7 +510,7 @@
}],
['OS!="ios" and chrome_multiple_dll!=1', {
'dependencies': [
- '<(DEPTH)/webkit/support/webkit_support.gyp:glue',
+ '<(DEPTH)/webkit/glue/webkit_glue.gyp:glue',
],
}],
['OS=="android"', {
@@ -603,8 +546,6 @@
['enable_mdns == 1', {
'sources': [
'common/local_discovery/local_discovery_messages.h',
- 'common/local_discovery/service_discovery_client.cc',
- 'common/local_discovery/service_discovery_client.h',
]
}],
['toolkit_uses_gtk == 1', {
diff --git a/chrome/chrome_exe.gypi b/chrome/chrome_exe.gypi
index 67b0efa..ae000d7 100644
--- a/chrome/chrome_exe.gypi
+++ b/chrome/chrome_exe.gypi
@@ -13,8 +13,6 @@
'enable_wexit_time_destructors': 1,
},
'sources': [
- 'app/breakpad_field_trial_win.cc',
- 'app/breakpad_field_trial_win.h',
'app/breakpad_win.cc',
'app/breakpad_win.h',
'app/chrome_exe_main_aura.cc',
diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi
index fd405ce..4f13094 100644
--- a/chrome/chrome_installer.gypi
+++ b/chrome/chrome_installer.gypi
@@ -270,6 +270,8 @@
'installer/mini_installer/chrome.release',
'installer/setup/archive_patch_helper.cc',
'installer/setup/archive_patch_helper.h',
+ 'installer/setup/cf_migration.cc',
+ 'installer/setup/cf_migration.h',
'installer/setup/chrome_frame_quick_enable.cc',
'installer/setup/chrome_frame_quick_enable.h',
'installer/setup/chrome_frame_ready_mode.cc',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 5f578ae..6dcb9c9 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -29,9 +29,9 @@
'../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
'../ui/surface/surface.gyp:surface',
'../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/support/webkit_support.gyp:glue_child',
+ '../webkit/glue/webkit_glue.gyp:glue',
+ '../webkit/glue/webkit_glue.gyp:glue_child',
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
- '../webkit/support/webkit_support.gyp:glue',
'../webkit/webkit_resources.gyp:webkit_resources',
],
'include_dirs': [
@@ -432,6 +432,13 @@
'defines': [
'ENABLE_MOBILE_YOUTUBE_PLUGIN',
],
+ 'conditions' : [
+ ['google_tv==1', {
+ 'sources!' : [
+ 'renderer/media/chrome_key_systems.cc',
+ ]
+ }],
+ ],
}],
['OS=="win"', {
'include_dirs': [
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 7142fd4..e69dd1e 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -3,6 +3,48 @@
# found in the LICENSE file.
{
'variables' : {
+ 'chromedriver_unittest_sources': [
+ 'test/chromedriver/capabilities_unittest.cc',
+ 'test/chromedriver/chrome/chrome_finder_unittest.cc',
+ 'test/chromedriver/chrome/console_logger_unittest.cc',
+ 'test/chromedriver/chrome/device_manager_unittest.cc',
+ 'test/chromedriver/chrome/devtools_client_impl_unittest.cc',
+ 'test/chromedriver/chrome/devtools_http_client_unittest.cc',
+ 'test/chromedriver/chrome/dom_tracker_unittest.cc',
+ 'test/chromedriver/chrome/frame_tracker_unittest.cc',
+ 'test/chromedriver/chrome/geolocation_override_manager_unittest.cc',
+ 'test/chromedriver/chrome/heap_snapshot_taker_unittest.cc',
+ 'test/chromedriver/chrome/javascript_dialog_manager_unittest.cc',
+ 'test/chromedriver/chrome/navigation_tracker_unittest.cc',
+ 'test/chromedriver/chrome/performance_logger_unittest.cc',
+ 'test/chromedriver/chrome/status_unittest.cc',
+ 'test/chromedriver/chrome/stub_chrome.cc',
+ 'test/chromedriver/chrome/stub_chrome.h',
+ 'test/chromedriver/chrome/stub_devtools_client.cc',
+ 'test/chromedriver/chrome/stub_devtools_client.h',
+ 'test/chromedriver/chrome/stub_web_view.cc',
+ 'test/chromedriver/chrome/stub_web_view.h',
+ 'test/chromedriver/chrome/web_view_impl_unittest.cc',
+ 'test/chromedriver/chrome_launcher_unittest.cc',
+ 'test/chromedriver/commands_unittest.cc',
+ 'test/chromedriver/logging_unittest.cc',
+ 'test/chromedriver/server/http_handler_unittest.cc',
+ 'test/chromedriver/session_commands_unittest.cc',
+ 'test/chromedriver/session_unittest.cc',
+ 'test/chromedriver/util_unittest.cc',
+ ],
+ 'chromedriver_test_sources': [
+ 'test/chromedriver/key_converter_unittest.cc',
+ 'test/chromedriver/keycode_text_conversion_unittest.cc',
+ 'test/chromedriver/net/net_util_unittest.cc',
+ 'test/chromedriver/net/port_server_unittest.cc',
+ 'test/chromedriver/net/sync_websocket_impl_unittest.cc',
+ 'test/chromedriver/net/test_http_server.cc',
+ 'test/chromedriver/net/test_http_server.h',
+ 'test/chromedriver/net/websocket_unittest.cc',
+ 'test/chromedriver/test_util.cc',
+ 'test/chromedriver/test_util.h',
+ ],
'pyautolib_sources': [
'app/chrome_command_ids.h',
'app/chrome_dll_resource.h',
@@ -68,8 +110,6 @@
'sources': [
'test/automation/proxy_launcher.cc',
'test/automation/proxy_launcher.h',
- 'test/reliability/automated_ui_test_base.cc',
- 'test/reliability/automated_ui_test_base.h',
'test/ui/javascript_test_util.cc',
'test/ui/run_all_unittests.cc',
'test/ui/ui_perf_test.cc',
@@ -100,70 +140,6 @@
'msvs_disabled_warnings': [ 4267, ],
},
{
- 'target_name': 'automated_ui_tests',
- 'type': 'executable',
- 'dependencies': [
- 'browser',
- 'chrome_resources.gyp:theme_resources',
- 'renderer',
- 'test_support_common',
- 'test_support_ui',
- 'test_support_ui_runner',
- '../base/base.gyp:base',
- '../skia/skia.gyp:skia',
- '../third_party/libxml/libxml.gyp:libxml',
- '../testing/gtest.gyp:gtest',
- ],
- 'include_dirs': [
- '..',
- ],
- 'sources': [
- 'test/reliability/automated_ui_tests.cc',
- 'test/reliability/automated_ui_tests.h',
- ],
- 'conditions': [
- ['OS=="win" and buildtype=="Official"', {
- 'configurations': {
- 'Release': {
- 'msvs_settings': {
- 'VCCLCompilerTool': {
- 'WholeProgramOptimization': 'false',
- },
- },
- },
- },
- },],
- ['use_x11==1', {
- 'dependencies': [
- '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
- ],
- }],
- ['OS=="win"', {
- 'dependencies': [
- 'automated_ui_tests_exe_pdb_workaround',
- ],
- 'include_dirs': [
- '<(DEPTH)/third_party/wtl/include',
- ],
- 'conditions': [
- ['win_use_allocator_shim==1', {
- 'dependencies': [
- '<(allocator_target)',
- ],
- }],
- ],
- }],
- ['OS=="linux" and enable_webrtc==1', {
- 'dependencies': [
- # TODO(tommi): Figure out why the 32bit lucid builder fails to
- # find this dependency for this target (other builders pick it up
- # correctly). crbug.com/231068.
- '../third_party/libjingle/libjingle.gyp:libpeerconnection',
- ],
- }],
- ],
- },
- {
'target_name': 'interactive_ui_tests',
'type': 'executable',
'dependencies': [
@@ -401,7 +377,6 @@
'../chromeos/chromeos.gyp:chromeos',
],
'sources': [
- 'browser/chromeos/input_method/keyboard_browsertest.cc',
'browser/chromeos/input_method/textinput_browsertest.cc',
'browser/chromeos/input_method/textinput_surroundingtext_browsertest.cc',
'browser/chromeos/input_method/textinput_test_helper.cc',
@@ -505,7 +480,7 @@
], # conditions
},
{
- 'target_name': 'chrome_devtools_lib',
+ 'target_name': 'automation_client_lib',
'type': 'static_library',
'hard_dependency': 1,
'dependencies': [
@@ -599,6 +574,8 @@
'test/chromedriver/net/adb_client_socket.h',
'test/chromedriver/net/net_util.cc',
'test/chromedriver/net/net_util.h',
+ 'test/chromedriver/net/port_server.cc',
+ 'test/chromedriver/net/port_server.h',
'test/chromedriver/net/sync_websocket.h',
'test/chromedriver/net/sync_websocket_factory.cc',
'test/chromedriver/net/sync_websocket_factory.h',
@@ -687,13 +664,12 @@
# 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',
+ 'target_name': 'chromedriver_lib',
'type': 'static_library',
'hard_dependency': 1,
'dependencies': [
- 'chrome_devtools_lib',
+ 'automation_client_lib',
'../base/base.gyp:base',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../crypto/crypto.gyp:crypto',
@@ -774,27 +750,11 @@
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
},
- # TODO(kkania): Remove this in favor of 'chromedriver' target right below.
- {
- 'target_name': 'chromedriver2_server',
- 'type': 'executable',
- 'dependencies': [
- 'chromedriver2_lib',
- ],
- 'include_dirs': [
- '..',
- ],
- 'sources': [
- 'test/chromedriver/server/chromedriver_server.cc',
- ],
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- 'msvs_disabled_warnings': [ 4267, ],
- },
{
'target_name': 'chromedriver',
'type': 'executable',
'dependencies': [
- 'chromedriver2_lib',
+ 'chromedriver_lib',
],
'include_dirs': [
'..',
@@ -806,10 +766,10 @@
'msvs_disabled_warnings': [ 4267, ],
},
{
- 'target_name': 'chromedriver2_unittests',
+ 'target_name': 'chromedriver_unittests',
'type': 'executable',
'dependencies': [
- 'chromedriver2_lib',
+ 'chromedriver_lib',
'../base/base.gyp:base',
'../base/base.gyp:run_all_unittests',
'../net/net.gyp:http_server',
@@ -817,51 +777,44 @@
'../testing/gtest.gyp:gtest',
'../ui/ui.gyp:ui',
],
+ 'include_dirs': [
+ '..,'
+ ],
'sources': [
- 'test/chromedriver/capabilities_unittest.cc',
- 'test/chromedriver/chrome/chrome_finder_unittest.cc',
- 'test/chromedriver/chrome/console_logger_unittest.cc',
- 'test/chromedriver/chrome/device_manager_unittest.cc',
- 'test/chromedriver/chrome/devtools_client_impl_unittest.cc',
- 'test/chromedriver/chrome/devtools_http_client_unittest.cc',
- 'test/chromedriver/chrome/dom_tracker_unittest.cc',
- 'test/chromedriver/chrome/frame_tracker_unittest.cc',
- 'test/chromedriver/chrome/geolocation_override_manager_unittest.cc',
- 'test/chromedriver/chrome/heap_snapshot_taker_unittest.cc',
- 'test/chromedriver/chrome/javascript_dialog_manager_unittest.cc',
- 'test/chromedriver/chrome/navigation_tracker_unittest.cc',
- 'test/chromedriver/chrome/performance_logger_unittest.cc',
- 'test/chromedriver/chrome/status_unittest.cc',
- 'test/chromedriver/chrome/stub_chrome.cc',
- 'test/chromedriver/chrome/stub_chrome.h',
- 'test/chromedriver/chrome/stub_devtools_client.cc',
- 'test/chromedriver/chrome/stub_devtools_client.h',
- 'test/chromedriver/chrome/stub_web_view.cc',
- 'test/chromedriver/chrome/stub_web_view.h',
- 'test/chromedriver/chrome/web_view_impl_unittest.cc',
- 'test/chromedriver/chrome_launcher_unittest.cc',
- 'test/chromedriver/commands_unittest.cc',
- 'test/chromedriver/logging_unittest.cc',
- 'test/chromedriver/server/http_handler_unittest.cc',
- 'test/chromedriver/session_commands_unittest.cc',
- 'test/chromedriver/session_unittest.cc',
- 'test/chromedriver/util_unittest.cc',
+ '<@(chromedriver_unittest_sources)',
],
- 'conditions': [
- # See http://crbug.com/162998#c4 for why this is needed.
- ['OS=="linux" and linux_use_tcmalloc==1', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ },
+ # TODO(kkania): Remove when infra no longer references this.
+ {
+ 'target_name': 'chromedriver2_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'chromedriver_lib',
+ '../base/base.gyp:base',
+ '../base/base.gyp:run_all_unittests',
+ '../net/net.gyp:http_server',
+ '../net/net.gyp:net',
+ '../testing/gtest.gyp:gtest',
+ '../ui/ui.gyp:ui',
],
+ 'include_dirs': [
+ '..,'
+ ],
+ 'sources': [
+ '<@(chromedriver_unittest_sources)',
+ ],
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
},
# ChromeDriver2 tests that aren't run on the main buildbot. Available
# as an optional test type on trybots.
{
- 'target_name': 'chromedriver2_tests',
+ 'target_name': 'chromedriver_tests',
'type': 'executable',
'dependencies': [
+ 'chromedriver_lib',
'../base/base.gyp:base',
'../base/base.gyp:run_all_unittests',
'../net/net.gyp:http_server',
@@ -869,21 +822,35 @@
'../net/net.gyp:net_test_support',
'../testing/gtest.gyp:gtest',
'../url/url.gyp:url_lib',
- 'chromedriver2_lib',
],
'include_dirs': [
'..,'
],
'sources': [
- 'test/chromedriver/key_converter_unittest.cc',
- 'test/chromedriver/keycode_text_conversion_unittest.cc',
- 'test/chromedriver/net/net_util_unittest.cc',
- 'test/chromedriver/net/sync_websocket_impl_unittest.cc',
- 'test/chromedriver/net/test_http_server.cc',
- 'test/chromedriver/net/test_http_server.h',
- 'test/chromedriver/net/websocket_unittest.cc',
- 'test/chromedriver/test_util.cc',
- 'test/chromedriver/test_util.h',
+ '<@(chromedriver_test_sources)',
+ ],
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ },
+ # TODO(kkania): Remove when infra no longer references this.
+ {
+ 'target_name': 'chromedriver2_tests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'chromedriver_lib',
+ '../base/base.gyp:base',
+ '../base/base.gyp:run_all_unittests',
+ '../net/net.gyp:http_server',
+ '../net/net.gyp:net',
+ '../net/net.gyp:net_test_support',
+ '../testing/gtest.gyp:gtest',
+ '../url/url.gyp:url_lib',
+ ],
+ 'include_dirs': [
+ '..,'
+ ],
+ 'sources': [
+ '<@(chromedriver_test_sources)',
],
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
@@ -949,6 +916,9 @@
'../components/autofill/content/renderer/test_password_autofill_agent.cc',
'../remoting/test/auth_browsertest.cc',
'../remoting/test/launch_browsertest.cc',
+ '../remoting/test/key_code_conv.cc',
+ '../remoting/test/key_code_conv.h',
+ '../remoting/test/key_code_map.h',
'../remoting/test/me2me_browsertest.cc',
'../remoting/test/remote_desktop_browsertest.cc',
'../remoting/test/remote_desktop_browsertest.h',
@@ -998,6 +968,7 @@
'browser/chromeos/extensions/file_manager/file_browser_private_apitest.cc',
'browser/chromeos/extensions/info_private_apitest.cc',
'browser/chromeos/extensions/input_method_apitest_chromeos.cc',
+ 'browser/chromeos/extensions/virtual_keyboard_browsertest.cc',
'browser/chromeos/extensions/wallpaper_private_apitest.cc',
'browser/chromeos/file_manager/desktop_notifications_browsertest.cc',
'browser/chromeos/file_manager/drive_test_util.cc',
@@ -1043,8 +1014,6 @@
'browser/chromeos/login/wizard_in_process_browser_test.cc',
'browser/chromeos/login/wizard_in_process_browser_test.h',
'browser/chromeos/memory/oom_priority_manager_browsertest.cc',
- 'browser/chromeos/policy/cros_enterprise_test_utils.cc',
- 'browser/chromeos/policy/cros_enterprise_test_utils.h',
'browser/chromeos/policy/device_local_account_browsertest.cc',
'browser/chromeos/policy/device_policy_cros_browser_test.cc',
'browser/chromeos/policy/device_policy_cros_browser_test.h',
@@ -1073,6 +1042,7 @@
'browser/errorpage_browsertest.cc',
'browser/extensions/active_tab_apitest.cc',
'browser/extensions/activity_log/activity_log_browsertest.cc',
+ 'browser/extensions/activity_log/uma_policy_browsertest.cc',
'browser/extensions/alert_apitest.cc',
'browser/extensions/all_urls_apitest.cc',
'browser/extensions/api/activity_log_private/activity_log_private_apitest.cc',
@@ -1105,6 +1075,7 @@
'browser/extensions/api/extension_action/page_action_apitest.cc',
'browser/extensions/api/extension_action/page_as_browser_action_apitest.cc',
'browser/extensions/api/extension_action/script_badge_apitest.cc',
+ 'browser/extensions/api/feedback_private/feedback_private_apitest.cc',
'browser/extensions/api/file_system/file_system_apitest.cc',
'browser/extensions/api/font_settings/font_settings_apitest.cc',
'browser/extensions/api/history/history_apitest.cc',
@@ -1136,7 +1107,6 @@
'browser/extensions/api/push_messaging/push_messaging_apitest.cc',
'browser/extensions/api/push_messaging/push_messaging_canary_test.cc',
'browser/extensions/api/push_messaging/sync_setup_helper.cc',
- 'browser/extensions/api/rtc_private/rtc_private_apitest.cc',
'browser/extensions/api/runtime/runtime_apitest.cc',
'browser/extensions/api/serial/serial_apitest.cc',
'browser/extensions/api/sessions/sessions_apitest.cc',
@@ -1186,7 +1156,6 @@
'browser/extensions/extension_apitest.cc',
'browser/extensions/extension_apitest.h',
'browser/extensions/extension_bindings_apitest.cc',
- 'browser/extensions/extension_blacklist_browsertest.cc',
'browser/extensions/extension_browsertest.cc',
'browser/extensions/extension_browsertest.h',
'browser/extensions/extension_context_menu_browsertest.cc',
@@ -1307,8 +1276,8 @@
'browser/printing/print_preview_dialog_controller_browsertest.cc',
'browser/printing/printing_layout_browsertest.cc',
'browser/process_singleton_browsertest.cc',
- 'browser/profiles/avatar_menu_model_browsertest.cc',
'browser/profiles/profile_browsertest.cc',
+ 'browser/profiles/profile_list_desktop_browsertest.cc',
'browser/profiles/profile_manager_browsertest.cc',
'browser/profile_resetter/profile_resetter_browsertest.cc',
'browser/referrer_policy_browsertest.cc',
@@ -1661,7 +1630,6 @@
['exclude', '^browser/ui/webui/options/chromeos/'],
],
'sources!': [
- 'browser/extensions/api/rtc_private/rtc_private_apitest.cc',
'browser/extensions/api/terminal/terminal_private_apitest.cc',
'browser/ui/ash/caps_lock_delegate_chromeos_browsertest.cc',
'test/data/webui/certificate_viewer_dialog_test.js',
@@ -2101,71 +2069,6 @@
], # conditions
}, # target performance_browser_tests
{
- # To run the tests from page_load_test.cc on Linux, we need to:
- #
- # a) Run with CHROME_HEADLESS=1 to generate crash dumps.
- # b) Strip the binary if it's a debug build. (binary may be over 2GB)
- 'target_name': 'reliability_tests',
- 'type': 'executable',
- 'dependencies': [
- 'browser',
- 'chrome',
- 'chrome_resources.gyp:theme_resources',
- 'test_support_common',
- 'test_support_ui',
- 'test_support_ui_runner',
- '../skia/skia.gyp:skia',
- '../testing/gtest.gyp:gtest',
- '../third_party/WebKit/public/blink.gyp:blink',
- ],
- 'include_dirs': [
- '..',
- ],
- 'sources': [
- 'test/reliability/page_load_test.cc',
- ],
- 'conditions': [
- ['OS=="win" and buildtype=="Official"', {
- 'configurations': {
- 'Release': {
- 'msvs_settings': {
- 'VCCLCompilerTool': {
- 'WholeProgramOptimization': 'false',
- },
- },
- },
- },
- },],
- ['OS=="win" and win_use_allocator_shim==1', {
- 'dependencies': [
- '<(allocator_target)',
- ],
- 'configurations': {
- 'Debug': {
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'LinkIncremental': '<(msvs_large_module_debug_link_mode)',
- },
- },
- },
- },
- },],
- ['toolkit_uses_gtk == 1', {
- 'dependencies': [
- '../build/linux/system.gyp:gtk',
- ],
- },],
- ['OS=="linux" and enable_webrtc==1', {
- 'dependencies': [
- # TODO(tommi): Figure out why the 32bit lucid builder fails to
- # find this dependency for this target (other builders pick it up
- # correctly). crbug.com/231068.
- '../third_party/libjingle/libjingle.gyp:libpeerconnection',
- ],
- }],
- ],
- },
- {
'target_name': 'performance_ui_tests',
'type': 'executable',
'dependencies': [
@@ -2664,7 +2567,7 @@
'../base/base.gyp:test_support_perf',
'../skia/skia.gyp:skia',
'../testing/gtest.gyp:gtest',
- '../webkit/support/webkit_support.gyp:glue',
+ '../webkit/glue/webkit_glue.gyp:glue',
],
'sources': [
'test/perf/perftests.cc',
@@ -2965,7 +2868,6 @@
'suppress_wildcard': 1,
'type': 'none',
'dependencies': [
- 'automated_ui_tests',
'../base/base.gyp:base_unittests',
# browser_tests's use of subprocesses chokes gcov on 10.6?
# Disabling for now (enabled on linux/windows below).
@@ -3010,7 +2912,6 @@
'gpu_tests',
'performance_ui_tests',
'pyautolib',
- 'reliability_tests',
'sync_integration_tests',
]}],
['OS=="mac"', {
@@ -3224,21 +3125,6 @@
'targets' : [
{
# This target is only depended upon in Windows.
- 'target_name': 'automated_ui_tests_exe_pdb_workaround',
- 'type': 'static_library',
- 'sources': [ 'empty_pdb_workaround.cc' ],
- 'msvs_settings': {
- 'VCCLCompilerTool': {
- # This *in the compile phase* must match the pdb name that's
- # output by the final link. See empty_pdb_workaround.cc for
- # more details.
- 'DebugInformationFormat': '3',
- 'ProgramDataBaseFileName': '<(PRODUCT_DIR)/automated_ui_tests.exe.pdb',
- },
- },
- },
- {
- # This target is only depended upon in Windows.
'target_name': 'browser_tests_exe_pdb_workaround',
'type': 'static_library',
'sources': [ 'empty_pdb_workaround.cc' ],
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index aa7b463..cb16621 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -73,6 +73,8 @@
'browser/chromeos/input_method/mock_input_method_manager.h',
'browser/chromeos/login/fake_login_utils.cc',
'browser/chromeos/login/fake_login_utils.h',
+ 'browser/chromeos/login/fake_user_manager.cc',
+ 'browser/chromeos/login/fake_user_manager.h',
'browser/chromeos/login/mock_authenticator.cc',
'browser/chromeos/login/mock_authenticator.h',
'browser/chromeos/login/mock_login_display.cc',
@@ -208,17 +210,12 @@
'renderer/safe_browsing/test_utils.h',
'test/automation/automation_handle_tracker.cc',
'test/automation/automation_handle_tracker.h',
- 'test/automation/automation_json_requests.cc',
- 'test/automation/automation_json_requests.h',
'test/automation/automation_proxy.cc',
'test/automation/automation_proxy.h',
'test/automation/browser_proxy.cc',
'test/automation/browser_proxy.h',
'test/automation/tab_proxy.cc',
'test/automation/tab_proxy.h',
- 'test/automation/value_conversion_traits.cc',
- 'test/automation/value_conversion_traits.h',
- 'test/automation/value_conversion_util.h',
'test/automation/window_proxy.cc',
'test/automation/window_proxy.h',
'test/base/chrome_render_view_host_test_harness.cc',
@@ -310,8 +307,9 @@
'../ipc/ipc.gyp:test_support_ipc',
'../media/media.gyp:media_test_support',
'../ppapi/ppapi_internal.gyp:ppapi_shared',
+ '../sql/sql.gyp:test_support_sql',
'../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
- '../webkit/support/webkit_support.gyp:glue_child',
+ '../webkit/glue/webkit_glue.gyp:glue_child',
],
'export_dependent_settings': [
'renderer',
@@ -678,6 +676,7 @@
'browser/chromeos/login/merge_session_load_page_unittest.cc',
'browser/chromeos/login/mock_auth_attempt_state_resolver.cc',
'browser/chromeos/login/mock_auth_attempt_state_resolver.h',
+ 'browser/chromeos/login/multi_profile_user_controller_unittest.cc',
'browser/chromeos/login/online_attempt_unittest.cc',
'browser/chromeos/login/parallel_authenticator_unittest.cc',
'browser/chromeos/login/screens/screen_context_unittest.cc',
@@ -706,6 +705,7 @@
'browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc',
'browser/chromeos/power/power_prefs_unittest.cc',
'browser/chromeos/preferences_unittest.cc',
+ 'browser/chromeos/profiles/profile_list_chromeos_unittest.cc',
'browser/chromeos/session_length_limiter_unittest.cc',
'browser/chromeos/proxy_config_service_impl_unittest.cc',
'browser/chromeos/settings/cros_settings_unittest.cc',
@@ -772,6 +772,7 @@
'browser/extensions/activity_log/counting_policy_unittest.cc',
'browser/extensions/activity_log/database_string_table_unittest.cc',
'browser/extensions/activity_log/fullstream_ui_policy_unittest.cc',
+ 'browser/extensions/activity_log/uma_policy_unittest.cc',
'browser/extensions/admin_policy_unittest.cc',
'browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc',
'browser/extensions/api/alarms/alarms_api_unittest.cc',
@@ -961,6 +962,7 @@
'browser/local_discovery/privet_url_fetcher_unittest.cc',
'browser/local_discovery/cloud_print_account_manager_unittest.cc',
'browser/local_discovery/cloud_print_printer_list_unittest.cc',
+ 'browser/local_discovery/service_discovery_client_mac_unittest.mm',
'browser/mac/keystone_glue_unittest.mm',
'browser/managed_mode/managed_mode_url_filter_unittest.cc',
'browser/managed_mode/managed_user_service_unittest.cc',
@@ -997,6 +999,7 @@
'browser/nacl_host/pnacl_translation_cache_unittest.cc',
'browser/nacl_host/pnacl_host_unittest.cc',
'browser/net/chrome_fraudulent_certificate_reporter_unittest.cc',
+ 'browser/net/chrome_network_data_saving_metrics_unittest.cc',
'browser/net/chrome_network_delegate_unittest.cc',
'browser/net/connection_tester_unittest.cc',
'browser/net/dns_probe_runner_unittest.cc',
@@ -1071,6 +1074,7 @@
'browser/policy/cloud/user_policy_signin_service_unittest.cc',
'browser/policy/config_dir_policy_loader_unittest.cc',
'browser/policy/configuration_policy_handler_unittest.cc',
+ 'browser/policy/configuration_policy_handler_list_unittest.cc',
'browser/policy/configuration_policy_pref_store_unittest.cc',
'browser/policy/configuration_policy_provider_test.cc',
'browser/policy/configuration_policy_provider_test.h',
@@ -1118,14 +1122,16 @@
'browser/process_info_snapshot_mac_unittest.cc',
'browser/process_singleton_linux_unittest.cc',
'browser/process_singleton_mac_unittest.cc',
+ 'browser/profile_resetter/jtl_interpreter_unittest.cc',
'browser/profile_resetter/profile_resetter_unittest.cc',
- 'browser/profiles/avatar_menu_model_unittest.cc',
+ 'browser/profiles/file_path_verifier_win_unittest.cc',
'browser/profiles/gaia_info_update_service_unittest.cc',
'browser/profiles/off_the_record_profile_impl_unittest.cc',
'browser/profiles/profile_downloader_unittest.cc',
'browser/profiles/profile_info_cache_unittest.cc',
'browser/profiles/profile_info_cache_unittest.h',
'browser/profiles/profile_info_util_unittest.cc',
+ 'browser/profiles/profile_list_desktop_unittest.cc',
'browser/profiles/profile_loader_unittest.cc',
'browser/profiles/profile_manager_unittest.cc',
'browser/profiles/profile_shortcut_manager_unittest_win.cc',
@@ -1169,6 +1175,9 @@
'browser/safe_browsing/signature_util_win_unittest.cc',
'browser/safe_browsing/two_phase_uploader_unittest.cc',
'browser/search/iframe_source_unittest.cc',
+ 'browser/search/instant_service_unittest.cc',
+ 'browser/search/instant_unittest_base.cc',
+ 'browser/search/instant_unittest_base.h',
'browser/search/most_visited_iframe_source_unittest.cc',
'browser/search/search_unittest.cc',
'browser/search_engines/search_host_to_urls_map_unittest.cc',
@@ -1321,6 +1330,8 @@
'browser/sync_file_system/drive_backend/drive_backend_test_util.cc',
'browser/sync_file_system/drive_backend/drive_backend_test_util.h',
'browser/sync_file_system/drive_backend/sync_engine_initializer_unittest.cc',
+ 'browser/sync_file_system/drive_backend/drive_backend_test_util.cc',
+ 'browser/sync_file_system/drive_backend/drive_backend_test_util.h',
'browser/sync_file_system/fake_remote_change_processor.cc',
'browser/sync_file_system/fake_remote_change_processor.h',
'browser/sync_file_system/file_change_unittest.cc',
@@ -1393,6 +1404,7 @@
'browser/ui/bookmarks/bookmark_unittest.cc',
'browser/ui/bookmarks/recently_used_folders_combo_model_unittest.cc',
'browser/ui/browser_command_controller_unittest.cc',
+ 'browser/ui/browser_instant_controller_unittest.cc',
'browser/ui/browser_iterator_unittest.cc',
'browser/ui/browser_unittest.cc',
'browser/ui/chrome_select_file_policy_unittest.cc',
@@ -1527,7 +1539,6 @@
'browser/ui/cocoa/location_bar/selected_keyword_decoration_unittest.mm',
'browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm',
'browser/ui/cocoa/menu_button_unittest.mm',
- 'browser/ui/cocoa/nine_part_button_cell_unittest.mm',
'browser/ui/cocoa/notifications/balloon_controller_unittest.mm',
'browser/ui/cocoa/notifications/message_center_tray_bridge_unittest.mm',
'browser/ui/cocoa/nsmenuitem_additions_unittest.mm',
@@ -1551,7 +1562,6 @@
'browser/ui/cocoa/tab_contents/sad_tab_view_unittest.mm',
'browser/ui/cocoa/table_row_nsimage_cache_unittest.mm',
'browser/ui/cocoa/tabpose_window_unittest.mm',
- 'browser/ui/cocoa/tabs/tab_audio_indicator_view_mac_unittest.mm',
'browser/ui/cocoa/tabs/tab_controller_unittest.mm',
'browser/ui/cocoa/tabs/tab_projecting_image_view_unittest.mm',
'browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm',
@@ -1617,7 +1627,6 @@
'browser/ui/tabs/pinned_tab_codec_unittest.cc',
'browser/ui/tabs/pinned_tab_service_unittest.cc',
'browser/ui/tabs/pinned_tab_test_utils.cc',
- 'browser/ui/tabs/tab_audio_indicator_unittest.cc',
'browser/ui/tabs/tab_menu_model_unittest.cc',
'browser/ui/tabs/tab_strip_model_unittest.cc',
'browser/ui/tabs/test_tab_strip_model_delegate.cc',
@@ -2242,6 +2251,7 @@
'browser/policy/cloud/user_cloud_policy_manager_unittest.cc',
'browser/policy/cloud/user_cloud_policy_store_unittest.cc',
'browser/policy/cloud/user_policy_signin_service_unittest.cc',
+ 'browser/profiles/profile_list_desktop_unittest.cc',
'browser/safe_browsing/download_protection_service_unittest.cc',
'browser/shell_integration_linux_unittest.cc',
'browser/signin/signin_manager_unittest.cc',
@@ -2495,13 +2505,16 @@
'browser/policy/config_dir_policy_loader_unittest.cc',
'browser/policy/policy_path_parser_unittest.cc',
'browser/profiles/off_the_record_profile_impl_unittest.cc',
+ 'browser/profiles/profile_list_desktop_unittest.cc',
'browser/profiles/profile_loader_unittest.cc',
+ 'browser/search/instant_service_unittest.cc',
'browser/search/search_unittest.cc',
'browser/signin/profile_oauth2_token_service_unittest.cc',
'browser/sync/profile_sync_service_session_unittest.cc',
'browser/sync/sync_global_error_unittest.cc',
'browser/tab_contents/render_view_context_menu_unittest.cc',
'browser/ui/autofill/autofill_dialog_controller_unittest.cc',
+ 'browser/ui/browser_instant_controller_unittest.cc',
'browser/ui/bookmarks/bookmark_bubble_sign_in_delegate_unittest.cc',
'browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc',
'browser/ui/bookmarks/bookmark_prompt_controller_unittest.cc',
@@ -2669,6 +2682,11 @@
'../third_party/cld/cld.gyp:cld',
],
}],
+ ['enable_app_list==1', {
+ 'sources': [
+ 'browser/ui/app_list/test/fast_show_pickler_unittest.cc',
+ ],
+ }],
],
'target_conditions': [
['OS == "ios"', {
@@ -2697,9 +2715,7 @@
'..',
],
'sources': [
- 'app/breakpad_field_trial_win.cc',
'app/breakpad_win.cc',
- 'app/breakpad_unittest_win.cc',
'app/delay_load_hook_win.cc',
'app/delay_load_hook_win.h',
'app/delay_load_hook_unittest_win.cc',
@@ -2794,5 +2810,25 @@
},
],
}],
+ ['enable_app_list==1', {
+ 'targets': [
+ {
+ # Unit tests for chrome app list, not run on any bots, this is for faster
+ # compile/link/test cycles during development.
+ 'target_name': 'chrome_app_list_unittests',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ '../base/base.gyp:run_all_unittests',
+ '../skia/skia.gyp:skia',
+ '../testing/gtest.gyp:gtest',
+ 'apps',
+ 'browser_ui',
+ ],
+ 'sources': [
+ 'browser/ui/app_list/test/fast_show_pickler_unittest.cc',
+ ],
+ },
+ ],
+ }],
], # 'conditions'
}
diff --git a/chrome/common/automation_constants.cc b/chrome/common/automation_constants.cc
index 1b8d32d..212864c 100644
--- a/chrome/common/automation_constants.cc
+++ b/chrome/common/automation_constants.cc
@@ -19,48 +19,4 @@
// AutomationProxy to an already-running browser instance.
const char kNamedInterfacePrefix[] = "NamedTestingInterface:";
-const int kChromeDriverAutomationVersion = 1;
-
-namespace {
-
-// Returns the string equivalent of the given |ErrorCode|.
-const char* DefaultMessageForErrorCode(ErrorCode code) {
- switch (code) {
- case kUnknownError:
- return "Unknown error";
- case kNoJavaScriptModalDialogOpen:
- return "No JavaScript modal dialog is open";
- case kBlockedByModalDialog:
- return "Command blocked by an open modal dialog";
- case kInvalidId:
- return "ID is invalid or does not refer to an existing object";
- default:
- return "<unknown>";
- }
-}
-
-} // namespace
-
-Error::Error() : code_(kUnknownError) { }
-
-Error::Error(ErrorCode code)
- : code_(code),
- message_(DefaultMessageForErrorCode(code)) { }
-
-Error::Error(const std::string& error_msg)
- : code_(kUnknownError), message_(error_msg) { }
-
-Error::Error(ErrorCode code, const std::string& error_msg)
- : code_(code), message_(error_msg) { }
-
-Error::~Error() { }
-
-ErrorCode Error::code() const {
- return code_;
-}
-
-const std::string& Error::message() const {
- return message_;
-}
-
} // namespace automation
diff --git a/chrome/common/automation_constants.h b/chrome/common/automation_constants.h
index 4742b39..112e29f 100644
--- a/chrome/common/automation_constants.h
+++ b/chrome/common/automation_constants.h
@@ -64,57 +64,6 @@
kNoButton,
};
-// The current version of ChromeDriver automation supported by Chrome.
-// This needs to be incremented for each change to ChromeDriver automation that
-// is not backwards compatible. Some examples of this would be:
-// - SendJSONRequest or Hello IPC messages change
-// - The interface for an individual ChromeDriver automation call changes in an
-// incompatible way
-// TODO(kkania): Investigate a better backwards compatible automation solution.
-extern const int kChromeDriverAutomationVersion;
-
-// Automation error codes. These provide the client a simple way
-// to detect certain types of errors it may be interested in handling.
-// The error code values must stay consistent across compatible versions.
-enum ErrorCode {
- // An unknown error occurred.
- kUnknownError = 0,
- // Trying to operate on a JavaScript modal dialog when none is open.
- kNoJavaScriptModalDialogOpen = 1,
- // An open modal dialog blocked the operation. The operation may have
- // partially completed.
- kBlockedByModalDialog = 2,
- // An ID was supplied that is invalid or does not refer to an existing object.
- kInvalidId = 3,
-};
-
-// Represents an automation error. Each error has a code and an error message.
-class Error {
- public:
- // Creates an invalid error.
- Error();
-
- // Creates an error for the given code. A default message for the given code
- // will be used as the error message.
- explicit Error(ErrorCode code);
-
- // Creates an error for the given message. The |kUnknownError| type will
- // be used.
- explicit Error(const std::string& error_msg);
-
- // Creates an error for the given code and message.
- Error(ErrorCode code, const std::string& error_msg);
-
- virtual ~Error();
-
- ErrorCode code() const;
- const std::string& message() const;
-
- private:
- ErrorCode code_;
- std::string message_;
-};
-
} // namespace automation
// Used by AutomationProxy, declared here so that other headers don't need
diff --git a/chrome/common/automation_id.cc b/chrome/common/automation_id.cc
deleted file mode 100644
index b1d5c3a..0000000
--- a/chrome/common/automation_id.cc
+++ /dev/null
@@ -1,72 +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/common/automation_id.h"
-
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-
-// static
-bool AutomationId::FromValue(
- base::Value* value, AutomationId* id, std::string* error) {
- base::DictionaryValue* dict;
- if (!value->GetAsDictionary(&dict)) {
- *error = "automation ID must be a dictionary";
- return false;
- }
- int type;
- if (!dict->GetInteger("type", &type)) {
- *error = "automation ID 'type' missing or invalid";
- return false;
- }
- std::string type_id;
- if (!dict->GetString("id", &type_id)) {
- *error = "automation ID 'type_id' missing or invalid";
- return false;
- }
- *id = AutomationId(static_cast<Type>(type), type_id);
- return true;
-}
-
-// static
-bool AutomationId::FromValueInDictionary(
- base::DictionaryValue* dict,
- const std::string& key,
- AutomationId* id,
- std::string* error) {
- base::Value* id_value;
- if (!dict->Get(key, &id_value)) {
- *error = base::StringPrintf("automation ID '%s' missing", key.c_str());
- return false;
- }
- return FromValue(id_value, id, error);
-}
-
-AutomationId::AutomationId() : type_(kTypeInvalid) { }
-
-AutomationId::AutomationId(Type type, const std::string& id)
- : type_(type), id_(id) { }
-
-bool AutomationId::operator==(const AutomationId& id) const {
- return type_ == id.type_ && id_ == id.id_;
-}
-
-base::DictionaryValue* AutomationId::ToValue() const {
- base::DictionaryValue* dict = new base::DictionaryValue();
- dict->SetInteger("type", type_);
- dict->SetString("id", id_);
- return dict;
-}
-
-bool AutomationId::is_valid() const {
- return type_ != kTypeInvalid;
-}
-
-AutomationId::Type AutomationId::type() const {
- return type_;
-}
-
-const std::string& AutomationId::id() const {
- return id_;
-}
diff --git a/chrome/common/automation_id.h b/chrome/common/automation_id.h
deleted file mode 100644
index b05f060..0000000
--- a/chrome/common/automation_id.h
+++ /dev/null
@@ -1,62 +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_AUTOMATION_ID_H_
-#define CHROME_COMMON_AUTOMATION_ID_H_
-
-#include <string>
-
-namespace base {
-class DictionaryValue;
-class Value;
-}
-
-// A unique ID that JSON automation clients can use to refer to browser
-// entities. The ID has a type so that:
-// 1) supplying an ID of the wrong type can be detected.
-// 2) the client does not have to explicitly supply the type in case multiple
-// ID types can be accepted (e.g., can use a tab ID or extension popup ID for
-// executing javascript).
-class AutomationId {
- public:
- // The value of each entry should be preserved.
- enum Type {
- kTypeInvalid = 0,
- kTypeTab,
- kTypeExtensionPopup,
- kTypeExtensionBgPage,
- kTypeExtensionInfobar,
- kTypeExtension,
- kTypeAppShell,
- };
-
- static bool FromValue(
- base::Value* value, AutomationId* id, std::string* error);
- static bool FromValueInDictionary(
- base::DictionaryValue* dict, const std::string& key, AutomationId* id,
- std::string* error);
-
- // Constructs an invalid ID.
- AutomationId();
-
- // Constructs an ID from the given type and type-specific ID.
- AutomationId(Type type, const std::string& id);
-
- bool operator==(const AutomationId& id) const;
-
- // Returns a new dictionary equivalent to this ID.
- base::DictionaryValue* ToValue() const;
-
- // Returns whether the automation ID is valid.
- bool is_valid() const;
-
- Type type() const;
- const std::string& id() const;
-
- private:
- Type type_;
- std::string id_;
-};
-
-#endif // CHROME_COMMON_AUTOMATION_ID_H_
diff --git a/chrome/common/badge_util.cc b/chrome/common/badge_util.cc
index ccbaca1..a762a6f 100644
--- a/chrome/common/badge_util.cc
+++ b/chrome/common/badge_util.cc
@@ -124,7 +124,7 @@
// Render the badge bitmap and overlay into a canvas.
scoped_ptr<gfx::Canvas> canvas(new gfx::Canvas(
- gfx::Size(badge_width, icon.height()), ui::SCALE_FACTOR_100P, false));
+ gfx::Size(badge_width, icon.height()), 1.0f, false));
canvas->DrawImageInt(gfx::ImageSkia::CreateFrom1xBitmap(icon), 0, 0);
// Draw the text overlay centered horizontally and vertically. Skia expects
diff --git a/chrome/common/child_process_logging.h b/chrome/common/child_process_logging.h
index 6132061..f437828 100644
--- a/chrome/common/child_process_logging.h
+++ b/chrome/common/child_process_logging.h
@@ -5,23 +5,10 @@
#ifndef CHROME_COMMON_CHILD_PROCESS_LOGGING_H_
#define CHROME_COMMON_CHILD_PROCESS_LOGGING_H_
-#include <set>
#include <string>
-#include <vector>
#include "base/basictypes.h"
#include "base/debug/crash_logging.h"
-#include "base/strings/string16.h"
-
-// The maximum number of variation chunks we will report.
-// Also used in chrome/app, but we define it here to avoid a common->app
-// dependency.
-static const size_t kMaxReportedVariationChunks = 15;
-
-// The maximum size of a variation chunk. This size was picked to be
-// consistent between platforms and the value was chosen from the Windows
-// limit of google_breakpad::CustomInfoEntry::kValueMaxLength.
-static const size_t kMaxVariationChunkSize = 64;
namespace child_process_logging {
@@ -29,8 +16,6 @@
// These are declared here so the crash reporter can access them directly in
// compromised context without going through the standard library.
extern char g_client_id[];
-extern char g_num_variations[];
-extern char g_variation_chunks[];
// Assume command line switches are less than 64 chars.
static const size_t kSwitchLen = 64;
@@ -43,18 +28,11 @@
// id in |client_id| if it's known, an empty string otherwise.
std::string GetClientId();
-// Initialize the list of experiment info to send along with crash reports.
-void SetExperimentList(const std::vector<string16>& state);
-
-} // namespace child_process_logging
-
#if defined(OS_WIN)
-namespace child_process_logging {
-
// Sets up the base/debug/crash_logging.h mechanism.
void Init();
+#endif // defined(OS_WIN)
} // namespace child_process_logging
-#endif // defined(OS_WIN)
#endif // CHROME_COMMON_CHILD_PROCESS_LOGGING_H_
diff --git a/chrome/common/child_process_logging_mac.mm b/chrome/common/child_process_logging_mac.mm
index 572fd52..5747945 100644
--- a/chrome/common/child_process_logging_mac.mm
+++ b/chrome/common/child_process_logging_mac.mm
@@ -7,9 +7,7 @@
#import <Foundation/Foundation.h>
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/common/metrics/variations/variations_util.h"
#include "chrome/installer/util/google_update_settings.h"
namespace child_process_logging {
@@ -45,31 +43,4 @@
return std::string(g_client_id);
}
-void SetExperimentList(const std::vector<string16>& experiments) {
- // These should match the corresponding strings in breakpad_win.cc.
- const char* kNumExperimentsKey = "num-experiments";
- const char* kExperimentChunkFormat = "experiment-chunk-%zu"; // 1-based
-
- std::vector<string16> chunks;
- chrome_variations::GenerateVariationChunks(experiments, &chunks);
-
- // Store up to |kMaxReportedVariationChunks| chunks.
- for (size_t i = 0; i < kMaxReportedVariationChunks; ++i) {
- std::string key = base::StringPrintf(kExperimentChunkFormat, i + 1);
- if (i < chunks.size()) {
- std::string value = UTF16ToUTF8(chunks[i]);
- SetCrashKeyValue(key, value);
- } else {
- ClearCrashKey(key);
- }
- }
-
- // Make note of the total number of experiments, which may be greater than
- // what was able to fit in |kMaxReportedVariationChunks|. This is useful when
- // correlating stability with the number of experiments running
- // simultaneously.
- SetCrashKeyValue(kNumExperimentsKey,
- base::StringPrintf("%zu", experiments.size()));
-}
-
} // namespace child_process_logging
diff --git a/chrome/common/child_process_logging_posix.cc b/chrome/common/child_process_logging_posix.cc
index 68f72d2..0ff249a 100644
--- a/chrome/common/child_process_logging_posix.cc
+++ b/chrome/common/child_process_logging_posix.cc
@@ -4,12 +4,8 @@
#include "chrome/common/child_process_logging.h"
-#include "base/format_macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/common/metrics/variations/variations_util.h"
#include "chrome/installer/util/google_update_settings.h"
namespace child_process_logging {
@@ -22,13 +18,6 @@
// these strings to the browser.
char g_client_id[kClientIdSize];
-static const size_t kNumSize = 32;
-char g_num_variations[kNumSize] = "";
-
-static const size_t kMaxVariationChunksSize =
- kMaxVariationChunkSize * kMaxReportedVariationChunks + 1;
-char g_variation_chunks[kMaxVariationChunksSize] = "";
-
void SetClientId(const std::string& client_id) {
std::string str(client_id);
ReplaceSubstringsAfterOffset(&str, 0, "-", std::string());
@@ -45,28 +34,4 @@
return std::string(g_client_id);
}
-void SetExperimentList(const std::vector<string16>& experiments) {
- std::vector<string16> chunks;
- chrome_variations::GenerateVariationChunks(experiments, &chunks);
-
- // Store up to |kMaxReportedVariationChunks| chunks.
- std::string chunks_str;
- const size_t number_of_chunks_to_report =
- std::min(chunks.size(), kMaxReportedVariationChunks);
- for (size_t i = 0; i < number_of_chunks_to_report; ++i) {
- chunks_str += UTF16ToUTF8(chunks[i]);
- // Align short chunks with spaces to be trimmed later.
- chunks_str.resize(i * kMaxVariationChunkSize, ' ');
- }
- base::strlcpy(g_variation_chunks, chunks_str.c_str(),
- arraysize(g_variation_chunks));
-
- // Make note of the total number of experiments, which may be greater than
- // what was able to fit in |kMaxReportedVariationChunks|. This is useful when
- // correlating stability with the number of experiments running
- // simultaneously.
- snprintf(g_num_variations, arraysize(g_num_variations), "%" PRIuS,
- experiments.size());
-}
-
} // namespace child_process_logging
diff --git a/chrome/common/child_process_logging_win.cc b/chrome/common/child_process_logging_win.cc
index 659096c..11a293e 100644
--- a/chrome/common/child_process_logging_win.cc
+++ b/chrome/common/child_process_logging_win.cc
@@ -6,12 +6,10 @@
#include <windows.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_constants.h"
#include "chrome/common/crash_keys.h"
-#include "chrome/common/metrics/variations/variations_util.h"
#include "chrome/installer/util/google_update_settings.h"
namespace child_process_logging {
@@ -21,10 +19,6 @@
// exported in breakpad_win.cc: void __declspec(dllexport) __cdecl SetClientId.
typedef void (__cdecl *MainSetClientId)(const wchar_t*);
-// exported in breakpad_field_trial_win.cc:
-// void __declspec(dllexport) __cdecl SetExperimentList3
-typedef void (__cdecl *MainSetExperimentList)(const wchar_t**, size_t, size_t);
-
// exported in breakpad_win.cc:
// void __declspec(dllexport) __cdecl SetCrashKeyValueImpl.
typedef void (__cdecl *SetCrashKeyValue)(const wchar_t*, const wchar_t*);
@@ -33,16 +27,6 @@
// void __declspec(dllexport) __cdecl ClearCrashKeyValueImpl.
typedef void (__cdecl *ClearCrashKeyValue)(const wchar_t*);
-
-// Copied from breakpad_win.cc.
-void StringVectorToCStringVector(const std::vector<std::wstring>& wstrings,
- std::vector<const wchar_t*>* cstrings) {
- cstrings->clear();
- cstrings->reserve(wstrings.size());
- for (size_t i = 0; i < wstrings.size(); ++i)
- cstrings->push_back(wstrings[i].c_str());
-}
-
} // namespace
void SetClientId(const std::string& client_id) {
@@ -81,34 +65,6 @@
return std::string();
}
-void SetExperimentList(const std::vector<string16>& experiments) {
- static MainSetExperimentList set_experiment_list = NULL;
- // note: benign race condition on set_experiment_list.
- if (!set_experiment_list) {
- HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName);
- if (!exe_module)
- return;
- set_experiment_list = reinterpret_cast<MainSetExperimentList>(
- GetProcAddress(exe_module, "SetExperimentList3"));
- if (!set_experiment_list)
- return;
- }
-
- std::vector<string16> chunks;
- chrome_variations::GenerateVariationChunks(experiments, &chunks);
-
- // If the list is empty, notify the child process of the number of experiments
- // and exit early.
- if (chunks.empty()) {
- (set_experiment_list)(NULL, 0, 0);
- return;
- }
-
- std::vector<const wchar_t*> cstrings;
- StringVectorToCStringVector(chunks, &cstrings);
- (set_experiment_list)(&cstrings[0], cstrings.size(), experiments.size());
-}
-
namespace {
void SetCrashKeyValueTrampoline(const base::StringPiece& key,
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index 3cd880d..70aedeb 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -73,8 +73,6 @@
const char kPnaclPluginMimeType[] = "application/x-pnacl";
const char kPnaclPluginExtension[] = "";
const char kPnaclPluginDescription[] = "Portable Native Client Executable";
-const uint32 kPnaclPluginPermissions = ppapi::PERMISSION_PRIVATE |
- ppapi::PERMISSION_DEV;
const char kO3DPluginName[] = "Google Talk Plugin Video Accelerator";
const char kO3DPluginMimeType[] ="application/vnd.o3d.auto";
@@ -90,6 +88,13 @@
const uint32 kO1DPluginPermissions = ppapi::PERMISSION_PRIVATE |
ppapi::PERMISSION_DEV;
+const char kEffectsPluginName[] = "Google Talk Effects Plugin";
+const char kEffectsPluginMimeType[] ="application/x-ppapi-hangouts-effects";
+const char kEffectsPluginExtension[] = "";
+const char kEffectsPluginDescription[] = "Google Talk Effects Plugin";
+const uint32 kEffectsPluginPermissions = ppapi::PERMISSION_PRIVATE |
+ ppapi::PERMISSION_DEV;
+
const char kGTalkPluginName[] = "Google Talk Plugin";
const char kGTalkPluginMimeType[] ="application/googletalk";
const char kGTalkPluginExtension[] = ".googletalk";
@@ -108,8 +113,6 @@
"shared with you. To use this plugin you must first install the "
"<a href=\"https://chrome.google.com/remotedesktop\">"
"Chrome Remote Desktop</a> webapp.";
-const base::FilePath::CharType kRemotingViewerPluginPath[] =
- FILE_PATH_LITERAL("internal-remoting-viewer");
// Use a consistent MIME-type regardless of branding.
const char kRemotingViewerPluginMimeType[] =
"application/vnd.chromium.remoting-viewer";
@@ -227,6 +230,27 @@
}
}
+ // TODO(vrk): Remove this when NaCl effects plugin replaces the ppapi effects
+ // plugin.
+ static bool skip_effects_file_check = false;
+ if (PathService::Get(chrome::FILE_EFFECTS_PLUGIN, &path)) {
+ if (skip_effects_file_check || base::PathExists(path)) {
+ content::PepperPluginInfo effects;
+ effects.path = path;
+ effects.name = kEffectsPluginName;
+ effects.is_out_of_process = true;
+ effects.is_sandboxed = true;
+ effects.permissions = kEffectsPluginPermissions;
+ content::WebPluginMimeType effects_mime_type(kEffectsPluginMimeType,
+ kEffectsPluginExtension,
+ kEffectsPluginDescription);
+ effects.mime_types.push_back(effects_mime_type);
+ plugins->push_back(effects);
+
+ skip_effects_file_check = true;
+ }
+ }
+
static bool skip_gtalk_file_check = false;
if (PathService::Get(chrome::FILE_GTALK_PLUGIN, &path)) {
if (skip_gtalk_file_check || base::PathExists(path)) {
@@ -278,7 +302,8 @@
info.is_out_of_process = true;
info.name = kRemotingViewerPluginName;
info.description = kRemotingViewerPluginDescription;
- info.path = base::FilePath(kRemotingViewerPluginPath);
+ info.path = base::FilePath(
+ chrome::ChromeContentClient::kRemotingViewerPluginPath);
content::WebPluginMimeType remoting_mime_type(
kRemotingViewerPluginMimeType,
kRemotingViewerPluginMimeExtension,
diff --git a/chrome/common/chrome_content_client.h b/chrome/common/chrome_content_client.h
index 1ee71d2..53b7441 100644
--- a/chrome/common/chrome_content_client.h
+++ b/chrome/common/chrome_content_client.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
#include "content/public/common/content_client.h"
namespace chrome {
@@ -18,6 +19,7 @@
static const char* const kPDFPluginName;
static const char* const kNaClPluginName;
static const char* const kNaClOldPluginName;
+ static const base::FilePath::CharType kRemotingViewerPluginPath[];
virtual void SetActiveURL(const GURL& url) OVERRIDE;
virtual void SetGpuInfo(const gpu::GPUInfo& gpu_info) OVERRIDE;
diff --git a/chrome/common/chrome_content_client_constants.cc b/chrome/common/chrome_content_client_constants.cc
index aeea06f..1366572 100644
--- a/chrome/common/chrome_content_client_constants.cc
+++ b/chrome/common/chrome_content_client_constants.cc
@@ -9,5 +9,8 @@
const char* const ChromeContentClient::kPDFPluginName = "Chrome PDF Viewer";
const char* const ChromeContentClient::kNaClPluginName = "Native Client";
const char* const ChromeContentClient::kNaClOldPluginName = "Chrome NaCl";
+const base::FilePath::CharType
+ ChromeContentClient::kRemotingViewerPluginPath[] =
+ FILE_PATH_LITERAL("internal-remoting-viewer");
} // namespace chrome
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc
index 904fbef..4238481 100644
--- a/chrome/common/chrome_paths.cc
+++ b/chrome/common/chrome_paths.cc
@@ -66,6 +66,9 @@
#if defined(OS_POSIX) && !defined(OS_MACOSX)
+const base::FilePath::CharType kEffectsPluginFileName[] =
+ FILE_PATH_LITERAL("pepper/libppeffects.so");
+
const base::FilePath::CharType kO3DPluginFileName[] =
FILE_PATH_LITERAL("pepper/libppo3dautoplugin.so");
@@ -330,6 +333,11 @@
return false;
cur = cur.Append(kO1DPluginFileName);
break;
+ case chrome::FILE_EFFECTS_PLUGIN:
+ if (!PathService::Get(base::DIR_MODULE, &cur))
+ return false;
+ cur = cur.Append(kEffectsPluginFileName);
+ break;
case chrome::FILE_GTALK_PLUGIN:
if (!PathService::Get(base::DIR_MODULE, &cur))
return false;
diff --git a/chrome/common/chrome_paths.h b/chrome/common/chrome_paths.h
index 9d1b050..fe5f6f2 100644
--- a/chrome/common/chrome_paths.h
+++ b/chrome/common/chrome_paths.h
@@ -85,6 +85,7 @@
// (subdir of DIR_PNACL_BASE).
FILE_O3D_PLUGIN, // Full path to the O3D Pepper plugin file.
FILE_O1D_PLUGIN, // Full path to the O1D Pepper plugin file.
+ FILE_EFFECTS_PLUGIN, // Full path to the Effects Pepper plugin file.
FILE_GTALK_PLUGIN, // Full path to the GTalk Pepper plugin file.
DIR_COMPONENT_WIDEVINE_CDM, // Directory that contains component-updated
// Widevine CDM files.
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 4693e36..2a6f133 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -577,6 +577,10 @@
// If true devtools experimental settings are enabled.
const char kEnableDevToolsExperiments[] = "enable-devtools-experiments";
+// Enable device discovery notifications.
+const char kEnableDeviceDiscoveryNotifications[] =
+ "enable-device-discovery-notifications";
+
// Force-enables DNS probes on main frame DNS errors. (The user must still
// opt in to "Use web service to resolve navigation errors".)
const char kEnableDnsProbes[] = "enable-dns-probes";
@@ -1130,8 +1134,10 @@
// prefetch_only: No prerendering, but enables prefetching.
const char kPrerenderModeSwitchValuePrefetchOnly[] = "prefetch_only";
+#if defined(OS_WIN)
// Enable conversion from vector to raster for any page.
const char kPrintRaster[] = "print-raster";
+#endif
// Use IPv6 only for privet HTTP.
const char kPrivetIPv6Only[] = "privet-ipv6-only";
@@ -1447,6 +1453,9 @@
// apps/origins. This should be used only for testing purpose.
const char kUnlimitedStorage[] = "unlimited-storage";
+// Use the cacheable New Tab page for Embedded Search.
+const char kUseCacheableNewTabPage[] = "use-cacheable-new-tab-page";
+
// Uses Spdy for the transport protocol instead of HTTP. This is a temporary
// testing flag.
const char kUseSpdy[] = "use-spdy";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 2db9cb4..8015e3d 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -171,6 +171,7 @@
extern const char kEnableComponentCloudPolicy[];
extern const char kEnableContacts[];
extern const char kEnableDevToolsExperiments[];
+extern const char kEnableDeviceDiscoveryNotifications[];
extern const char kEnableDnsProbes[];
extern const char kEnableDomDistiller[];
extern const char kEnableExtensionActivityLogging[];
@@ -387,6 +388,7 @@
extern const char kUninstallExtension[];
extern const char kUninstall[];
extern const char kUnlimitedStorage[];
+extern const char kUseCacheableNewTabPage[];
extern const char kUseSimpleCacheBackend[];
extern const char kUseSpdy[];
extern const char kUseSpellingSuggestions[];
diff --git a/chrome/common/cloud_print/cloud_print_constants.cc b/chrome/common/cloud_print/cloud_print_constants.cc
index 4a82258..c1bad6b 100644
--- a/chrome/common/cloud_print/cloud_print_constants.cc
+++ b/chrome/common/cloud_print/cloud_print_constants.cc
@@ -20,6 +20,7 @@
const char kPrinterStatusValue[] = "status";
const char kPrinterTagValue[] = "tag";
const char kPrinterRemoveTagValue[] = "remove_tag";
+const char kPrinterLocalSettingsValue[] = "local_settings";
const char kMessageTextValue[] = "message";
const char kPrintSystemFailedMessageId[] = "printsystemfail";
@@ -44,6 +45,10 @@
const char kPrinterTypeValue[] = "type";
const char kUserValue[] = "request.user";
const char kUsersValue[] = "request.users";
+const char kLocalSettingsPendingXmppValue[] =
+ "local_settings.pending.xmpp_timeout_value";
+
+const char kNotificationUpdateSettings[] = "/update_settings";
const char kChromeVersionTagName[] = "chrome_version";
const char kSystemNameTagName[] = "system_name";
@@ -60,4 +65,9 @@
const char kJobFetchReasonFailure[] = "failure";
const char kJobFetchReasonRetry[] = "retry";
+const char kCreateLocalSettingsXmppPingFormat[] =
+ "{\"current\":{\"xmpp_timeout_value\": %d}}";
+const char kUpdateLocalSettingsXmppPingFormat[] =
+ "{\"current\":{\"xmpp_timeout_value\": %d},\"pending\":{}}";
+
} // namespace cloud_print
diff --git a/chrome/common/cloud_print/cloud_print_constants.h b/chrome/common/cloud_print/cloud_print_constants.h
index 71811d3..f6a4db7 100644
--- a/chrome/common/cloud_print/cloud_print_constants.h
+++ b/chrome/common/cloud_print/cloud_print_constants.h
@@ -28,6 +28,7 @@
extern const char kPrinterStatusValue[];
extern const char kPrinterTagValue[];
extern const char kPrinterRemoveTagValue[];
+extern const char kPrinterLocalSettingsValue[];
extern const char kMessageTextValue[];
// Value of "code" parameter in cloud print "/message" requests.
@@ -54,6 +55,10 @@
extern const char kPrinterTypeValue[];
extern const char kUserValue[];
extern const char kUsersValue[];
+extern const char kLocalSettingsPendingXmppValue[];
+
+// Value in XMPP notification.
+extern const char kNotificationUpdateSettings[];
// Printer tag names. Don't need prefixes. They will be added on submit.
extern const char kChromeVersionTagName[];
@@ -79,6 +84,10 @@
// Job fetch due to scheduled retry.
extern const char kJobFetchReasonRetry[];
+// Format of the local settings containing only XMPP ping.
+extern const char kCreateLocalSettingsXmppPingFormat[];
+extern const char kUpdateLocalSettingsXmppPingFormat[];
+
// Max retry count for job data fetch requests.
const int kJobDataMaxRetryCount = 1;
// Max retry count (infinity) for API fetch requests.
@@ -95,8 +104,8 @@
// When we have XMPP notifications available, we ping server to keep connection
// alive or check connection status.
-const int kDefaultXmppPingTimeoutSecs = 5*60; // 5 minutes in seconds
-const int kMinimumXmppPingTimeoutSecs = 2*60; // 2 minutes in seconds
+const int kDefaultXmppPingTimeoutSecs = 5*60;
+const int kMinXmppPingTimeoutSecs = 1*60;
const int kXmppPingCheckIntervalSecs = 60;
// Number of failed pings before we try to reinstablish XMPP connection.
diff --git a/chrome/common/cloud_print/cloud_print_helpers.cc b/chrome/common/cloud_print/cloud_print_helpers.cc
index 1f308cf..41838e1 100644
--- a/chrome/common/cloud_print/cloud_print_helpers.cc
+++ b/chrome/common/cloud_print/cloud_print_helpers.cc
@@ -136,12 +136,14 @@
GURL GetUrlForJobStatusUpdate(const GURL& cloud_print_server_url,
const std::string& job_id,
- const std::string& status_string) {
+ const std::string& status_string,
+ int connector_code) {
std::string path(AppendPathToUrl(cloud_print_server_url, "control"));
GURL::Replacements replacements;
replacements.SetPathStr(path);
std::string query = base::StringPrintf(
- "jobid=%s&status=%s", job_id.c_str(), status_string.c_str());
+ "jobid=%s&status=%s&connector_code=%d", job_id.c_str(),
+ status_string.c_str(), connector_code);
replacements.SetQueryStr(query);
return cloud_print_server_url.ReplaceComponents(replacements);
}
diff --git a/chrome/common/cloud_print/cloud_print_helpers.h b/chrome/common/cloud_print/cloud_print_helpers.h
index 23a9f8f..7b3b6f8 100644
--- a/chrome/common/cloud_print/cloud_print_helpers.h
+++ b/chrome/common/cloud_print/cloud_print_helpers.h
@@ -48,7 +48,8 @@
const std::string& job_id);
GURL GetUrlForJobStatusUpdate(const GURL& cloud_print_server_url,
const std::string& job_id,
- const std::string& status_string);
+ const std::string& status_string,
+ int connector_code);
GURL GetUrlForUserMessage(const GURL& cloud_print_server_url,
const std::string& message_id);
GURL GetUrlForGetAuthCode(const GURL& cloud_print_server_url,
diff --git a/chrome/common/cloud_print/cloud_print_helpers_unittest.cc b/chrome/common/cloud_print/cloud_print_helpers_unittest.cc
index 1fdd038..662ee58 100644
--- a/chrome/common/cloud_print/cloud_print_helpers_unittest.cc
+++ b/chrome/common/cloud_print/cloud_print_helpers_unittest.cc
@@ -52,10 +52,11 @@
expected_url_base.c_str()),
GetUrlForJobDelete(server_base_url, "myprinter").spec());
- EXPECT_EQ(base::StringPrintf("%scontrol?jobid=myprinter&status=s1",
+ EXPECT_EQ(base::StringPrintf(
+ "%scontrol?jobid=myprinter&status=s1&connector_code=0",
expected_url_base.c_str()),
GetUrlForJobStatusUpdate(
- server_base_url, "myprinter", "s1").spec());
+ server_base_url, "myprinter", "s1", 0).spec());
EXPECT_EQ(base::StringPrintf("%smessage?code=testmsg",
expected_url_base.c_str()),
diff --git a/chrome/common/content_settings_types.h b/chrome/common/content_settings_types.h
index c1b03a5..cf091fe 100644
--- a/chrome/common/content_settings_types.h
+++ b/chrome/common/content_settings_types.h
@@ -32,6 +32,8 @@
CONTENT_SETTINGS_TYPE_SAVE_PASSWORD,
#if defined(OS_WIN)
CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP,
+#elif defined(OS_ANDROID)
+ CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
#endif
CONTENT_SETTINGS_NUM_TYPES,
};
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc
index 583d533..65b1b90 100644
--- a/chrome/common/crash_keys.cc
+++ b/chrome/common/crash_keys.cc
@@ -58,6 +58,9 @@
const char kSwitch[] = "switch-%" PRIuS;
const char kNumSwitches[] = "num-switches";
+const char kNumVariations[] = "num-experiments";
+const char kVariations[] = "variations";
+
const char kExtensionID[] = "extension-%" PRIuS;
const char kNumExtensionsCount[] = "num-extensions";
@@ -108,6 +111,8 @@
{ kChannel, kSmallSize },
{ kActiveURL, kLargeSize },
{ kNumSwitches, kSmallSize },
+ { kNumVariations, kSmallSize },
+ { kVariations, kLargeSize },
{ kNumExtensionsCount, kSmallSize },
{ kNumberOfViews, kSmallSize },
#if !defined(OS_ANDROID)
@@ -270,6 +275,25 @@
}
}
+void SetVariationsList(const std::vector<std::string>& variations) {
+ base::debug::SetCrashKeyValue(kNumVariations,
+ base::StringPrintf("%" PRIuS, variations.size()));
+
+ std::string variations_string;
+ variations_string.reserve(kLargeSize);
+
+ for (size_t i = 0; i < variations.size(); ++i) {
+ const std::string& variation = variations[i];
+ // Do not truncate an individual experiment.
+ if (variations_string.size() + variation.size() >= kLargeSize)
+ break;
+ variations_string += variation;
+ variations_string += ",";
+ }
+
+ base::debug::SetCrashKeyValue(kVariations, variations_string);
+}
+
void SetActiveExtensions(const std::set<std::string>& extensions) {
base::debug::SetCrashKeyValue(kNumExtensionsCount,
base::StringPrintf("%" PRIuS, extensions.size()));
diff --git a/chrome/common/crash_keys.h b/chrome/common/crash_keys.h
index 23fda46..cc57868 100644
--- a/chrome/common/crash_keys.h
+++ b/chrome/common/crash_keys.h
@@ -7,6 +7,7 @@
#include <set>
#include <string>
+#include <vector>
#include "base/debug/crash_logging.h"
@@ -21,6 +22,9 @@
// Sets the kSwitch and kNumSwitches keys based on the given |command_line|.
void SetSwitchesFromCommandLine(const CommandLine* command_line);
+// Sets the list of active experiment/variations info.
+void SetVariationsList(const std::vector<std::string>& variations);
+
// Sets the list of "active" extensions in this process. We overload "active" to
// mean different things depending on the process type:
// - browser: all enabled extensions
@@ -56,6 +60,12 @@
// |kSwitchesMaxCount| are present.
extern const char kNumSwitches[];
+// The total number of experiments the instance has.
+extern const char kNumVariations[];
+// The experiments chunk. Hashed experiment names separated by |,|. This is
+// typically set by SetExperimentList.
+extern const char kVariations[];
+
// Installed extensions. |kExtensionID| should be formatted with an integer,
// in the range [0, kExtensionIDMaxCount).
const size_t kExtensionIDMaxCount = 10;
diff --git a/chrome/common/encrypted_media_messages_android.cc b/chrome/common/encrypted_media_messages_android.cc
deleted file mode 100644
index 4ad9bb9..0000000
--- a/chrome/common/encrypted_media_messages_android.cc
+++ /dev/null
@@ -1,20 +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/common/encrypted_media_messages_android.h"
-
-namespace android {
-
-SupportedKeySystemRequest::SupportedKeySystemRequest()
- : codecs(NO_SUPPORTED_CODECS) {}
-
-SupportedKeySystemRequest::~SupportedKeySystemRequest() {}
-
-SupportedKeySystemResponse::SupportedKeySystemResponse()
- : compositing_codecs(NO_SUPPORTED_CODECS),
- non_compositing_codecs(NO_SUPPORTED_CODECS) {}
-
-SupportedKeySystemResponse::~SupportedKeySystemResponse() {}
-
-} // namespace android
diff --git a/chrome/common/encrypted_media_messages_android.h b/chrome/common/encrypted_media_messages_android.h
index 39c0ddf..00a77d0 100644
--- a/chrome/common/encrypted_media_messages_android.h
+++ b/chrome/common/encrypted_media_messages_android.h
@@ -24,28 +24,6 @@
MP4_AVC1 = 1 << 2,
};
-struct SupportedKeySystemRequest {
- SupportedKeySystemRequest();
- ~SupportedKeySystemRequest();
-
- // Key system UUID.
- std::vector<uint8> uuid;
- // Bitmask of requested codecs.
- SupportedCodecs codecs;
-};
-
-struct SupportedKeySystemResponse {
- SupportedKeySystemResponse();
- ~SupportedKeySystemResponse();
-
- // Key system UUID.
- std::vector<uint8> uuid;
- // Bitmask of supported compositing codecs.
- SupportedCodecs compositing_codecs;
- // Bitmask of supported non-compositing codecs.
- SupportedCodecs non_compositing_codecs;
-};
-
} // namespace android
#endif // CHROME_COMMON_ENCRYPTED_MEDIA_MESSAGES_ANDROID_H
@@ -55,22 +33,24 @@
IPC_ENUM_TRAITS(android::SupportedCodecs)
-IPC_STRUCT_TRAITS_BEGIN(android::SupportedKeySystemRequest)
- IPC_STRUCT_TRAITS_MEMBER(uuid)
- IPC_STRUCT_TRAITS_MEMBER(codecs)
-IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_BEGIN(SupportedKeySystemRequest)
+ IPC_STRUCT_MEMBER(std::vector<uint8>, uuid)
+ IPC_STRUCT_MEMBER(android::SupportedCodecs, codecs,
+ android::NO_SUPPORTED_CODECS)
+IPC_STRUCT_END()
-IPC_STRUCT_TRAITS_BEGIN(android::SupportedKeySystemResponse)
- IPC_STRUCT_TRAITS_MEMBER(uuid)
- IPC_STRUCT_TRAITS_MEMBER(compositing_codecs)
- IPC_STRUCT_TRAITS_MEMBER(non_compositing_codecs)
-IPC_STRUCT_TRAITS_END()
-
+IPC_STRUCT_BEGIN(SupportedKeySystemResponse)
+ IPC_STRUCT_MEMBER(std::vector<uint8>, uuid)
+ IPC_STRUCT_MEMBER(android::SupportedCodecs, compositing_codecs,
+ android::NO_SUPPORTED_CODECS)
+ IPC_STRUCT_MEMBER(android::SupportedCodecs, non_compositing_codecs,
+ android::NO_SUPPORTED_CODECS)
+IPC_STRUCT_END()
// Messages sent from the renderer to the browser.
// Synchronously get a list of supported EME key systems.
IPC_SYNC_MESSAGE_CONTROL1_1(
ChromeViewHostMsg_GetSupportedKeySystems,
- android::SupportedKeySystemRequest /* key system information request */,
- android::SupportedKeySystemResponse /* key system information response */)
+ SupportedKeySystemRequest /* key system information request */,
+ SupportedKeySystemResponse /* key system information response */)
diff --git a/chrome/common/extensions/OWNERS b/chrome/common/extensions/OWNERS
index a2ed46fd..db382d2 100644
--- a/chrome/common/extensions/OWNERS
+++ b/chrome/common/extensions/OWNERS
@@ -18,5 +18,4 @@
per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
diff --git a/chrome/common/extensions/PRESUBMIT.py b/chrome/common/extensions/PRESUBMIT.py
index 7841212..2e138c9 100644
--- a/chrome/common/extensions/PRESUBMIT.py
+++ b/chrome/common/extensions/PRESUBMIT.py
@@ -144,7 +144,12 @@
cwd=input_api.PresubmitLocalPath())
except input_api.subprocess.CalledProcessError:
results.append(output_api.PresubmitError('IntegrationTest failed!'))
- _CheckLinks(input_api, output_api, results)
+
+ # TODO(kalman): Re-enable this check, or decide to delete it forever. Now
+ # that we have multiple directories it no longer works.
+ # See http://crbug.com/297178.
+ #_CheckLinks(input_api, output_api, results)
+
return results
def CheckChangeOnUpload(input_api, output_api):
diff --git a/chrome/common/extensions/api/PRESUBMIT.py b/chrome/common/extensions/api/PRESUBMIT.py
index 20d61fa..771f7fd 100644
--- a/chrome/common/extensions/api/PRESUBMIT.py
+++ b/chrome/common/extensions/api/PRESUBMIT.py
@@ -2,8 +2,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-def _GetJSONParseError(input_api, contents):
+def _GetJSONParseError(input_api, filename):
try:
+ contents = input_api.ReadFile(filename)
json_comment_eater = input_api.os_path.join(
input_api.PresubmitLocalPath(),
'..', '..', '..', '..', 'tools',
@@ -11,7 +12,8 @@
process = input_api.subprocess.Popen(
[input_api.python_executable, json_comment_eater],
stdin=input_api.subprocess.PIPE,
- stdout=input_api.subprocess.PIPE)
+ stdout=input_api.subprocess.PIPE,
+ universal_newlines=True)
(nommed, _) = process.communicate(input=contents)
input_api.json.loads(nommed)
except ValueError as e:
@@ -19,6 +21,20 @@
return None
+def _GetIDLParseError(input_api, filename):
+ idl_schema = input_api.os_path.join(
+ input_api.PresubmitLocalPath(),
+ '..', '..', '..', '..', 'tools',
+ 'json_schema_compiler', 'idl_schema.py')
+ process = input_api.subprocess.Popen(
+ [input_api.python_executable, idl_schema, filename],
+ stdout=input_api.subprocess.PIPE,
+ stderr=input_api.subprocess.PIPE,
+ universal_newlines=True)
+ (_, error) = process.communicate()
+ return error or None
+
+
def _GetParseErrors(input_api, output_api):
# Run unit tests.
results = []
@@ -27,17 +43,24 @@
results = input_api.canned_checks.RunUnitTestsInDirectory(
input_api, output_api, '.', whitelist=[r'^PRESUBMIT_test\.py$'])
+ actions = {
+ '.idl': _GetIDLParseError,
+ '.json': _GetJSONParseError,
+ }
+
+ def get_action(affected_file):
+ filename = affected_file.LocalPath()
+ return actions.get(input_api.os_path.splitext(filename)[1])
+
for affected_file in input_api.AffectedFiles(
- file_filter=lambda f: f.LocalPath().endswith('.json'),
+ file_filter=
+ lambda f: "test_presubmit" not in f.LocalPath() and get_action(f),
include_deletes=False):
- filename = affected_file.AbsoluteLocalPath()
- contents = input_api.ReadFile(filename)
- parse_error = _GetJSONParseError(input_api, contents)
+ parse_error = get_action(affected_file)(input_api,
+ affected_file.AbsoluteLocalPath())
if parse_error:
- results.append(output_api.PresubmitError(
- 'Features file %s could not be parsed: %s' %
+ results.append(output_api.PresubmitError('%s could not be parsed: %s' %
(affected_file.LocalPath(), parse_error)))
- # TODO(yoz): Also ensure IDL files are parseable.
return results
diff --git a/chrome/common/extensions/api/PRESUBMIT_test.py b/chrome/common/extensions/api/PRESUBMIT_test.py
index f14ea7e..88d28e6 100755
--- a/chrome/common/extensions/api/PRESUBMIT_test.py
+++ b/chrome/common/extensions/api/PRESUBMIT_test.py
@@ -3,6 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import glob
import json
import os
import subprocess
@@ -22,40 +23,59 @@
def PresubmitLocalPath(self):
return os.path.dirname(__file__)
+ def ReadFile(self, filename, mode='rU'):
+ with open(filename, mode=mode) as f:
+ return f.read()
+
class JSONParsingTest(unittest.TestCase):
def testSuccess(self):
input_api = MockInputApi()
- input_json = '''
-// This is a comment.
-{
- "key1": ["value1", "value2"],
- "key2": 3 // This is an inline comment.
-}
-'''
+ filename = 'test_presubmit/valid_json.json'
self.assertEqual(None,
- PRESUBMIT._GetJSONParseError(input_api, input_json))
+ PRESUBMIT._GetJSONParseError(input_api, filename))
def testFailure(self):
input_api = MockInputApi()
- input_json = '{ x }'
- self.assertEqual('Expecting property name: line 1 column 2 (char 2)',
- str(PRESUBMIT._GetJSONParseError(input_api, input_json)))
+ expected_errors = [
+ 'Expecting property name: line 8 column 3 (char 9)',
+ 'Invalid control character at: line 8 column 19 (char 25)',
+ 'Expecting property name: line 8 column 23 (char 29)',
+ 'Expecting , delimiter: line 8 column 12 (char 18)',
+ ]
+ actual_errors = [
+ str(PRESUBMIT._GetJSONParseError(input_api, filename))
+ for filename in sorted(glob.glob('test_presubmit/invalid_*.json'))
+ ]
+ self.assertEqual(expected_errors, actual_errors)
- input_json = '{ "hello": "world }'
- self.assertEqual(
- 'Unterminated string starting at: line 1 column 11 (char 11)',
- str(PRESUBMIT._GetJSONParseError(input_api, input_json)))
- input_json = '{ "a": "b", "c": "d", }'
- self.assertEqual(
- 'Expecting property name: line 1 column 22 (char 22)',
- str(PRESUBMIT._GetJSONParseError(input_api, input_json)))
+class IDLParsingTest(unittest.TestCase):
+ def testSuccess(self):
+ input_api = MockInputApi()
+ filename = 'test_presubmit/valid_idl_basics.idl'
+ self.assertEqual(None,
+ PRESUBMIT._GetIDLParseError(input_api, filename))
- input_json = '{ "a": "b" "c": "d" }'
- self.assertEqual(
- 'Expecting , delimiter: line 1 column 11 (char 11)',
- str(PRESUBMIT._GetJSONParseError(input_api, input_json)))
+ def testFailure(self):
+ input_api = MockInputApi()
+ expected_errors = [
+ 'Unexpected "{" after keyword "dictionary".',
+ 'Unexpected symbol DOMString after symbol a.',
+ 'Unexpected symbol name2 after symbol name1.',
+ 'Trailing comma in block.',
+ 'Unexpected ";" after "(".',
+ 'Unexpected ")" after symbol long.',
+ 'Unexpected symbol Events after symbol interace.',
+ 'Did not process Interface Interface(NotEvent)',
+ 'Interface missing name.',
+ ]
+ actual_errors = [
+ PRESUBMIT._GetIDLParseError(input_api, filename)
+ for filename in sorted(glob.glob('test_presubmit/invalid_*.idl'))
+ ]
+ for (expected_error, actual_error) in zip(expected_errors, actual_errors):
+ self.assertTrue(expected_error in actual_error)
if __name__ == "__main__":
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index afe3be2..c2f64ec 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -233,7 +233,6 @@
"contexts": ["blessed_extension", "unblessed_extension", "content_script"]
},
"feedbackPrivate": {
- "platform": "chromeos",
"dependencies": ["permission:feedbackPrivate"],
"contexts": ["blessed_extension"]
},
@@ -482,7 +481,7 @@
"contexts": ["blessed_extension"]
},
"sockets.udp": {
- "dependencies": ["permission:sockets.udp"],
+ "dependencies": ["manifest:sockets"],
"channel": "dev",
"contexts": ["blessed_extension"]
},
@@ -595,6 +594,10 @@
"channel": "stable",
"contexts": ["blessed_extension", "unblessed_extension", "content_script"]
},
+ "webrtcLoggingPrivate": {
+ "dependencies": ["permission:webrtcLoggingPrivate"],
+ "contexts": ["blessed_extension"]
+ },
"webstore": {
// Hosted apps can use the webstore API from within a blessed context.
"channel": "stable",
diff --git a/chrome/common/extensions/api/_manifest_features.json b/chrome/common/extensions/api/_manifest_features.json
index 81a8427..605560e 100644
--- a/chrome/common/extensions/api/_manifest_features.json
+++ b/chrome/common/extensions/api/_manifest_features.json
@@ -204,6 +204,12 @@
"platform_app"
]
},
+ "kiosk_only": {
+ "channel": "dev",
+ "extension_types": [
+ "platform_app"
+ ]
+ },
"manifest_version": {
"channel": "stable",
"extension_types": "all"
@@ -331,6 +337,10 @@
"channel": "stable",
"extension_types": "all"
},
+ "sockets": {
+ "channel": "dev",
+ "extension_types": ["platform_app"]
+ },
"spellcheck": {
"channel": "dev",
"extension_types": ["extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index 6dd7b28..c39821c 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -125,6 +125,8 @@
"channel": "stable",
"extension_types": ["extension", "legacy_packaged_app", "platform_app"],
"whitelist": [
+ "1C93BD3CF875F4A73C0B2A163BB8FBDA8B8B3D80", // http://crbug.com/293683
+ "A3BC37E2148AC4E99BE4B16AF9D42DD1E592BBBE", // http://crbug.com/293683
"8C3741E3AF0B93B6E8E0DDD499BB0B74839EA578", // http://crbug.com/234235
"E703483CEF33DEC18B4B6DD84B5C776FB9182BDB" // http://crbug.com/234235
]
@@ -184,7 +186,7 @@
"extension_types": ["extension", "legacy_packaged_app"]
},
"developerPrivate": {
- "channel": "dev",
+ "channel": "stable",
"extension_types": ["platform_app"],
"whitelist": [
"ohmmkhmmmpcnpikjeljgnaoabkaalbgc", // Published Apps developer tool.
@@ -242,15 +244,15 @@
}
],
"downloads": {
- "channel": "beta",
+ "channel": "stable",
"extension_types": ["extension"]
},
"downloads.open": {
- "channel": "beta",
+ "channel": "stable",
"extension_types": ["extension"]
},
"downloads.shelf": {
- "channel": "beta",
+ "channel": "stable",
"extension_types": ["extension"]
},
"dial": {
@@ -283,6 +285,8 @@
"extension_types": ["extension", "platform_app"],
"whitelist": [
"7910EAFDAF64B947E1CB31B333A9BD14CA556B6C", // Feedback UI.
+ "1C93BD3CF875F4A73C0B2A163BB8FBDA8B8B3D80", // http://crbug.com/293683
+ "A3BC37E2148AC4E99BE4B16AF9D42DD1E592BBBE", // http://crbug.com/293683
"8C3741E3AF0B93B6E8E0DDD499BB0B74839EA578", // http://crbug.com/234235
"E703483CEF33DEC18B4B6DD84B5C776FB9182BDB" // http://crbug.com/234235
]
@@ -305,11 +309,11 @@
"whitelist": [ "2FC374607C2DF285634B67C64A2E356C607091C3" ]
}],
"fileSystem.directory": [{
- "channel": "dev",
+ "channel": "stable",
"extension_types": ["platform_app"]
}],
"fileSystem.retainEntries": [{
- "channel": "dev",
+ "channel": "stable",
"extension_types": ["platform_app"]
}],
"fileSystem.write": [{
@@ -415,7 +419,8 @@
"lphgohfeebnhcpiohjndkgbhhkoapkjc", // Apps Developer tool.
"gonnpeheodhmhdjiimoiheniambmdcco", // Apps Editor old.
"cbelnpbjogfbjamhpbofhlnklecjpido", // Apps Editor published.
- "abjoigjokfeibfhiahiijggogladbmfm" // Activity Log (Watchdog).
+ "abjoigjokfeibfhiahiijggogladbmfm", // Watchdog (Activity Log)
+ "hhcnncjlpehbepkbgccanfpkneoejnpb" // Watchdog Test Version
]
}
],
@@ -573,12 +578,11 @@
"extension_types": ["extension", "platform_app"]
},
"imageWriterPrivate": {
- "channel": "dev",
+ "channel": "stable",
"extension_types": ["platform_app"],
"whitelist": [
- "nmedaodmkamdcnmfceajookiaicfnkhd", // ImageWriter API Dev App
- "jdnamgpmgjhphalijaakigbpccepfllk", // Chrome OS Recovery Tool local
- "jobolcahaebjkjhdedcfcnfkgpjcmkcg" // Chrome OS Recovery Tool CWS
+ "jobolcahaebjkjhdedcfcnfkgpjcmkcg", // Dev version
+ "D7986543275120831B39EF28D1327552FC343960" // Release version
]
},
"rtcPrivate": {
@@ -750,12 +754,18 @@
"channel": "stable",
"extension_types": ["extension", "legacy_packaged_app"]
},
+ "webrtcLoggingPrivate": {
+ "channel": "dev",
+ "extension_types": ["extension"],
+ "whitelist": ["80B9DC58E5210749F052F5B4DB239C50CF72AEB6"]
+ },
"webstorePrivate": {
"channel": "stable",
"extension_types": ["extension", "legacy_packaged_app"],
"whitelist": [
"ahfgeienlihckogmohjhadlkjgocpleb", // Web Store
- "afchcafgojfnemjkcbhfekplkmjaldaa" // Enterprise Web Store
+ "afchcafgojfnemjkcbhfekplkmjaldaa", // Enterprise Web Store
+ "dofmkfphhdaddeofjngcjphcegkbbooh" // Chrome Login Proxy (prototype)
]
},
"webRequest": {
@@ -766,8 +776,18 @@
"channel": "stable",
"extension_types": ["extension", "legacy_packaged_app"]
},
- "webview": {
+ "webview": [{
"channel": "stable",
"extension_types": ["platform_app"]
- }
+ }, {
+ // General support for webview in component extensions still in progress.
+ // Only allowed for whitelisted extensions until all the caveats are
+ // addressed. Tracked in crbug/285151.
+ "channel": "stable",
+ "extension_types": ["extension"],
+ "location": "component",
+ "whitelist": [
+ "mfffpogegjflfpflabcdkioaeobkgjik" // GAIA Component Extension
+ ]
+ }]
}
diff --git a/chrome/common/extensions/api/api.gyp b/chrome/common/extensions/api/api.gyp
index b868bbd..48b4ae8 100644
--- a/chrome/common/extensions/api/api.gyp
+++ b/chrome/common/extensions/api/api.gyp
@@ -87,7 +87,6 @@
'power.idl',
'push_messaging.idl',
'image_writer_private.idl',
- 'rtc_private.idl',
'runtime.json',
'serial.idl',
'sessions.json',
@@ -107,10 +106,12 @@
'test.json',
'top_sites.json',
'usb.idl',
+ 'virtual_keyboard_private.json',
'wallpaper.json',
'wallpaper_private.json',
'web_navigation.json',
'web_request.json',
+ 'webrtc_logging_private.idl',
'webstore_private.json',
'webview.json',
'windows.json',
@@ -154,7 +155,6 @@
'music_manager_private.idl',
'networking_private.json',
'power.idl',
- 'rtc_private.idl',
'system_indicator.idl',
'system_private.json',
'terminal_private.json',
@@ -167,7 +167,14 @@
'schema_files!': [
'file_browser_handler_internal.json',
'log_private.idl',
- 'rtc_private.idl',
+ 'virtual_keyboard_private.json',
+ 'wallpaper.json',
+ 'wallpaper_private.json',
+ ],
+ }],
+ ['enable_webrtc==0', {
+ 'schema_files!': [
+ 'webrtc_logging_private.idl',
],
}],
],
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl
index 027268e..e33fa17 100644
--- a/chrome/common/extensions/api/autotest_private.idl
+++ b/chrome/common/extensions/api/autotest_private.idl
@@ -42,6 +42,9 @@
// Get login status.
static void loginStatus(LoginStatusCallback callback);
+ // Locks the screen.
+ static void lockScreen();
+
// Simulates a memory access bug for asan testing.
static void simulateAsanMemoryBug();
};
diff --git a/chrome/common/extensions/api/extension_api.cc b/chrome/common/extensions/api/extension_api.cc
index ca3ffeb..a609ac8 100644
--- a/chrome/common/extensions/api/extension_api.cc
+++ b/chrome/common/extensions/api/extension_api.cc
@@ -260,8 +260,6 @@
RegisterSchemaResource("tts", IDR_EXTENSION_API_JSON_TTS);
RegisterSchemaResource("types", IDR_EXTENSION_API_JSON_TYPES);
RegisterSchemaResource("types.private", IDR_EXTENSION_API_JSON_TYPES_PRIVATE);
- RegisterSchemaResource("virtualKeyboardPrivate",
- IDR_EXTENSION_API_JSON_VIRTUALKEYBOARDPRIVATE);
RegisterSchemaResource("webRequestInternal",
IDR_EXTENSION_API_JSON_WEBREQUESTINTERNAL);
RegisterSchemaResource("webstore", IDR_EXTENSION_API_JSON_WEBSTORE);
diff --git a/chrome/common/extensions/api/feedback_private.idl b/chrome/common/extensions/api/feedback_private.idl
index 5641caa..93f799c 100644
--- a/chrome/common/extensions/api/feedback_private.idl
+++ b/chrome/common/extensions/api/feedback_private.idl
@@ -48,9 +48,9 @@
SystemInformation[]? systemInformation;
// TODO(rkc): Remove these once we have bindings to send blobs to Chrome.
- // Used internally to store the blob Url after parameter customization.
- DOMString? attachedFileBlobUrl;
- DOMString? screenshotBlobUrl;
+ // Used internally to store the blob uuid after parameter customization.
+ DOMString? attachedFileBlobUuid;
+ DOMString? screenshotBlobUuid;
};
// Status of the sending of a feedback report.
diff --git a/chrome/common/extensions/api/file_browser_private.json b/chrome/common/extensions/api/file_browser_private.json
index 7300335..8d65788 100644
--- a/chrome/common/extensions/api/file_browser_private.json
+++ b/chrome/common/extensions/api/file_browser_private.json
@@ -264,14 +264,19 @@
"properties": {
"type": {
"type": "string",
- "enum": ["begin_entry_copy", "end_entry_copy", "progress", "success", "error"],
- "description": "The type of the progress event. \"begin_entry_copy\" is fired for each entry (file or directory) before starting the copy operation, \"end_entry_copy\" is fired for each entry (file or directory) after ending the copy operation. \"progress\" is fired periodically to report progress of a file copy (not directory). \"success\" is fired after all entries are copied. \"error\" is fired when an error occurs."
+ "enum": ["begin_copy_entry", "end_copy_entry", "progress", "success", "error"],
+ "description": "The type of the progress event. \"begin_copy_entry\" is fired for each entry (file or directory) before starting the copy operation, \"end_copy_entry\" is fired for each entry (file or directory) after ending the copy operation. \"progress\" is fired periodically to report progress of a file copy (not directory). \"success\" is fired after all entries are copied. \"error\" is fired when an error occurs."
},
- "url": {
+ "sourceUrl": {
"type": "string",
"optional": true,
"description": "URL for the entry currently being copied. This field is particularly useful when a directory copy is initiated with startCopy(). The field tells what file/directory in that directory is now being copied."
},
+ "destinationUrl": {
+ "type": "string",
+ "optional": true,
+ "description": "URL for the entry currently being created. This field is particularly useful when a directory copy is initiated with startCopy(). The field tells what file/directory in that directory is being created. Available only for end_copy_entry and success."
+ },
"size": {
"type": "number",
"optional": true,
@@ -899,12 +904,10 @@
"properties": {
"query": {
"type": "string",
- "optional": true,
"description": "Search query."
},
"nextFeed": {
"type": "string",
- "optional": true,
"description": "ID of the search feed that should be fetched next. Value passed here should be gotten from previous searchDrive call. It can be empty for the initial search request."
}
}
@@ -943,18 +946,15 @@
"properties": {
"query": {
"type": "string",
- "optional": true,
"description": "Search query. It can be empty. Any filename matches to an empty query."
},
"types": {
"type": "string",
"enum": ["EXCLUDE_DIRECTORIES", "SHARED_WITH_ME", "OFFLINE", "ALL"],
- "optional": true,
"description": "The type of entry that is needed. Default to ALL."
},
"maxResults": {
"type": "integer",
- "optional": true,
"description": "Maximum number of results."
}
}
@@ -1199,29 +1199,29 @@
// Suppose a/b/c.txt (100bytes) and a/b/d.txt (200bytes), and trying to
// copy a to x recursively. The events will be:
//
- // begin_entry_copy a
+ // begin_copy_entry "a"
// <create empty directory x/a>
- // end_entry_copy a
+ // end_copy_entry "a" "x/a"
//
- // begin_entry_copy a/b
+ // begin_copy_entry "a/b"
// <create empty directory x/a/b>
- // end_entry_copy a/b
+ // end_copy_entry "a/b" "x/a/b"
//
- // begin_entry_copy a/b/c.txt
- // progress a/b/c.txt 0
- // progress a/b/c.txt 10
+ // begin_copy_entry "a/b/c.txt"
+ // progress "a/b/c.txt" 0
+ // progress "a/b/c.txt" 10
// :
- // progress a/b/c.txt 100
- // end_entry_copy a/b/c.txt
+ // progress "a/b/c.txt" 100
+ // end_copy_entry "a/b/c.txt" "x/a/b/c.txt"
//
- // begin_entry_copy a/b/d.txt
- // progress a/b/d.txt 0
- // progress a/b/d.txt 10
+ // begin_copy_entry "a/b/d.txt"
+ // progress "a/b/d.txt" 0
+ // progress "a/b/d.txt" 10
// :
- // progress a/b/d.txt 200
- // end_entry_copy a/b/d.txt
+ // progress "a/b/d.txt" 200
+ // end_copy_entry "a/b/d.txt" "x/a/b/d.txt"
//
- // success x/a
+ // success "a" "x/a"
{
"name": "onCopyProgress",
"type": "function",
diff --git a/chrome/common/extensions/api/file_system.idl b/chrome/common/extensions/api/file_system.idl
index 7e3d6d6..0d82c92 100644
--- a/chrome/common/extensions/api/file_system.idl
+++ b/chrome/common/extensions/api/file_system.idl
@@ -116,10 +116,10 @@
// Returns an id that can be passed to restoreEntry to regain access to a
// given file entry. Only the 500 most recently used entries are retained,
// where calls to retainEntry and restoreEntry count as use. If the app has
- // the 'retainEntries' permission under 'fileSystem' (currently restricted
- // to dev channel), entries are retained indefinitely. Otherwise, entries
- // are retained only while the app is running and across restarts. This
- // method is new in Chrome 30.
+ // the 'retainEntries' permission under 'fileSystem' (new in Chrome 31),
+ // entries are retained indefinitely. Otherwise, entries are retained only
+ // while the app is running and across restarts. This method is new in
+ // Chrome 30.
static DOMString retainEntry([instanceOf=Entry] object entry);
};
};
diff --git a/chrome/common/extensions/api/identity.idl b/chrome/common/extensions/api/identity.idl
index 6771794..cba84e4 100644
--- a/chrome/common/extensions/api/identity.idl
+++ b/chrome/common/extensions/api/identity.idl
@@ -10,7 +10,7 @@
// 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
+ // <code>false</code> or omitted, <code>getAuthToken</code> will
// return failure any time a prompt would be required.
boolean? interactive;
};
@@ -33,7 +33,7 @@
//
// 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>
+ // <code>false</code> or omitted, <code>launchWebAuthFlow</code>
// will return with an error if the initial navigation does not
// complete the flow.
boolean? interactive;
diff --git a/chrome/common/extensions/api/input_ime/input_components_handler.cc b/chrome/common/extensions/api/input_ime/input_components_handler.cc
index c6b1a33..b6376d6 100644
--- a/chrome/common/extensions/api/input_ime/input_components_handler.cc
+++ b/chrome/common/extensions/api/input_ime/input_components_handler.cc
@@ -199,6 +199,11 @@
return true;
}
+const std::vector<std::string>
+InputComponentsHandler::PrerequisiteKeys() const {
+ return SingleKey(keys::kOptionsPage);
+}
+
const std::vector<std::string> InputComponentsHandler::Keys() const {
return SingleKey(keys::kInputComponents);
}
diff --git a/chrome/common/extensions/api/input_ime/input_components_handler.h b/chrome/common/extensions/api/input_ime/input_components_handler.h
index 1261ae2..977e56b 100644
--- a/chrome/common/extensions/api/input_ime/input_components_handler.h
+++ b/chrome/common/extensions/api/input_ime/input_components_handler.h
@@ -61,6 +61,9 @@
virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ // Requires kOptionsPage is already parsed.
+ virtual const std::vector<std::string> PrerequisiteKeys() const OVERRIDE;
+
private:
virtual const std::vector<std::string> Keys() const OVERRIDE;
diff --git a/chrome/common/extensions/api/manifest_types.json b/chrome/common/extensions/api/manifest_types.json
index e14ed37..1658cf6 100644
--- a/chrome/common/extensions/api/manifest_types.json
+++ b/chrome/common/extensions/api/manifest_types.json
@@ -32,6 +32,35 @@
"items": {"type": "string"}
}
}
+ },
+ {
+ "id": "sockets",
+ "type": "object",
+ "description": "The <code>sockets</code> manifest property declares which sockets operations an app can issue.",
+ "properties": {
+ "udp": {
+ "description": "The <code>udp</code> manifest property declares which sockets.udp operations an app can issue.",
+ "optional": true,
+ "type": "object",
+ "properties": {
+ "bind": {
+ "description": "<p>The host:port pattern for <code>bind</code> operations.</p>",
+ "optional": true,
+ "type": "string"
+ },
+ "send": {
+ "description": "<p>The host:port pattern for <code>send</code> operations.</p>",
+ "optional": true,
+ "type": "string"
+ },
+ "multicastMembership": {
+ "description": "<p>The host:port pattern for <code>joinGroup</code> operations.</p>",
+ "optional": true,
+ "type": "string"
+ }
+ }
+ }
+ }
}
]
}
diff --git a/chrome/common/extensions/api/rtc_private.idl b/chrome/common/extensions/api/rtc_private.idl
deleted file mode 100644
index 73e26af..0000000
--- a/chrome/common/extensions/api/rtc_private.idl
+++ /dev/null
@@ -1,30 +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.
-
-// rtcPrivate.
-namespace rtcPrivate {
- // Launch action type.
- enum ActionType {chat, voice, video};
-
- dictionary LaunchIntent {
- // Launch action.
- ActionType action;
-
- // Launch data payload.
- object data;
-
- // MIME type.
- DOMString type;
- };
-
- dictionary LaunchData {
- // Launch intent.
- LaunchIntent intent;
- };
-
- interface Events {
- // Fired when an RTC launch event is raised.
- static void onLaunch(optional LaunchData data);
- };
-};
diff --git a/chrome/common/extensions/api/signed_in_devices.idl b/chrome/common/extensions/api/signed_in_devices.idl
index 15a421a..6a56ee3 100644
--- a/chrome/common/extensions/api/signed_in_devices.idl
+++ b/chrome/common/extensions/api/signed_in_devices.idl
@@ -60,6 +60,6 @@
// change or a new device is added or a device removed.
// |callback|: The callback to be invoked with the array of DeviceInfo
// objects.
- static void onDeviceInfoChange(DeviceInfoCallback callback);
+ static void onDeviceInfoChange(DeviceInfo[] devices);
};
};
\ No newline at end of file
diff --git a/chrome/common/extensions/api/sockets/sockets_handler.cc b/chrome/common/extensions/api/sockets/sockets_handler.cc
new file mode 100644
index 0000000..a367239
--- /dev/null
+++ b/chrome/common/extensions/api/sockets/sockets_handler.cc
@@ -0,0 +1,139 @@
+// Copyright 2013 The Chromium 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/api/sockets/sockets_handler.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/extensions/api/manifest_types.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/permissions/api_permission_set.h"
+#include "chrome/common/extensions/permissions/permissions_data.h"
+#include "chrome/common/extensions/permissions/socket_permission_data.h"
+#include "extensions/common/error_utils.h"
+#include "extensions/common/manifest_constants.h"
+
+namespace extensions {
+
+namespace sockets_errors {
+const char kErrorInvalidHostPattern[] = "Invalid host:port pattern '*'";
+}
+
+namespace keys = extensions::manifest_keys;
+namespace errors = sockets_errors;
+using api::manifest_types::Sockets;
+
+SocketsHandler::SocketsHandler() {}
+
+SocketsHandler::~SocketsHandler() {}
+
+bool SocketsHandler::Parse(Extension* extension, string16* error) {
+ const base::Value* sockets = NULL;
+ CHECK(extension->manifest()->Get(keys::kSockets, &sockets));
+ std::vector<InstallWarning> install_warnings;
+ scoped_ptr<SocketsManifestData> data =
+ SocketsManifestData::FromValue(*sockets,
+ &install_warnings,
+ error);
+ if (!data)
+ return false;
+
+ extension->AddInstallWarnings(install_warnings);
+ extension->SetManifestData(keys::kSockets, data.release());
+ return true;
+}
+
+const std::vector<std::string> SocketsHandler::Keys() const {
+ return SingleKey(manifest_keys::kSockets);
+}
+
+SocketsManifestData::SocketsManifestData() {}
+SocketsManifestData::~SocketsManifestData() {}
+
+// static
+SocketsManifestData* SocketsManifestData::Get(const Extension* extension) {
+ return static_cast<SocketsManifestData*>(
+ extension->GetManifestData(keys::kSockets));
+}
+
+// static
+bool SocketsManifestData::CheckRequest(
+ const Extension* extension,
+ const content::SocketPermissionRequest& request) {
+ SocketsManifestData* data = SocketsManifestData::Get(extension);
+ if (data == NULL)
+ return false;
+
+ return data->CheckRequestImpl(extension, request);
+}
+
+// static
+scoped_ptr<SocketsManifestData> SocketsManifestData::FromValue(
+ const base::Value& value,
+ std::vector<InstallWarning>* install_warnings,
+ string16* error) {
+ scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error);
+ if (!sockets)
+ return scoped_ptr<SocketsManifestData>();
+
+ scoped_ptr<SocketsManifestData> result(new SocketsManifestData());
+ if (sockets->udp) {
+ if (!ParseHostPattern(result.get(),
+ content::SocketPermissionRequest::UDP_BIND,
+ sockets->udp->bind,
+ error)) {
+ return scoped_ptr<SocketsManifestData>();
+ }
+ if (!ParseHostPattern(result.get(),
+ content::SocketPermissionRequest::UDP_SEND_TO,
+ sockets->udp->send,
+ error)) {
+ return scoped_ptr<SocketsManifestData>();
+ }
+ if (!ParseHostPattern(result.get(),
+ content::SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
+ sockets->udp->multicast_membership,
+ error)) {
+ return scoped_ptr<SocketsManifestData>();
+ }
+ }
+ return result.Pass();
+}
+
+// static
+bool SocketsManifestData::ParseHostPattern(
+ SocketsManifestData* manifest_data,
+ content::SocketPermissionRequest::OperationType operation_type,
+ const scoped_ptr<std::string>& value,
+ string16* error) {
+ if (value) {
+ SocketPermissionEntry entry;
+ if (!SocketPermissionEntry::ParseHostPattern(
+ operation_type, *value, &entry)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kErrorInvalidHostPattern, *value);
+ return false;
+ }
+ manifest_data->AddPermission(entry);
+ }
+ return true;
+}
+
+void SocketsManifestData::AddPermission(const SocketPermissionEntry& entry) {
+ permissions_.insert(entry);
+}
+
+bool SocketsManifestData::CheckRequestImpl(
+ const Extension* extension,
+ const content::SocketPermissionRequest& request) {
+ for (PermissionSet::const_iterator it = permissions_.begin();
+ it != permissions_.end(); ++it) {
+ if (it->Check(request))
+ return true;
+ }
+ return false;
+}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/api/sockets/sockets_handler.h b/chrome/common/extensions/api/sockets/sockets_handler.h
new file mode 100644
index 0000000..ff280d1
--- /dev/null
+++ b/chrome/common/extensions/api/sockets/sockets_handler.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_COMMON_EXTENSIONS_API_SOCKETS_SOCKETS_HANDLER_H_
+#define CHROME_COMMON_EXTENSIONS_API_SOCKETS_SOCKETS_HANDLER_H_
+
+#include "base/strings/string16.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/manifest_handler.h"
+#include "chrome/common/extensions/permissions/socket_permission_data.h"
+
+namespace extensions {
+
+// Parses the "sockets" manifest key.
+class SocketsHandler : public ManifestHandler {
+ public:
+ SocketsHandler();
+ virtual ~SocketsHandler();
+
+ virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+
+ private:
+ virtual const std::vector<std::string> Keys() const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(SocketsHandler);
+};
+
+// The parsed form of the "sockets" manifest entry.
+class SocketsManifestData : public Extension::ManifestData {
+ public:
+ SocketsManifestData();
+ virtual ~SocketsManifestData();
+
+ // Gets the ExternallyConnectableInfo for |extension|, or NULL if none was
+ // specified.
+ static SocketsManifestData* Get(const Extension* extension);
+
+ static bool CheckRequest(const Extension* extension,
+ const content::SocketPermissionRequest& request);
+
+ // Tries to construct the info based on |value|, as it would have appeared in
+ // the manifest. Sets |error| and returns an empty scoped_ptr on failure.
+ static scoped_ptr<SocketsManifestData> FromValue(
+ const base::Value& value,
+ std::vector<InstallWarning>* install_warnings,
+ string16* error);
+
+ private:
+ typedef std::set<SocketPermissionEntry> PermissionSet;
+
+ static bool ParseHostPattern(
+ SocketsManifestData* manifest_data,
+ content::SocketPermissionRequest::OperationType operation_type,
+ const scoped_ptr<std::string>& value,
+ string16* error);
+
+ void AddPermission(const SocketPermissionEntry& entry);
+
+ bool CheckRequestImpl(const Extension* extension,
+ const content::SocketPermissionRequest& request);
+
+ PermissionSet permissions_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_COMMON_EXTENSIONS_API_SOCKETS_SOCKETS_HANDLER_H_
diff --git a/chrome/common/extensions/api/storage/storage_schema_manifest_handler.cc b/chrome/common/extensions/api/storage/storage_schema_manifest_handler.cc
index 28c8557..d95a967 100644
--- a/chrome/common/extensions/api/storage/storage_schema_manifest_handler.cc
+++ b/chrome/common/extensions/api/storage/storage_schema_manifest_handler.cc
@@ -15,7 +15,7 @@
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/permissions/api_permission.h"
-#include "components/policy/core/common/policy_schema.h"
+#include "components/policy/core/common/schema.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
@@ -29,13 +29,13 @@
StorageSchemaManifestHandler::~StorageSchemaManifestHandler() {}
// static
-scoped_ptr<policy::PolicySchema> StorageSchemaManifestHandler::GetSchema(
+scoped_ptr<policy::SchemaOwner> StorageSchemaManifestHandler::GetSchema(
const Extension* extension,
std::string* error) {
if (!extension->HasAPIPermission(APIPermission::kStorage)) {
*error = base::StringPrintf("The storage permission is required to use %s",
kStorageManagedSchema);
- return scoped_ptr<policy::PolicySchema>();
+ return scoped_ptr<policy::SchemaOwner>();
}
std::string path;
extension->manifest()->GetString(kStorageManagedSchema, &path);
@@ -43,20 +43,20 @@
if (file.IsAbsolute() || file.ReferencesParent()) {
*error = base::StringPrintf("%s must be a relative path without ..",
kStorageManagedSchema);
- return scoped_ptr<policy::PolicySchema>();
+ return scoped_ptr<policy::SchemaOwner>();
}
file = extension->path().AppendASCII(path);
if (!base::PathExists(file)) {
*error =
base::StringPrintf("File does not exist: %s", file.value().c_str());
- return scoped_ptr<policy::PolicySchema>();
+ return scoped_ptr<policy::SchemaOwner>();
}
std::string content;
if (!base::ReadFileToString(file, &content)) {
*error = base::StringPrintf("Can't read %s", file.value().c_str());
- return scoped_ptr<policy::PolicySchema>();
+ return scoped_ptr<policy::SchemaOwner>();
}
- return policy::PolicySchema::Parse(content, error);
+ return policy::SchemaOwner::Parse(content, error);
}
bool StorageSchemaManifestHandler::Parse(Extension* extension,
diff --git a/chrome/common/extensions/api/storage/storage_schema_manifest_handler.h b/chrome/common/extensions/api/storage/storage_schema_manifest_handler.h
index c988362..d2406d6 100644
--- a/chrome/common/extensions/api/storage/storage_schema_manifest_handler.h
+++ b/chrome/common/extensions/api/storage/storage_schema_manifest_handler.h
@@ -9,7 +9,7 @@
#include "chrome/common/extensions/manifest_handler.h"
namespace policy {
-class PolicySchema;
+class SchemaOwner;
}
namespace extensions {
@@ -24,8 +24,8 @@
// If the schema is invalid then NULL is returned, and the failure reason
// is stored in |error|.
// This function does file I/O and must be called on a thread that allows I/O.
- static scoped_ptr<policy::PolicySchema> GetSchema(const Extension* extension,
- std::string* error);
+ static scoped_ptr<policy::SchemaOwner> GetSchema(const Extension* extension,
+ std::string* error);
private:
// ManifestHandler implementation:
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_idl_1.idl b/chrome/common/extensions/api/test_presubmit/invalid_idl_1.idl
new file mode 100644
index 0000000..32a048e
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_idl_1.idl
@@ -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.
+
+// Tests an invalid IDL file.
+
+namespace test {
+ // Unexpected "{" after keyword "dictionary".
+ dictionary {
+ DOMString s;
+ };
+};
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_idl_2.idl b/chrome/common/extensions/api/test_presubmit/invalid_idl_2.idl
new file mode 100644
index 0000000..72996ed
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_idl_2.idl
@@ -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.
+
+// Tests an invalid IDL file.
+
+namespace test {
+ // Unexpected symbol DOMString after symbol a.
+ dictionary MissingSemicolon {
+ DOMString a
+ DOMString b;
+ };
+};
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_idl_3.idl b/chrome/common/extensions/api/test_presubmit/invalid_idl_3.idl
new file mode 100644
index 0000000..e70e095
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_idl_3.idl
@@ -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.
+
+// Tests an invalid IDL file.
+
+namespace test {
+ // Unexpected symbol name2 after symbol name1.
+ enum MissingComma {
+ name1
+ name2
+ };
+};
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_idl_4.idl b/chrome/common/extensions/api/test_presubmit/invalid_idl_4.idl
new file mode 100644
index 0000000..28b42ff
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_idl_4.idl
@@ -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.
+
+// Tests an invalid IDL file.
+
+namespace test {
+ // Trailing comma in block.
+ enum TrailingComma {
+ name1,
+ name2,
+ };
+};
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_idl_5.idl b/chrome/common/extensions/api/test_presubmit/invalid_idl_5.idl
new file mode 100644
index 0000000..c3ed4f7
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_idl_5.idl
@@ -0,0 +1,10 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Tests an invalid IDL file.
+
+namespace test {
+ // Unexpected ";" after "(".
+ callback Callback1 = void(;
+};
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_idl_6.idl b/chrome/common/extensions/api/test_presubmit/invalid_idl_6.idl
new file mode 100644
index 0000000..2b2ff68
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_idl_6.idl
@@ -0,0 +1,10 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Tests an invalid IDL file.
+
+namespace test {
+ // Unexpected ")" after symbol long.
+ callback Callback1 = void(long );
+};
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_idl_7.idl b/chrome/common/extensions/api/test_presubmit/invalid_idl_7.idl
new file mode 100644
index 0000000..da69c33
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_idl_7.idl
@@ -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.
+
+// Tests an invalid IDL file.
+
+namespace test {
+ // Unexpected symbol Events after symbol interace.
+ interace Events {
+ static void onFoo1();
+ };
+};
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_idl_8.idl b/chrome/common/extensions/api/test_presubmit/invalid_idl_8.idl
new file mode 100644
index 0000000..5cfc9ec
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_idl_8.idl
@@ -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.
+
+// Tests an invalid IDL file.
+
+namespace test {
+ // Did not process Interface Interface(NotEvent).
+ interface NotEvent {
+ static void onFoo1();
+ };
+};
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_idl_9.idl b/chrome/common/extensions/api/test_presubmit/invalid_idl_9.idl
new file mode 100644
index 0000000..3f2905c
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_idl_9.idl
@@ -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.
+
+// Tests an invalid IDL file.
+
+namespace test {
+ // Interface missing name.
+ interface {
+ static void function1();
+ };
+};
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_json_1.json b/chrome/common/extensions/api/test_presubmit/invalid_json_1.json
new file mode 100644
index 0000000..fcaa875
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_json_1.json
@@ -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.
+
+// Tests an invalid JSON file.
+
+// Expecting property name: line 8 column 3 (char 9).
+{ x }
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_json_2.json b/chrome/common/extensions/api/test_presubmit/invalid_json_2.json
new file mode 100644
index 0000000..d157424
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_json_2.json
@@ -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.
+
+// Tests an invalid JSON file.
+
+// Invalid control character at: line 8 column 19 (char 25).
+{ "hello": "world }
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_json_3.json b/chrome/common/extensions/api/test_presubmit/invalid_json_3.json
new file mode 100644
index 0000000..9dd3500
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_json_3.json
@@ -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.
+
+// Tests an invalid JSON file.
+
+// Expecting property name: line 8 column 23 (char 29).
+{ "a": "b", "c": "d", }
diff --git a/chrome/common/extensions/api/test_presubmit/invalid_json_4.json b/chrome/common/extensions/api/test_presubmit/invalid_json_4.json
new file mode 100644
index 0000000..af6a1a6
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/invalid_json_4.json
@@ -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.
+
+// Tests an invalid JSON file.
+
+// Expecting , delimiter: line 8 column 12 (char 18).
+{ "a": "b" "c": "d" }
diff --git a/chrome/common/extensions/api/test_presubmit/valid_idl_basics.idl b/chrome/common/extensions/api/test_presubmit/valid_idl_basics.idl
new file mode 100644
index 0000000..d0071e1
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/valid_idl_basics.idl
@@ -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.
+
+// Tests a valid IDL file.
+
+namespace idl_basics {
+ enum EnumType {
+ name1,
+ name2
+ };
+
+ dictionary MyType1 {
+ DOMString a;
+ };
+
+ callback Callback1 = void();
+ callback Callback2 = void(long x);
+ callback Callback3 = void(MyType1 arg);
+ callback Callback4 = void(EnumType type);
+
+ interface Functions {
+ static void function1();
+ static void function2(long x);
+ static void function3(MyType1 arg);
+ static void function4(Callback1 cb);
+ static void function5(Callback2 cb);
+ static void function6(Callback3 cb);
+ static void function7(Callback4 cb);
+ };
+
+ interface Events {
+ static void onFoo1();
+ static void onFoo2(long x);
+ static void onFoo2(MyType1 arg);
+ static void onFoo3(EnumType type);
+ };
+};
diff --git a/chrome/common/extensions/api/test_presubmit/valid_json.json b/chrome/common/extensions/api/test_presubmit/valid_json.json
new file mode 100644
index 0000000..615ea28
--- /dev/null
+++ b/chrome/common/extensions/api/test_presubmit/valid_json.json
@@ -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.
+
+// Tests a valid IDL file.
+
+// This is a comment.
+{
+ "key1": ["value1", "value2"],
+ "key2": 3 // This is an inline comment.
+}
diff --git a/chrome/common/extensions/api/virtual_keyboard_private.json b/chrome/common/extensions/api/virtual_keyboard_private.json
index 35129cd..9094008 100644
--- a/chrome/common/extensions/api/virtual_keyboard_private.json
+++ b/chrome/common/extensions/api/virtual_keyboard_private.json
@@ -5,6 +5,9 @@
[
{
"namespace": "virtualKeyboardPrivate",
+ "compiler_options": {
+ "implemented_in": "chrome/browser/extensions/api/input/input.h"
+ },
"platforms": ["chromeos"],
"description": "none",
"types": [
@@ -88,6 +91,27 @@
}
]
}
+ ],
+ "events": [
+ {
+ "name": "onTextInputBoxFocused",
+ "type": "function",
+ "description": "This event is sent when focus enters a text input box.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "context",
+ "description": "Describes the text input box that has acquired focus. Note only the type of text input box is passed. This API is intended to be used by non-ime virtual keyboard only. Normal ime virtual keyboard should use chrome.input.ime.onFocus to get the more detailed InputContext.",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The value of type attribute of the focused text input box.",
+ "enum": ["text", "number", "password", "date", "url", "tel", "email"]
+ }
+ }
+ }
+ ]
+ }
]
}
]
diff --git a/chrome/common/extensions/api/wallpaper.json b/chrome/common/extensions/api/wallpaper.json
index d24f260..7cb631f 100644
--- a/chrome/common/extensions/api/wallpaper.json
+++ b/chrome/common/extensions/api/wallpaper.json
@@ -6,7 +6,7 @@
{
"namespace":"wallpaper",
"compiler_options": {
- "implemented_in": "chrome/browser/chromeos/extensions/wallpaper_api.h"
+ "implemented_in": "chrome/browser/chromeos/extensions/wallpaper_api.h"
},
"platforms": ["chromeos"],
"description": "none",
diff --git a/chrome/common/extensions/api/webrtc_logging_private.idl b/chrome/common/extensions/api/webrtc_logging_private.idl
new file mode 100644
index 0000000..b43c895
--- /dev/null
+++ b/chrome/common/extensions/api/webrtc_logging_private.idl
@@ -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.
+
+// Use the <code>chrome.webrtcLoggingPrivate</code> API to control diagnostic
+// WebRTC logging.
+[nodoc] namespace webrtcLoggingPrivate {
+ dictionary UploadResult {
+ // The report ID for the uploaded log. Will be empty if not successful.
+ DOMString reportId;
+ };
+
+ callback GenericDoneCallback = void ();
+ callback UploadDoneCallback = void (UploadResult result);
+
+ interface Functions {
+ // Sets additional custom meta data that will be uploaded along with the
+ // log. |metaData| is a dictionary of the metadata (key, value).
+ static void setMetaData(object metaData, GenericDoneCallback callback);
+
+ // Starts logging. If logging has already been started for this render
+ // process, the call will be ignored. |appSessionId| is the unique session
+ // ID which will be added to the log.
+ static void start(GenericDoneCallback callback);
+
+ // Sets whether the log should be uploaded automatically for the case when
+ // the render process goes away (tab is closed or crashes) and stop has not
+ // been called before that. If |shouldUpload| is true it will be uploaded,
+ // otherwise it will be discarded. The default setting is to discard it.
+ static void setUploadOnRenderClose(boolean shouldUpload);
+
+ // Stops logging. After stop has finished, either upload() or discard()
+ // should be called, otherwise the log will be kept in memory until the
+ // render process is closed or logging restarted.
+ static void stop(GenericDoneCallback callback);
+
+ // Uploads the log. Logging must be stopped before this function is called.
+ static void upload(UploadDoneCallback callback);
+
+ // Discards the log. Logging must be stopped before this function is called.
+ static void discard(GenericDoneCallback callback);
+ };
+};
diff --git a/chrome/common/extensions/api/webview.json b/chrome/common/extensions/api/webview.json
index 7fe3548..dbce3d5 100644
--- a/chrome/common/extensions/api/webview.json
+++ b/chrome/common/extensions/api/webview.json
@@ -165,6 +165,20 @@
]
},
{
+ "name": "overrideUserAgent",
+ "type": "function",
+ "parameters": [
+ {
+ "type": "integer",
+ "name": "instanceId"
+ },
+ {
+ "type": "string",
+ "name": "userAgentOverride"
+ }
+ ]
+ },
+ {
"name": "reload",
"type": "function",
"parameters": [
diff --git a/chrome/common/extensions/chrome_manifest_handlers.cc b/chrome/common/extensions/chrome_manifest_handlers.cc
index 07137d9..c4cf4db 100644
--- a/chrome/common/extensions/chrome_manifest_handlers.cc
+++ b/chrome/common/extensions/chrome_manifest_handlers.cc
@@ -20,6 +20,7 @@
#include "chrome/common/extensions/api/media_galleries_private/media_galleries_handler.h"
#include "chrome/common/extensions/api/omnibox/omnibox_handler.h"
#include "chrome/common/extensions/api/plugins/plugins_handler.h"
+#include "chrome/common/extensions/api/sockets/sockets_handler.h"
#include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h"
#include "chrome/common/extensions/api/spellcheck/spellcheck_handler.h"
#include "chrome/common/extensions/api/system_indicator/system_indicator_handler.h"
@@ -32,7 +33,7 @@
#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
#include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
-#include "chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h"
+#include "chrome/common/extensions/manifest_handlers/kiosk_mode_info.h"
#include "chrome/common/extensions/manifest_handlers/minimum_chrome_version_checker.h"
#include "chrome/common/extensions/manifest_handlers/nacl_modules_handler.h"
#include "chrome/common/extensions/manifest_handlers/offline_enabled_info.h"
@@ -70,7 +71,7 @@
#if defined(OS_CHROMEOS)
(new InputComponentsHandler)->Register();
#endif
- (new KioskEnabledHandler)->Register();
+ (new KioskModeHandler)->Register();
(new ManagedModeHandler)->Register();
(new MediaGalleriesHandlerParser)->Register();
(new MimeTypesHandlerParser)->Register();
@@ -86,6 +87,7 @@
(new SandboxedPageHandler)->Register();
(new ScriptBadgeHandler)->Register();
(new SharedModuleHandler)->Register();
+ (new SocketsHandler)->Register();
(new SpellcheckHandler)->Register();
(new StorageSchemaManifestHandler)->Register();
(new SystemIndicatorHandler)->Register();
diff --git a/chrome/common/extensions/csp_validator.cc b/chrome/common/extensions/csp_validator.cc
index f33e1ac..523d51e 100644
--- a/chrome/common/extensions/csp_validator.cc
+++ b/chrome/common/extensions/csp_validator.cc
@@ -21,7 +21,6 @@
const char kSandboxDirectiveName[] = "sandbox";
const char kAllowSameOriginToken[] = "allow-same-origin";
const char kAllowTopNavigation[] = "allow-top-navigation";
-const char kAllowPopups[] = "allow-popups";
struct DirectiveStatus {
explicit DirectiveStatus(const char* name)
diff --git a/chrome/common/extensions/docs/server2/api_schema_graph.py b/chrome/common/extensions/docs/server2/api_schema_graph.py
index 03d3744..b81102a 100644
--- a/chrome/common/extensions/docs/server2/api_schema_graph.py
+++ b/chrome/common/extensions/docs/server2/api_schema_graph.py
@@ -2,8 +2,48 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import collections
import json
+from collections import Iterable, Mapping
+from copy import deepcopy
+
+class LookupResult(object):
+ '''Returned from APISchemaGraph.Lookup(), and relays whether or not
+ some element was found and what annotation object was associated with it,
+ if any.
+ '''
+
+ def __init__(self, found=None, annotation=None):
+ assert found is not None, 'LookupResult was given None value for |found|.'
+ self.found = found
+ self.annotation = annotation
+
+ def __eq__(self, other):
+ return self.found == other.found and self.annotation == other.annotation
+
+ def __ne__(self, other):
+ return not (self == other)
+
+
+class _GraphNode(dict):
+ '''Represents some element of an API schema, and allows extra information
+ about that element to be stored on the |_annotation| object.
+ '''
+
+ def __init__(self, *args, **kwargs):
+ # Use **kwargs here since Python is picky with ordering of default args
+ # and variadic args in the method signature. The only keyword arg we care
+ # about here is 'annotation'. Intentionally don't pass |**kwargs| into the
+ # superclass' __init__().
+ dict.__init__(self, *args)
+ self._annotation = kwargs.get('annotation')
+
+ def __eq__(self, other):
+ # _GraphNode inherits __eq__() from dict, which will not take annotation
+ # objects into account when comparing.
+ return dict.__eq__(self, other)
+
+ def __ne__(self, other):
+ return not (self == other)
def _NameForNode(node):
@@ -14,6 +54,7 @@
if 'name' in node: return node['name']
if 'id' in node: return node['id']
if 'type' in node: return node['type']
+ if '$ref' in node: return node['$ref']
assert False, 'Problems with naming node: %s' % json.dumps(node, indent=3)
@@ -21,25 +62,29 @@
'''Determines whether or not |value| is a list made up entirely of
dict-like objects.
'''
- return (isinstance(value, collections.Iterable) and
- all(isinstance(node, collections.Mapping) for node in value))
+ return (isinstance(value, Iterable) and
+ all(isinstance(node, Mapping) for node in value))
def _CreateGraph(root):
'''Recursively moves through an API schema, replacing lists of objects
and non-object values with objects.
'''
- schema_graph = {}
+ schema_graph = _GraphNode()
if _IsObjectList(root):
for node in root:
name = _NameForNode(node)
- assert name not in schema_graph, 'Duplicate name in availability graph.'
- schema_graph[name] = dict((key, _CreateGraph(value)) for key, value
- in node.iteritems())
- elif isinstance(root, collections.Mapping):
+ assert name not in schema_graph, 'Duplicate name in API schema graph.'
+ schema_graph[name] = _GraphNode((key, _CreateGraph(value)) for
+ key, value in node.iteritems())
+
+ elif isinstance(root, Mapping):
for name, node in root.iteritems():
- schema_graph[name] = dict((key, _CreateGraph(value)) for key, value
- in node.iteritems())
+ if not isinstance(node, Mapping):
+ schema_graph[name] = _GraphNode()
+ else:
+ schema_graph[name] = _GraphNode((key, _CreateGraph(value)) for
+ key, value in node.iteritems())
return schema_graph
@@ -48,7 +93,7 @@
which contains key-value pairs found in |minuend| but not in
|subtrahend|.
'''
- difference = {}
+ difference = _GraphNode()
for key in minuend:
if key not in subtrahend:
# Record all of this key's children as being part of the difference.
@@ -63,19 +108,49 @@
return difference
+def _Update(base, addend, annotation=None):
+ '''A Set Union adaptation for graphs. Returns a graph which contains
+ the key-value pairs from |base| combined with any key-value pairs
+ from |addend| that are not present in |base|.
+ '''
+ for key in addend:
+ if key not in base:
+ # Add this key and the rest of its children.
+ base[key] = _Update(_GraphNode(annotation=annotation),
+ addend[key],
+ annotation=annotation)
+ else:
+ # The key is already in |base|, but check its children.
+ _Update(base[key], addend[key], annotation=annotation)
+ return base
+
+
+
class APISchemaGraph(object):
'''Provides an interface for interacting with an API schema graph, a
nested dict structure that allows for simpler lookups of schema data.
'''
- def __init__(self, api_schema):
- self._graph = _CreateGraph(api_schema)
+ def __init__(self, api_schema=None, _graph=None):
+ self._graph = _graph if _graph is not None else _CreateGraph(api_schema)
+
+ def __eq__(self, other):
+ return self._graph == other._graph
+
+ def __ne__(self, other):
+ return not (self == other)
def Subtract(self, other):
'''Returns an APISchemaGraph instance representing keys that are in
this graph but not in |other|.
'''
- return APISchemaGraph(_Subtract(self._graph, other._graph))
+ return APISchemaGraph(_graph=_Subtract(self._graph, other._graph))
+
+ def Update(self, other, annotation=None):
+ '''Modifies this graph by adding keys from |other| that are not
+ already present in this graph.
+ '''
+ _Update(self._graph, other._graph, annotation=annotation)
def Lookup(self, *path):
'''Given a list of path components, |path|, checks if the
@@ -85,8 +160,8 @@
for path_piece in path:
node = node.get(path_piece)
if node is None:
- return False
- return True
+ return LookupResult(found=False, annotation=None)
+ return LookupResult(found=True, annotation=node._annotation)
def IsEmpty(self):
'''Checks for an empty schema graph.
diff --git a/chrome/common/extensions/docs/server2/api_schema_graph_test.py b/chrome/common/extensions/docs/server2/api_schema_graph_test.py
index 14ccc52..d27e535 100755
--- a/chrome/common/extensions/docs/server2/api_schema_graph_test.py
+++ b/chrome/common/extensions/docs/server2/api_schema_graph_test.py
@@ -5,7 +5,7 @@
import unittest
-from api_schema_graph import APISchemaGraph
+from api_schema_graph import APISchemaGraph, LookupResult
API_SCHEMA = [{
@@ -62,56 +62,80 @@
# A few assertions to make sure that Lookup works on empty sets.
empty_graph = APISchemaGraph({})
self.assertTrue(empty_graph.IsEmpty())
- self.assertFalse(empty_graph.Lookup('tabs', 'properties',
+ self.assertEqual(LookupResult(False, None),
+ empty_graph.Lookup('tabs', 'properties',
'TAB_PROPERTY_ONE'))
- self.assertFalse(empty_graph.Lookup('tabs', 'functions', 'get',
+ self.assertEqual(LookupResult(False, None),
+ empty_graph.Lookup('tabs', 'functions', 'get',
'parameters', 'tab'))
- self.assertFalse(empty_graph.Lookup('tabs', 'functions', 'get',
+ self.assertEqual(LookupResult(False, None),
+ empty_graph.Lookup('tabs', 'functions', 'get',
'parameters', 'tabId'))
- self.assertFalse(empty_graph.Lookup('tabs', 'events', 'onActivated',
+ self.assertEqual(LookupResult(False, None),
+ empty_graph.Lookup('tabs', 'events', 'onActivated',
'parameters', 'activeInfo'))
- self.assertFalse(empty_graph.Lookup('tabs', 'events', 'onUpdated',
+ self.assertEqual(LookupResult(False, None),
+ empty_graph.Lookup('tabs', 'events', 'onUpdated',
'parameters', 'updateInfo'))
def testSubtractEmpty(self):
self._testApiSchema(
APISchemaGraph(API_SCHEMA).Subtract(APISchemaGraph({})))
+ def _testApiSchema(self, api_schema_graph):
+ self.assertEqual(LookupResult(True, None),
+ api_schema_graph.Lookup('tabs', 'properties',
+ 'TAB_PROPERTY_ONE'))
+ self.assertEqual(LookupResult(True, None),
+ api_schema_graph.Lookup('tabs', 'types', 'Tab'))
+ self.assertEqual(LookupResult(True, None),
+ api_schema_graph.Lookup('tabs', 'functions', 'get',
+ 'parameters', 'tab'))
+ self.assertEqual(LookupResult(True, None),
+ api_schema_graph.Lookup('tabs', 'functions', 'get',
+ 'parameters', 'tabId'))
+ self.assertEqual(LookupResult(True, None),
+ api_schema_graph.Lookup('tabs', 'functions', 'get',
+ 'parameters', 'tab', 'type'))
+ self.assertEqual(LookupResult(True, None),
+ api_schema_graph.Lookup('tabs', 'events',
+ 'onActivated', 'parameters',
+ 'activeInfo'))
+ self.assertEqual(LookupResult(True, None),
+ api_schema_graph.Lookup('tabs', 'events', 'onUpdated',
+ 'parameters', 'updateInfo'))
+ self.assertEqual(LookupResult(True, None),
+ api_schema_graph.Lookup('tabs', 'properties',
+ 'lowercase', 'properties',
+ 'one', 'value'))
+ self.assertEqual(LookupResult(True, None),
+ api_schema_graph.Lookup('tabs', 'properties',
+ 'lowercase', 'properties',
+ 'two', 'description'))
+ self.assertEqual(LookupResult(False, None),
+ api_schema_graph.Lookup('windows'))
+ self.assertEqual(LookupResult(False, None),
+ api_schema_graph.Lookup('tabs', 'properties',
+ 'TAB_PROPERTY_DEUX'))
+ self.assertEqual(LookupResult(False, None),
+ api_schema_graph.Lookup('tabs', 'events', 'onActivated',
+ 'parameters', 'callback'))
+ self.assertEqual(LookupResult(False, None),
+ api_schema_graph.Lookup('tabs', 'functions', 'getById',
+ 'parameters', 'tab'))
+ self.assertEqual(LookupResult(False, None),
+ api_schema_graph.Lookup('tabs', 'functions', 'get',
+ 'parameters', 'type'))
+ self.assertEqual(LookupResult(False, None),
+ api_schema_graph.Lookup('tabs', 'properties',
+ 'lowercase', 'properties',
+ 'two', 'value'))
+
def testSubtractSelf(self):
self.assertTrue(
APISchemaGraph(API_SCHEMA).Subtract(APISchemaGraph(API_SCHEMA))
.IsEmpty())
- def _testApiSchema(self, api_schema_graph):
- self.assertTrue(api_schema_graph.Lookup('tabs', 'properties',
- 'TAB_PROPERTY_ONE'))
- self.assertTrue(api_schema_graph.Lookup('tabs', 'types', 'Tab'))
- self.assertTrue(api_schema_graph.Lookup('tabs', 'functions', 'get',
- 'parameters', 'tab'))
- self.assertTrue(api_schema_graph.Lookup('tabs', 'functions', 'get',
- 'parameters', 'tabId'))
- self.assertTrue(api_schema_graph.Lookup('tabs', 'functions', 'get',
- 'parameters', 'tab', 'type'))
- self.assertTrue(api_schema_graph.Lookup('tabs', 'events', 'onActivated',
- 'parameters', 'activeInfo'))
- self.assertTrue(api_schema_graph.Lookup('tabs', 'events', 'onUpdated',
- 'parameters', 'updateInfo'))
- self.assertTrue(api_schema_graph.Lookup('tabs', 'properties', 'lowercase',
- 'properties', 'one', 'value'))
- self.assertTrue(api_schema_graph.Lookup('tabs', 'properties', 'lowercase',
- 'properties', 'two', 'description'))
-
- self.assertFalse(api_schema_graph.Lookup('windows'))
- self.assertFalse(api_schema_graph.Lookup('tabs', 'properties',
- 'TAB_PROPERTY_DEUX'))
- self.assertFalse(api_schema_graph.Lookup('tabs', 'events', 'onActivated',
- 'parameters', 'callback'))
- self.assertFalse(api_schema_graph.Lookup('tabs', 'functions', 'getById',
- 'parameters', 'tab'))
- self.assertFalse(api_schema_graph.Lookup('tabs', 'functions', 'get',
- 'parameters', 'type'))
- self.assertFalse(api_schema_graph.Lookup('tabs', 'properties', 'lowercase',
- 'properties', 'two', 'value'))
def testSubtractDisjointSet(self):
difference = APISchemaGraph(API_SCHEMA).Subtract(APISchemaGraph({
@@ -148,23 +172,33 @@
}
}
}))
- self.assertTrue(difference.Lookup('tabs', 'properties',
+ self.assertEqual(LookupResult(True, None),
+ difference.Lookup('tabs', 'properties',
'TAB_PROPERTY_ONE'))
- self.assertTrue(difference.Lookup('tabs', 'functions', 'get',
+ self.assertEqual(LookupResult(True, None),
+ difference.Lookup('tabs', 'functions', 'get',
'parameters', 'tab'))
- self.assertTrue(difference.Lookup('tabs', 'events', 'onUpdated',
+ self.assertEqual(LookupResult(True, None),
+ difference.Lookup('tabs', 'events', 'onUpdated',
'parameters', 'updateInfo'))
- self.assertTrue(difference.Lookup('tabs', 'functions', 'get',
+ self.assertEqual(LookupResult(True, None),
+ difference.Lookup('tabs', 'functions', 'get',
'parameters', 'tabId'))
- self.assertFalse(difference.Lookup('contextMenus', 'properties',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('contextMenus', 'properties',
'CONTEXT_MENU_PROPERTY_ONE'))
- self.assertFalse(difference.Lookup('contextMenus', 'types', 'Menu'))
- self.assertFalse(difference.Lookup('contextMenus', 'types', 'Menu',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('contextMenus', 'types', 'Menu'))
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('contextMenus', 'types', 'Menu',
'properties', 'id'))
- self.assertFalse(difference.Lookup('contextMenus', 'functions'))
- self.assertFalse(difference.Lookup('contextMenus', 'events', 'onClicked',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('contextMenus', 'functions'))
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('contextMenus', 'events', 'onClicked',
'parameters', 'clickInfo'))
- self.assertFalse(difference.Lookup('contextMenus', 'events', 'onUpdated',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('contextMenus', 'events', 'onUpdated',
'parameters', 'updateInfo'))
def testSubtractSubset(self):
@@ -197,22 +231,31 @@
}
}
}))
- self.assertTrue(difference.Lookup('tabs'))
- self.assertTrue(difference.Lookup('tabs', 'properties',
- 'TAB_PROPERTY_TWO'))
- self.assertTrue(difference.Lookup('tabs', 'properties', 'lowercase',
- 'properties', 'two', 'description'))
- self.assertTrue(difference.Lookup('tabs', 'types', 'Tab', 'properties',
- 'url'))
- self.assertTrue(difference.Lookup('tabs', 'events', 'onActivated',
- 'parameters', 'activeInfo'))
- self.assertFalse(difference.Lookup('tabs', 'events', 'onUpdated',
+ self.assertEqual(LookupResult(True, None),
+ difference.Lookup('tabs'))
+ self.assertEqual(LookupResult(True, None),
+ difference.Lookup('tabs', 'properties',
+ 'TAB_PROPERTY_TWO'))
+ self.assertEqual(LookupResult(True, None),
+ difference.Lookup('tabs', 'properties', 'lowercase',
+ 'properties', 'two', 'description'))
+ self.assertEqual(LookupResult(True, None),
+ difference.Lookup('tabs', 'types', 'Tab', 'properties',
+ 'url'))
+ self.assertEqual(LookupResult(True, None),
+ difference.Lookup('tabs', 'events', 'onActivated',
+ 'parameters', 'activeInfo'))
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'events', 'onUpdated',
'parameters', 'updateInfo'))
- self.assertFalse(difference.Lookup('tabs', 'properties',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'properties',
'TAB_PROPERTY_ONE'))
- self.assertFalse(difference.Lookup('tabs', 'properties',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'properties',
'TAB_PROPERTY_ONE', 'value'))
- self.assertFalse(difference.Lookup('tabs', 'functions', 'get',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'functions', 'get',
'parameters', 'tab'))
def testSubtractSuperset(self):
@@ -279,23 +322,127 @@
}
}
}))
- self.assertFalse(difference.Lookup('tabs'))
- self.assertFalse(difference.Lookup('tabs', 'properties',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs'))
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'properties',
'TAB_PROPERTY_TWO'))
- self.assertFalse(difference.Lookup('tabs', 'properties'))
- self.assertFalse(difference.Lookup('tabs', 'types', 'Tab', 'properties',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'properties'))
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'types', 'Tab', 'properties',
'url'))
- self.assertFalse(difference.Lookup('tabs', 'types', 'Tab', 'properties',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'types', 'Tab', 'properties',
'id'))
- self.assertFalse(difference.Lookup('tabs', 'events', 'onUpdated',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'events', 'onUpdated',
'parameters', 'updateInfo'))
- self.assertFalse(difference.Lookup('tabs', 'properties',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'properties',
'TAB_PROPERTY_ONE'))
- self.assertFalse(difference.Lookup('tabs', 'functions', 'get',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('tabs', 'functions', 'get',
'parameters', 'tabId'))
- self.assertFalse(difference.Lookup('events', 'onUpdated', 'parameters',
+ self.assertEqual(LookupResult(False, None),
+ difference.Lookup('events', 'onUpdated', 'parameters',
'updateInfo'))
+ def testUpdate(self):
+ result = APISchemaGraph(API_SCHEMA)
+ to_add = APISchemaGraph({
+ 'tabs': {
+ 'properties': {
+ 'TAB_PROPERTY_THREE': { 'description': 'better than two' },
+ 'TAB_PROPERTY_FOUR': { 'value': 4 }
+ },
+ 'functions': {
+ 'get': {
+ 'name': {},
+ 'parameters': {
+ 'tab': {
+ 'type': {},
+ 'name': {},
+ 'description': {},
+ 'surprise': {}
+ }
+ }
+ },
+ 'getAllInWindow': {
+ 'parameters': {
+ 'windowId': { 'type': 'object' }
+ }
+ }
+ }
+ }
+ })
+ result.Update(to_add, annotation='first')
+ # Looking up elements that were originally available in |result|. Because
+ # of this, no |annotation| object should be attached to the LookupResult
+ # object.
+ self.assertEqual(LookupResult(True, None),
+ result.Lookup('tabs'))
+ self.assertEqual(LookupResult(True, None),
+ result.Lookup('tabs', 'functions', 'get',
+ 'parameters'))
+ self.assertEqual(LookupResult(True, None),
+ result.Lookup('tabs', 'properties',
+ 'TAB_PROPERTY_ONE'))
+ self.assertEqual(LookupResult(True, None),
+ result.Lookup('tabs', 'properties',
+ 'TAB_PROPERTY_ONE'))
+ self.assertEqual(LookupResult(True, None),
+ result.Lookup('tabs', 'functions', 'get',
+ 'parameters', 'tabId'))
+
+ # Looking up elements that were just added to |result|.
+ self.assertEqual(LookupResult(True, 'first'),
+ result.Lookup('tabs', 'properties',
+ 'TAB_PROPERTY_THREE'))
+ self.assertEqual(LookupResult(True, 'first'),
+ result.Lookup('tabs', 'properties',
+ 'TAB_PROPERTY_FOUR'))
+ self.assertEqual(LookupResult(True, 'first'),
+ result.Lookup('tabs', 'functions', 'getAllInWindow',
+ 'parameters', 'windowId'))
+ self.assertEqual(LookupResult(True, 'first'),
+ result.Lookup('tabs', 'functions', 'get', 'parameters',
+ 'tab', 'surprise'))
+
+ to_add = APISchemaGraph({
+ 'tabs': {
+ 'properties': {
+ 'TAB_PROPERTY_FIVE': { 'description': 'stayin\' alive' }
+ },
+ 'functions': {
+ 'getAllInWindow': {
+ 'parameters': {
+ 'callback': { 'type': 'function' }
+ }
+ }
+ }
+ }
+ })
+ result.Update(to_add, annotation='second')
+ # Looking up the second group of elements added to |result|.
+ self.assertEqual(LookupResult(True, 'first'),
+ result.Lookup('tabs', 'properties',
+ 'TAB_PROPERTY_FOUR'))
+ self.assertEqual(LookupResult(True, 'second'),
+ result.Lookup('tabs', 'properties',
+ 'TAB_PROPERTY_FIVE'))
+ self.assertEqual(LookupResult(True, 'first'),
+ result.Lookup('tabs', 'functions',
+ 'getAllInWindow', 'parameters',
+ 'windowId'))
+ self.assertEqual(LookupResult(True, 'second'),
+ result.Lookup('tabs', 'functions',
+ 'getAllInWindow', 'parameters',
+ 'callback'))
+ self.assertEqual(LookupResult(True, 'first'),
+ result.Lookup('tabs', 'functions',
+ 'getAllInWindow'))
+
if __name__ == '__main__':
unittest.main()
diff --git a/chrome/common/extensions/docs/server2/app.yaml b/chrome/common/extensions/docs/server2/app.yaml
index aec5138..bc42d42 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-28-2
+version: 2-28-3
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
index b4ab31a..e88523b 100644
--- a/chrome/common/extensions/docs/server2/availability_finder.py
+++ b/chrome/common/extensions/docs/server2/availability_finder.py
@@ -5,15 +5,18 @@
import collections
import os
-import svn_constants
+from api_schema_graph import APISchemaGraph
from branch_utility import BranchUtility
from compiled_file_system import CompiledFileSystem
-from file_system import FileNotFoundError
-from third_party.json_schema_compiler import json_parse
-from third_party.json_schema_compiler.memoize import memoize
+from svn_constants import API_PATH
+from third_party.json_schema_compiler import idl_schema, idl_parser, json_parse
+from third_party.json_schema_compiler.json_parse import OrderedDict
from third_party.json_schema_compiler.model import UnixName
+_EXTENSION_API = 'extension_api.json'
+
+
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
@@ -35,38 +38,55 @@
return _GetChannelFromFeatures(
api_name,
file_system,
- '%s/_api_features.json' % svn_constants.API_PATH)
+ '%s/_api_features.json' % API_PATH)
def _GetChannelFromManifestFeatures(api_name, file_system):
return _GetChannelFromFeatures(
UnixName(api_name), #_manifest_features uses unix_style API names
file_system,
- '%s/_manifest_features.json' % svn_constants.API_PATH)
+ '%s/_manifest_features.json' % API_PATH)
def _GetChannelFromPermissionFeatures(api_name, file_system):
return _GetChannelFromFeatures(
api_name,
file_system,
- '%s/_permission_features.json' % svn_constants.API_PATH)
+ '%s/_permission_features.json' % API_PATH)
-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.
+def _GetApiSchema(api_name, file_system):
+ '''Searches |file_system| for |api_name|'s API schema data, and parses and
+ returns it if found.
'''
- try:
- extension_api_json = file_system.GetFromFile(
- '%s/extension_api.json' % svn_constants.API_PATH)
- api_rows = [row.get('namespace') for row in extension_api_json
- if 'namespace' in row]
- return api_name in api_rows
- except FileNotFoundError:
- # This should only happen on preview.py since extension_api.json is no
- # longer present in trunk.
- return False
+ file_names = file_system.ReadSingle('%s/' % API_PATH)
+ # API names can be represented in unix_style and camelCase formats.
+ possibilities = (api_name, UnixName(api_name))
+
+ def get_file_data(file_name):
+ return file_system.ReadSingle('%s/%s' % (API_PATH, file_name))
+
+ if _EXTENSION_API in file_names:
+ # Prior to Chrome version 18, extension_api.json contained all API schema
+ # data, which replaced the current implementation of individual API files.
+ #
+ # TODO(epeterson) This file will be parsed a lot, but the data remains the
+ # same for each API. Avoid doing unnecessary work by re-parsing.
+ # (see http://crbug.com/295812)
+ extension_api_json = json_parse.Parse(get_file_data(_EXTENSION_API))
+ api = [api for api in extension_api_json if api['namespace'] == api_name]
+ return api if api else None
+
+ def check_file(file_name):
+ return os.path.splitext(file_name)[0] in (api_name, UnixName(api_name))
+
+ for file_name in file_names:
+ if check_file(file_name):
+ if file_name.endswith('idl'):
+ idl_data = idl_parser.IDLParser().ParseData(get_file_data(file_name))
+ return idl_schema.IDLSchema(idl_data).process()
+ return json_parse.Parse(get_file_data(file_name))
+ return None
class AvailabilityFinder(object):
@@ -77,23 +97,16 @@
def __init__(self,
file_system_iterator,
object_store_creator,
- branch_utility):
+ branch_utility,
+ host_file_system):
self._file_system_iterator = file_system_iterator
self._object_store_creator = object_store_creator
- self._object_store = self._object_store_creator.Create(AvailabilityFinder)
+ def create_object_store(category):
+ return object_store_creator.Create(AvailabilityFinder, category=category)
+ self._top_level_object_store = create_object_store('top_level')
+ self._node_level_object_store = create_object_store('node_level')
self._branch_utility = branch_utility
-
- def _ExistsInFileSystem(self, api_name, file_system):
- '''Checks for existence of |api_name| within the list of api files in the
- api/ directory found using the given |file_system|.
- '''
- file_names = file_system.ReadSingle('%s/' % svn_constants.API_PATH)
- api_names = tuple(os.path.splitext(name)[0] for name in file_names
- if os.path.splitext(name)[1][1:] in ['json', 'idl'])
-
- # API file names in api/ are unix_name at every version except for versions
- # 18, 19, and 20. Since unix_name is the more common format, check it first.
- return (UnixName(api_name) in api_names) or (api_name in api_names)
+ self._host_file_system = host_file_system
def _CheckStableAvailability(self, api_name, file_system, version):
'''Checks for availability of an API, |api_name|, on the stable channel.
@@ -122,15 +135,11 @@
or _GetChannelFromManifestFeatures(api_name, features_fs))
if available_channel is not None:
return available_channel == 'stable'
- if version >= 18:
- # Fall back to a check for file system existence if the API is not
- # stable in any of the _features.json files, OR if we're dealing with
- # version 18 or 19, which don't contain relevant _features information.
- return self._ExistsInFileSystem(api_name, file_system)
if version >= 5:
- # Versions 17 down to 5 have an extension_api.json file which
- # contains namespaces for each API that was available at the time.
- return _ExistsInExtensionApi(api_name, features_fs)
+ # Fall back to a check for file system existence if the API is not
+ # stable in any of the _features.json files, or if the _features files
+ # do not exist (version 19 and earlier).
+ return _GetApiSchema(api_name, file_system) is not None
def _CheckChannelAvailability(self, api_name, file_system, channel_name):
'''Searches through the _features files in a given |file_system| and
@@ -146,7 +155,7 @@
or _GetChannelFromPermissionFeatures(api_name, features_fs)
or _GetChannelFromManifestFeatures(api_name, features_fs))
if (available_channel is None and
- self._ExistsInFileSystem(api_name, file_system)):
+ _GetApiSchema(api_name, file_system) is not None):
# 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.
@@ -175,7 +184,7 @@
HostFileSystemIterator instance to traverse multiple version of the
SVN filesystem.
'''
- availability = self._object_store.Get(api_name).Get()
+ availability = self._top_level_object_store.Get(api_name).Get()
if availability is not None:
return availability
@@ -188,5 +197,37 @@
if availability is None:
# The API wasn't available on 'dev', so it must be a 'trunk'-only API.
availability = self._branch_utility.GetChannelInfo('trunk')
- self._object_store.Set(api_name, availability)
+ self._top_level_object_store.Set(api_name, availability)
return availability
+
+ def GetApiNodeAvailability(self, api_name):
+ '''Returns an APISchemaGraph annotated with each node's availability (the
+ ChannelInfo at the oldest channel it's available in).
+ '''
+ availability_graph = self._node_level_object_store.Get(api_name).Get()
+ if availability_graph is not None:
+ return availability_graph
+
+ availability_graph = APISchemaGraph()
+ trunk_graph = APISchemaGraph(_GetApiSchema(api_name,
+ self._host_file_system))
+ def update_availability_graph(file_system, channel_info):
+ version_graph = APISchemaGraph(_GetApiSchema(api_name, file_system))
+ # Keep track of any new schema elements from this version by adding
+ # them to |availability_graph|.
+ #
+ # Calling |availability_graph|.Lookup() on the nodes being updated
+ # will return the |annotation| object.
+ availability_graph.Update(version_graph.Subtract(availability_graph),
+ annotation=channel_info)
+
+ # Continue looping until there are no longer differences between this
+ # version and trunk.
+ return trunk_graph != version_graph
+
+ self._file_system_iterator.Ascending(
+ self.GetApiAvailability(api_name),
+ update_availability_graph)
+
+ self._node_level_object_store.Set(api_name, availability_graph)
+ return availability_graph
diff --git a/chrome/common/extensions/docs/server2/availability_finder_test.py b/chrome/common/extensions/docs/server2/availability_finder_test.py
index 83ab7c7..0cfc373 100755
--- a/chrome/common/extensions/docs/server2/availability_finder_test.py
+++ b/chrome/common/extensions/docs/server2/availability_finder_test.py
@@ -2,12 +2,14 @@
# Copyright 2013 The Chromium 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 os
import sys
import unittest
from availability_finder import AvailabilityFinder
+from api_schema_graph import LookupResult
from branch_utility import BranchUtility
from compiled_file_system import CompiledFileSystem
from fake_url_fetcher import FakeUrlFetcher
@@ -15,30 +17,40 @@
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)
+from test_data.object_level_availability.tabs import TABS_SCHEMA_BRANCHES
class FakeHostFileSystemCreator(object):
+ def __init__(self, file_system_data):
+ self._file_system_data = file_system_data
+
def Create(self, branch):
- return TestFileSystem(CANNED_API_FILE_SYSTEM_DATA[str(branch)])
+ return TestFileSystem(self._file_system_data[str(branch)])
class AvailabilityFinderTest(unittest.TestCase):
def setUp(self):
- branch_utility = BranchUtility(
+ self._branch_utility = 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())
- fake_host_file_system_creator = FakeHostFileSystemCreator()
- file_system_iterator = HostFileSystemIterator(
- fake_host_file_system_creator,
- fake_host_file_system_creator.Create('trunk'),
- branch_utility)
- self._avail_finder = AvailabilityFinder(file_system_iterator,
- ObjectStoreCreator.ForTest(),
- branch_utility)
+
+ def create_availability_finder(file_system_data):
+ fake_host_fs_creator = FakeHostFileSystemCreator(file_system_data)
+ fake_host_fs = fake_host_fs_creator.Create('trunk')
+ return AvailabilityFinder(HostFileSystemIterator(
+ fake_host_fs_creator,
+ fake_host_fs,
+ self._branch_utility),
+ ObjectStoreCreator.ForTest(),
+ self._branch_utility,
+ fake_host_fs)
+
+ self._avail_finder = create_availability_finder(CANNED_API_FILE_SYSTEM_DATA)
+ self._node_avail_finder = create_availability_finder(TABS_SCHEMA_BRANCHES)
def testGetApiAvailability(self):
# Key: Using 'channel' (i.e. 'beta') to represent an availability listing
@@ -46,7 +58,7 @@
# represent the development channel, or phase of development, where an API's
# availability is being checked.
- # Testing whitelisted API
+ # Testing a whitelisted API.
self.assertEquals('beta',
self._avail_finder.GetApiAvailability('declarativeWebRequest').channel)
self.assertEquals(27,
@@ -174,5 +186,108 @@
self.assertEquals('trunk',
self._avail_finder.GetApiAvailability('events').version)
+ def testGetApiNodeAvailability(self):
+ availability_graph = self._node_avail_finder.GetApiNodeAvailability('tabs')
+
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetChannelInfo('trunk')),
+ availability_graph.Lookup('tabs', 'properties',
+ 'fakeTabsProperty3'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetChannelInfo('dev')),
+ availability_graph.Lookup('tabs', 'events', 'onActivated',
+ 'parameters', 'activeInfo', 'properties',
+ 'windowId'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetChannelInfo('dev')),
+ availability_graph.Lookup('tabs', 'events', 'onUpdated', 'parameters',
+ 'tab'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetChannelInfo('beta')),
+ availability_graph.Lookup('tabs', 'events','onActivated'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetChannelInfo('beta')),
+ availability_graph.Lookup('tabs', 'functions', 'get', 'parameters',
+ 'tabId'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetChannelInfo('stable')),
+ availability_graph.Lookup('tabs', 'types', 'InjectDetails',
+ 'properties', 'code'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetChannelInfo('stable')),
+ availability_graph.Lookup('tabs', 'types', 'InjectDetails',
+ 'properties', 'file'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(25)),
+ availability_graph.Lookup('tabs', 'types', 'InjectDetails'))
+
+ # Nothing new in version 24 or 23.
+
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(22)),
+ availability_graph.Lookup('tabs', 'types', 'Tab', 'properties',
+ 'windowId'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(21)),
+ availability_graph.Lookup('tabs', 'types', 'Tab', 'properties',
+ 'selected'))
+
+ # Nothing new in version 20.
+
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(19)),
+ availability_graph.Lookup('tabs', 'functions', 'getCurrent'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(18)),
+ availability_graph.Lookup('tabs', 'types', 'Tab', 'properties',
+ 'index'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(17)),
+ availability_graph.Lookup('tabs', 'events', 'onUpdated', 'parameters',
+ 'changeInfo'))
+
+ # Nothing new in version 16.
+
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(15)),
+ availability_graph.Lookup('tabs', 'properties',
+ 'fakeTabsProperty2'))
+
+ # Everything else is available at the API's release, version 14 here.
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
+ availability_graph.Lookup('tabs', 'types', 'Tab'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
+ availability_graph.Lookup('tabs', 'types', 'Tab',
+ 'properties', 'url'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
+ availability_graph.Lookup('tabs', 'properties',
+ 'fakeTabsProperty1'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
+ availability_graph.Lookup('tabs', 'functions', 'get', 'parameters',
+ 'callback'))
+ self.assertEquals(
+ LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
+ availability_graph.Lookup('tabs', 'events', 'onUpdated'))
+
+ # Test things that aren't available.
+ self.assertEqual(LookupResult(False, None),
+ availability_graph.Lookup('tabs', 'types',
+ 'UpdateInfo'))
+ self.assertEqual(LookupResult(False, None),
+ availability_graph.Lookup('tabs', 'functions', 'get',
+ 'parameters', 'callback',
+ 'parameters', 'tab', 'id'))
+ self.assertEqual(LookupResult(False, None),
+ availability_graph.Lookup('functions'))
+ self.assertEqual(LookupResult(False, None),
+ availability_graph.Lookup('events', 'onActivated',
+ 'parameters', 'activeInfo',
+ 'tabId'))
+
+
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 eb1dffc..7eb164c 100644
--- a/chrome/common/extensions/docs/server2/branch_utility.py
+++ b/chrome/common/extensions/docs/server2/branch_utility.py
@@ -189,7 +189,7 @@
# 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])
+ self._branch_object_store.Set(str(version), int(version_title[2]))
return int(version_title[2])
raise ValueError('The branch for %s could not be found.' % version)
diff --git a/chrome/common/extensions/docs/server2/cron.yaml b/chrome/common/extensions/docs/server2/cron.yaml
index 5a1047b..dc55ff3 100644
--- a/chrome/common/extensions/docs/server2/cron.yaml
+++ b/chrome/common/extensions/docs/server2/cron.yaml
@@ -2,4 +2,4 @@
- description: Repopulates all cached data.
url: /_cron
schedule: every 5 minutes
- target: 2-28-2
+ target: 2-28-3
diff --git a/chrome/common/extensions/docs/server2/new_github_file_system_test.py b/chrome/common/extensions/docs/server2/new_github_file_system_test.py
index 8eae40a..157dc08 100755
--- a/chrome/common/extensions/docs/server2/new_github_file_system_test.py
+++ b/chrome/common/extensions/docs/server2/new_github_file_system_test.py
@@ -86,11 +86,13 @@
def testReads(self):
self._gfs.Refresh().Get()
expected = {
- '/src/': ['hello.notpy', '__init__.notpy'],
- '/': ['requirements.txt', '.gitignore', 'README.md', 'src/']
+ '/src/': sorted(['hello.notpy', '__init__.notpy']),
+ '/': sorted(['requirements.txt', '.gitignore', 'README.md', 'src/'])
}
- self.assertEqual(expected, self._gfs.Read(['/', '/src/']).Get())
+ read = self._gfs.Read(['/', '/src/']).Get()
+ self.assertEqual(expected['/src/'], sorted(read['/src/']))
+ self.assertEqual(expected['/'], sorted(read['/']))
def testStat(self):
self._gfs.Refresh().Get()
diff --git a/chrome/common/extensions/docs/server2/server_instance.py b/chrome/common/extensions/docs/server2/server_instance.py
index ef92a06..1194e9e 100644
--- a/chrome/common/extensions/docs/server2/server_instance.py
+++ b/chrome/common/extensions/docs/server2/server_instance.py
@@ -52,7 +52,8 @@
self.availability_finder = AvailabilityFinder(
self.host_file_system_iterator,
object_store_creator,
- branch_utility)
+ branch_utility,
+ host_file_system)
self.api_list_data_source_factory = APIListDataSource.Factory(
self.compiled_host_fs_factory,
diff --git a/chrome/common/extensions/docs/server2/test_data/canned_data.py b/chrome/common/extensions/docs/server2/test_data/canned_data.py
index b3a0136..a227f1a 100644
--- a/chrome/common/extensions/docs/server2/test_data/canned_data.py
+++ b/chrome/common/extensions/docs/server2/test_data/canned_data.py
@@ -181,11 +181,11 @@
'channel': 'trunk'
}
}),
- 'idle.json': 'idle contents',
- 'input_ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'tabs.json': 'tabs contents',
- 'windows.json': 'windows contents'
+ 'idle.json': '{}',
+ 'input_ime.json': '{}',
+ 'menus.json': '{}',
+ 'tabs.json': '{}',
+ 'windows.json': '{}'
},
'docs': {
'templates': {
@@ -280,11 +280,11 @@
'channel': 'beta'
}
}),
- 'idle.json': 'idle contents',
- 'input_ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'tabs.json': 'tabs contents',
- 'windows.json': 'windows contents'
+ 'idle.json': '{}',
+ 'input_ime.json': '{}',
+ 'menus.json': '{}',
+ 'tabs.json': '{}',
+ 'windows.json': '{}'
}
},
'1453': {
@@ -348,11 +348,11 @@
'channel': 'dev'
}
}),
- 'idle.json': 'idle contents',
- 'input_ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'tabs.json': 'tabs contents',
- 'windows.json': 'windows contents'
+ 'idle.json': '{}',
+ 'input_ime.json': '{}',
+ 'menus.json': '{}',
+ 'tabs.json': '{}',
+ 'windows.json': '{}'
}
},
'1410': {
@@ -399,11 +399,11 @@
'channel': 'stable'
}
}),
- 'idle.json': 'idle contents',
- 'input_ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'tabs.json': 'tabs contents',
- 'windows.json': 'windows contents'
+ 'idle.json': '{}',
+ 'input_ime.json': '{}',
+ 'menus.json': '{}',
+ 'tabs.json': '{}',
+ 'windows.json': '{}'
}
},
'1364': {
@@ -430,11 +430,11 @@
'channel': 'stable'
}
}),
- 'idle.json': 'idle contents',
- 'input_ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'tabs.json': 'tabs contents',
- 'windows.json': 'windows contents'
+ 'idle.json': '{}',
+ 'input_ime.json': '{}',
+ 'menus.json': '{}',
+ 'tabs.json': '{}',
+ 'windows.json': '{}'
}
},
'1312': {
@@ -461,11 +461,11 @@
'channel': 'stable'
}
}),
- 'idle.json': 'idle contents',
- 'input_ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'tabs.json': 'tabs contents',
- 'windows.json': 'windows contents'
+ 'idle.json': '{}',
+ 'input_ime.json': '{}',
+ 'menus.json': '{}',
+ 'tabs.json': '{}',
+ 'windows.json': '{}'
}
},
'1271': {
@@ -492,12 +492,12 @@
'channel': 'stable'
}
}),
- 'alarms.idl': 'alarms contents',
- 'idle.json': 'idle contents',
- 'input_ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'tabs.json': 'tabs contents',
- 'windows.json': 'windows contents'
+ 'alarms.idl': '{}',
+ 'idle.json': '{}',
+ 'input_ime.json': '{}',
+ 'menus.json': '{}',
+ 'tabs.json': '{}',
+ 'windows.json': '{}'
}
},
'1229': {
@@ -521,12 +521,12 @@
'channel': 'beta'
}
}),
- 'alarms.idl': 'alarms contents',
- 'idle.json': 'idle contents',
- 'input_ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'system_info_display.idl': 'systemInfo.display contents',
- 'tabs.json': 'tabs contents'
+ 'alarms.idl': '{}',
+ 'idle.json': '{}',
+ 'input_ime.json': '{}',
+ 'menus.json': '{}',
+ 'system_info_display.idl': '{}',
+ 'tabs.json': '{}'
}
},
'1180': {
@@ -547,11 +547,11 @@
'channel': 'stable'
}
}),
- 'bookmarks.json': 'bookmarks contents',
- 'idle.json': 'idle contents',
- 'input_ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'tabs.json': 'tabs contents'
+ 'bookmarks.json': '{}',
+ 'idle.json': '{}',
+ 'input_ime.json': '{}',
+ 'menus.json': '{}',
+ 'tabs.json': '{}'
}
},
'1132': {
@@ -569,11 +569,11 @@
'channel': 'stable'
}
}),
- 'bookmarks.json': 'bookmarks contents',
- 'idle.json': 'idle contents',
- 'input.ime.json': 'input.ime contents',
- 'menus.json': 'menus contents',
- 'tabs.json': 'tabs contents'
+ 'bookmarks.json': '{}',
+ 'idle.json': '{}',
+ 'input.ime.json': '{}',
+ 'menus.json': '{}',
+ 'tabs.json': '{}'
}
},
'1084': {
@@ -581,22 +581,22 @@
'_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'
+ 'idle.json': '{}',
+ 'input.ime.json': '{}',
+ 'menus.json': '{}',
+ 'pageAction.json': '{}',
+ 'tabs.json': '{}',
+ 'webRequest.json': '{}'
}
},
'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'
+ 'idle.json': '{}',
+ 'input.ime.json': '{}',
+ 'menus.json': '{}',
+ 'pageAction.json': '{}',
+ 'tabs.json': '{}',
+ 'webRequest.json': '{}'
}
},
'963': {
diff --git a/chrome/common/extensions/docs/server2/test_data/github_file_system/test_owner/repo/zipball b/chrome/common/extensions/docs/server2/test_data/github_file_system/test_owner/repo/zipball
index be0dde6..1992481 100644
--- a/chrome/common/extensions/docs/server2/test_data/github_file_system/test_owner/repo/zipball
+++ b/chrome/common/extensions/docs/server2/test_data/github_file_system/test_owner/repo/zipball
Binary files differ
diff --git a/chrome/test/functional/ispy/ispy_core/__init__.py b/chrome/common/extensions/docs/server2/test_data/object_level_availability/__init__.py
similarity index 100%
copy from chrome/test/functional/ispy/ispy_core/__init__.py
copy to chrome/common/extensions/docs/server2/test_data/object_level_availability/__init__.py
diff --git a/chrome/common/extensions/docs/server2/test_data/object_level_availability/tabs.py b/chrome/common/extensions/docs/server2/test_data/object_level_availability/tabs.py
new file mode 100644
index 0000000..e2a2b24
--- /dev/null
+++ b/chrome/common/extensions/docs/server2/test_data/object_level_availability/tabs.py
@@ -0,0 +1,1108 @@
+# Copyright 2013 The Chromium 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
+
+
+TABS_SCHEMA_BRANCHES = {
+ 'trunk': {
+ 'api': {
+ '_api_features.json': json.dumps({}),
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'selected': {},
+ 'id': {},
+ 'windowId': {}
+ }
+ },
+ {
+ 'id': 'InjectDetails',
+ 'properties': {
+ 'allFrames': {},
+ 'code': {},
+ 'file': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {},
+ 'fakeTabsProperty3': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ },
+ {
+ 'name': 'tabId'
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onActivated',
+ 'parameters': [
+ {
+ 'name': 'activeInfo',
+ 'properties': {
+ 'tabId': {},
+ 'windowId': {}
+ }
+ }
+ ]
+ },
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'tab'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1500': {
+ 'api': {
+ '_api_features.json': json.dumps({}),
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'selected': {},
+ 'id': {},
+ 'windowId': {}
+ }
+ },
+ {
+ 'id': 'InjectDetails',
+ 'properties': {
+ 'allFrames': {},
+ 'code': {},
+ 'file': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ },
+ {
+ 'name': 'tabId'
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onActivated',
+ 'parameters': [
+ {
+ 'name': 'activeInfo',
+ 'properties': {
+ 'tabId': {},
+ 'windowId': {}
+ }
+ }
+ ]
+ },
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'tab'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1453': {
+ 'api': {
+ '_api_features.json': json.dumps({}),
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'selected': {},
+ 'id': {},
+ 'windowId': {}
+ }
+ },
+ {
+ 'id': 'InjectDetails',
+ 'properties': {
+ 'allFrames': {},
+ 'code': {},
+ 'file': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ },
+ {
+ 'name': 'tabId'
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onActivated',
+ 'parameters': [
+ {
+ 'name': 'activeInfo',
+ 'properties': {
+ 'tabId': {}
+ }
+ }
+ ]
+ },
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1410': {
+ 'api': {
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'selected': {},
+ 'id': {},
+ 'windowId': {}
+ }
+ },
+ {
+ 'id': 'InjectDetails',
+ 'properties': {
+ 'allFrames': {},
+ 'code': {},
+ 'file': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1364': {
+ 'api': {
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'selected': {},
+ 'id': {},
+ 'windowId': {}
+ }
+ },
+ {
+ 'id': 'InjectDetails',
+ 'properties': {
+ 'allFrames': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1312': {
+ 'api': {
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'selected': {},
+ 'id': {},
+ 'windowId': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1271': {
+ 'api': {
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'selected': {},
+ 'id': {},
+ 'windowId': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1229': {
+ 'api': {
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'selected': {},
+ 'id': {},
+ 'windowId': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1180': {
+ 'api': {
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'selected': {},
+ 'id': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1132': {
+ 'api': {
+ '_manifest_features.json': json.dumps({}),
+ '_permission_features.json': json.dumps({}),
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'id': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1084': {
+ 'api': {
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'id': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'getCurrent',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '1025': {
+ 'api': {
+ 'tabs.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'index': {},
+ 'id': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '963': {
+ 'api': {
+ 'extension_api.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'id': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ },
+ {
+ 'name': 'changeInfo',
+ 'properties': {
+ 'pinned': {},
+ 'status': {}
+ }
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '912': {
+ 'api': {
+ 'extension_api.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'id': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '874': {
+ 'api': {
+ 'extension_api.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'id': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {},
+ 'fakeTabsProperty2': {}
+ },
+ 'functions': [
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '835': {
+ 'api': {
+ 'extension_api.json': json.dumps([{
+ 'namespace': 'tabs',
+ 'types': [
+ {
+ 'id': 'Tab',
+ 'properties': {
+ 'url': {},
+ 'id': {}
+ }
+ }
+ ],
+ 'properties': {
+ 'fakeTabsProperty1': {}
+ },
+ 'functions': [
+ {
+ 'name': 'get',
+ 'parameters': [
+ {
+ 'name': 'callback',
+ 'parameters': [
+ {
+ 'name': 'tab'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ 'events': [
+ {
+ 'name': 'onUpdated',
+ 'parameters': [
+ {
+ 'name': 'tabId'
+ }
+ ]
+ }
+ ]
+ }])
+ }
+ },
+ '782': {
+ 'api': {
+ 'extension_api.json': json.dumps({})
+ }
+ }
+}
diff --git a/chrome/common/extensions/docs/templates/articles/about_apps.html b/chrome/common/extensions/docs/templates/articles/about_apps.html
index dd130ee..ab41e52 100644
--- a/chrome/common/extensions/docs/templates/articles/about_apps.html
+++ b/chrome/common/extensions/docs/templates/articles/about_apps.html
@@ -12,7 +12,7 @@
</p>
<p>
-<iframe title="YouTube video player" width="610" height="380" src="http://www.youtube.com/embed/lBUGTVIJVfM" frameborder="0" allowfullscreen></iframe>
+<iframe title="YouTube video player" width="610" height="380" src="//www.youtube.com/embed/lBUGTVIJVfM" frameborder="0" allowfullscreen></iframe>
</p>
<p>
diff --git a/chrome/common/extensions/docs/templates/articles/api_index.html b/chrome/common/extensions/docs/templates/articles/api_index.html
index f9a1232..891a7c9 100644
--- a/chrome/common/extensions/docs/templates/articles/api_index.html
+++ b/chrome/common/extensions/docs/templates/articles/api_index.html
@@ -54,6 +54,6 @@
{{^is_apps}}
<p class="doc-family extensions">
-<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/bmxr75CV36A?rel=0" frameborder="0" allowfullscreen></iframe>
+<iframe title="YouTube video player" width="640" height="390" src="//www.youtube.com/embed/bmxr75CV36A?rel=0" frameborder="0" allowfullscreen></iframe>
</p>
{{/is_apps}}
diff --git a/chrome/common/extensions/docs/templates/articles/app_architecture.html b/chrome/common/extensions/docs/templates/articles/app_architecture.html
index 3f61720..f74d9dc 100644
--- a/chrome/common/extensions/docs/templates/articles/app_architecture.html
+++ b/chrome/common/extensions/docs/templates/articles/app_architecture.html
@@ -67,7 +67,7 @@
<p>
<p>
-<iframe title="YouTube video player" width="610" height="380" src="http://www.youtube.com/embed/yr1jgREbH8U" frameborder="0" allowfullscreen></iframe>
+<iframe title="YouTube video player" width="610" height="380" src="//www.youtube.com/embed/yr1jgREbH8U" frameborder="0" allowfullscreen></iframe>
</p>
<h3 id="lifecycle">App lifecycle at a glance</h3>
@@ -167,7 +167,7 @@
</p>
<p>
-<iframe title="YouTube video player" width="610" height="380" src="http://www.youtube.com/embed/EDtiWN42lHs" frameborder="0" allowfullscreen></iframe>
+<iframe title="YouTube video player" width="610" height="380" src="//www.youtube.com/embed/EDtiWN42lHs" frameborder="0" allowfullscreen></iframe>
</p>
<p class="backtotop"><a href="#top">Back to top</a></p>
diff --git a/chrome/common/extensions/docs/templates/articles/content_scripts.html b/chrome/common/extensions/docs/templates/articles/content_scripts.html
index 5cecf95..3811402 100644
--- a/chrome/common/extensions/docs/templates/articles/content_scripts.html
+++ b/chrome/common/extensions/docs/templates/articles/content_scripts.html
@@ -448,7 +448,7 @@
</p>
<p>
-<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/laLudeUmXHM?rel=0" frameborder="0" allowfullscreen></iframe>
+<iframe title="YouTube video player" width="640" height="390" src="//www.youtube.com/embed/laLudeUmXHM?rel=0" frameborder="0" allowfullscreen></iframe>
</p>
<p>
@@ -458,5 +458,5 @@
</p>
<p>
-<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/B4M_a7xejYI?rel=0" frameborder="0" allowfullscreen></iframe>
+<iframe title="YouTube video player" width="640" height="390" src="//www.youtube.com/embed/B4M_a7xejYI?rel=0" frameborder="0" allowfullscreen></iframe>
</p>
diff --git a/chrome/common/extensions/docs/templates/articles/extensions_index.html b/chrome/common/extensions/docs/templates/articles/extensions_index.html
index 182694c..0f317a8 100644
--- a/chrome/common/extensions/docs/templates/articles/extensions_index.html
+++ b/chrome/common/extensions/docs/templates/articles/extensions_index.html
@@ -65,5 +65,5 @@
</p>
<p>
- <iframe title="YouTube video player" width="300" height="199" src="http://www.youtube.com/embed/wRDPTnY3yO8?rel=0" frameborder="0" allowfullscreen=""></iframe>
+ <iframe title="YouTube video player" width="300" height="199" src="//www.youtube.com/embed/wRDPTnY3yO8?rel=0" frameborder="0" allowfullscreen=""></iframe>
</p>
diff --git a/chrome/common/extensions/docs/templates/articles/manifest/externally_connectable.html b/chrome/common/extensions/docs/templates/articles/manifest/externally_connectable.html
index 6eab3fe..e0a5e6d 100644
--- a/chrome/common/extensions/docs/templates/articles/manifest/externally_connectable.html
+++ b/chrome/common/extensions/docs/templates/articles/manifest/externally_connectable.html
@@ -1,7 +1,7 @@
<h1>externally_connectable</h1>
<p>
-The <code>externally_connectable</code> manifest property declares which extensions, apps, and web pages can connect to your extension via <a href="../runtime.html#method-connect">runtime.connect</a> and <a href="../runtime.html#method-sendMessage">runtime.sendMessage</a>.
+The <code>externally_connectable</code> manifest property declares which extensions, apps, and web pages can connect to your {{platform}} via <a href="../runtime.html#method-connect">runtime.connect</a> and <a href="../runtime.html#method-sendMessage">runtime.sendMessage</a>.
</p>
<p>
diff --git a/chrome/common/extensions/docs/templates/articles/manifest/kiosk_enabled.html b/chrome/common/extensions/docs/templates/articles/manifest/kiosk_enabled.html
index 0256389..8eb7b58 100644
--- a/chrome/common/extensions/docs/templates/articles/manifest/kiosk_enabled.html
+++ b/chrome/common/extensions/docs/templates/articles/manifest/kiosk_enabled.html
@@ -6,3 +6,10 @@
display (forced full screen). The kiosk-enabled apps are expected to be designed
with this constraint in mind.
</p>
+
+<h1 id="kiosk_only">Manifest - Kiosk Only</h1>
+
+<p>
+Whether the packaged app is only intended to be installed and run in ChromeOS
+kiosk mode. This field is only valid if the <code>kiosk_enabled</code> field is <code>true</code>.
+</p>
diff --git a/chrome/common/extensions/docs/templates/json/manifest.json b/chrome/common/extensions/docs/templates/json/manifest.json
index b3ac91f..2cb5331 100644
--- a/chrome/common/extensions/docs/templates/json/manifest.json
+++ b/chrome/common/extensions/docs/templates/json/manifest.json
@@ -75,7 +75,11 @@
"example": "publicKey"
},
"kiosk_enabled": {
- "documentation": "manifest/kiosk_enabled.html",
+ "documentation": "manifest/kiosk_enabled.html#kiosk_enabled",
+ "example": true
+ },
+ "kiosk_only": {
+ "documentation": "manifest/kiosk_enabled.html#kiosk_only",
"example": true
},
"manifest_version": {
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index 7e75d73..2894283 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -87,6 +87,11 @@
const char kGalleryBrowsePrefix[] = "https://chrome.google.com/webstore";
+const char kWebstoreSourceField[] = "utm_source";
+
+const char kLaunchSourceAppList[] = "chrome-app-launcher";
+const char kLaunchSourceAppListSearch[] = "chrome-app-launcher-search";
+
} // namespace extension_urls
namespace extension_misc {
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index 52eb362..7938d4f 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -54,6 +54,13 @@
// The greatest common prefixes of the main extensions gallery's browse and
// download URLs.
extern const char kGalleryBrowsePrefix[];
+
+ // Field to use with webstore URL for tracking launch source.
+ extern const char kWebstoreSourceField[];
+
+ // Values to use with webstore URL launch source field.
+ extern const char kLaunchSourceAppList[];
+ extern const char kLaunchSourceAppListSearch[];
} // namespace extension_urls
namespace extension_misc {
diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h
index 8d3b3e1..00a3275 100644
--- a/chrome/common/extensions/extension_messages.h
+++ b/chrome/common/extensions/extension_messages.h
@@ -168,9 +168,13 @@
IPC_STRUCT_TRAITS_MEMBER(port)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(extensions::SocketPermissionEntry)
+ IPC_STRUCT_TRAITS_MEMBER(pattern_)
+ IPC_STRUCT_TRAITS_MEMBER(match_subdomains_)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(extensions::SocketPermissionData)
- IPC_STRUCT_TRAITS_MEMBER(pattern())
- IPC_STRUCT_TRAITS_MEMBER(match_subdomains())
+ IPC_STRUCT_TRAITS_MEMBER(entry())
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(extensions::UsbDevicePermissionData)
diff --git a/chrome/common/extensions/manifest_handlers/kiosk_enabled_info.cc b/chrome/common/extensions/manifest_handlers/kiosk_enabled_info.cc
deleted file mode 100644
index 4c50de5..0000000
--- a/chrome/common/extensions/manifest_handlers/kiosk_enabled_info.cc
+++ /dev/null
@@ -1,60 +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/common/extensions/manifest_handlers/kiosk_enabled_info.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "extensions/common/manifest_constants.h"
-
-namespace extensions {
-
-namespace keys = manifest_keys;
-
-KioskEnabledInfo::KioskEnabledInfo(bool is_kiosk_enabled)
- : kiosk_enabled(is_kiosk_enabled) {
-}
-
-KioskEnabledInfo::~KioskEnabledInfo() {
-}
-
-// static
-bool KioskEnabledInfo::IsKioskEnabled(const Extension* extension) {
- KioskEnabledInfo* info = static_cast<KioskEnabledInfo*>(
- extension->GetManifestData(keys::kKioskEnabled));
- return info ? info->kiosk_enabled : false;
-}
-
-KioskEnabledHandler::KioskEnabledHandler() {
-}
-
-KioskEnabledHandler::~KioskEnabledHandler() {
-}
-
-bool KioskEnabledHandler::Parse(Extension* extension, string16* error) {
- DCHECK(extension->manifest()->HasKey(keys::kKioskEnabled));
-
- bool kiosk_enabled = false;
- if (!extension->manifest()->GetBoolean(keys::kKioskEnabled, &kiosk_enabled)) {
- *error = ASCIIToUTF16(manifest_errors::kInvalidKioskEnabled);
- return false;
- }
-
- // All other use cases should be already filtered out by manifest feature
- // checks.
- DCHECK(extension->is_platform_app());
-
- extension->SetManifestData(keys::kKioskEnabled,
- new KioskEnabledInfo(kiosk_enabled));
- return true;
-}
-
-const std::vector<std::string> KioskEnabledHandler::Keys() const {
- return SingleKey(keys::kKioskEnabled);
-}
-
-} // namespace extensions
diff --git a/chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h b/chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h
deleted file mode 100644
index 3c61b08..0000000
--- a/chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h
+++ /dev/null
@@ -1,42 +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_COMMON_EXTENSIONS_MANIFEST_HANDLERS_KIOSK_ENABLED_INFO_H_
-#define CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_KIOSK_ENABLED_INFO_H_
-
-#include <string>
-#include <vector>
-
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/manifest_handler.h"
-#include "extensions/common/manifest.h"
-
-namespace extensions {
-
-struct KioskEnabledInfo : public Extension::ManifestData {
- explicit KioskEnabledInfo(bool is_kiosk_enabled);
- virtual ~KioskEnabledInfo();
-
- bool kiosk_enabled;
-
- // Whether the extension or app should be enabled in app kiosk mode.
- static bool IsKioskEnabled(const Extension* extension);
-};
-
-// Parses the "kiosk_enabled" manifest key.
-class KioskEnabledHandler : public ManifestHandler {
- public:
- KioskEnabledHandler();
- virtual ~KioskEnabledHandler();
-
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
- private:
- virtual const std::vector<std::string> Keys() const OVERRIDE;
-
- DISALLOW_COPY_AND_ASSIGN(KioskEnabledHandler);
-};
-
-} // namespace extensions
-
-#endif // CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_KIOSK_ENABLED_INFO_H_
diff --git a/chrome/common/extensions/manifest_handlers/kiosk_mode_info.cc b/chrome/common/extensions/manifest_handlers/kiosk_mode_info.cc
new file mode 100644
index 0000000..e610490
--- /dev/null
+++ b/chrome/common/extensions/manifest_handlers/kiosk_mode_info.cc
@@ -0,0 +1,89 @@
+// Copyright 2013 The Chromium 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_handlers/kiosk_mode_info.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "extensions/common/manifest_constants.h"
+
+namespace extensions {
+
+namespace keys = manifest_keys;
+
+KioskModeInfo::KioskModeInfo(KioskStatus kiosk_status)
+ : kiosk_status(kiosk_status) {
+}
+
+KioskModeInfo::~KioskModeInfo() {
+}
+
+// static
+bool KioskModeInfo::IsKioskEnabled(const Extension* extension) {
+ KioskModeInfo* info = static_cast<KioskModeInfo*>(
+ extension->GetManifestData(keys::kKioskMode));
+ return info ? info->kiosk_status != NONE : false;
+}
+
+// static
+bool KioskModeInfo::IsKioskOnly(const Extension* extension) {
+ KioskModeInfo* info = static_cast<KioskModeInfo*>(
+ extension->GetManifestData(keys::kKioskMode));
+ return info ? info->kiosk_status == ONLY : false;
+}
+
+KioskModeHandler::KioskModeHandler() {
+ supported_keys_.push_back(keys::kKioskEnabled);
+ supported_keys_.push_back(keys::kKioskOnly);
+}
+
+KioskModeHandler::~KioskModeHandler() {
+}
+
+bool KioskModeHandler::Parse(Extension* extension, string16* error) {
+ const Manifest* manifest = extension->manifest();
+ DCHECK(manifest->HasKey(keys::kKioskEnabled) ||
+ manifest->HasKey(keys::kKioskOnly));
+
+ bool kiosk_enabled = false;
+ if (manifest->HasKey(keys::kKioskEnabled) &&
+ !manifest->GetBoolean(keys::kKioskEnabled, &kiosk_enabled)) {
+ *error = ASCIIToUTF16(manifest_errors::kInvalidKioskEnabled);
+ return false;
+ }
+
+ bool kiosk_only = false;
+ if (manifest->HasKey(keys::kKioskOnly) &&
+ !manifest->GetBoolean(keys::kKioskOnly, &kiosk_only)) {
+ *error = ASCIIToUTF16(manifest_errors::kInvalidKioskOnly);
+ return false;
+ }
+
+ if (kiosk_only && !kiosk_enabled) {
+ *error = ASCIIToUTF16(manifest_errors::kInvalidKioskOnlyButNotEnabled);
+ return false;
+ }
+
+ // All other use cases should be already filtered out by manifest feature
+ // checks.
+ DCHECK(extension->is_platform_app());
+
+ KioskModeInfo::KioskStatus kiosk_status = KioskModeInfo::NONE;
+ if (kiosk_enabled)
+ kiosk_status = kiosk_only ? KioskModeInfo::ONLY : KioskModeInfo::ENABLED;
+
+ extension->SetManifestData(keys::kKioskMode,
+ new KioskModeInfo(kiosk_status));
+
+ return true;
+}
+
+const std::vector<std::string> KioskModeHandler::Keys() const {
+ return supported_keys_;
+}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/manifest_handlers/kiosk_mode_info.h b/chrome/common/extensions/manifest_handlers/kiosk_mode_info.h
new file mode 100644
index 0000000..05a553a
--- /dev/null
+++ b/chrome/common/extensions/manifest_handlers/kiosk_mode_info.h
@@ -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.
+
+#ifndef CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_KIOSK_MODE_INFO_H_
+#define CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_KIOSK_MODE_INFO_H_
+
+#include <string>
+#include <vector>
+
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/manifest_handler.h"
+#include "extensions/common/manifest.h"
+
+namespace extensions {
+
+struct KioskModeInfo : public Extension::ManifestData {
+ public:
+ enum KioskStatus {
+ NONE,
+ ENABLED,
+ ONLY
+ };
+
+ explicit KioskModeInfo(KioskStatus kiosk_status);
+ virtual ~KioskModeInfo();
+
+ KioskStatus kiosk_status;
+
+ // Whether the extension or app is enabled for app kiosk mode.
+ static bool IsKioskEnabled(const Extension* extension);
+
+ // Whether the extension or app should only be available in kiosk mode.
+ static bool IsKioskOnly(const Extension* extension);
+};
+
+// Parses the "kiosk_enabled" and "kiosk_only" manifest keys.
+class KioskModeHandler : public ManifestHandler {
+ public:
+ KioskModeHandler();
+ virtual ~KioskModeHandler();
+
+ virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+
+ private:
+ virtual const std::vector<std::string> Keys() const OVERRIDE;
+
+ std::vector<std::string> supported_keys_;
+
+ DISALLOW_COPY_AND_ASSIGN(KioskModeHandler);
+};
+
+} // namespace extensions
+
+#endif // CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_KIOSK_MODE_INFO_H_
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_kiosk_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_kiosk_unittest.cc
index b63abee..fa00693 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_kiosk_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_kiosk_unittest.cc
@@ -3,55 +3,97 @@
// found in the LICENSE file.
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h"
+#include "chrome/common/extensions/manifest_handlers/kiosk_mode_info.h"
#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
#include "extensions/common/manifest_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
-class ExtensionManifestKioskEnabledTest : public ExtensionManifestTest {
+class ExtensionManifestKioskModeTest : public ExtensionManifestTest {
};
-TEST_F(ExtensionManifestKioskEnabledTest, InvalidKioskEnabled) {
+TEST_F(ExtensionManifestKioskModeTest, InvalidKioskEnabled) {
LoadAndExpectError("kiosk_enabled_invalid.json",
manifest_errors::kInvalidKioskEnabled);
}
-TEST_F(ExtensionManifestKioskEnabledTest, KioskEnabledHostedApp) {
+TEST_F(ExtensionManifestKioskModeTest, KioskEnabledHostedApp) {
scoped_refptr<Extension> extension(
LoadAndExpectSuccess("kiosk_enabled_hosted_app.json"));
- EXPECT_FALSE(KioskEnabledInfo::IsKioskEnabled(extension.get()));
+ EXPECT_FALSE(KioskModeInfo::IsKioskEnabled(extension.get()));
}
-TEST_F(ExtensionManifestKioskEnabledTest, KioskEnabledPackagedApp) {
+TEST_F(ExtensionManifestKioskModeTest, KioskEnabledPackagedApp) {
scoped_refptr<Extension> extension(
LoadAndExpectSuccess("kiosk_enabled_packaged_app.json"));
- EXPECT_FALSE(KioskEnabledInfo::IsKioskEnabled(extension.get()));
+ EXPECT_FALSE(KioskModeInfo::IsKioskEnabled(extension.get()));
}
-TEST_F(ExtensionManifestKioskEnabledTest, KioskEnabledExtension) {
+TEST_F(ExtensionManifestKioskModeTest, KioskEnabledExtension) {
scoped_refptr<Extension> extension(
LoadAndExpectSuccess("kiosk_enabled_extension.json"));
- EXPECT_FALSE(KioskEnabledInfo::IsKioskEnabled(extension.get()));
+ EXPECT_FALSE(KioskModeInfo::IsKioskEnabled(extension.get()));
}
-TEST_F(ExtensionManifestKioskEnabledTest, KioskEnabledPlatformApp) {
+TEST_F(ExtensionManifestKioskModeTest, KioskEnabledPlatformApp) {
scoped_refptr<Extension> extension(
LoadAndExpectSuccess("kiosk_enabled_platform_app.json"));
- EXPECT_TRUE(KioskEnabledInfo::IsKioskEnabled(extension.get()));
+ EXPECT_TRUE(KioskModeInfo::IsKioskEnabled(extension.get()));
}
-TEST_F(ExtensionManifestKioskEnabledTest, KioskDisabledPlatformApp) {
+TEST_F(ExtensionManifestKioskModeTest, KioskDisabledPlatformApp) {
scoped_refptr<Extension> extension(
LoadAndExpectSuccess("kiosk_disabled_platform_app.json"));
- EXPECT_FALSE(KioskEnabledInfo::IsKioskEnabled(extension.get()));
+ EXPECT_FALSE(KioskModeInfo::IsKioskEnabled(extension.get()));
}
-TEST_F(ExtensionManifestKioskEnabledTest, KioskDefaultPlatformApp) {
+TEST_F(ExtensionManifestKioskModeTest, KioskDefaultPlatformApp) {
scoped_refptr<Extension> extension(
LoadAndExpectSuccess("kiosk_default_platform_app.json"));
- EXPECT_FALSE(KioskEnabledInfo::IsKioskEnabled(extension.get()));
+ EXPECT_FALSE(KioskModeInfo::IsKioskEnabled(extension.get()));
+ EXPECT_FALSE(KioskModeInfo::IsKioskOnly(extension.get()));
+}
+
+TEST_F(ExtensionManifestKioskModeTest, KioskEnabledDefaultRequired) {
+ scoped_refptr<Extension> extension(
+ LoadAndExpectSuccess("kiosk_enabled_platform_app.json"));
+ EXPECT_TRUE(KioskModeInfo::IsKioskEnabled(extension.get()));
+ EXPECT_FALSE(KioskModeInfo::IsKioskOnly(extension.get()));
+}
+
+TEST_F(ExtensionManifestKioskModeTest, KioskOnlyPlatformApp) {
+ scoped_refptr<Extension> extension(
+ LoadAndExpectSuccess("kiosk_only_platform_app.json"));
+ EXPECT_TRUE(KioskModeInfo::IsKioskOnly(extension.get()));
+}
+
+TEST_F(ExtensionManifestKioskModeTest, KioskOnlyInvalid) {
+ LoadAndExpectError("kiosk_only_invalid.json",
+ manifest_errors::kInvalidKioskOnly);
+}
+
+TEST_F(ExtensionManifestKioskModeTest, KioskOnlyButNotEnabled) {
+ LoadAndExpectError("kiosk_only_not_enabled.json",
+ manifest_errors::kInvalidKioskOnlyButNotEnabled);
+}
+
+TEST_F(ExtensionManifestKioskModeTest, KioskOnlyHostedApp) {
+ scoped_refptr<Extension> extension(
+ LoadAndExpectSuccess("kiosk_only_hosted_app.json"));
+ EXPECT_FALSE(KioskModeInfo::IsKioskOnly(extension.get()));
+}
+
+TEST_F(ExtensionManifestKioskModeTest, KioskOnlyPackagedApp) {
+ scoped_refptr<Extension> extension(
+ LoadAndExpectSuccess("kiosk_only_packaged_app.json"));
+ EXPECT_FALSE(KioskModeInfo::IsKioskOnly(extension.get()));
+}
+
+TEST_F(ExtensionManifestKioskModeTest, KioskOnlyExtension) {
+ scoped_refptr<Extension> extension(
+ LoadAndExpectSuccess("kiosk_only_extension.json"));
+ EXPECT_FALSE(KioskModeInfo::IsKioskOnly(extension.get()));
}
} // namespace extensions
diff --git a/chrome/common/extensions/permissions/api_permission.h b/chrome/common/extensions/permissions/api_permission.h
index 311aa3f..2775d78 100644
--- a/chrome/common/extensions/permissions/api_permission.h
+++ b/chrome/common/extensions/permissions/api_permission.h
@@ -151,6 +151,7 @@
kWebRequest,
kWebRequestBlocking,
kWebRequestInternal,
+ kWebrtcLoggingPrivate,
kWebstorePrivate,
kWebView,
kSystemCpu,
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index f57c58e..308aaef 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -234,6 +234,8 @@
{ APIPermission::kEnterprisePlatformKeysPrivate,
"enterprise.platformKeysPrivate",
APIPermissionInfo::kFlagCannotBeOptional },
+ { APIPermission::kWebrtcLoggingPrivate, "webrtcLoggingPrivate",
+ APIPermissionInfo::kFlagCannotBeOptional },
// Full url access permissions.
{ APIPermission::kDebugger, "debugger",
diff --git a/chrome/common/extensions/permissions/permission_message.cc b/chrome/common/extensions/permissions/permission_message.cc
index b792ae9..006e91a 100644
--- a/chrome/common/extensions/permissions/permission_message.cc
+++ b/chrome/common/extensions/permissions/permission_message.cc
@@ -45,17 +45,27 @@
default:
message_id = kHosts4OrMore;
- message = l10n_util::GetStringFUTF16(
- IDS_EXTENSION_PROMPT_WARNING_HOSTS,
- base::IntToString16(host_list.size()));
+ const int kRetainedFilesMessageIDs[6] = {
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_DEFAULT,
+ IDS_EXTENSION_PROMPT_WARNING_HOST_SINGULAR,
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_ZERO,
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_TWO,
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_FEW,
+ IDS_EXTENSION_PROMPT_WARNING_HOSTS_MANY,
+ };
+ std::vector<int> message_ids;
+ for (size_t i = 0; i < arraysize(kRetainedFilesMessageIDs); i++) {
+ message_ids.push_back(kRetainedFilesMessageIDs[i]);
+ }
+ message = l10n_util::GetPluralStringFUTF16(message_ids, host_list.size());
- for (size_t i = 0; i < host_list.size(); ++i) {
- if (i > 0)
- details += ASCIIToUTF16("\n");
- details += l10n_util::GetStringFUTF16(
- IDS_EXTENSION_PROMPT_WARNING_HOST_LIST_ENTRY,
- UTF8ToUTF16(host_list[i]));
- }
+ for (size_t i = 0; i < host_list.size(); ++i) {
+ if (i > 0)
+ details += ASCIIToUTF16("\n");
+ details += l10n_util::GetStringFUTF16(
+ IDS_EXTENSION_PROMPT_WARNING_HOST_LIST_ENTRY,
+ UTF8ToUTF16(host_list[i]));
+ }
}
return PermissionMessage(message_id, message, details);
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index 9991ecc..cd4a2e1 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -729,6 +729,7 @@
skip.insert(APIPermission::kVirtualKeyboardPrivate);
skip.insert(APIPermission::kWallpaperPrivate);
skip.insert(APIPermission::kWebRequestInternal);
+ skip.insert(APIPermission::kWebrtcLoggingPrivate);
skip.insert(APIPermission::kWebstorePrivate);
// Warned as part of host permissions.
diff --git a/chrome/common/extensions/permissions/permissions_data_unittest.cc b/chrome/common/extensions/permissions/permissions_data_unittest.cc
index d1b70e9..1fc56c5 100644
--- a/chrome/common/extensions/permissions/permissions_data_unittest.cc
+++ b/chrome/common/extensions/permissions/permissions_data_unittest.cc
@@ -175,7 +175,7 @@
PermissionsData::GetPermissionMessageDetailsStrings(extension.get());
ASSERT_EQ(1u, warnings.size());
ASSERT_EQ(1u, warnings_details.size());
- EXPECT_EQ("Access your data on 5 website(s)", UTF16ToUTF8(warnings[0]));
+ EXPECT_EQ("Access your data on 5 websites", UTF16ToUTF8(warnings[0]));
EXPECT_EQ("- www.a.com\n- www.b.com\n- www.c.com\n- www.d.com\n- www.e.com",
UTF16ToUTF8(warnings_details[0]));
}
diff --git a/chrome/common/extensions/permissions/socket_permission.cc b/chrome/common/extensions/permissions/socket_permission.cc
index ebf7205..9f2c35c 100644
--- a/chrome/common/extensions/permissions/socket_permission.cc
+++ b/chrome/common/extensions/permissions/socket_permission.cc
@@ -37,8 +37,8 @@
bool SocketPermission::AddAnyHostMessage(PermissionMessages& messages) const {
std::set<SocketPermissionData>::const_iterator i;
for (i = data_set_.begin(); i != data_set_.end(); ++i) {
- if (i->IsAddressBoundType() &&
- i->GetHostType() == SocketPermissionData::ANY_HOST) {
+ if (i->entry().IsAddressBoundType() &&
+ i->entry().GetHostType() == SocketPermissionEntry::ANY_HOST) {
messages.push_back(PermissionMessage(
PermissionMessage::kSocketAnyHost,
l10n_util::GetStringUTF16(
@@ -54,8 +54,8 @@
std::set<string16> domains;
std::set<SocketPermissionData>::const_iterator i;
for (i = data_set_.begin(); i != data_set_.end(); ++i) {
- if (i->GetHostType() == SocketPermissionData::HOSTS_IN_DOMAINS)
- domains.insert(UTF8ToUTF16(i->GetHost()));
+ if (i->entry().GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
+ domains.insert(UTF8ToUTF16(i->entry().pattern().host));
}
if (!domains.empty()) {
int id = (domains.size() == 1) ?
@@ -76,8 +76,8 @@
std::set<string16> hostnames;
std::set<SocketPermissionData>::const_iterator i;
for (i = data_set_.begin(); i != data_set_.end(); ++i) {
- if (i->GetHostType() == SocketPermissionData::SPECIFIC_HOSTS)
- hostnames.insert(UTF8ToUTF16(i->GetHost()));
+ if (i->entry().GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
+ hostnames.insert(UTF8ToUTF16(i->entry().pattern().host));
}
if (!hostnames.empty()) {
int id = (hostnames.size() == 1) ?
@@ -97,7 +97,8 @@
PermissionMessages& messages) const {
std::set<SocketPermissionData>::const_iterator i;
for (i = data_set_.begin(); i != data_set_.end(); ++i) {
- if (i->pattern().type == content::SocketPermissionRequest::NETWORK_STATE) {
+ if (i->entry().pattern().type ==
+ content::SocketPermissionRequest::NETWORK_STATE) {
messages.push_back(PermissionMessage(
PermissionMessage::kNetworkState,
l10n_util::GetStringUTF16(
diff --git a/chrome/common/extensions/permissions/socket_permission_data.cc b/chrome/common/extensions/permissions/socket_permission_data.cc
index fc7908e..e87fd84 100644
--- a/chrome/common/extensions/permissions/socket_permission_data.cc
+++ b/chrome/common/extensions/permissions/socket_permission_data.cc
@@ -23,8 +23,6 @@
using extensions::SocketPermissionData;
const char kColon = ':';
-const char kDot = '.';
-const char kWildcard[] = "*";
const char kInvalid[] = "invalid";
const char kTCPConnect[] = "tcp-connect";
const char kTCPListen[] = "tcp-listen";
@@ -34,8 +32,6 @@
const char kResolveHost[] = "resolve-host";
const char kResolveProxy[] = "resolve-proxy";
const char kNetworkState[] = "network-state";
-const int kWildcardPortNumber = 0;
-const int kInvalidPort = -1;
SocketPermissionRequest::OperationType StringToType(const std::string& s) {
if (s == kTCPConnect)
@@ -80,52 +76,20 @@
}
}
-bool StartsOrEndsWithWhitespace(const std::string& str) {
- if (str.find_first_not_of(kWhitespaceASCII) != 0)
- return true;
- if (str.find_last_not_of(kWhitespaceASCII) != str.length() - 1)
- return true;
- return false;
-}
-
} // namespace
namespace extensions {
-SocketPermissionData::SocketPermissionData()
- : pattern_(SocketPermissionRequest::NONE, std::string(), kInvalidPort) {
- Reset();
-}
+SocketPermissionData::SocketPermissionData() { }
-SocketPermissionData::~SocketPermissionData() {
-}
+SocketPermissionData::~SocketPermissionData() { }
bool SocketPermissionData::operator<(const SocketPermissionData& rhs) const {
- if (pattern_.type < rhs.pattern_.type)
- return true;
- if (pattern_.type > rhs.pattern_.type)
- return false;
-
- if (pattern_.host < rhs.pattern_.host)
- return true;
- if (pattern_.host > rhs.pattern_.host)
- return false;
-
- if (match_subdomains_ < rhs.match_subdomains_)
- return true;
- if (match_subdomains_ > rhs.match_subdomains_)
- return false;
-
- if (pattern_.port < rhs.pattern_.port)
- return true;
- return false;
+ return entry_ < rhs.entry_;
}
bool SocketPermissionData::operator==(const SocketPermissionData& rhs) const {
- return (pattern_.type == rhs.pattern_.type) &&
- (pattern_.host == rhs.pattern_.host) &&
- (match_subdomains_ == rhs.match_subdomains_) &&
- (pattern_.port == rhs.pattern_.port);
+ return entry_ == rhs.entry_;
}
bool SocketPermissionData::Check(
@@ -136,41 +100,7 @@
*static_cast<const SocketPermission::CheckParam*>(param);
const SocketPermissionRequest &request = specific_param.request;
- if (pattern_.type != request.type)
- return false;
-
- std::string lhost = StringToLowerASCII(request.host);
- if (pattern_.host != lhost) {
- if (!match_subdomains_)
- return false;
-
- if (!pattern_.host.empty()) {
- // Do not wildcard part of IP address.
- url_parse::Component component(0, lhost.length());
- url_canon::RawCanonOutputT<char, 128> ignored_output;
- url_canon::CanonHostInfo host_info;
- url_canon::CanonicalizeIPAddress(lhost.c_str(), component,
- &ignored_output, &host_info);
- if (host_info.IsIPAddress())
- return false;
-
- // host should equal one or more chars + "." + host_.
- int i = lhost.length() - pattern_.host.length();
- if (i < 2)
- return false;
-
- if (lhost.compare(i, pattern_.host.length(), pattern_.host) != 0)
- return false;
-
- if (lhost[i - 1] != kDot)
- return false;
- }
- }
-
- if (pattern_.port != request.port && pattern_.port != kWildcardPortNumber)
- return false;
-
- return true;
+ return entry_.Check(request);
}
scoped_ptr<base::Value> SocketPermissionData::ToValue() const {
@@ -185,95 +115,27 @@
return Parse(spec);
}
-bool SocketPermissionData::IsAddressBoundType() const {
- return pattern_.type == SocketPermissionRequest::TCP_CONNECT ||
- pattern_.type == SocketPermissionRequest::TCP_LISTEN ||
- pattern_.type == SocketPermissionRequest::UDP_BIND ||
- pattern_.type == SocketPermissionRequest::UDP_SEND_TO;
-}
-
-SocketPermissionData::HostType SocketPermissionData::GetHostType() const {
- return pattern_.host.empty() ? SocketPermissionData::ANY_HOST :
- match_subdomains_ ? SocketPermissionData::HOSTS_IN_DOMAINS :
- SocketPermissionData::SPECIFIC_HOSTS;
-}
-
-const std::string SocketPermissionData::GetHost() const {
- return pattern_.host;
-}
-
-content::SocketPermissionRequest& SocketPermissionData::pattern() {
- // Clear the spec because the caller could mutate |this|.
- spec_.clear();
- return pattern_;
-}
-
-bool& SocketPermissionData::match_subdomains() {
- // Clear the spec because the caller could mutate |this|.
- spec_.clear();
- return match_subdomains_;
+SocketPermissionEntry& SocketPermissionData::entry() {
+ // Clear the spec because the caller could mutate |this|.
+ spec_.clear();
+ return entry_;
}
// TODO(ikarienator): Rewrite this method to support IPv6.
bool SocketPermissionData::Parse(const std::string& permission) {
- do {
- pattern_.host.clear();
- match_subdomains_ = true;
- pattern_.port = kWildcardPortNumber;
- spec_.clear();
-
- std::vector<std::string> tokens;
- base::SplitStringDontTrim(permission, kColon, &tokens);
-
- if (tokens.empty() || tokens.size() > 3)
- break;
-
- pattern_.type = StringToType(tokens[0]);
- if (pattern_.type == SocketPermissionRequest::NONE)
- break;
-
- if (tokens.size() == 1)
- return true;
-
- // Return an error if address is specified for permissions that don't
- // need it (such as 'resolve-host').
- if (!IsAddressBoundType())
- break;
-
- pattern_.host = tokens[1];
- if (!pattern_.host.empty()) {
- if (StartsOrEndsWithWhitespace(pattern_.host))
- break;
- pattern_.host = StringToLowerASCII(pattern_.host);
-
- // The first component can optionally be '*' to match all subdomains.
- std::vector<std::string> host_components;
- base::SplitString(pattern_.host, kDot, &host_components);
- DCHECK(!host_components.empty());
-
- if (host_components[0] == kWildcard || host_components[0].empty()) {
- host_components.erase(host_components.begin(),
- host_components.begin() + 1);
- } else {
- match_subdomains_ = false;
- }
- pattern_.host = JoinString(host_components, kDot);
- }
-
- if (tokens.size() == 2 || tokens[2].empty() || tokens[2] == kWildcard)
- return true;
-
- if (StartsOrEndsWithWhitespace(tokens[2]))
- break;
-
- if (!base::StringToInt(tokens[2], &pattern_.port) ||
- pattern_.port < 1 || pattern_.port > 65535)
- break;
- return true;
- } while (false);
-
Reset();
- return false;
+
+ std::vector<std::string> tokens;
+ base::SplitStringDontTrim(permission, kColon, &tokens);
+ if (tokens.empty())
+ return false;
+
+ SocketPermissionRequest::OperationType type = StringToType(tokens[0]);
+ if (type == SocketPermissionRequest::NONE)
+ return false;
+
+ tokens.erase(tokens.begin());
+ return SocketPermissionEntry::ParseHostPattern(type, tokens, &entry_);
}
const std::string& SocketPermissionData::GetAsString() const {
@@ -281,32 +143,16 @@
return spec_;
spec_.reserve(64);
- spec_.append(TypeToString(pattern_.type));
-
- if (!IsAddressBoundType())
- return spec_;
-
- if (match_subdomains_) {
- spec_.append(1, kColon).append(kWildcard);
- if (!pattern_.host.empty())
- spec_.append(1, kDot).append(pattern_.host);
- } else {
- spec_.append(1, kColon).append(pattern_.host);
+ spec_.append(TypeToString(entry_.pattern().type));
+ std::string pattern = entry_.GetHostPatternAsString();
+ if (!pattern.empty()) {
+ spec_.append(1, kColon).append(pattern);
}
-
- if (pattern_.port == kWildcardPortNumber)
- spec_.append(1, kColon).append(kWildcard);
- else
- spec_.append(1, kColon).append(base::IntToString(pattern_.port));
-
return spec_;
}
void SocketPermissionData::Reset() {
- pattern_.type = SocketPermissionRequest::NONE;
- pattern_.host.clear();
- match_subdomains_ = false;
- pattern_.port = kInvalidPort;
+ entry_ = SocketPermissionEntry();
spec_.clear();
}
diff --git a/chrome/common/extensions/permissions/socket_permission_data.h b/chrome/common/extensions/permissions/socket_permission_data.h
index 1a23cc2..d647568 100644
--- a/chrome/common/extensions/permissions/socket_permission_data.h
+++ b/chrome/common/extensions/permissions/socket_permission_data.h
@@ -6,9 +6,11 @@
#include <string>
-#include "base/memory/scoped_ptr.h"
#include "chrome/common/extensions/permissions/api_permission.h"
-#include "content/public/common/socket_permission_request.h"
+#include "chrome/common/extensions/permissions/socket_permission_entry.h"
+#include "ipc/ipc_param_traits.h"
+
+template <class T> struct FuzzTraits;
namespace extensions {
@@ -35,12 +37,6 @@
// The multicast membership permission implies a permission to any address.
class SocketPermissionData {
public:
- enum HostType {
- ANY_HOST,
- HOSTS_IN_DOMAINS,
- SPECIFIC_HOSTS,
- };
-
SocketPermissionData();
~SocketPermissionData();
@@ -59,33 +55,26 @@
// Populate |this| from a base::Value.
bool FromValue(const base::Value* value);
- // Returns true if the permission type can be bound to a host or port.
- bool IsAddressBoundType() const;
-
- HostType GetHostType() const;
- const std::string GetHost() const;
-
- const content::SocketPermissionRequest& pattern() const { return pattern_; }
- const bool& match_subdomains() const { return match_subdomains_; }
-
- // These accessors are provided for IPC_STRUCT_TRAITS_MEMBER. Please
- // think twice before using them for anything else.
- content::SocketPermissionRequest& pattern();
- bool& match_subdomains();
-
// TODO(bryeung): SocketPermissionData should be encoded as a base::Value
// instead of a string. Until that is done, expose these methods for
// testing.
bool ParseForTest(const std::string& permission) { return Parse(permission); }
const std::string& GetAsStringForTest() const { return GetAsString(); }
+ const SocketPermissionEntry& entry() const { return entry_; }
+
private:
+ // Friend so ParamTraits can serialize us.
+ friend struct IPC::ParamTraits<SocketPermissionData>;
+ friend struct FuzzTraits<SocketPermissionData>;
+
+ SocketPermissionEntry& entry();
+
bool Parse(const std::string& permission);
const std::string& GetAsString() const;
void Reset();
- content::SocketPermissionRequest pattern_;
- bool match_subdomains_;
+ SocketPermissionEntry entry_;
mutable std::string spec_;
};
diff --git a/chrome/common/extensions/permissions/socket_permission_entry.cc b/chrome/common/extensions/permissions/socket_permission_entry.cc
new file mode 100644
index 0000000..17f2ef7
--- /dev/null
+++ b/chrome/common/extensions/permissions/socket_permission_entry.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/common/extensions/permissions/socket_permission_entry.h"
+
+#include <cstdlib>
+#include <sstream>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "chrome/common/extensions/permissions/api_permission.h"
+#include "chrome/common/extensions/permissions/socket_permission.h"
+#include "url/url_canon.h"
+
+namespace {
+
+using content::SocketPermissionRequest;
+
+const char kColon = ':';
+const char kDot = '.';
+const char kWildcard[] = "*";
+const int kWildcardPortNumber = 0;
+const int kInvalidPort = -1;
+
+bool StartsOrEndsWithWhitespace(const std::string& str) {
+ if (str.find_first_not_of(kWhitespaceASCII) != 0)
+ return true;
+ if (str.find_last_not_of(kWhitespaceASCII) != str.length() - 1)
+ return true;
+ return false;
+}
+
+} // namespace
+
+namespace extensions {
+
+SocketPermissionEntry::SocketPermissionEntry()
+ : pattern_(SocketPermissionRequest::NONE, std::string(), kInvalidPort),
+ match_subdomains_(false) {
+}
+
+SocketPermissionEntry::~SocketPermissionEntry() {}
+
+bool SocketPermissionEntry::operator<(const SocketPermissionEntry& rhs) const {
+ if (pattern_.type < rhs.pattern_.type)
+ return true;
+ if (pattern_.type > rhs.pattern_.type)
+ return false;
+
+ if (pattern_.host < rhs.pattern_.host)
+ return true;
+ if (pattern_.host > rhs.pattern_.host)
+ return false;
+
+ if (match_subdomains_ < rhs.match_subdomains_)
+ return true;
+ if (match_subdomains_ > rhs.match_subdomains_)
+ return false;
+
+ if (pattern_.port < rhs.pattern_.port)
+ return true;
+ return false;
+}
+
+bool SocketPermissionEntry::operator==(const SocketPermissionEntry& rhs) const {
+ return (pattern_.type == rhs.pattern_.type) &&
+ (pattern_.host == rhs.pattern_.host) &&
+ (match_subdomains_ == rhs.match_subdomains_) &&
+ (pattern_.port == rhs.pattern_.port);
+}
+
+bool SocketPermissionEntry::Check(
+ const content::SocketPermissionRequest& request) const {
+ if (pattern_.type != request.type)
+ return false;
+
+ std::string lhost = StringToLowerASCII(request.host);
+ if (pattern_.host != lhost) {
+ if (!match_subdomains_)
+ return false;
+
+ if (!pattern_.host.empty()) {
+ // Do not wildcard part of IP address.
+ url_parse::Component component(0, lhost.length());
+ url_canon::RawCanonOutputT<char, 128> ignored_output;
+ url_canon::CanonHostInfo host_info;
+ url_canon::CanonicalizeIPAddress(lhost.c_str(), component,
+ &ignored_output, &host_info);
+ if (host_info.IsIPAddress())
+ return false;
+
+ // host should equal one or more chars + "." + host_.
+ int i = lhost.length() - pattern_.host.length();
+ if (i < 2)
+ return false;
+
+ if (lhost.compare(i, pattern_.host.length(), pattern_.host) != 0)
+ return false;
+
+ if (lhost[i - 1] != kDot)
+ return false;
+ }
+ }
+
+ if (pattern_.port != request.port && pattern_.port != kWildcardPortNumber)
+ return false;
+
+ return true;
+}
+
+SocketPermissionEntry::HostType SocketPermissionEntry::GetHostType() const {
+ return pattern_.host.empty() ? SocketPermissionEntry::ANY_HOST :
+ match_subdomains_ ? SocketPermissionEntry::HOSTS_IN_DOMAINS :
+ SocketPermissionEntry::SPECIFIC_HOSTS;
+}
+
+bool SocketPermissionEntry::IsAddressBoundType() const {
+ return pattern_.type == SocketPermissionRequest::TCP_CONNECT ||
+ pattern_.type == SocketPermissionRequest::TCP_LISTEN ||
+ pattern_.type == SocketPermissionRequest::UDP_BIND ||
+ pattern_.type == SocketPermissionRequest::UDP_SEND_TO;
+}
+
+// static
+bool SocketPermissionEntry::ParseHostPattern(
+ SocketPermissionRequest::OperationType type,
+ const std::string& pattern,
+ SocketPermissionEntry* entry) {
+ std::vector<std::string> tokens;
+ base::SplitStringDontTrim(pattern, kColon, &tokens);
+ return ParseHostPattern(type, tokens, entry);
+}
+
+// static
+bool SocketPermissionEntry::ParseHostPattern(
+ SocketPermissionRequest::OperationType type,
+ const std::vector<std::string>& pattern_tokens,
+ SocketPermissionEntry* entry) {
+
+ SocketPermissionEntry result;
+
+ if (type == SocketPermissionRequest::NONE)
+ return false;
+
+ if (pattern_tokens.size() > 2)
+ return false;
+
+ result.pattern_.type = type;
+ result.pattern_.port = kWildcardPortNumber;
+ result.match_subdomains_ = true;
+
+ if (pattern_tokens.size() == 0) {
+ *entry = result;
+ return true;
+ }
+
+ // Return an error if address is specified for permissions that don't
+ // need it (such as 'resolve-host').
+ if (!result.IsAddressBoundType())
+ return false;
+
+ result.pattern_.host = pattern_tokens[0];
+ if (!result.pattern_.host.empty()) {
+ if (StartsOrEndsWithWhitespace(result.pattern_.host))
+ return false;
+ result.pattern_.host = StringToLowerASCII(result.pattern_.host);
+
+ // The first component can optionally be '*' to match all subdomains.
+ std::vector<std::string> host_components;
+ base::SplitString(result.pattern_.host, kDot, &host_components);
+ DCHECK(!host_components.empty());
+
+ if (host_components[0] == kWildcard || host_components[0].empty()) {
+ host_components.erase(host_components.begin(),
+ host_components.begin() + 1);
+ } else {
+ result.match_subdomains_ = false;
+ }
+ result.pattern_.host = JoinString(host_components, kDot);
+ }
+
+ if (pattern_tokens.size() == 1 ||
+ pattern_tokens[1].empty() ||
+ pattern_tokens[1] == kWildcard) {
+ *entry = result;
+ return true;
+ }
+
+ if (StartsOrEndsWithWhitespace(pattern_tokens[1]))
+ return false;
+
+ if (!base::StringToInt(pattern_tokens[1], &result.pattern_.port) ||
+ result.pattern_.port < 1 || result.pattern_.port > 65535)
+ return false;
+
+ *entry = result;
+ return true;
+}
+
+std::string SocketPermissionEntry::GetHostPatternAsString() const {
+ std::string result;
+
+ if (!IsAddressBoundType())
+ return result;
+
+ if (match_subdomains()) {
+ result.append(kWildcard);
+ if (!pattern_.host.empty())
+ result.append(1, kDot).append(pattern_.host);
+ } else {
+ result.append(pattern_.host);
+ }
+
+ if (pattern_.port == kWildcardPortNumber)
+ result.append(1, kColon).append(kWildcard);
+ else
+ result.append(1, kColon).append(base::IntToString(pattern_.port));
+
+ return result;
+}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/permissions/socket_permission_entry.h b/chrome/common/extensions/permissions/socket_permission_entry.h
new file mode 100644
index 0000000..b656471
--- /dev/null
+++ b/chrome/common/extensions/permissions/socket_permission_entry.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_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
+#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
+
+#include <string>
+#include <vector>
+
+#include "content/public/common/socket_permission_request.h"
+#include "ipc/ipc_param_traits.h"
+
+template <class T> struct FuzzTraits;
+
+namespace extensions {
+
+// Internal representation of a socket permission for a specific operation, such
+// as UDP "bind", host 127.0.0.1, port *.
+class SocketPermissionEntry {
+ public:
+ enum HostType {
+ ANY_HOST,
+ HOSTS_IN_DOMAINS,
+ SPECIFIC_HOSTS,
+ };
+
+ SocketPermissionEntry();
+ ~SocketPermissionEntry();
+
+ // operators <, == are needed by container std::set and algorithms
+ // std::set_includes and std::set_differences.
+ bool operator<(const SocketPermissionEntry& rhs) const;
+ bool operator==(const SocketPermissionEntry& rhs) const;
+
+ bool Check(const content::SocketPermissionRequest& request) const;
+
+ // Parse a host:port pattern for a given operation type.
+ // <pattern> := '' |
+ // <host> |
+ // ':' <port> |
+ // <host> ':' <port> |
+ //
+ // <host> := '*' |
+ // '*.' <anychar except '/' and '*'>+ |
+ // <anychar except '/' and '*'>+
+ //
+ // <port> := '*' |
+ // <port number between 0 and 65535>)
+ static bool ParseHostPattern(
+ content::SocketPermissionRequest::OperationType type,
+ const std::string& pattern,
+ SocketPermissionEntry* entry);
+
+ static bool ParseHostPattern(
+ content::SocketPermissionRequest::OperationType type,
+ const std::vector<std::string>& pattern_tokens,
+ SocketPermissionEntry* entry);
+
+ // Returns true if the permission type can be bound to a host or port.
+ bool IsAddressBoundType() const;
+
+ std::string GetHostPatternAsString() const;
+ HostType GetHostType() const;
+
+ const content::SocketPermissionRequest& pattern() const { return pattern_; }
+ bool match_subdomains() const { return match_subdomains_; }
+
+ private:
+ // Friend so ParamTraits can serialize us.
+ friend struct IPC::ParamTraits<SocketPermissionEntry>;
+ friend struct FuzzTraits<SocketPermissionEntry>;
+
+ // The permission type, host and port.
+ content::SocketPermissionRequest pattern_;
+
+ // True if there was a wildcard in the host name.
+ bool match_subdomains_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
diff --git a/chrome/common/external_ipc_fuzzer.cc b/chrome/common/external_ipc_fuzzer.cc
index 9e125cc..10416c4 100644
--- a/chrome/common/external_ipc_fuzzer.cc
+++ b/chrome/common/external_ipc_fuzzer.cc
@@ -6,17 +6,16 @@
#if defined(OS_LINUX)
#include <dlfcn.h>
-#endif
typedef IPC::ChannelProxy::OutgoingMessageFilter *(*GetFuzzerFunction)();
const char kFuzzLibraryName[] = "libipcfuzz.so";
const char kFuzzEntryName[] = "GetFilter";
+#endif
IPC::ChannelProxy::OutgoingMessageFilter* LoadExternalIPCFuzzer() {
IPC::ChannelProxy::OutgoingMessageFilter* result = NULL;
#if defined(OS_LINUX)
-
// Fuzz is currently linux-only feature
void *fuzz_library = dlopen(kFuzzLibraryName, RTLD_NOW);
if (fuzz_library) {
diff --git a/chrome/common/icon_with_badge_image_source.cc b/chrome/common/icon_with_badge_image_source.cc
index 1665030..007292c 100644
--- a/chrome/common/icon_with_badge_image_source.cc
+++ b/chrome/common/icon_with_badge_image_source.cc
@@ -5,6 +5,7 @@
#include "chrome/common/icon_with_badge_image_source.h"
#include "chrome/common/badge_util.h"
+//#include "ui/base/layout.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/rect.h"
diff --git a/chrome/common/importer/OWNERS b/chrome/common/importer/OWNERS
index 66d2678..6238904 100644
--- a/chrome/common/importer/OWNERS
+++ b/chrome/common/importer/OWNERS
@@ -8,5 +8,4 @@
per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
diff --git a/chrome/common/local_discovery/local_discovery_messages.h b/chrome/common/local_discovery/local_discovery_messages.h
index a5ebccc..1add9a2 100644
--- a/chrome/common/local_discovery/local_discovery_messages.h
+++ b/chrome/common/local_discovery/local_discovery_messages.h
@@ -73,6 +73,9 @@
// Utility process host messages:
// These are messages from the utility process to the browser.
+// Notifies browser process if process failed.
+IPC_MESSAGE_CONTROL0(LocalDiscoveryHostMsg_Error)
+
// Notifies browser process about new services.
IPC_MESSAGE_CONTROL3(LocalDiscoveryHostMsg_WatcherCallback,
uint64 /* id */,
diff --git a/chrome/common/localized_error.cc b/chrome/common/localized_error.cc
index 893e379..c9d774c 100644
--- a/chrome/common/localized_error.cc
+++ b/chrome/common/localized_error.cc
@@ -491,7 +491,9 @@
const char LocalizedError::kHttpErrorDomain[] = "http";
-void LocalizedError::GetStrings(const WebKit::WebURLError& error,
+void LocalizedError::GetStrings(int error_code,
+ const std::string& error_domain,
+ const GURL& failed_url,
bool is_post,
const std::string& locale,
base::DictionaryValue* error_strings) {
@@ -509,15 +511,11 @@
SUGGEST_NONE,
};
- const std::string error_domain = error.domain.utf8();
- int error_code = error.reason;
const LocalizedErrorMap* error_map = LookupErrorMap(error_domain, error_code,
is_post);
if (error_map)
options = *error_map;
- const GURL failed_url = error.unreachableURL;
-
// If we got "access denied" but the url was a file URL, then we say it was a
// file instead of just using the "not available" default message. Just adding
// ERR_ACCESS_DENIED to the map isn't sufficient, since that message may be
@@ -788,7 +786,6 @@
}
void LocalizedError::GetAppErrorStrings(
- const WebURLError& error,
const GURL& display_url,
const extensions::Extension* app,
base::DictionaryValue* error_strings) {
diff --git a/chrome/common/localized_error.h b/chrome/common/localized_error.h
index 3fb8b28..7323c59 100644
--- a/chrome/common/localized_error.h
+++ b/chrome/common/localized_error.h
@@ -28,7 +28,9 @@
public:
// Fills |error_strings| with values to be used to build an error page used
// on HTTP errors, like 404 or connection reset.
- static void GetStrings(const WebKit::WebURLError& error,
+ static void GetStrings(int error_code,
+ const std::string& error_domain,
+ const GURL& failed_url,
bool is_post,
const std::string& locale,
base::DictionaryValue* strings);
@@ -44,8 +46,7 @@
// on HTTP errors, like 404 or connection reset, but using information from
// the associated |app| in order to make the error page look like it's more
// part of the app.
- static void GetAppErrorStrings(const WebKit::WebURLError& error,
- const GURL& display_url,
+ static void GetAppErrorStrings(const GURL& display_url,
const extensions::Extension* app,
base::DictionaryValue* error_strings);
diff --git a/chrome/common/metrics/variations/variations_util.cc b/chrome/common/metrics/variations/variations_util.cc
index 5ef0bf8..0ae01e1 100644
--- a/chrome/common/metrics/variations/variations_util.cc
+++ b/chrome/common/metrics/variations/variations_util.cc
@@ -13,6 +13,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/child_process_logging.h"
+#include "chrome/common/crash_keys.h"
#include "chrome/installer/util/google_update_experiment_util.h"
namespace chrome_variations {
@@ -68,39 +69,20 @@
}
void GetFieldTrialActiveGroupIdsAsStrings(
- std::vector<string16>* output) {
+ std::vector<std::string>* output) {
DCHECK(output->empty());
std::vector<ActiveGroupId> name_group_ids;
GetFieldTrialActiveGroupIds(&name_group_ids);
for (size_t i = 0; i < name_group_ids.size(); ++i) {
- output->push_back(UTF8ToUTF16(base::StringPrintf(
- "%x-%x", name_group_ids[i].name, name_group_ids[i].group)));
+ output->push_back(base::StringPrintf(
+ "%x-%x", name_group_ids[i].name, name_group_ids[i].group));
}
}
-void GenerateVariationChunks(const std::vector<string16>& experiments,
- std::vector<string16>* chunks) {
- string16 current_chunk;
- for (size_t i = 0; i < experiments.size(); ++i) {
- const size_t needed_length =
- (current_chunk.empty() ? 1 : 0) + experiments[i].length();
- if (current_chunk.length() + needed_length > kMaxVariationChunkSize) {
- chunks->push_back(current_chunk);
- current_chunk = experiments[i];
- } else {
- if (!current_chunk.empty())
- current_chunk.push_back(',');
- current_chunk += experiments[i];
- }
- }
- if (!current_chunk.empty())
- chunks->push_back(current_chunk);
-}
-
void SetChildProcessLoggingVariationList() {
- std::vector<string16> experiment_strings;
+ std::vector<std::string> experiment_strings;
GetFieldTrialActiveGroupIdsAsStrings(&experiment_strings);
- child_process_logging::SetExperimentList(experiment_strings);
+ crash_keys::SetVariationsList(experiment_strings);
}
string16 BuildGoogleUpdateExperimentLabel(
diff --git a/chrome/common/metrics/variations/variations_util.h b/chrome/common/metrics/variations/variations_util.h
index cd0c787..d32cae7 100644
--- a/chrome/common/metrics/variations/variations_util.h
+++ b/chrome/common/metrics/variations/variations_util.h
@@ -5,6 +5,7 @@
#ifndef CHROME_COMMON_METRICS_VARIATIONS_VARIATIONS_UTIL_H_
#define CHROME_COMMON_METRICS_VARIATIONS_VARIATIONS_UTIL_H_
+#include <string>
#include <vector>
#include "base/metrics/field_trial.h"
@@ -24,12 +25,7 @@
// has a chosen group. The strings are formatted as "<TrialName>-<GroupName>",
// with the names as hex strings. Field Trials for which a group has not been
// chosen yet are NOT returned in this list.
-void GetFieldTrialActiveGroupIdsAsStrings(std::vector<string16>* output);
-
-// Generates variation chunks from |variation_strings| that are suitable for
-// crash reporting.
-void GenerateVariationChunks(const std::vector<string16>& variation_strings,
- std::vector<string16>* chunks);
+void GetFieldTrialActiveGroupIdsAsStrings(std::vector<std::string>* output);
// Get the current set of chosen FieldTrial groups (aka variations) and send
// them to the child process logging module so it can save it for crash dumps.
diff --git a/chrome/common/metrics/variations/variations_util_unittest.cc b/chrome/common/metrics/variations/variations_util_unittest.cc
index 1f9e140..e14d53a 100644
--- a/chrome/common/metrics/variations/variations_util_unittest.cc
+++ b/chrome/common/metrics/variations/variations_util_unittest.cc
@@ -104,60 +104,6 @@
EXPECT_EQ(0U, expected_groups.size());
}
-TEST_F(VariationsUtilTest, GenerateExperimentChunks) {
- const char* kExperimentStrings[] = {
- "1d3048f1-9de009d0",
- "cd73da34-cf196cb",
- "6214fa18-9e6dc24d",
- "4dcb0cd6-d31c4ca1",
- "9d5bce6-30d7d8ac",
- };
- const char* kExpectedChunks1[] = {
- "1d3048f1-9de009d0",
- };
- const char* kExpectedChunks2[] = {
- "1d3048f1-9de009d0,cd73da34-cf196cb",
- };
- const char* kExpectedChunks3[] = {
- "1d3048f1-9de009d0,cd73da34-cf196cb,6214fa18-9e6dc24d",
- };
- const char* kExpectedChunks4[] = {
- "1d3048f1-9de009d0,cd73da34-cf196cb,6214fa18-9e6dc24d",
- "4dcb0cd6-d31c4ca1",
- };
- const char* kExpectedChunks5[] = {
- "1d3048f1-9de009d0,cd73da34-cf196cb,6214fa18-9e6dc24d",
- "4dcb0cd6-d31c4ca1,9d5bce6-30d7d8ac",
- };
-
- struct {
- size_t strings_length;
- size_t expected_chunks_length;
- const char** expected_chunks;
- } cases[] = {
- { 0, 0, NULL },
- { 1, arraysize(kExpectedChunks1), kExpectedChunks1 },
- { 2, arraysize(kExpectedChunks2), kExpectedChunks2 },
- { 3, arraysize(kExpectedChunks3), kExpectedChunks3 },
- { 4, arraysize(kExpectedChunks4), kExpectedChunks4 },
- { 5, arraysize(kExpectedChunks5), kExpectedChunks5 },
- };
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
- ASSERT_LE(cases[i].strings_length, arraysize(kExperimentStrings));
-
- std::vector<string16> experiments;
- for (size_t j = 0; j < cases[i].strings_length; ++j)
- experiments.push_back(UTF8ToUTF16(kExperimentStrings[j]));
-
- std::vector<string16> chunks;
- GenerateVariationChunks(experiments, &chunks);
- ASSERT_EQ(cases[i].expected_chunks_length, chunks.size());
- for (size_t j = 0; j < chunks.size(); ++j)
- EXPECT_EQ(UTF8ToUTF16(cases[i].expected_chunks[j]), chunks[j]);
- }
-}
-
TEST_F(VariationsUtilTest, BuildGoogleUpdateExperimentLabel) {
struct {
const char* active_group_pairs;
diff --git a/chrome/common/omaha_query_params/omaha_query_params.cc b/chrome/common/omaha_query_params/omaha_query_params.cc
index f320310..f68c9be 100644
--- a/chrome/common/omaha_query_params/omaha_query_params.cc
+++ b/chrome/common/omaha_query_params/omaha_query_params.cc
@@ -46,14 +46,18 @@
#endif
const char kChrome[] = "chrome";
-const char kChromeCrx[] = "chromecrx";
-const char kChromiumCrx[] = "chromiumcrx";
const char kStable[] = "stable";
const char kBeta[] = "beta";
const char kDev[] = "dev";
const char kCanary[] = "canary";
+#if defined(GOOGLE_CHROME_BUILD)
+const char kChromeCrx[] = "chromecrx";
+#else
+const char kChromiumCrx[] = "chromiumcrx";
+#endif // defined(GOOGLE_CHROME_BUILD)
+
} // namespace
namespace chrome {
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index d7e195b..1ff7bde 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -844,6 +844,16 @@
// A boolean pref that tracks whether the user indicated they wish to be asked
// for consent for every site that uses remote attestation.
const char kRAConsentAlways[] = "settings.privacy.ra_consent_always";
+
+// A boolean pref recording whether user has dismissed the multiprofile
+// notification.
+const char kMultiProfileNotificationDismissed[] =
+ "settings.multi_profile_notification_dismissed";
+
+// A string pref that holds string enum values of how the user should behave
+// in a multiprofile session. See ChromeOsMultiProfileUserBehavior policy
+// for more details of the valid values.
+const char kMultiProfileUserBehavior[] = "settings.multiprofile_user_behavior";
#endif // defined(OS_CHROMEOS)
// The disabled messages in IPC logging.
@@ -1233,6 +1243,11 @@
// platforms.
extern const char kFullscreenAllowed[] = "fullscreen.allowed";
+// Enable notifications for new devices on the local network that can be
+// registered to the user's account, e.g. Google Cloud Print printers.
+const char kLocalDiscoveryNotificationsEnabled[] =
+ "local_discovery.notifications_enabled";
+
// *************** LOCAL STATE ***************
// These are attached to the machine/installation
@@ -1688,33 +1703,6 @@
// Boolean indicating whether the web store is active for the current locale.
const char kNtpWebStoreEnabled[] = "ntp.webstore_enabled";
-// The id of the last web store promo actually displayed on the NTP.
-const char kNtpWebStorePromoLastId[] = "ntp.webstore_last_promo_id";
-
-// The id of the current web store promo.
-const char kNtpWebStorePromoId[] = "ntp.webstorepromo.id";
-
-// The header line for the NTP web store promo.
-const char kNtpWebStorePromoHeader[] = "ntp.webstorepromo.header";
-
-// The button text for the NTP web store promo.
-const char kNtpWebStorePromoButton[] = "ntp.webstorepromo.button";
-
-// The button link for the NTP web store promo.
-const char kNtpWebStorePromoLink[] = "ntp.webstorepromo.link";
-
-// The image URL for the NTP web store promo logo.
-const char kNtpWebStorePromoLogo[] = "ntp.webstorepromo.logo";
-
-// The original URL for the NTP web store promo logo.
-const char kNtpWebStorePromoLogoSource[] = "ntp.webstorepromo.logo_source";
-
-// The "hide this" link text for the NTP web store promo.
-const char kNtpWebStorePromoExpire[] = "ntp.webstorepromo.expire";
-
-// Specifies what users should maximize the NTP web store promo.
-const char kNtpWebStorePromoUserGroup[] = "ntp.webstorepromo.usergroup";
-
// Customized app page names that appear on the New Tab Page.
const char kNtpAppPageNames[] = "ntp.app_page_names";
@@ -1999,30 +1987,36 @@
const char kHttpOriginalContentLength[] = "http_original_content_length";
#if defined(OS_ANDROID) || defined(OS_IOS)
-// A List pref that contains daily totals of the original size of all HTTP
-// that was received over the network.
+// A List pref that contains daily totals of the original size of all HTTP/HTTPS
+// that was received from the network.
const char kDailyHttpOriginalContentLength[] =
"data_reduction.daily_original_length";
-// A List pref that contains daily totals of the size of all HTTP content that
-// has been received from the network.
+// A List pref that contains daily totals of the size of all HTTP/HTTPS content
+// that was received from the network.
const char kDailyHttpReceivedContentLength[] =
"data_reduction.daily_received_length";
-// A List pref that contains daily totals of the size of all HTTP content that
-// has been received via the data reduction proxy.
-const char kDailyHttpReceivedContentLengthViaDataReductionProxy[] =
- "data_reduction.daily_received_length_via_data_reduction_proxy";
+// A List pref that contains daily totals of the original size of all HTTP/HTTPS
+// that was received while the data reduction proxy is enabled.
+const char kDailyOriginalContentLengthWithDataReductionProxyEnabled[] =
+ "data_reduction.daily_original_length_with_data_reduction_proxy_enabled";
-// A List pref that contains daily totals of the size of all HTTP content that
-// has been received when the data reduction proxy is enabled.
-// Note: this is different from
-// kDailyHttpReceivedContentLengthViaDataReductionProxy because content
-// doesn't necessarily go through the data reduction proxy when it is enabled.
-// E.g., the proxy doesn't handle HTTPS traffic.
-const char kDailyHttpReceivedContentLengthWithDataReductionProxyEnabled[] =
+// A List pref that contains daily totals of the size of all HTTP/HTTPS
+// that was received while the data reduction proxy is enabled.
+const char kDailyContentLengthWithDataReductionProxyEnabled[] =
"data_reduction.daily_received_length_with_data_reduction_proxy_enabled";
+// A List pref that contains daily totals of the original size of all HTTP/HTTPS
+// that was received via the data reduction proxy.
+const char kDailyOriginalContentLengthViaDataReductionProxy[] =
+ "data_reduction.daily_original_length_via_data_reduction_proxy";
+
+// A List pref that contains daily totals of the size of all HTTP/HTTPS
+// that was received via the data reduction proxy.
+const char kDailyContentLengthViaDataReductionProxy[] =
+ "data_reduction.daily_received_length_via_data_reduction_proxy";
+
// An int64 pref that contains an internal representation of midnight on the
// date of the last update to |kDailyHttp{Original,Received}ContentLength|.
const char kDailyHttpContentLengthLastUpdateDate[] =
@@ -2052,6 +2046,12 @@
// TODO(tommi): Update comment when this is supported for all modes.
const char kVideoCaptureAllowedUrls[] = "hardware.video_capture_allowed_urls";
+#if defined(OS_ANDROID)
+// Boolean that controls the global enabled-state of protected media identifier.
+const char kProtectedMediaIdentifierEnabled[] =
+ "protected_media_identifier.enabled";
+#endif
+
#if defined(OS_CHROMEOS)
// Dictionary for transient storage of settings that should go into device
// settings storage before owner has been assigned.
@@ -2138,6 +2138,10 @@
// A dictionary pref of the echo offer check flag. It sets offer info when
// an offer is checked.
extern const char kEchoCheckedOffers[] = "EchoCheckedOffers";
+
+// Key name of a dictionary in local state to store cached multiprofle user
+// behavior policy value.
+const char kCachedMultiProfileUserBehavior[] = "CachedMultiProfileUserBehavior";
#endif
// Whether there is a Flash version installed that supports clearing LSO data.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 721c4de..3aa63fb 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -288,6 +288,8 @@
extern const char kRAConsentFirstTime[];
extern const char kRAConsentDomains[];
extern const char kRAConsentAlways[];
+extern const char kMultiProfileNotificationDismissed[];
+extern const char kMultiProfileUserBehavior[];
#endif // defined(OS_CHROMEOS)
extern const char kIpcDisabledMessages[];
extern const char kShowHomeButton[];
@@ -411,6 +413,8 @@
extern const char kFullscreenAllowed[];
+extern const char kLocalDiscoveryNotificationsEnabled[];
+
// Local state prefs. Please add Profile prefs above instead.
extern const char kCertRevocationCheckingEnabled[];
extern const char kCertRevocationCheckingRequiredLocalAnchors[];
@@ -734,6 +738,10 @@
extern const char kVideoCaptureAllowed[];
extern const char kVideoCaptureAllowedUrls[];
+#if defined(OS_ANDROID)
+extern const char kProtectedMediaIdentifierEnabled[];
+#endif
+
#if defined(OS_CHROMEOS)
extern const char kDeviceSettingsCache[];
extern const char kHardwareKeyboardLayout[];
@@ -756,6 +764,7 @@
extern const char kDeviceEnrollmentCanExit[];
extern const char kUsersLRUInputMethod[];
extern const char kEchoCheckedOffers[];
+extern const char kCachedMultiProfileUserBehavior[];
#endif
extern const char kClearPluginLSODataEnabled[];
@@ -790,9 +799,10 @@
#if defined(OS_ANDROID) || defined(OS_IOS)
extern const char kDailyHttpOriginalContentLength[];
extern const char kDailyHttpReceivedContentLength[];
-extern const char kDailyHttpReceivedContentLengthViaDataReductionProxy[];
-extern const char
- kDailyHttpReceivedContentLengthWithDataReductionProxyEnabled[];
+extern const char kDailyOriginalContentLengthWithDataReductionProxyEnabled[];
+extern const char kDailyContentLengthWithDataReductionProxyEnabled[];
+extern const char kDailyOriginalContentLengthViaDataReductionProxy[];
+extern const char kDailyContentLengthViaDataReductionProxy[];
extern const char kDailyHttpContentLengthLastUpdateDate[];
#endif
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index f5d997d..174f189 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -442,6 +442,11 @@
// Misc messages
// These are messages sent from the renderer to the browser process.
+// Provides the contents for the given page that was loaded recently.
+IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_PageContents,
+ GURL /* URL of the page */,
+ string16 /* page contents */)
+
// Notification that the language for the tab has been determined.
IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_TranslateLanguageDetermined,
LanguageDetectionDetails /* details about lang detection */,
@@ -623,11 +628,6 @@
std::string /* the translated language */,
TranslateErrors::Type /* the error type if available */)
-// Message sent from the renderer to the browser to notify it of events which
-// may lead to the cancellation of a prerender. The message is sent only when
-// the renderer is prerendering.
-IPC_MESSAGE_ROUTED0(ChromeViewHostMsg_MaybeCancelPrerenderForHTML5Media)
-
// Message sent from the renderer to the browser to notify it of a
// window.print() call which should cancel the prerender. The message is sent
// only when the renderer is prerendering.
diff --git a/chrome/common/safe_browsing/OWNERS b/chrome/common/safe_browsing/OWNERS
index dc45c86..cd4e37c 100644
--- a/chrome/common/safe_browsing/OWNERS
+++ b/chrome/common/safe_browsing/OWNERS
@@ -10,5 +10,4 @@
per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 5fa5190..c84731e 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -235,7 +235,7 @@
const char kChromeUIWelcomeHost[] = "welcome";
#endif
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
const char kChromeUILinuxProxyConfigHost[] = "linux-proxy-config";
const char kChromeUISandboxHost[] = "sandbox";
#endif
@@ -519,8 +519,10 @@
kChromeUIChromeURLsHost,
kChromeUICrashesHost,
kChromeUICreditsHost,
+ kChromeUIDevicesHost,
kChromeUIDNSHost,
kChromeUIFlagsHost,
+ kChromeUIHelpHost,
kChromeUIHistoryHost,
kChromeUIIPCHost,
kChromeUIMemoryHost,
@@ -539,6 +541,7 @@
kChromeUISyncInternalsHost,
kChromeUITermsHost,
kChromeUITranslateInternalsHost,
+ kChromeUIUberHost,
kChromeUIUserActionsHost,
kChromeUIVersionHost,
#if defined(OS_ANDROID)
@@ -555,7 +558,7 @@
#if defined(OS_WIN)
kChromeUIConflictsHost,
#endif
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
kChromeUILinuxProxyConfigHost,
kChromeUISandboxHost,
#endif
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 7030610..3acb602 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -227,7 +227,7 @@
extern const char kChromeUIWelcomeHost[];
#endif
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
extern const char kChromeUILinuxProxyConfigHost[];
extern const char kChromeUISandboxHost[];
#endif
@@ -469,10 +469,10 @@
#if defined(OS_CHROMEOS)
extern const char kCrosScheme[];
extern const char kDriveScheme[];
+#endif
// "Learn more" URL for the Cloud Print section under Options.
extern const char kCloudPrintLearnMoreURL[];
-#endif
// Parameters that get appended to force SafeSearch.
extern const char kSafeSearchSafeParameter[];
diff --git a/chrome/installer/gcapi_mac/gcapi.mm b/chrome/installer/gcapi_mac/gcapi.mm
index 57f0d02..1ca5839 100644
--- a/chrome/installer/gcapi_mac/gcapi.mm
+++ b/chrome/installer/gcapi_mac/gcapi.mm
@@ -34,9 +34,6 @@
@"~~/Library/Application Support/Google/Chrome/"
"Google Chrome Master Preferences";
-NSString* const kChannelKey = @"KSChannelID";
-NSString* const kVersionKey = @"KSVersion";
-
// Condensed from chromium's base/mac/mac_util.mm.
bool IsOSXVersionSupported() {
// On 10.6, Gestalt() was observed to be able to spawn threads (see
@@ -60,8 +57,8 @@
// 10.2.
int mac_os_x_minor_version = darwin_major_version - 4;
- // Chrome is known to work on 10.6 - 10.8.
- return mac_os_x_minor_version >= 6 && mac_os_x_minor_version <= 8;
+ // Chrome is known to work on 10.6 - 10.9.
+ return mac_os_x_minor_version >= 6 && mac_os_x_minor_version <= 9;
}
// Returns the pid/gid of the logged-in user, even if getuid() claims that the
diff --git a/chrome/installer/linux/debian/build.sh b/chrome/installer/linux/debian/build.sh
index 290aaef..dad1f03 100755
--- a/chrome/installer/linux/debian/build.sh
+++ b/chrome/installer/linux/debian/build.sh
@@ -94,9 +94,13 @@
echo "Packaging ${ARCHITECTURE}..."
PREDEPENDS="$COMMON_PREDEPS"
DEPENDS="${COMMON_DEPS}"
- REPLACES=""
- CONFLICTS=""
- PROVIDES="www-browser"
+ # Trunk is a special package, mostly for development testing, so don't make
+ # it replace any installed release packages.
+ if [ "$CHANNEL" != "trunk" ] && [ "$CHANNEL" != "asan" ]; then
+ REPLACES="${PACKAGE}"
+ CONFLICTS="${PACKAGE}"
+ PROVIDES="${PACKAGE}, www-browser"
+ fi
gen_changelog
process_template "${SCRIPTDIR}/control.template" "${DEB_CONTROL}"
export DEB_HOST_ARCH="${ARCHITECTURE}"
diff --git a/chrome/installer/setup/cf_migration.cc b/chrome/installer/setup/cf_migration.cc
new file mode 100644
index 0000000..313f2ce
--- /dev/null
+++ b/chrome/installer/setup/cf_migration.cc
@@ -0,0 +1,131 @@
+// Copyright 2013 The Chromium 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/installer/setup/cf_migration.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/process/launch.h"
+#include "base/win/registry.h"
+#include "chrome/installer/setup/setup_constants.h"
+#include "chrome/installer/setup/setup_main.h"
+#include "chrome/installer/setup/setup_util.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/installation_state.h"
+#include "chrome/installer/util/installer_state.h"
+#include "chrome/installer/util/master_preferences.h"
+#include "chrome/installer/util/util_constants.h"
+
+namespace installer {
+
+bool LaunchChromeFrameMigrationProcess(
+ const ProductState& chrome_frame_product,
+ const CommandLine& command_line,
+ const base::FilePath& installer_directory,
+ bool system_level) {
+ // Before running the migration, mutate the CF ap value to include a
+ // "-migrate" beacon. This beacon value will be cleaned up by the "ap"
+ // cleanup in MigrateGoogleUpdateStateMultiToSingle that calls
+ // ChannelInfo::RemoveAllModifiersAndSuffixes().
+ if (chrome_frame_product.is_multi_install()) {
+ const HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ base::win::RegKey state_key;
+ installer::ChannelInfo channel_info;
+ BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_FRAME);
+
+ LONG result = state_key.Open(root, dist->GetStateKey().c_str(),
+ KEY_QUERY_VALUE | KEY_SET_VALUE);
+ if (result != ERROR_SUCCESS || !channel_info.Initialize(state_key)) {
+ LOG(ERROR) << "Failed to read CF channel to store beacon.";
+ } else if (!channel_info.SetMigratingSuffix(true)) {
+ LOG(WARNING) << "CF already has migration beacon in channel.";
+ } else {
+ VLOG(1) << "Writing CF migration beacon to channel: "
+ << channel_info.value();
+ channel_info.Write(&state_key);
+ }
+ }
+
+ // Call the installed setup.exe using the current installer command line and
+ // adding the migration flags. This seems like it could be unsafe, here's why
+ // it's safe today:
+ // 1) MigrateChromeFrameInChildProcess is called only during a multi update.
+ // 2) Multi update processing occurs after HandleNonInstallCmdLineOptions is
+ // called.
+ // 3) Setup exits if there were any non-install command line options handled.
+ // 4) Thus, the command line being copied will have no non-install command
+ // line options at time of copying.
+ // 5) kMigrateChromeFrame is a non-install command line option.
+ // 6) Thus, it will be handled (and the child setup process will exit) before
+ // the child setup process acts on any other flags on the command line.
+ // 7) Furthermore, --uncompressed-archive takes precedence over
+ // --install-archive, so it is safe to add the former to the command line
+ // without removing the latter.
+ CommandLine setup_cmd(command_line);
+ setup_cmd.SetProgram(installer_directory.Append(installer::kSetupExe));
+ setup_cmd.AppendSwitchPath(
+ switches::kUncompressedArchive,
+ installer_directory.Append(installer::kChromeArchive));
+ setup_cmd.AppendSwitch(switches::kMigrateChromeFrame);
+
+ VLOG(1) << "Running Chrome Frame migration process with command line: "
+ << setup_cmd.GetCommandLineString();
+
+ base::LaunchOptions options;
+ options.force_breakaway_from_job_ = true;
+ if (!base::LaunchProcess(setup_cmd, options, NULL)) {
+ PLOG(ERROR) << "Launching Chrome Frame migration process failed. "
+ << "(Command line: " << setup_cmd.GetCommandLineString() << ")";
+ return false;
+ }
+
+ return true;
+}
+
+InstallStatus MigrateChromeFrame(const InstallationState& original_state,
+ InstallerState* installer_state) {
+ const bool system_level = installer_state->system_install();
+
+ // Nothing to do if multi-install Chrome Frame is not installed.
+ const ProductState* multi_chrome_frame = original_state.GetProductState(
+ system_level, BrowserDistribution::CHROME_FRAME);
+ if (!multi_chrome_frame || !multi_chrome_frame->is_multi_install())
+ return INVALID_STATE_FOR_OPTION;
+
+ // Install SxS Chrome Frame.
+ InstallerState install_gcf(installer_state->level());
+ {
+ scoped_ptr<Product> chrome_frame(
+ new Product(BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_FRAME)));
+ install_gcf.AddProduct(&chrome_frame);
+ }
+ DCHECK(!install_gcf.is_multi_install());
+
+ ArchiveType archive_type = UNKNOWN_ARCHIVE_TYPE;
+ bool delegated_to_existing = false;
+ InstallStatus install_status = InstallProductsHelper(
+ original_state, *CommandLine::ForCurrentProcess(),
+ MasterPreferences::ForCurrentProcess(), install_gcf,
+ NULL, &archive_type, &delegated_to_existing);
+
+ if (!InstallUtil::GetInstallReturnCode(install_status)) {
+ // Migration was successful. There's no turning back now. The multi-install
+ // npchrome_frame.dll and/or chrome.exe may still be in use at this point,
+ // although the user-level helper will not be. It is not safe to delete the
+ // multi-install binaries until npchrome_frame.dll and chrome.exe are no
+ // longer in use. The remaining tasks here are best-effort. Failure does not
+ // do any harm.
+ MigrateGoogleUpdateStateMultiToSingle(system_level,
+ BrowserDistribution::CHROME_FRAME,
+ original_state);
+ }
+
+ return install_status;
+}
+
+} // namespace installer
diff --git a/chrome/installer/setup/cf_migration.h b/chrome/installer/setup/cf_migration.h
new file mode 100644
index 0000000..976e544
--- /dev/null
+++ b/chrome/installer/setup/cf_migration.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_INSTALLER_SETUP_CF_MIGRATION_H_
+#define CHROME_INSTALLER_SETUP_CF_MIGRATION_H_
+
+#include "chrome/installer/util/util_constants.h"
+
+class CommandLine;
+
+namespace base {
+class FilePath;
+}
+
+namespace installer {
+
+class InstallationState;
+class InstallerState;
+class ProductState;
+
+// Invokes a child helper instance of the setup.exe in |installer_directory| to
+// run MigrateChromeFrame (see comments below) using the archive in
+// |installer_directory| for the given installation level. Returns true if the
+// process is launched.
+bool LaunchChromeFrameMigrationProcess(
+ const ProductState& chrome_frame_product,
+ const CommandLine& command_line,
+ const base::FilePath& installer_directory,
+ bool system_level);
+
+// Migrates multi-install Chrome Frame to single-install at the current
+// level. Does not remove the multi-install binaries if no other products are
+// using them. --uncompressed-archive=chrome.7z is expected to be given on the
+// command line to point this setup.exe at the (possibly patched) archive from
+// the calling instance.
+// Note about process model: this is called in a child setup.exe that is
+// invoked from the setup.exe instance run as part of an update to a
+// multi-install Chrome Frame.
+InstallStatus MigrateChromeFrame(const InstallationState& original_state,
+ InstallerState* installer_state);
+
+} // namespace installer
+
+#endif // CHROME_INSTALLER_SETUP_CF_MIGRATION_H_
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 688df1c..5049fdc 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -17,6 +17,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/process/launch.h"
+#include "base/safe_numerics.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -340,9 +341,10 @@
// Write the manifest to |src_path|.
const std::string manifest(UTF16ToUTF8(manifest16));
+ int size = base::checked_numeric_cast<int>(manifest.size());
if (file_util::WriteFile(
- src_path.Append(installer::kVisualElementsManifest),
- manifest.c_str(), manifest.size())) {
+ src_path.Append(installer::kVisualElementsManifest),
+ manifest.c_str(), size) == size) {
VLOG(1) << "Successfully wrote " << installer::kVisualElementsManifest
<< " to " << src_path.value();
return true;
@@ -504,10 +506,8 @@
DCHECK(products.size());
if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
// Make sure that we don't end up deleting installed files on next reboot.
- if (!RemoveFromMovesPendingReboot(
- installer_state.target_path().value().c_str())) {
+ if (!RemoveFromMovesPendingReboot(installer_state.target_path()))
LOG(ERROR) << "Error accessing pending moves value.";
- }
}
// Create VisualElementManifest.xml in |src_path| (if required) so that it
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 171ac7c..9f38cff 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -36,6 +36,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/installer/setup/archive_patch_helper.h"
+#include "chrome/installer/setup/cf_migration.h"
#include "chrome/installer/setup/chrome_frame_quick_enable.h"
#include "chrome/installer/setup/chrome_frame_ready_mode.h"
#include "chrome/installer/setup/install.h"
@@ -71,10 +72,10 @@
using installer::InstallerState;
using installer::InstallationState;
using installer::InstallationValidator;
+using installer::MasterPreferences;
using installer::Product;
using installer::ProductState;
using installer::Products;
-using installer::MasterPreferences;
const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\";
@@ -691,7 +692,8 @@
const InstallationState& original_state,
const CommandLine& cmd_line,
const MasterPreferences& prefs,
- InstallerState* installer_state) {
+ InstallerState* installer_state,
+ base::FilePath* installer_directory) {
DCHECK(installer_state);
const bool system_install = installer_state->system_install();
installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
@@ -706,8 +708,8 @@
&install_status)) {
VLOG(1) << "Installing to " << installer_state->target_path().value();
install_status = InstallProductsHelper(
- original_state, cmd_line, prefs, *installer_state, &archive_type,
- &delegated_to_existing);
+ original_state, cmd_line, prefs, *installer_state,
+ installer_directory, &archive_type, &delegated_to_existing);
} else {
// CheckPreInstallConditions must set the status on failure.
DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
@@ -723,7 +725,7 @@
LOG(ERROR) << "Failed deleting master preferences file "
<< prefs_path.value()
<< ", scheduling for deletion after reboot.";
- ScheduleFileSystemEntityForDeletion(prefs_path.value().c_str());
+ ScheduleFileSystemEntityForDeletion(prefs_path);
}
}
@@ -981,55 +983,6 @@
return status;
}
-// Migrates multi-install Chrome Frame to single-install at the current
-// level. Does not remove the multi-install binaries if no other products are
-// using them. --uncompressed-archive=chrome.7z is expected to be given on the
-// command line to point this setup.exe at the (possibly patched) archive from
-// the calling instance.
-installer::InstallStatus MigrateChromeFrame(
- const InstallationState& original_state,
- InstallerState* installer_state) {
- const bool system_level = installer_state->system_install();
-
- // Nothing to do if multi-install Chrome Frame is not installed.
- const ProductState* multi_chrome_frame = original_state.GetProductState(
- system_level, BrowserDistribution::CHROME_FRAME);
- if (!multi_chrome_frame || !multi_chrome_frame->is_multi_install())
- return installer::INVALID_STATE_FOR_OPTION;
-
- // Install SxS Chrome Frame.
- InstallerState install_gcf(installer_state->level());
- {
- scoped_ptr<Product> chrome_frame(
- new Product(BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_FRAME)));
- install_gcf.AddProduct(&chrome_frame);
- }
- DCHECK(!install_gcf.is_multi_install());
-
- installer::ArchiveType archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
- bool delegated_to_existing = false;
- installer::InstallStatus install_status = InstallProductsHelper(
- original_state, *CommandLine::ForCurrentProcess(),
- MasterPreferences::ForCurrentProcess(), install_gcf,
- &archive_type, &delegated_to_existing);
-
- if (!InstallUtil::GetInstallReturnCode(install_status)) {
- // Migration was successful. There's no turning back now. The multi-install
- // npchrome_frame.dll and/or chrome.exe may still be in use at this point,
- // although the user-level helper will not be. It is not safe to delete the
- // multi-install binaries until npchrome_frame.dll and chrome.exe are no
- // longer in use. The remaining tasks here are best-effort. Failure does not
- // do any harm.
- installer::MigrateGoogleUpdateStateMultiToSingle(
- system_level,
- BrowserDistribution::CHROME_FRAME,
- original_state);
- }
-
- return install_status;
-}
-
// This method processes any command line options that make setup.exe do
// various tasks other than installation (renaming chrome.exe, showing eula
// among others). This function returns true if any such command line option
@@ -1070,7 +1023,7 @@
// the Windows last-error code.
LOG(WARNING) << "Scheduling temporary path " << temp_path.path().value()
<< " for deletion at reboot.";
- ScheduleDirectoryForDeletion(temp_path.path().value().c_str());
+ ScheduleDirectoryForDeletion(temp_path.path());
}
}
@@ -1401,42 +1354,43 @@
namespace installer {
-installer::InstallStatus InstallProductsHelper(
+InstallStatus InstallProductsHelper(
const InstallationState& original_state,
const CommandLine& cmd_line,
const MasterPreferences& prefs,
const InstallerState& installer_state,
- installer::ArchiveType* archive_type,
+ base::FilePath* installer_directory,
+ ArchiveType* archive_type,
bool* delegated_to_existing) {
DCHECK(archive_type);
DCHECK(delegated_to_existing);
const bool system_install = installer_state.system_install();
- installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
+ InstallStatus install_status = UNKNOWN_STATUS;
// Drop to background processing mode if the process was started below the
// normal process priority class.
- bool entered_background_mode = installer::AdjustProcessPriority();
+ bool entered_background_mode = AdjustProcessPriority();
VLOG_IF(1, entered_background_mode) << "Entered background processing mode.";
// Create a temp folder where we will unpack Chrome archive. If it fails,
// then we are doomed, so return immediately and no cleanup is required.
- installer::SelfCleaningTempDir temp_path;
+ SelfCleaningTempDir temp_path;
base::FilePath unpack_path;
if (!CreateTemporaryAndUnpackDirectories(installer_state, &temp_path,
&unpack_path)) {
- installer_state.WriteInstallerResult(installer::TEMP_DIR_FAILED,
+ installer_state.WriteInstallerResult(TEMP_DIR_FAILED,
IDS_INSTALL_TEMP_DIR_FAILED_BASE,
NULL);
- return installer::TEMP_DIR_FAILED;
+ return TEMP_DIR_FAILED;
}
// Uncompress and optionally patch the archive if an uncompressed archive was
// not specified on the command line and a compressed archive is found.
- *archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
+ *archive_type = UNKNOWN_ARCHIVE_TYPE;
base::FilePath uncompressed_archive(cmd_line.GetSwitchValuePath(
- installer::switches::kUncompressedArchive));
+ switches::kUncompressedArchive));
if (uncompressed_archive.empty()) {
- scoped_ptr<installer::ArchivePatchHelper> archive_helper(
+ scoped_ptr<ArchivePatchHelper> archive_helper(
CreateChromeArchiveHelper(cmd_line, installer_state, unpack_path));
if (archive_helper) {
VLOG(1) << "Installing Chrome from compressed archive "
@@ -1446,7 +1400,7 @@
archive_helper.get(),
archive_type,
&install_status)) {
- DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
+ DCHECK_NE(install_status, UNKNOWN_STATUS);
return install_status;
}
uncompressed_archive = archive_helper->target();
@@ -1458,19 +1412,19 @@
// was not given or generated.
if (uncompressed_archive.empty()) {
uncompressed_archive =
- cmd_line.GetProgram().DirName().Append(installer::kChromeArchive);
+ cmd_line.GetProgram().DirName().Append(kChromeArchive);
}
- if (*archive_type == installer::UNKNOWN_ARCHIVE_TYPE) {
+ if (*archive_type == UNKNOWN_ARCHIVE_TYPE) {
// An archive was not uncompressed or patched above.
if (uncompressed_archive.empty() ||
!base::PathExists(uncompressed_archive)) {
LOG(ERROR) << "Cannot install Chrome without an uncompressed archive.";
installer_state.WriteInstallerResult(
- installer::INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
- return installer::INVALID_ARCHIVE;
+ INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
+ return INVALID_ARCHIVE;
}
- *archive_type = installer::FULL_ARCHIVE_TYPE;
+ *archive_type = FULL_ARCHIVE_TYPE;
}
// Unpack the uncompressed archive.
@@ -1478,20 +1432,20 @@
unpack_path.value(),
NULL)) {
installer_state.WriteInstallerResult(
- installer::UNCOMPRESSION_FAILED,
+ UNCOMPRESSION_FAILED,
IDS_INSTALL_UNCOMPRESSION_FAILED_BASE,
NULL);
- return installer::UNCOMPRESSION_FAILED;
+ return UNCOMPRESSION_FAILED;
}
VLOG(1) << "unpacked to " << unpack_path.value();
base::FilePath src_path(
- unpack_path.Append(installer::kInstallSourceChromeDir));
+ unpack_path.Append(kInstallSourceChromeDir));
scoped_ptr<Version>
- installer_version(installer::GetMaxVersionFromArchiveDir(src_path));
+ installer_version(GetMaxVersionFromArchiveDir(src_path));
if (!installer_version.get()) {
LOG(ERROR) << "Did not find any valid version in installer.";
- install_status = installer::INVALID_ARCHIVE;
+ install_status = INVALID_ARCHIVE;
installer_state.WriteInstallerResult(install_status,
IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
} else {
@@ -1508,7 +1462,7 @@
if (GetExistingHigherInstaller(original_state, system_install,
*installer_version, &setup_exe)) {
VLOG(1) << "Deferring to existing installer.";
- installer_state.UpdateStage(installer::DEFERRING_TO_HIGHER_VERSION);
+ installer_state.UpdateStage(DEFERRING_TO_HIGHER_VERSION);
if (DeferToExistingInstall(setup_exe, cmd_line, installer_state,
temp_path.path(), &install_status)) {
*delegated_to_existing = true;
@@ -1546,7 +1500,7 @@
int message_id = 0;
proceed_with_installation = false;
- install_status = installer::HIGHER_VERSION_EXISTS;
+ install_status = HIGHER_VERSION_EXISTS;
switch (higher_products) {
case kBrowserBit:
message_id = IDS_INSTALL_HIGHER_VERSION_BASE;
@@ -1579,16 +1533,17 @@
if (!google_update::EnsureUserLevelGoogleUpdatePresent()) {
LOG(ERROR) << "Failed to install Google Update";
proceed_with_installation = false;
- install_status = installer::INSTALL_OF_GOOGLE_UPDATE_FAILED;
+ install_status = INSTALL_OF_GOOGLE_UPDATE_FAILED;
installer_state.WriteInstallerResult(install_status, 0, NULL);
}
}
+
}
if (proceed_with_installation) {
base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative(
- installer::switches::kInstallerData));
- install_status = installer::InstallOrUpdateProduct(
+ switches::kInstallerData));
+ install_status = InstallOrUpdateProduct(
original_state, installer_state, cmd_line.GetProgram(),
uncompressed_archive, temp_path.path(), src_path, prefs_source_path,
prefs, *installer_version);
@@ -1596,27 +1551,26 @@
int install_msg_base = IDS_INSTALL_FAILED_BASE;
string16 chrome_exe;
string16 quoted_chrome_exe;
- if (install_status == installer::SAME_VERSION_REPAIR_FAILED) {
+ if (install_status == SAME_VERSION_REPAIR_FAILED) {
if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE;
} else {
install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE;
}
- } else if (install_status != installer::INSTALL_FAILED) {
+ } else if (install_status != INSTALL_FAILED) {
if (installer_state.target_path().empty()) {
// If we failed to construct install path, it means the OS call to
// get %ProgramFiles% or %AppData% failed. Report this as failure.
install_msg_base = IDS_INSTALL_OS_ERROR_BASE;
- install_status = installer::OS_ERROR;
+ install_status = OS_ERROR;
} else {
- chrome_exe = installer_state.target_path()
- .Append(installer::kChromeExe).value();
+ chrome_exe = installer_state.target_path().Append(kChromeExe).value();
quoted_chrome_exe = L"\"" + chrome_exe + L"\"";
install_msg_base = 0;
}
}
- installer_state.UpdateStage(installer::FINISHING);
+ installer_state.UpdateStage(FINISHING);
// Only do Chrome-specific stuff (like launching the browser) if
// Chrome was specifically requested (rather than being upgraded as
@@ -1627,48 +1581,45 @@
bool do_not_register_for_update_launch = false;
if (chrome_install) {
- prefs.GetBool(
- installer::master_preferences::kDoNotRegisterForUpdateLaunch,
- &do_not_register_for_update_launch);
+ prefs.GetBool(master_preferences::kDoNotRegisterForUpdateLaunch,
+ &do_not_register_for_update_launch);
} else {
do_not_register_for_update_launch = true; // Never register.
}
bool write_chrome_launch_string =
(!do_not_register_for_update_launch &&
- install_status != installer::IN_USE_UPDATED);
+ install_status != IN_USE_UPDATED);
installer_state.WriteInstallerResult(install_status, install_msg_base,
write_chrome_launch_string ? "ed_chrome_exe : NULL);
- if (install_status == installer::FIRST_INSTALL_SUCCESS) {
+ if (install_status == FIRST_INSTALL_SUCCESS) {
VLOG(1) << "First install successful.";
if (chrome_install) {
// We never want to launch Chrome in system level install mode.
bool do_not_launch_chrome = false;
- prefs.GetBool(
- installer::master_preferences::kDoNotLaunchChrome,
- &do_not_launch_chrome);
+ prefs.GetBool(master_preferences::kDoNotLaunchChrome,
+ &do_not_launch_chrome);
if (!system_install && !do_not_launch_chrome)
chrome_install->LaunchChrome(installer_state.target_path());
}
- } else if ((install_status == installer::NEW_VERSION_UPDATED) ||
- (install_status == installer::IN_USE_UPDATED)) {
+ } else if ((install_status == NEW_VERSION_UPDATED) ||
+ (install_status == IN_USE_UPDATED)) {
const Product* chrome = installer_state.FindProduct(
BrowserDistribution::CHROME_BROWSER);
if (chrome != NULL) {
DCHECK_NE(chrome_exe, string16());
- installer::RemoveChromeLegacyRegistryKeys(chrome->distribution(),
- chrome_exe);
+ RemoveChromeLegacyRegistryKeys(chrome->distribution(), chrome_exe);
}
}
if (prefs.install_chrome_app_launcher() &&
InstallUtil::GetInstallReturnCode(install_status) == 0) {
std::string webstore_item(google_update::GetUntrustedDataValue(
- installer::kInstallFromWebstore));
+ kInstallFromWebstore));
if (!webstore_item.empty()) {
- bool success = installer::InstallFromWebstore(webstore_item);
+ bool success = InstallFromWebstore(webstore_item);
VLOG_IF(1, !success) << "Failed to launch app installation.";
}
}
@@ -1699,6 +1650,15 @@
}
}
+ // If installation completed successfully, return the path to the directory
+ // containing the newly installed setup.exe and uncompressed archive if the
+ // caller requested it.
+ if (installer_directory &&
+ InstallUtil::GetInstallReturnCode(install_status) == 0) {
+ *installer_directory =
+ installer_state.GetInstallerDirectory(*installer_version);
+ }
+
// temp_path's dtor will take care of deleting or scheduling itself for
// deletion at reboot when this scope closes.
VLOG(1) << "Deleting temporary directory " << temp_path.path().value();
@@ -1798,6 +1758,7 @@
}
}
+ base::FilePath installer_directory;
installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
// If --uninstall option is given, uninstall the identified product(s)
if (is_uninstall) {
@@ -1806,7 +1767,8 @@
} else {
// If --uninstall option is not specified, we assume it is install case.
install_status =
- InstallProducts(original_state, cmd_line, prefs, &installer_state);
+ InstallProducts(original_state, cmd_line, prefs, &installer_state,
+ &installer_directory);
}
// Validate that the machine is now in a good state following the operation.
@@ -1820,7 +1782,6 @@
const Product* cf_install =
installer_state.FindProduct(BrowserDistribution::CHROME_FRAME);
-
if (cf_install &&
!cmd_line.HasSwitch(installer::switches::kForceUninstall)) {
if (install_status == installer::UNINSTALL_REQUIRES_REBOOT) {
@@ -1849,11 +1810,31 @@
// MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will
// rollback the action. If we're uninstalling we want to avoid this, so always
// report success, squashing any more informative return codes.
- if (!(installer_state.is_msi() && is_uninstall))
+ if (!(installer_state.is_msi() && is_uninstall)) {
// Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT
// to pass through, since this is only returned on uninstall which is
// never invoked directly by Google Update.
return_code = InstallUtil::GetInstallReturnCode(install_status);
+ }
+
+ // Reinitialize original_state to make sure it reflects the now-current
+ // state of the system.
+ original_state.Initialize();
+
+ // If multi Chrome Frame was just updated, migrate the installation to a SxS
+ // install. Do this right before quitting.
+ const ProductState* chrome_frame_state =
+ original_state.GetProductState(system_install,
+ BrowserDistribution::CHROME_FRAME);
+ if ((install_status == installer::NEW_VERSION_UPDATED ||
+ install_status == installer::IN_USE_UPDATED) &&
+ chrome_frame_state &&
+ installer_state.operation() == InstallerState::MULTI_UPDATE) {
+ // Call the newly updated setup.exe with kUncompressedArchive and
+ // kMigrateChromeFrame to perform the migration.
+ LaunchChromeFrameMigrationProcess(*chrome_frame_state, cmd_line,
+ installer_directory, system_install);
+ }
VLOG(1) << "Installation complete, returning: " << return_code;
diff --git a/chrome/installer/setup/setup_main.h b/chrome/installer/setup/setup_main.h
index f39e742..f87509c 100644
--- a/chrome/installer/setup/setup_main.h
+++ b/chrome/installer/setup/setup_main.h
@@ -12,20 +12,27 @@
class CommandLine;
-namespace installer {
+namespace base {
+class FilePath;
+} // namespace base
+namespace installer {
class InstallationState;
class InstallerState;
class MasterPreferences;
// Helper function that performs the installation of a set of products.
-installer::InstallStatus InstallProductsHelper(
- const installer::InstallationState& original_state,
- const CommandLine& cmd_line,
- const installer::MasterPreferences& prefs,
- const installer::InstallerState& installer_state,
- installer::ArchiveType* archive_type,
- bool* delegated_to_existing);
+// |installer_directory|, if non-NULL, is populated with the path to the
+// directory containing the newly installed setup.exe. |archive_type| is
+// populated with the type of archive found. |delegated_to_existing| is set to
+// |true| if installation was delegated to a pre-existing higher version.
+InstallStatus InstallProductsHelper(const InstallationState& original_state,
+ const CommandLine& cmd_line,
+ const MasterPreferences& prefs,
+ const InstallerState& installer_state,
+ base::FilePath* installer_directory,
+ ArchiveType* archive_type,
+ bool* delegated_to_existing);
} // namespace installer
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 2387ab3..ad0b0d2 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -428,13 +428,13 @@
bool ScheduleParentAndGrandparentForDeletion(const base::FilePath& path) {
base::FilePath parent_dir = path.DirName();
- bool ret = ScheduleFileSystemEntityForDeletion(parent_dir.value().c_str());
+ bool ret = ScheduleFileSystemEntityForDeletion(parent_dir);
if (!ret) {
LOG(ERROR) << "Failed to schedule parent dir for deletion: "
<< parent_dir.value();
} else {
base::FilePath grandparent_dir(parent_dir.DirName());
- ret = ScheduleFileSystemEntityForDeletion(grandparent_dir.value().c_str());
+ ret = ScheduleFileSystemEntityForDeletion(grandparent_dir);
if (!ret) {
LOG(ERROR) << "Failed to schedule grandparent dir for deletion: "
<< grandparent_dir.value();
@@ -508,7 +508,7 @@
LOG(ERROR) << "Failed to delete user profile dir: "
<< user_local_state.value();
if (schedule_on_failure) {
- ScheduleDirectoryForDeletion(user_local_state.value().c_str());
+ ScheduleDirectoryForDeletion(user_local_state);
result = DELETE_REQUIRES_REBOOT;
} else {
result = DELETE_FAILED;
@@ -652,9 +652,9 @@
// return a value that will trigger a reboot prompt.
base::FileEnumerator::FileInfo find_info = file_enumerator.GetInfo();
if (find_info.IsDirectory())
- ScheduleDirectoryForDeletion(to_delete.value().c_str());
+ ScheduleDirectoryForDeletion(to_delete);
else
- ScheduleFileSystemEntityForDeletion(to_delete.value().c_str());
+ ScheduleFileSystemEntityForDeletion(to_delete);
result = DELETE_REQUIRES_REBOOT;
} else {
// Try closing any running Chrome processes and deleting files once
@@ -1496,7 +1496,7 @@
if (*uninstall_status == installer::UNINSTALL_REQUIRES_REBOOT) {
// Delete the Application directory at reboot if empty.
- ScheduleFileSystemEntityForDeletion(target_path.value().c_str());
+ ScheduleFileSystemEntityForDeletion(target_path);
// If we need a reboot to continue, schedule the parent directories for
// deletion unconditionally. If they are not empty, the session manager
diff --git a/chrome/installer/util/channel_info.cc b/chrome/installer/util/channel_info.cc
index e52ae77..48a4e32 100644
--- a/chrome/installer/util/channel_info.cc
+++ b/chrome/installer/util/channel_info.cc
@@ -22,6 +22,7 @@
const wchar_t kModReadyMode[] = L"-readymode";
const wchar_t kModStage[] = L"-stage:";
const wchar_t kSfxFull[] = L"-full";
+const wchar_t kSfxMigrating[] = L"-migrating";
const wchar_t kSfxMultiFail[] = L"-multifail";
const wchar_t* const kChannels[] = {
@@ -38,7 +39,8 @@
kModAppLauncher,
kModReadyMode,
kSfxMultiFail,
- kSfxFull
+ kSfxMigrating,
+ kSfxFull,
};
enum ModifierIndex {
@@ -50,6 +52,7 @@
MOD_APP_LAUNCHER,
MOD_READY_MODE,
SFX_MULTI_FAIL,
+ SFX_MIGRATING,
SFX_FULL,
NUM_MODIFIERS
};
@@ -281,6 +284,14 @@
return SetModifier(SFX_MULTI_FAIL, value, &value_);
}
+bool ChannelInfo::SetMigratingSuffix(bool value) {
+ return SetModifier(SFX_MIGRATING, value, &value_);
+}
+
+bool ChannelInfo::HasMigratingSuffix() const {
+ return HasModifier(SFX_MIGRATING, value_);
+}
+
bool ChannelInfo::RemoveAllModifiersAndSuffixes() {
bool modified = false;
diff --git a/chrome/installer/util/channel_info.h b/chrome/installer/util/channel_info.h
index 438966f..f148113 100644
--- a/chrome/installer/util/channel_info.h
+++ b/chrome/installer/util/channel_info.h
@@ -101,6 +101,13 @@
// modified.
bool SetMultiFailSuffix(bool value);
+ // Adds or removes the -migrating suffix, returning true if the value is
+ // modified.
+ bool SetMigratingSuffix(bool value);
+
+ // Returns true if the -migrating suffix is present in the value.
+ bool HasMigratingSuffix() const;
+
// Removes all modifiers and suffixes. For example, 2.0-dev-multi-chrome-full
// becomes 2.0-dev. Returns true if the value is modified.
bool RemoveAllModifiersAndSuffixes();
diff --git a/chrome/installer/util/channel_info_unittest.cc b/chrome/installer/util/channel_info_unittest.cc
index 1aacb24..d08f2c3 100644
--- a/chrome/installer/util/channel_info_unittest.cc
+++ b/chrome/installer/util/channel_info_unittest.cc
@@ -118,6 +118,38 @@
EXPECT_EQ(L"2.0-beta", ci.value());
}
+TEST(ChannelInfoTest, Migration) {
+ ChannelInfo ci;
+
+ ci.set_value(L"");
+ EXPECT_TRUE(ci.SetMigratingSuffix(true));
+ EXPECT_TRUE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"-migrating", ci.value());
+ EXPECT_FALSE(ci.SetMigratingSuffix(true));
+ EXPECT_TRUE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"-migrating", ci.value());
+ EXPECT_TRUE(ci.SetMigratingSuffix(false));
+ EXPECT_FALSE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"", ci.value());
+ EXPECT_FALSE(ci.SetMigratingSuffix(false));
+ EXPECT_FALSE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"", ci.value());
+
+ ci.set_value(L"2.0-beta");
+ EXPECT_TRUE(ci.SetMigratingSuffix(true));
+ EXPECT_TRUE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"2.0-beta-migrating", ci.value());
+ EXPECT_FALSE(ci.SetMigratingSuffix(true));
+ EXPECT_TRUE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"2.0-beta-migrating", ci.value());
+ EXPECT_TRUE(ci.SetMigratingSuffix(false));
+ EXPECT_FALSE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"2.0-beta", ci.value());
+ EXPECT_FALSE(ci.SetMigratingSuffix(false));
+ EXPECT_FALSE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"2.0-beta", ci.value());
+}
+
TEST(ChannelInfoTest, Combinations) {
ChannelInfo ci;
@@ -212,7 +244,7 @@
EXPECT_FALSE(ci.RemoveAllModifiersAndSuffixes());
EXPECT_EQ(L"", ci.value());
- ci.set_value(L"2.0-dev-multi-chrome-chromeframe");
+ ci.set_value(L"2.0-dev-multi-chrome-chromeframe-migrating");
EXPECT_TRUE(ci.RemoveAllModifiersAndSuffixes());
EXPECT_EQ(L"2.0-dev", ci.value());
}
diff --git a/chrome/installer/util/delete_after_reboot_helper.cc b/chrome/installer/util/delete_after_reboot_helper.cc
index 5131b1d..fb7956e 100644
--- a/chrome/installer/util/delete_after_reboot_helper.cc
+++ b/chrome/installer/util/delete_after_reboot_helper.cc
@@ -30,20 +30,19 @@
// Returns true if this directory name is 'safe' for deletion (doesn't contain
// "..", doesn't specify a drive root)
-bool IsSafeDirectoryNameForDeletion(const wchar_t* dir_name) {
- DCHECK(dir_name);
-
+bool IsSafeDirectoryNameForDeletion(const base::FilePath& dir_name) {
// empty name isn't allowed
- if (!(dir_name && *dir_name))
+ if (dir_name.empty())
return false;
// require a character other than \/:. after the last :
// disallow anything with ".."
bool ok = false;
- for (const wchar_t* s = dir_name; *s; ++s) {
+ const wchar_t* dir_name_str = dir_name.value().c_str();
+ for (const wchar_t* s = dir_name_str; *s; ++s) {
if (*s != L'\\' && *s != L'/' && *s != L':' && *s != L'.')
ok = true;
- if (*s == L'.' && s > dir_name && *(s - 1) == L'.')
+ if (*s == L'.' && s > dir_name_str && *(s - 1) == L'.')
return false;
if (*s == L':')
ok = false;
@@ -54,22 +53,23 @@
} // end namespace
// Must only be called for regular files or directories that will be empty.
-bool ScheduleFileSystemEntityForDeletion(const wchar_t* path) {
+bool ScheduleFileSystemEntityForDeletion(const base::FilePath& path) {
// Check if the file exists, return false if not.
WIN32_FILE_ATTRIBUTE_DATA attrs = {0};
- if (!::GetFileAttributesEx(path, ::GetFileExInfoStandard, &attrs)) {
- PLOG(WARNING) << path << " does not exist.";
+ if (!::GetFileAttributesEx(path.value().c_str(),
+ ::GetFileExInfoStandard, &attrs)) {
+ PLOG(WARNING) << path.value() << " does not exist.";
return false;
}
DWORD flags = MOVEFILE_DELAY_UNTIL_REBOOT;
- if (!base::DirectoryExists(base::FilePath::FromWStringHack(path))) {
+ if (!base::DirectoryExists(path)) {
// This flag valid only for files
flags |= MOVEFILE_REPLACE_EXISTING;
}
- if (!::MoveFileEx(path, NULL, flags)) {
- PLOG(ERROR) << "Could not schedule " << path << " for deletion.";
+ if (!::MoveFileEx(path.value().c_str(), NULL, flags)) {
+ PLOG(ERROR) << "Could not schedule " << path.value() << " for deletion.";
return false;
}
@@ -77,51 +77,53 @@
// Useful debugging code to track down what files are in use.
if (flags & MOVEFILE_REPLACE_EXISTING) {
// Attempt to open the file exclusively.
- HANDLE file = ::CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
- OPEN_EXISTING, 0, NULL);
+ HANDLE file = ::CreateFileW(path.value().c_str(),
+ GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, 0, NULL);
if (file != INVALID_HANDLE_VALUE) {
- LOG(INFO) << " file not in use: " << path;
+ LOG(INFO) << " file not in use: " << path.value();
::CloseHandle(file);
} else {
- PLOG(INFO) << " file in use (or not found?): " << path;
+ PLOG(INFO) << " file in use (or not found?): " << path.value();
}
}
#endif
- VLOG(1) << "Scheduled for deletion: " << path;
+ VLOG(1) << "Scheduled for deletion: " << path.value();
return true;
}
-bool ScheduleDirectoryForDeletion(const wchar_t* dir_name) {
+bool ScheduleDirectoryForDeletion(const base::FilePath& dir_name) {
if (!IsSafeDirectoryNameForDeletion(dir_name)) {
- LOG(ERROR) << "Unsafe directory name for deletion: " << dir_name;
+ LOG(ERROR) << "Unsafe directory name for deletion: " << dir_name.value();
return false;
}
// Make sure the directory exists (it is ok if it doesn't)
- DWORD dir_attributes = ::GetFileAttributes(dir_name);
+ DWORD dir_attributes = ::GetFileAttributes(dir_name.value().c_str());
if (dir_attributes == INVALID_FILE_ATTRIBUTES) {
if (::GetLastError() == ERROR_FILE_NOT_FOUND) {
return true; // Ok if directory is missing
} else {
- PLOG(ERROR) << "Could not GetFileAttributes for " << dir_name;
+ PLOG(ERROR) << "Could not GetFileAttributes for " << dir_name.value();
return false;
}
}
// Confirm it is a directory
if (!(dir_attributes & FILE_ATTRIBUTE_DIRECTORY)) {
- LOG(ERROR) << "Scheduled directory is not a directory: " << dir_name;
+ LOG(ERROR) << "Scheduled directory is not a directory: "
+ << dir_name.value();
return false;
}
// First schedule all the normal files for deletion.
{
bool success = true;
- base::FileEnumerator file_enum(base::FilePath(dir_name), false,
+ base::FileEnumerator file_enum(dir_name, false,
base::FileEnumerator::FILES);
for (base::FilePath file = file_enum.Next(); !file.empty();
file = file_enum.Next()) {
- success = ScheduleFileSystemEntityForDeletion(file.value().c_str());
+ success = ScheduleFileSystemEntityForDeletion(file);
if (!success) {
LOG(ERROR) << "Failed to schedule file for deletion: " << file.value();
return false;
@@ -132,11 +134,11 @@
// Then recurse to all the subdirectories.
{
bool success = true;
- base::FileEnumerator dir_enum(base::FilePath(dir_name), false,
+ base::FileEnumerator dir_enum(dir_name, false,
base::FileEnumerator::DIRECTORIES);
for (base::FilePath sub_dir = dir_enum.Next(); !sub_dir.empty();
sub_dir = dir_enum.Next()) {
- success = ScheduleDirectoryForDeletion(sub_dir.value().c_str());
+ success = ScheduleDirectoryForDeletion(sub_dir);
if (!success) {
LOG(ERROR) << "Failed to schedule subdirectory for deletion: "
<< sub_dir.value();
@@ -146,8 +148,10 @@
}
// Now schedule the empty directory itself
- if (!ScheduleFileSystemEntityForDeletion(dir_name))
- LOG(ERROR) << "Failed to schedule directory for deletion: " << dir_name;
+ if (!ScheduleFileSystemEntityForDeletion(dir_name)) {
+ LOG(ERROR) << "Failed to schedule directory for deletion: "
+ << dir_name.value();
+ }
return true;
}
@@ -240,9 +244,10 @@
DCHECK(++write_pointer == end_pointer);
}
-std::wstring GetShortPathName(const wchar_t* path) {
+base::FilePath GetShortPathName(const base::FilePath& path) {
std::wstring short_path;
- DWORD length = GetShortPathName(path, WriteInto(&short_path, MAX_PATH),
+ DWORD length = GetShortPathName(path.value().c_str(),
+ WriteInto(&short_path, MAX_PATH),
MAX_PATH);
DWORD last_error = ::GetLastError();
DLOG_IF(WARNING, length == 0 && last_error != ERROR_PATH_NOT_FOUND)
@@ -255,11 +260,10 @@
}
short_path.resize(length);
- return short_path;
+ return base::FilePath(short_path);
}
-HRESULT GetPendingMovesValue(
- std::vector<PendingMove>* pending_moves) {
+HRESULT GetPendingMovesValue(std::vector<PendingMove>* pending_moves) {
DCHECK(pending_moves);
pending_moves->clear();
@@ -319,9 +323,10 @@
return hr;
}
-bool MatchPendingDeletePath(const std::wstring& short_form_needle,
- const std::wstring& reg_path) {
- std::wstring match_path(reg_path); // Stores the path stored in each entry.
+bool MatchPendingDeletePath(const base::FilePath& short_form_needle,
+ const base::FilePath& reg_path) {
+ // Stores the path stored in each entry.
+ std::wstring match_path(reg_path.value());
// First chomp the prefix since that will mess up GetShortPathName.
std::wstring prefix(L"\\??\\");
@@ -329,17 +334,16 @@
match_path = match_path.substr(4);
// Get the short path name of the entry.
- std::wstring short_match_path(GetShortPathName(match_path.c_str()));
+ base::FilePath short_match_path(GetShortPathName(base::FilePath(match_path)));
// Now compare the paths. If it isn't one we're looking for, add it
// to the list to keep.
- return StartsWith(short_match_path, short_form_needle, false);
+ return StartsWith(short_match_path.value(), short_form_needle.value(), false);
}
// Removes all pending moves for the given |directory| and any contained
// files or subdirectories. Returns true on success
-bool RemoveFromMovesPendingReboot(const wchar_t* directory) {
- DCHECK(directory);
+bool RemoveFromMovesPendingReboot(const base::FilePath& directory) {
std::vector<PendingMove> pending_moves;
HRESULT hr = GetPendingMovesValue(&pending_moves);
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
@@ -352,12 +356,13 @@
}
// Get the short form of |directory| and use that to match.
- std::wstring short_directory(GetShortPathName(directory));
+ base::FilePath short_directory(GetShortPathName(directory));
std::vector<PendingMove> strings_to_keep;
for (std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
- iter != pending_moves.end(); iter++) {
- if (!MatchPendingDeletePath(short_directory, iter->first)) {
+ iter != pending_moves.end(); ++iter) {
+ base::FilePath move_path(iter->first);
+ if (!MatchPendingDeletePath(short_directory, move_path)) {
// This doesn't match the deletions we are looking for. Preserve
// this string pair, making sure that it is in fact a pair.
strings_to_keep.push_back(*iter);
diff --git a/chrome/installer/util/delete_after_reboot_helper.h b/chrome/installer/util/delete_after_reboot_helper.h
index 6d59b26..55cc522 100644
--- a/chrome/installer/util/delete_after_reboot_helper.h
+++ b/chrome/installer/util/delete_after_reboot_helper.h
@@ -13,6 +13,10 @@
#include <windows.h>
+namespace base {
+class FilePath;
+}
+
// Used by the unit tests.
extern const wchar_t kSessionManagerKey[];
extern const wchar_t kPendingFileRenameOps[];
@@ -20,14 +24,14 @@
typedef std::pair<std::wstring, std::wstring> PendingMove;
// Attempts to schedule only the item at path for deletion.
-bool ScheduleFileSystemEntityForDeletion(const wchar_t* path);
+bool ScheduleFileSystemEntityForDeletion(const base::FilePath& path);
// Attempts to recursively schedule the directory for deletion.
-bool ScheduleDirectoryForDeletion(const wchar_t* dir_name);
+bool ScheduleDirectoryForDeletion(const base::FilePath& dir_name);
// Removes all pending moves that are registered for |directory| and all
// elements contained in |directory|.
-bool RemoveFromMovesPendingReboot(const wchar_t* directory);
+bool RemoveFromMovesPendingReboot(const base::FilePath& directory);
// Retrieves the list of pending renames from the registry and returns a vector
// containing pairs of strings that represent the operations. If the list
@@ -39,8 +43,8 @@
// |short_form_needle| is a file system path that has been shortened by
// GetShortPathName and |reg_path| is a path stored in the
// PendingFileRenameOperations key.
-bool MatchPendingDeletePath(const std::wstring& short_form_needle,
- const std::wstring& reg_path);
+bool MatchPendingDeletePath(const base::FilePath& short_form_needle,
+ const base::FilePath& reg_path);
// Converts the strings found in |buffer| to a list of PendingMoves that is
// returned in |value|.
@@ -63,9 +67,9 @@
std::vector<char>* buffer);
// A helper function for the win32 GetShortPathName that more conveniently
-// returns a correctly sized wstring. Note that if |path| is not present on the
-// file system then GetShortPathName will return |path| unchanged, unlike the
-// win32 GetShortPathName which will return an error.
-std::wstring GetShortPathName(const wchar_t* path);
+// returns a FilePath. Note that if |path| is not present on the file system
+// then GetShortPathName will return |path| unchanged, unlike the win32
+// GetShortPathName which will return an error.
+base::FilePath GetShortPathName(const base::FilePath& path);
#endif // CHROME_INSTALLER_UTIL_DELETE_AFTER_REBOOT_HELPER_H_
diff --git a/chrome/installer/util/delete_after_reboot_helper_unittest.cc b/chrome/installer/util/delete_after_reboot_helper_unittest.cc
index 7fb7360..c97cecd 100644
--- a/chrome/installer/util/delete_after_reboot_helper_unittest.cc
+++ b/chrome/installer/util/delete_after_reboot_helper_unittest.cc
@@ -96,7 +96,8 @@
base::FilePath temp_subdir_;
base::FilePath temp_subdir_file_;
};
-}
+
+} // namespace
TEST_F(DeleteAfterRebootHelperTest, TestStringListToMultiSZConversions) {
struct StringTest {
@@ -143,22 +144,23 @@
return;
}
- EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_.value().c_str()));
+ EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_));
std::vector<PendingMove> pending_moves;
EXPECT_TRUE(SUCCEEDED(GetPendingMovesValue(&pending_moves)));
// We should see, somewhere in this key, deletion writs for
// temp_file_, temp_subdir_file_, temp_subdir_ and temp_dir_ in that order.
- EXPECT_TRUE(pending_moves.size() > 3);
+ EXPECT_GT(pending_moves.size(), 3U);
// Get the short form of temp_file_ and use that to match.
- std::wstring short_temp_file(GetShortPathName(temp_file_.value().c_str()));
+ base::FilePath short_temp_file(GetShortPathName(temp_file_));
// Scan for the first expected delete.
std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
for (; iter != pending_moves.end(); iter++) {
- if (MatchPendingDeletePath(short_temp_file, iter->first))
+ base::FilePath move_path(iter->first);
+ if (MatchPendingDeletePath(short_temp_file, move_path))
break;
}
@@ -168,21 +170,22 @@
for (int i = 0; i < arraysize(expected_paths); ++i) {
EXPECT_FALSE(iter == pending_moves.end());
if (iter != pending_moves.end()) {
- std::wstring short_path_name(
- GetShortPathName(expected_paths[i].value().c_str()));
- EXPECT_TRUE(MatchPendingDeletePath(short_path_name, iter->first));
+ base::FilePath short_path_name(GetShortPathName(expected_paths[i]));
+ base::FilePath move_path(iter->first);
+ EXPECT_TRUE(MatchPendingDeletePath(short_path_name, move_path));
++iter;
}
}
// Test that we can remove the pending deletes.
- EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_.value().c_str()));
+ EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_));
HRESULT hr = GetPendingMovesValue(&pending_moves);
EXPECT_TRUE(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
std::vector<PendingMove>::const_iterator check_iter(pending_moves.begin());
for (; check_iter != pending_moves.end(); ++check_iter) {
- EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, check_iter->first));
+ base::FilePath move_path(check_iter->first);
+ EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, move_path));
}
}
@@ -195,7 +198,7 @@
GetPendingMovesValue(&initial_pending_moves);
size_t initial_pending_moves_size = initial_pending_moves.size();
- EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_.value().c_str()));
+ EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_));
std::vector<PendingMove> pending_moves;
EXPECT_TRUE(SUCCEEDED(GetPendingMovesValue(&pending_moves)));
@@ -205,12 +208,13 @@
EXPECT_TRUE(pending_moves.size() > 3);
// Get the short form of temp_file_ and use that to match.
- std::wstring short_temp_file(GetShortPathName(temp_file_.value().c_str()));
+ base::FilePath short_temp_file(GetShortPathName(temp_file_));
// Scan for the first expected delete.
std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
for (; iter != pending_moves.end(); iter++) {
- if (MatchPendingDeletePath(short_temp_file, iter->first))
+ base::FilePath move_path(iter->first);
+ if (MatchPendingDeletePath(short_temp_file, move_path))
break;
}
@@ -220,9 +224,9 @@
for (int i = 0; i < arraysize(expected_paths); ++i) {
EXPECT_FALSE(iter == pending_moves.end());
if (iter != pending_moves.end()) {
- std::wstring short_path_name(
- GetShortPathName(expected_paths[i].value().c_str()));
- EXPECT_TRUE(MatchPendingDeletePath(short_path_name, iter->first));
+ base::FilePath short_path_name(GetShortPathName(expected_paths[i]));
+ base::FilePath move_path(iter->first);
+ EXPECT_TRUE(MatchPendingDeletePath(short_path_name, move_path));
++iter;
}
}
@@ -231,7 +235,7 @@
base::DeleteFile(temp_dir_, true);
// Test that we can remove the pending deletes.
- EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_.value().c_str()));
+ EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_));
HRESULT hr = GetPendingMovesValue(&pending_moves);
EXPECT_TRUE(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
@@ -239,7 +243,8 @@
std::vector<PendingMove>::const_iterator check_iter(pending_moves.begin());
for (; check_iter != pending_moves.end(); ++check_iter) {
- EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, check_iter->first));
+ base::FilePath move_path(check_iter->first);
+ EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, move_path));
}
}
diff --git a/chrome/installer/util/self_cleaning_temp_dir.cc b/chrome/installer/util/self_cleaning_temp_dir.cc
index 6426dd9..23d3091 100644
--- a/chrome/installer/util/self_cleaning_temp_dir.cc
+++ b/chrome/installer/util/self_cleaning_temp_dir.cc
@@ -84,7 +84,7 @@
LOG(WARNING) << "Failed to delete temporary directory " << path().value()
<< ". Scheduling for deletion at reboot.";
schedule_deletes = true;
- if (!ScheduleDirectoryForDeletion(path().value().c_str()))
+ if (!ScheduleDirectoryForDeletion(path()))
return false; // Entirely unexpected failure (Schedule logs the reason).
}
@@ -101,7 +101,7 @@
if (schedule_deletes) {
// Ignore the return code. If we fail to schedule, go ahead and add the
// other parent directories anyway.
- ScheduleFileSystemEntityForDeletion(next_dir.value().c_str());
+ ScheduleFileSystemEntityForDeletion(next_dir);
}
if (next_dir == base_dir_)
break; // We just processed the topmost directory we created.
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index c747547..19a5feb 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -697,8 +697,7 @@
DCHECK(InstallUtil::IsPerUserInstall(chrome_exe.c_str()));
DCHECK_LT(base::win::GetVersion(), base::win::VERSION_WIN8);
base::FilePath exe_path =
- base::FilePath::FromWStringHack(chrome_exe).DirName()
- .Append(installer::kSetupExe);
+ base::FilePath(chrome_exe).DirName().Append(installer::kSetupExe);
if (!base::PathExists(exe_path)) {
HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
@@ -1696,6 +1695,8 @@
}
ShellUtil::DefaultState ShellUtil::GetChromeDefaultState() {
+ if (!BrowserDistribution::GetDistribution()->CanSetAsDefault())
+ return NOT_DEFAULT;
// When we check for default browser we don't necessarily want to count file
// type handlers and icons as having changed the default browser status,
// since the user may have changed their shell settings to cause HTML files
@@ -1711,6 +1712,8 @@
ShellUtil::DefaultState ShellUtil::GetChromeDefaultProtocolClientState(
const string16& protocol) {
+ if (!BrowserDistribution::GetDistribution()->CanSetAsDefault())
+ return NOT_DEFAULT;
if (protocol.empty())
return UNKNOWN_DEFAULT;
diff --git a/chrome/js_unittest_vars.gypi b/chrome/js_unittest_vars.gypi
index 8146ea2..b8ae1d4 100644
--- a/chrome/js_unittest_vars.gypi
+++ b/chrome/js_unittest_vars.gypi
@@ -8,6 +8,6 @@
'js2gtest': '<(DEPTH)/chrome/test/base/js2gtest.js',
'mock_js': '<(DEPTH)/chrome/third_party/mock4js/mock4js.js',
'test_api_js': '<(DEPTH)/chrome/test/data/webui/test_api.js',
- 'accessibility_audit_js': '<(DEPTH)/third_party/accessibility-developer-tools/gen/axs_testing.js',
+ 'accessibility_audit_js': '<(DEPTH)/third_party/accessibility-audit/axs_testing.js',
},
}
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index aee9188..b466ccb 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -411,15 +411,12 @@
return l10n_util::GetStringUTF8(IDS_DEFAULT_ENCODING);
}
-const Extension* ChromeContentRendererClient::GetExtension(
+const Extension* ChromeContentRendererClient::GetExtensionByOrigin(
const WebSecurityOrigin& origin) const {
if (!EqualsASCII(origin.protocol(), extensions::kExtensionScheme))
return NULL;
const std::string extension_id = origin.host().utf8().data();
- if (!extension_dispatcher_->IsExtensionActive(extension_id))
- return NULL;
-
return extension_dispatcher_->extensions()->GetByID(extension_id);
}
@@ -435,7 +432,7 @@
return false;
WebDocument document = frame->document();
const Extension* extension =
- GetExtension(document.securityOrigin());
+ GetExtensionByOrigin(document.securityOrigin());
if (extension) {
const extensions::APIPermission::ID perms[] = {
extensions::APIPermission::kWebView,
@@ -886,8 +883,7 @@
int resource_id;
base::DictionaryValue error_strings;
if (extension && !extension->from_bookmark()) {
- LocalizedError::GetAppErrorStrings(error, failed_url, extension,
- &error_strings);
+ LocalizedError::GetAppErrorStrings(failed_url, extension, &error_strings);
// TODO(erikkay): Should we use a different template for different
// error messages?
@@ -898,7 +894,9 @@
frame, error, is_post, locale, &error_strings)) {
// In most cases, the NetErrorHelper won't provide DNS-probe-specific
// error pages, so fall back to LocalizedError.
- LocalizedError::GetStrings(error, is_post, locale, &error_strings);
+ LocalizedError::GetStrings(error.reason, error.domain.utf8(),
+ error.unreachableURL, is_post, locale,
+ &error_strings);
}
resource_id = IDR_NET_ERROR_HTML;
}
@@ -945,8 +943,10 @@
// If this is the Instant process, fork all navigations originating from the
// renderer. The destination page will then be bucketed back to this Instant
// process if it is an Instant url, or to another process if not.
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInstantProcess))
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInstantProcess)) {
+ *send_referrer = true;
return true;
+ }
// For now, we skip the rest for POST submissions. This is because
// http://crbug.com/101395 is more likely to cause compatibility issues
@@ -970,8 +970,11 @@
// to swap in the prerendered page on the browser process. If the prerendered
// page no longer exists by the time the OpenURL IPC is handled, a normal
// navigation is attempted.
- if (prerender_dispatcher_.get() && prerender_dispatcher_->IsPrerenderURL(url))
+ if (prerender_dispatcher_.get() &&
+ prerender_dispatcher_->IsPrerenderURL(url)) {
+ *send_referrer = true;
return true;
+ }
const ExtensionSet* extensions = extension_dispatcher_->extensions();
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index 1885c57..599c5e8 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -173,7 +173,9 @@
private:
FRIEND_TEST_ALL_PREFIXES(ChromeContentRendererClientTest, NaClRestriction);
- const extensions::Extension* GetExtension(
+ // Gets extension by the given origin, regardless of whether the extension
+ // is active in the current process.
+ const extensions::Extension* GetExtensionByOrigin(
const WebKit::WebSecurityOrigin& origin) const;
// Returns true if the frame is navigating to an URL either into or out of an
diff --git a/chrome/renderer/chrome_content_renderer_client_unittest.cc b/chrome/renderer/chrome_content_renderer_client_unittest.cc
index ca1335f..f28d2fd 100644
--- a/chrome/renderer/chrome_content_renderer_client_unittest.cc
+++ b/chrome/renderer/chrome_content_renderer_client_unittest.cc
@@ -34,7 +34,6 @@
const bool kNotHostedApp = false;
const bool kHostedApp = true;
-const char kNaClMimeType[] = "application/x-nacl";
const char kExtensionUrl[] = "chrome-extension://extension_id/background.html";
const char kPhotosAppURL1[] = "https://foo.plus.google.com";
diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc
index 4c1f5b5..01f0730 100644
--- a/chrome/renderer/chrome_render_view_observer.cc
+++ b/chrome/renderer/chrome_render_view_observer.cc
@@ -11,6 +11,7 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.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"
#include "chrome/common/chrome_switches.h"
@@ -402,8 +403,6 @@
void ChromeRenderViewObserver::OnRetrieveWebappInformation(
const GURL& expected_url) {
- bool webapp_capable = false;
-
WebFrame* main_frame = render_view()->GetWebView()->mainFrame();
WebDocument document =
main_frame ? main_frame->document() : WebDocument();
@@ -414,6 +413,9 @@
// Make sure we're checking the right page.
bool success = document_url == expected_url;
+ bool is_mobile_webapp_capable = false;
+ bool is_apple_mobile_webapp_capable = false;
+
// Search the DOM for the webapp <meta> tags.
if (!head.isNull()) {
WebNodeList children = head.childNodes();
@@ -426,9 +428,12 @@
if (elem.hasTagName("meta") && elem.hasAttribute("name")) {
std::string name = elem.getAttribute("name").utf8();
WebString content = elem.getAttribute("content");
- if (content == "yes" && (name == "mobile-web-app-capable"
- || name == "apple-mobile-web-app-capable")) {
- webapp_capable = true;
+ if (LowerCaseEqualsASCII(content, "yes")) {
+ if (name == "mobile-web-app-capable") {
+ is_mobile_webapp_capable = true;
+ } else if (name == "apple-mobile-web-app-capable") {
+ is_apple_mobile_webapp_capable = true;
+ }
}
}
}
@@ -436,6 +441,19 @@
success = false;
}
+ if (main_frame && is_apple_mobile_webapp_capable &&
+ !is_mobile_webapp_capable) {
+ WebKit::WebConsoleMessage message(
+ WebKit::WebConsoleMessage::LevelWarning,
+ "<meta name=\"apple-mobile-web-app-capable\" content=\"yes\"> is "
+ "deprecated. Please include <meta name=\"mobile-web-app-capable\" "
+ "content=\"yes\"> - "
+ "http://developers.google.com/chrome/mobile/docs/installtohomescreen");
+ main_frame->addMessageToConsole(message);
+ }
+
+ bool webapp_capable =
+ is_mobile_webapp_capable || is_apple_mobile_webapp_capable;
Send(new ChromeViewHostMsg_DidRetrieveWebappInformation(routing_id(),
success,
webapp_capable,
@@ -926,6 +944,12 @@
TRACE_EVENT0("renderer", "ChromeRenderViewObserver::CapturePageInfo");
+ if (contents.size()) {
+ // Send the text to the browser for indexing (the browser might decide not
+ // to index, if the URL is HTTPS for instance).
+ Send(new ChromeViewHostMsg_PageContents(routing_id(), url, contents));
+ }
+
#if defined(FULL_SAFE_BROWSING)
// Will swap out the string.
if (phishing_classifier_)
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index ce2408f..672cf86 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -479,8 +479,7 @@
InitOriginPermissions(extension);
}
- if (IsWithinPlatformApp())
- EnableCustomElementWhiteList();
+ EnableCustomElementWhiteList();
is_webkit_initialized_ = true;
}
@@ -1114,18 +1113,17 @@
module_system->Require("windowControls");
}
- // Only platform apps support the <webview> tag, because the "webView" and
- // "denyWebView" modules will affect the performance of DOM modifications
- // (http://crbug.com/196453).
- if (context_type == Feature::BLESSED_EXTENSION_CONTEXT &&
- is_within_platform_app) {
+ if (context_type == Feature::BLESSED_EXTENSION_CONTEXT) {
// Note: setting up the WebView class here, not the chrome.webview API.
// The API will be automatically set up when first used.
if (extension->HasAPIPermission(APIPermission::kWebView)) {
module_system->Require("webView");
+ // TODO(mtomasz): Remove the Files app from the whitelist in M-31.
+ // crbug.com/297936
bool includeExperimental =
GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV ||
- extension->id() == extension_misc::kIdentityApiUiAppId;
+ extension->id() == extension_misc::kIdentityApiUiAppId ||
+ extension->id() == "hhaomjibdihmijegdhdafkllkbggdgoj"; // Files App.
if (!includeExperimental) {
// TODO(asargent) We need a whitelist for webview experimental.
// crbug.com/264852
@@ -1244,16 +1242,8 @@
if (is_webkit_initialized_) {
InitOriginPermissions(extension);
- // DOMActivity logger for a main world controlled by an extension (as in
- // the case of an extension background page, options page, popup etc.)
- // gets an empty title.
DOMActivityLogger::AttachToWorld(DOMActivityLogger::kMainWorldId,
- extension_id,
- extension->url(),
- string16());
-
- if (IsWithinPlatformApp())
- EnableCustomElementWhiteList();
+ extension_id);
}
}
diff --git a/chrome/renderer/extensions/document_custom_bindings.cc b/chrome/renderer/extensions/document_custom_bindings.cc
index 36406c2..253b612 100644
--- a/chrome/renderer/extensions/document_custom_bindings.cc
+++ b/chrome/renderer/extensions/document_custom_bindings.cc
@@ -7,10 +7,9 @@
#include <string>
#include "base/bind.h"
-#include "content/public/renderer/render_view.h"
+#include "chrome/renderer/extensions/chrome_v8_context.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebView.h"
#include "v8/include/v8.h"
namespace extensions {
@@ -26,16 +25,6 @@
// Attach an event name to an object.
void DocumentCustomBindings::RegisterElement(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- content::RenderView* render_view = GetRenderView();
- if (!render_view) {
- return;
- }
-
- WebKit::WebView* web_view = render_view->GetWebView();
- if (!web_view) {
- return;
- }
-
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsObject()) {
NOTREACHED();
return;
@@ -45,7 +34,7 @@
v8::Local<v8::Object> options = args[1]->ToObject();
WebKit::WebExceptionCode ec = 0;
- WebKit::WebDocument document = web_view->mainFrame()->document();
+ WebKit::WebDocument document = context()->web_frame()->document();
v8::Handle<v8::Value> constructor =
document.registerEmbedderCustomElement(
WebKit::WebString::fromUTF8(element_name), options, ec);
diff --git a/chrome/renderer/extensions/dom_activity_logger.cc b/chrome/renderer/extensions/dom_activity_logger.cc
index ea0fb9b..394fc4f 100644
--- a/chrome/renderer/extensions/dom_activity_logger.cc
+++ b/chrome/renderer/extensions/dom_activity_logger.cc
@@ -12,24 +12,26 @@
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/v8_value_converter.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDOMActivityLogger.h"
#include "v8/include/v8.h"
using content::V8ValueConverter;
+using WebKit::WebString;
+using WebKit::WebURL;
namespace extensions {
-DOMActivityLogger::DOMActivityLogger(const std::string& extension_id,
- const GURL& url,
- const string16& title)
- : extension_id_(extension_id), url_(url), title_(title) {
-} // namespace extensions
+DOMActivityLogger::DOMActivityLogger(const std::string& extension_id)
+ : extension_id_(extension_id) {}
void DOMActivityLogger::log(
const WebString& api_name,
int argc,
const v8::Handle<v8::Value> argv[],
- const WebString& call_type) {
+ const WebString& call_type,
+ const WebURL& url,
+ const WebString& title) {
scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
ActivityLogConverterStrategy strategy;
converter->SetFunctionAllowed(true);
@@ -40,8 +42,8 @@
i, converter->FromV8Value(argv[i], v8::Context::GetCurrent()));
}
ExtensionHostMsg_DOMAction_Params params;
- params.url = url_;
- params.url_title = title_;
+ params.url = url;
+ params.url_title = title;
params.api_call = api_name.utf8();
params.arguments.Swap(argv_list_value.get());
const std::string type = call_type.utf8();
@@ -57,15 +59,15 @@
}
void DOMActivityLogger::AttachToWorld(int world_id,
- const std::string& extension_id,
- const GURL& url,
- const string16& title) {
+ const std::string& extension_id) {
+#if defined(ENABLE_EXTENSIONS)
// If there is no logger registered for world_id, construct a new logger
// and register it with world_id.
if (!WebKit::hasDOMActivityLogger(world_id)) {
- DOMActivityLogger* logger = new DOMActivityLogger(extension_id, url, title);
+ DOMActivityLogger* logger = new DOMActivityLogger(extension_id);
WebKit::setDOMActivityLogger(world_id, logger);
}
+#endif
}
} // namespace extensions
diff --git a/chrome/renderer/extensions/dom_activity_logger.h b/chrome/renderer/extensions/dom_activity_logger.h
index 0c9ea5a..a188bec 100644
--- a/chrome/renderer/extensions/dom_activity_logger.h
+++ b/chrome/renderer/extensions/dom_activity_logger.h
@@ -9,12 +9,11 @@
#include "base/strings/string_piece.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDOMActivityLogger.h"
#include "url/gurl.h"
#include "v8/include/v8.h"
-using WebKit::WebString;
-
// Used to log DOM API calls from within WebKit. The events are sent via IPC to
// extensions::ActivityLog for recording and display.
namespace extensions {
@@ -22,31 +21,27 @@
class DOMActivityLogger: public WebKit::WebDOMActivityLogger {
public:
static const int kMainWorldId = 0;
- DOMActivityLogger(const std::string& extension_id,
- const GURL& url,
- const string16& title);
+ explicit DOMActivityLogger(const std::string& extension_id);
// Marshalls the arguments into an ExtensionHostMsg_DOMAction_Params
// and sends it over to the browser (via IPC) for appending it to the
// extension activity log.
// (Overrides the log method in WebKit::WebDOMActivityLogger)
- virtual void log(const WebString& api_name,
+ virtual void log(const WebKit::WebString& api_name,
int argc,
const v8::Handle<v8::Value> argv[],
- const WebString& call_type);
+ const WebKit::WebString& call_type,
+ const WebKit::WebURL& url,
+ const WebKit::WebString& title);
// Check (using the WebKit API) if there is no logger attached to the world
// corresponding to world_id, and if so, construct a new logger and attach it.
- // worl_id = 0 indicates the main world.
+ // world_id = 0 indicates the main world.
static void AttachToWorld(int world_id,
- const std::string& extension_id,
- const GURL& url,
- const string16& title);
+ const std::string& extension_id);
private:
std::string extension_id_;
- GURL url_;
- string16 title_;
DISALLOW_COPY_AND_ASSIGN(DOMActivityLogger);
};
diff --git a/chrome/renderer/extensions/feedback_private_custom_bindings.cc b/chrome/renderer/extensions/feedback_private_custom_bindings.cc
index a4fc075..64e8373 100644
--- a/chrome/renderer/extensions/feedback_private_custom_bindings.cc
+++ b/chrome/renderer/extensions/feedback_private_custom_bindings.cc
@@ -11,10 +11,14 @@
namespace {
-void GetBlobUrl(const v8::FunctionCallbackInfo<v8::Value> &args) {
+void GetBlobUuid(const v8::FunctionCallbackInfo<v8::Value> &args) {
DCHECK(args.Length() == 1);
WebKit::WebBlob blob = WebKit::WebBlob::fromV8Value(args[0]);
+#ifdef USE_BLOB_UUIDS
+ args.GetReturnValue().Set(v8::String::New(blob.uuid().utf8().data()));
+#else
args.GetReturnValue().Set(v8::String::New(blob.url().spec().data()));
+#endif
}
} // namespace
@@ -24,7 +28,7 @@
FeedbackPrivateCustomBindings::FeedbackPrivateCustomBindings(
Dispatcher* dispatcher,
ChromeV8Context* context) : ChromeV8Extension(dispatcher, context) {
- RouteFunction("GetBlobUrl", base::Bind(&GetBlobUrl));
+ RouteFunction("GetBlobUuid", base::Bind(&GetBlobUuid));
}
} // namespace extensions
diff --git a/chrome/renderer/extensions/user_script_scheduler.cc b/chrome/renderer/extensions/user_script_scheduler.cc
index 2c6e5a2..86dc7d3 100644
--- a/chrome/renderer/extensions/user_script_scheduler.cc
+++ b/chrome/renderer/extensions/user_script_scheduler.cc
@@ -207,11 +207,8 @@
v8::Local<v8::Value> script_value;
if (params.in_main_world) {
- DOMActivityLogger::AttachToWorld(
- DOMActivityLogger::kMainWorldId,
- extension->id(),
- UserScriptSlave::GetDataSourceURLForFrame(child_frame),
- child_frame->document().title());
+ DOMActivityLogger::AttachToWorld(DOMActivityLogger::kMainWorldId,
+ extension->id());
script_value = child_frame->executeScriptAndReturnValue(source);
} else {
WebKit::WebVector<v8::Local<v8::Value> > results;
@@ -220,11 +217,7 @@
int isolated_world_id =
dispatcher_->user_script_slave()->GetIsolatedWorldIdForExtension(
extension, child_frame);
- DOMActivityLogger::AttachToWorld(
- isolated_world_id,
- extension->id(),
- UserScriptSlave::GetDataSourceURLForFrame(child_frame),
- child_frame->document().title());
+ DOMActivityLogger::AttachToWorld(isolated_world_id, extension->id());
child_frame->executeScriptInIsolatedWorld(
isolated_world_id, &sources.front(),
sources.size(), EXTENSION_GROUP_CONTENT_SCRIPTS, &results);
diff --git a/chrome/renderer/extensions/user_script_slave.cc b/chrome/renderer/extensions/user_script_slave.cc
index 16af7a3..ceb3dae 100644
--- a/chrome/renderer/extensions/user_script_slave.cc
+++ b/chrome/renderer/extensions/user_script_slave.cc
@@ -334,11 +334,7 @@
int isolated_world_id = GetIsolatedWorldIdForExtension(extension, frame);
PerfTimer exec_timer;
- DOMActivityLogger::AttachToWorld(
- isolated_world_id,
- extension->id(),
- UserScriptSlave::GetDataSourceURLForFrame(frame),
- frame->document().title());
+ DOMActivityLogger::AttachToWorld(isolated_world_id, extension->id());
frame->executeScriptInIsolatedWorld(
isolated_world_id, &sources.front(), sources.size(),
EXTENSION_GROUP_CONTENT_SCRIPTS);
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc
index 62ce7b6..c12a3ed 100644
--- a/chrome/renderer/media/chrome_key_systems.cc
+++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -25,16 +25,18 @@
using content::KeySystemInfo;
-static const char kAudioWebM[] = "audio/webm";
-static const char kVideoWebM[] = "video/webm";
-static const char kVorbis[] = "vorbis";
-static const char kVorbisVP8[] = "vorbis,vp8,vp8.0";
+const char kAudioWebM[] = "audio/webm";
+const char kVideoWebM[] = "video/webm";
+const char kVorbis[] = "vorbis";
+const char kVorbisVP8[] = "vorbis,vp8,vp8.0";
-static const char kAudioMp4[] = "audio/mp4";
-static const char kVideoMp4[] = "video/mp4";
-static const char kMp4a[] = "mp4a";
-static const char kAvc1[] = "avc1";
-static const char kMp4aAvc1[] = "mp4a,avc1";
+#if defined(USE_PROPRIETARY_CODECS)
+const char kAudioMp4[] = "audio/mp4";
+const char kVideoMp4[] = "video/mp4";
+const char kMp4a[] = "mp4a";
+const char kAvc1[] = "avc1";
+const char kMp4aAvc1[] = "mp4a,avc1";
+#endif // defined(USE_PROPRIETARY_CODECS)
#if defined(ENABLE_PEPPER_CDMS)
static bool IsPepperCdmRegistered(const std::string& pepper_type) {
@@ -77,7 +79,9 @@
enum WidevineCdmType {
WIDEVINE,
WIDEVINE_HR,
- WIDEVINE_HRSURFACE,
+#if defined(OS_ANDROID)
+ WIDEVINE_HR_NON_COMPOSITING,
+#endif
};
// Defines bitmask values used to specify supported codecs.
@@ -133,9 +137,11 @@
case WIDEVINE_HR:
info.key_system.append(".hr");
break;
- case WIDEVINE_HRSURFACE:
- info.key_system.append(".hrsurface");
+#if defined(OS_ANDROID)
+ case WIDEVINE_HR_NON_COMPOSITING:
+ info.key_system.append(".hrnoncompositing");
break;
+#endif
default:
NOTREACHED();
}
@@ -199,8 +205,8 @@
#elif defined(OS_ANDROID)
static void AddAndroidWidevine(
std::vector<KeySystemInfo>* concrete_key_systems) {
- android::SupportedKeySystemRequest request;
- android::SupportedKeySystemResponse response;
+ SupportedKeySystemRequest request;
+ SupportedKeySystemResponse response;
request.uuid.insert(request.uuid.begin(), kWidevineUuid,
kWidevineUuid + arraysize(kWidevineUuid));
@@ -212,16 +218,16 @@
new ChromeViewHostMsg_GetSupportedKeySystems(request, &response));
DCHECK_EQ(response.compositing_codecs >> 3, 0) << "unrecognized codec";
DCHECK_EQ(response.non_compositing_codecs >> 3, 0) << "unrecognized codec";
- if (response.compositing_codecs > 0) {
+ if (response.compositing_codecs != android::NO_SUPPORTED_CODECS) {
AddWidevineWithCodecs(
WIDEVINE,
static_cast<SupportedCodecs>(response.compositing_codecs),
concrete_key_systems);
}
- if (response.non_compositing_codecs > 0) {
+ if (response.non_compositing_codecs != android::NO_SUPPORTED_CODECS) {
AddWidevineWithCodecs(
- WIDEVINE_HRSURFACE,
+ WIDEVINE_HR_NON_COMPOSITING,
static_cast<SupportedCodecs>(response.non_compositing_codecs),
concrete_key_systems);
}
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index 364ff93..618d43b 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -182,13 +182,11 @@
return false;
// Get the strings for a fake "DNS probe possible" error.
- WebKit::WebURLError fake_error;
- fake_error.domain = WebKit::WebString::fromUTF8(
- chrome_common_net::kDnsProbeErrorDomain);
- fake_error.reason = chrome_common_net::DNS_PROBE_POSSIBLE;
- fake_error.unreachableURL = error.unreachableURL;
LocalizedError::GetStrings(
- fake_error, is_failed_post, locale, error_strings);
+ chrome_common_net::DNS_PROBE_POSSIBLE,
+ chrome_common_net::kDnsProbeErrorDomain,
+ error.unreachableURL,
+ is_failed_post, locale, error_strings);
return true;
}
@@ -214,8 +212,11 @@
void NetErrorHelper::UpdateErrorPage() {
DCHECK(forwarding_probe_results_);
+ WebKit::WebURLError error = GetUpdatedError();
base::DictionaryValue error_strings;
- LocalizedError::GetStrings(GetUpdatedError(),
+ LocalizedError::GetStrings(error.reason,
+ error.domain.utf8(),
+ error.unreachableURL,
is_failed_post_,
RenderThread::Get()->GetLocale(),
&error_strings);
diff --git a/chrome/renderer/pepper/pepper_flash_fullscreen_host.cc b/chrome/renderer/pepper/pepper_flash_fullscreen_host.cc
index 37bea81..4ebcbd9 100644
--- a/chrome/renderer/pepper/pepper_flash_fullscreen_host.cc
+++ b/chrome/renderer/pepper/pepper_flash_fullscreen_host.cc
@@ -41,10 +41,8 @@
bool fullscreen) {
content::PepperPluginInstance* plugin_instance =
renderer_ppapi_host_->GetPluginInstance(pp_instance());
- if (plugin_instance) {
- plugin_instance->FlashSetFullscreen(fullscreen, true);
+ if (plugin_instance && plugin_instance->FlashSetFullscreen(fullscreen, true))
return PP_OK;
- }
return PP_ERROR_FAILED;
}
diff --git a/chrome/renderer/pepper/pepper_pdf_host.cc b/chrome/renderer/pepper/pepper_pdf_host.cc
index 9b78c93..e187c52 100644
--- a/chrome/renderer/pepper/pepper_pdf_host.cc
+++ b/chrome/renderer/pepper/pepper_pdf_host.cc
@@ -296,18 +296,15 @@
if (res_id == 0)
return PP_ERROR_FAILED;
- ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale);
-
gfx::ImageSkia* res_image_skia =
ResourceBundle::GetSharedInstance().GetImageSkiaNamed(res_id);
if (!res_image_skia)
return PP_ERROR_FAILED;
- gfx::ImageSkiaRep image_skia_rep = res_image_skia->GetRepresentation(
- scale_factor);
+ gfx::ImageSkiaRep image_skia_rep = res_image_skia->GetRepresentation(scale);
- if (image_skia_rep.is_null() || image_skia_rep.scale_factor() != scale_factor)
+ if (image_skia_rep.is_null() || image_skia_rep.scale() != scale)
return PP_ERROR_FAILED;
PP_Size pp_size;
diff --git a/chrome/renderer/pepper/ppb_pdf_impl.cc b/chrome/renderer/pepper/ppb_pdf_impl.cc
index d245870..d63443e 100644
--- a/chrome/renderer/pepper/ppb_pdf_impl.cc
+++ b/chrome/renderer/pepper/ppb_pdf_impl.cc
@@ -44,7 +44,7 @@
namespace {
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
class PrivateFontFile : public ppapi::Resource {
public:
PrivateFontFile(PP_Instance instance, int fd)
@@ -192,7 +192,7 @@
PP_Instance instance_id,
const PP_BrowserFont_Trusted_Description* description,
PP_PrivateFontCharset charset) {
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
// Validate the instance before using it below.
if (!content::PepperPluginInstance::Get(instance_id))
return 0;
@@ -224,7 +224,7 @@
uint32_t table,
void* output,
uint32_t* output_length) {
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
ppapi::Resource* resource =
PpapiGlobals::Get()->GetResourceTracker()->GetResource(font_file);
if (!resource)
diff --git a/chrome/renderer/printing/print_web_view_helper.cc b/chrome/renderer/printing/print_web_view_helper.cc
index bf3e3c7..e2b9599 100644
--- a/chrome/renderer/printing/print_web_view_helper.cc
+++ b/chrome/renderer/printing/print_web_view_helper.cc
@@ -478,7 +478,7 @@
WebKit::WebPrintParams webkit_params(page_size);
webkit_params.printerDPI = GetDPI(¶ms);
- frame->printBegin(webkit_params, WebKit::WebNode(), NULL);
+ frame->printBegin(webkit_params);
frame->printPage(0, canvas);
frame->printEnd();
@@ -599,7 +599,7 @@
print_params.print_scaling_option ==
WebKit::WebPrintScalingOptionFitToPrintableArea;
ComputeWebKitPrintParamsInDesiredDpi(params, &web_print_params_);
- frame->printBegin(web_print_params_, node_to_print_, NULL);
+ frame->printBegin(web_print_params_, node_to_print_);
print_params = CalculatePrintParamsForCss(frame, 0, print_params,
ignore_css_margins, fit_to_page,
NULL);
@@ -639,10 +639,8 @@
ResizeForPrinting();
WebKit::WebView* web_view = frame_.view();
web_view->settings()->setShouldPrintBackgrounds(should_print_backgrounds_);
- // TODO(vitalybuka): Update call after
- // https://bugs.webkit.org/show_bug.cgi?id=107718 is fixed.
expected_pages_count_ =
- frame()->printBegin(web_print_params_, node_to_print_, NULL);
+ frame()->printBegin(web_print_params_, node_to_print_);
is_printing_started_ = true;
}
diff --git a/chrome/renderer/resources/extensions/feedback_private_custom_bindings.js b/chrome/renderer/resources/extensions/feedback_private_custom_bindings.js
index 6b2122b..cca402f 100644
--- a/chrome/renderer/resources/extensions/feedback_private_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/feedback_private_custom_bindings.js
@@ -12,18 +12,18 @@
var apiFunctions = bindingsAPI.apiFunctions;
apiFunctions.setUpdateArgumentsPostValidate(
"sendFeedback", function(feedbackInfo, callback) {
- var attachedFileBlobUrl = '';
- var screenshotBlobUrl = '';
+ var attachedFileBlobUuid = '';
+ var screenshotBlobUuid = '';
if (feedbackInfo.attachedFile)
- attachedFileBlobUrl =
- feedbackPrivateNatives.GetBlobUrl(feedbackInfo.attachedFile.data);
+ attachedFileBlobUuid =
+ feedbackPrivateNatives.GetBlobUuid(feedbackInfo.attachedFile.data);
if (feedbackInfo.screenshot)
- screenshotBlobUrl =
- feedbackPrivateNatives.GetBlobUrl(feedbackInfo.screenshot);
+ screenshotBlobUuid =
+ feedbackPrivateNatives.GetBlobUuid(feedbackInfo.screenshot);
- feedbackInfo.attachedFileBlobUrl = attachedFileBlobUrl;
- feedbackInfo.screenshotBlobUrl = screenshotBlobUrl;
+ feedbackInfo.attachedFileBlobUuid = attachedFileBlobUuid;
+ feedbackInfo.screenshotBlobUuid = screenshotBlobUuid;
return [feedbackInfo, callback];
});
diff --git a/chrome/renderer/resources/extensions/send_request.js b/chrome/renderer/resources/extensions/send_request.js
index 28798ba..15df02b 100644
--- a/chrome/renderer/resources/extensions/send_request.js
+++ b/chrome/renderer/resources/extensions/send_request.js
@@ -32,7 +32,7 @@
// The chrome objects we will set lastError on. Really we should only be
// setting this on the callback's chrome object, but set on ours too since
// it's conceivable that something relies on that.
- var chromesForLastError = [chrome];
+ var callerChrome = chrome;
try {
var request = requests[requestId];
@@ -41,19 +41,19 @@
// lastError needs to be set on the caller's chrome object no matter what,
// though chances are it's the same as ours (it will be different when
// calling API methods on other contexts).
- if (request.callback) {
- var chromeForCallback = natives.GetGlobal(request.callback).chrome;
- if (chromeForCallback != chrome)
- $Array.push(chromesForLastError, chromeForCallback);
- }
+ if (request.callback)
+ callerChrome = natives.GetGlobal(request.callback).chrome;
- $Array.forEach(chromesForLastError, function(c) {lastError.clear(c)});
+ lastError.clear(chrome);
+ if (callerChrome !== chrome)
+ lastError.clear(callerChrome);
+
if (!success) {
if (!error)
error = "Unknown error.";
- $Array.forEach(chromesForLastError, function(c) {
- lastError.set(name, error, request.stack, c)
- });
+ lastError.set(name, error, request.stack, chrome);
+ if (callerChrome !== chrome)
+ lastError.set(name, error, request.stack, callerChrome);
}
if (request.customCallback) {
@@ -77,22 +77,21 @@
}
} finally {
delete requests[requestId];
- $Array.forEach(chromesForLastError, function(c) {lastError.clear(c)});
+ lastError.clear(chrome);
+ if (callerChrome !== chrome)
+ lastError.clear(callerChrome);
}
};
function getExtensionStackTrace(call_name) {
var stack = $String.split(new Error().stack, '\n');
+ var id = processNatives.GetExtensionId();
// Remove stack frames before and after that weren't associated with the
// extension.
- var id = processNatives.GetExtensionId();
- while (stack.length > 0 && stack[0].indexOf(id) == -1)
- stack.shift();
- while (stack.length > 0 && stack[stack.length - 1].indexOf(id) == -1)
- stack.pop();
-
- return stack.join('\n');
+ return $Array.join(stack.filter(function(line) {
+ return line.indexOf(id) != -1;
+ }), '\n');
}
function prepareRequest(args, argSchemas) {
diff --git a/chrome/renderer/resources/extensions/web_view.js b/chrome/renderer/resources/extensions/web_view.js
index b995ea9..a14c351 100644
--- a/chrome/renderer/resources/extensions/web_view.js
+++ b/chrome/renderer/resources/extensions/web_view.js
@@ -558,6 +558,9 @@
'api': 'webview',
'instanceId': self.viewInstanceId_
};
+ if (self.userAgentOverride_) {
+ params['userAgentOverride'] = self.userAgentOverride_;
+ }
self.browserPluginNode_['-internal-attach'](params);
var events = self.getEvents_();
@@ -568,6 +571,12 @@
this.browserPluginNode_.addEventListener('-internal-instanceid-allocated',
onInstanceIdAllocated);
this.setupWebRequestEvents_();
+
+ this.on_ = {};
+ var events = self.getEvents_();
+ for (var eventName in events) {
+ this.setupEventProperty_(eventName);
+ }
};
/**
@@ -595,6 +604,30 @@
};
/**
+ * Adds an 'on<event>' property on the webview, which can be used to set/unset
+ * an event handler.
+ * @private
+ */
+WebViewInternal.prototype.setupEventProperty_ = function(eventName) {
+ var propertyName = 'on' + eventName.toLowerCase();
+ var self = this;
+ var webviewNode = this.webviewNode_;
+ Object.defineProperty(webviewNode, propertyName, {
+ get: function() {
+ return self.on_[propertyName];
+ },
+ set: function(value) {
+ if (self.on_[propertyName])
+ webviewNode.removeEventListener(eventName, self.on_[propertyName]);
+ self.on_[propertyName] = value;
+ if (value)
+ webviewNode.addEventListener(eventName, value);
+ },
+ enumerable: true
+ });
+};
+
+/**
* @private
*/
WebViewInternal.prototype.getPermissionTypes_ = function() {
@@ -838,8 +871,8 @@
prototype: proto});
delete proto.createdCallback;
- delete proto.enteredDocumentCallback;
- delete proto.leftDocumentCallback;
+ delete proto.enteredViewCallback;
+ delete proto.leftViewCallback;
delete proto.attributeChangedCallback;
}
@@ -909,8 +942,8 @@
// Delete the callbacks so developers cannot call them and produce unexpected
// behavior.
delete proto.createdCallback;
- delete proto.enteredDocumentCallback;
- delete proto.leftDocumentCallback;
+ delete proto.enteredViewCallback;
+ delete proto.leftViewCallback;
delete proto.attributeChangedCallback;
}
diff --git a/chrome/renderer/resources/extensions/web_view_deny.js b/chrome/renderer/resources/extensions/web_view_deny.js
index 6566f86..5c86ec9 100644
--- a/chrome/renderer/resources/extensions/web_view_deny.js
+++ b/chrome/renderer/resources/extensions/web_view_deny.js
@@ -2,10 +2,37 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-var addTagWatcher = require("tagWatcher").addTagWatcher;
+var DocumentNatives = requireNative('document_natives');
-// Output error message to console when using <webview> tag with no permission.
-var errorMessage = "You do not have permission to use <webview> tag." +
- " Be sure to declare 'webview' permission in your manifest.";
+// Output error message to console when using the <webview> tag with no
+// permission.
+var errorMessage = "You do not have permission to use the webview element." +
+ " Be sure to declare the 'webview' permission in your manifest file.";
-addTagWatcher('WEBVIEW', function() { console.error(errorMessage); });
+// Registers <webview> custom element.
+function registerWebViewElement() {
+ var proto = Object.create(HTMLElement.prototype);
+
+ proto.createdCallback = function() {
+ console.error(errorMessage);
+ };
+
+ window.WebView =
+ DocumentNatives.RegisterElement('webview', {prototype: proto});
+
+ // Delete the callbacks so developers cannot call them and produce unexpected
+ // behavior.
+ delete proto.createdCallback;
+ delete proto.enteredDocumentCallback;
+ delete proto.leftDocumentCallback;
+ delete proto.attributeChangedCallback;
+}
+
+var useCapture = true;
+window.addEventListener('readystatechange', function listener(event) {
+ if (document.readyState == 'loading')
+ return;
+
+ registerWebViewElement();
+ window.removeEventListener(event.type, listener, useCapture);
+}, useCapture);
diff --git a/chrome/renderer/resources/extensions/web_view_experimental.js b/chrome/renderer/resources/extensions/web_view_experimental.js
index afa20b1..ee8f089 100644
--- a/chrome/renderer/resources/extensions/web_view_experimental.js
+++ b/chrome/renderer/resources/extensions/web_view_experimental.js
@@ -113,13 +113,12 @@
}
};
-/**
- * @private
- */
+/** @private */
WebViewInternal.prototype.maybeGetExperimentalEvents_ = function() {
return WEB_VIEW_EXPERIMENTAL_EVENTS;
};
+/** @private */
WebViewInternal.prototype.clearData_ = function(var_args) {
if (!this.instanceId_) {
return;
@@ -128,9 +127,43 @@
$Function.apply(WebView.clearData, null, args);
};
+/** @private */
+WebViewInternal.prototype.getUserAgent_ = function() {
+ return this.userAgentOverride_ || navigator.userAgent;
+};
+
+/** @private */
+WebViewInternal.prototype.isUserAgentOverridden_ = function() {
+ return !!this.userAgentOverride_ &&
+ this.userAgentOverride_ != navigator.userAgent;
+};
+
+/** @private */
+WebViewInternal.prototype.setUserAgentOverride_ = function(userAgentOverride) {
+ this.userAgentOverride_ = userAgentOverride;
+ if (!this.instanceId_) {
+ // If we are not attached yet, then we will pick up the user agent on
+ // attachment.
+ return;
+ }
+ WebView.overrideUserAgent(this.instanceId_, userAgentOverride);
+};
+
WebViewInternal.maybeRegisterExperimentalAPIs = function(proto, secret) {
proto.clearData = function(var_args) {
var internal = this.internal_(secret);
$Function.apply(internal.clearData_, internal, arguments);
};
+
+ proto.getUserAgent = function() {
+ return this.internal_(secret).getUserAgent_();
+ };
+
+ proto.isUserAgentOverridden = function() {
+ return this.internal_(secret).isUserAgentOverridden_();
+ };
+
+ proto.setUserAgentOverride = function(userAgentOverride) {
+ this.internal_(secret).setUserAgentOverride_(userAgentOverride);
+ };
};
diff --git a/chrome/service/cloud_print/cloud_print_connector.cc b/chrome/service/cloud_print/cloud_print_connector.cc
index 75cfe70..27372cf 100644
--- a/chrome/service/cloud_print/cloud_print_connector.cc
+++ b/chrome/service/cloud_print/cloud_print_connector.cc
@@ -124,6 +124,17 @@
}
}
+void CloudPrintConnector::UpdatePrinterSettings(const std::string& printer_id) {
+ // Since connector is managing many printers we need to go through all of them
+ // to select the correct settings.
+ GURL printer_list_url = GetUrlForPrinterList(
+ settings_.server_url(), settings_.proxy_id());
+ StartGetRequest(
+ printer_list_url,
+ kCloudPrintRegisterMaxRetryCount,
+ &CloudPrintConnector::HandlePrinterListResponseSettingsUpdate);
+}
+
void CloudPrintConnector::OnPrinterAdded() {
AddPendingAvailableTask();
}
@@ -182,6 +193,8 @@
if (!succeeded)
return CloudPrintURLFetcher::RETRY_REQUEST;
+ UpdateSettingsFromPrintersList(json_data);
+
// Now we need to get the list of printers from the print system
// and split printers into 3 categories:
// - existing and registered printers
@@ -252,6 +265,20 @@
}
CloudPrintURLFetcher::ResponseAction
+CloudPrintConnector::HandlePrinterListResponseSettingsUpdate(
+ const net::URLFetcher* source,
+ const GURL& url,
+ DictionaryValue* json_data,
+ bool succeeded) {
+ DCHECK(succeeded);
+ if (!succeeded)
+ return CloudPrintURLFetcher::RETRY_REQUEST;
+
+ UpdateSettingsFromPrintersList(json_data);
+ return CloudPrintURLFetcher::STOP_PROCESSING;
+}
+
+CloudPrintURLFetcher::ResponseAction
CloudPrintConnector::HandlePrinterDeleteResponse(
const net::URLFetcher* source,
const GURL& url,
@@ -376,6 +403,12 @@
}
}
}
+
+ int xmpp_timeout = 0;
+ printer_data->GetInteger(kLocalSettingsPendingXmppValue, &xmpp_timeout);
+ printer_info_cloud.current_xmpp_timeout = settings_.xmpp_ping_timeout_sec();
+ printer_info_cloud.pending_xmpp_timeout = xmpp_timeout;
+
scoped_refptr<PrinterJobHandler> job_handler;
job_handler = new PrinterJobHandler(printer_info,
printer_info_cloud,
@@ -386,6 +419,32 @@
job_handler->Initialize();
}
+void CloudPrintConnector::UpdateSettingsFromPrintersList(
+ DictionaryValue* json_data) {
+ ListValue* printer_list = NULL;
+ int min_xmpp_timeout = std::numeric_limits<int>::max();
+ // There may be no "printers" value in the JSON
+ if (json_data->GetList(kPrinterListValue, &printer_list) && printer_list) {
+ for (size_t index = 0; index < printer_list->GetSize(); index++) {
+ DictionaryValue* printer_data = NULL;
+ if (printer_list->GetDictionary(index, &printer_data)) {
+ int xmpp_timeout = 0;
+ if (printer_data->GetInteger(kLocalSettingsPendingXmppValue,
+ &xmpp_timeout)) {
+ min_xmpp_timeout = std::min(xmpp_timeout, min_xmpp_timeout);
+ }
+ }
+ }
+ }
+
+ if (min_xmpp_timeout != std::numeric_limits<int>::max()) {
+ DCHECK(min_xmpp_timeout >= kMinXmppPingTimeoutSecs);
+ settings_.SetXmppPingTimeoutSec(min_xmpp_timeout);
+ client_->OnXmppPingUpdated(min_xmpp_timeout);
+ }
+}
+
+
void CloudPrintConnector::AddPendingAvailableTask() {
PendingTask task;
task.type = PENDING_PRINTERS_AVAILABLE;
@@ -536,6 +595,11 @@
net::AddMultipartValueForUpload(kPrinterStatusValue,
base::StringPrintf("%d", info.printer_status),
mime_boundary, std::string(), &post_data);
+ // Add local_settings with a current XMPP ping interval.
+ net::AddMultipartValueForUpload(kPrinterLocalSettingsValue,
+ base::StringPrintf(kCreateLocalSettingsXmppPingFormat,
+ settings_.xmpp_ping_timeout_sec()),
+ mime_boundary, std::string(), &post_data);
post_data += GetPostDataForPrinterInfo(info, mime_boundary);
net::AddMultipartValueForUpload(kPrinterCapsValue,
caps_and_defaults.printer_capabilities, mime_boundary,
diff --git a/chrome/service/cloud_print/cloud_print_connector.h b/chrome/service/cloud_print/cloud_print_connector.h
index 9e6c690..1cf1bd7 100644
--- a/chrome/service/cloud_print/cloud_print_connector.h
+++ b/chrome/service/cloud_print/cloud_print_connector.h
@@ -33,6 +33,7 @@
class Client {
public:
virtual void OnAuthFailed() = 0;
+ virtual void OnXmppPingUpdated(int ping_timeout) = 0;
protected:
virtual ~Client() {}
};
@@ -50,6 +51,9 @@
// jobs will be checked for all available printers.
void CheckForJobs(const std::string& reason, const std::string& printer_id);
+ // Update settings for specific printer.
+ void UpdatePrinterSettings(const std::string& printer_id);
+
private:
friend class base::RefCountedThreadSafe<CloudPrintConnector>;
@@ -106,6 +110,12 @@
DictionaryValue* json_data,
bool succeeded);
+ CloudPrintURLFetcher::ResponseAction HandlePrinterListResponseSettingsUpdate(
+ const net::URLFetcher* source,
+ const GURL& url,
+ DictionaryValue* json_data,
+ bool succeeded);
+
CloudPrintURLFetcher::ResponseAction HandlePrinterDeleteResponse(
const net::URLFetcher* source,
const GURL& url,
@@ -138,6 +148,8 @@
void InitJobHandlerForPrinter(DictionaryValue* printer_data);
+ void UpdateSettingsFromPrintersList(DictionaryValue* json_data);
+
void AddPendingAvailableTask();
void AddPendingDeleteTask(const std::string& id);
void AddPendingRegisterTask(const printing::PrinterBasicInfo& info);
diff --git a/chrome/service/cloud_print/cloud_print_helpers.cc b/chrome/service/cloud_print/cloud_print_helpers.cc
index 716c17e..8479c16 100644
--- a/chrome/service/cloud_print/cloud_print_helpers.cc
+++ b/chrome/service/cloud_print/cloud_print_helpers.cc
@@ -32,16 +32,18 @@
return ret;
}
-}
+} // namespace
namespace cloud_print {
GURL GetUrlForJobStatusUpdate(const GURL& cloud_print_server_url,
const std::string& job_id,
- PrintJobStatus status) {
+ PrintJobStatus status,
+ int connector_code) {
return GetUrlForJobStatusUpdate(cloud_print_server_url,
job_id,
- StringFromJobStatus(status));
+ StringFromJobStatus(status),
+ connector_code);
}
GURL GetUrlForJobStatusUpdate(const GURL& cloud_print_server_url,
diff --git a/chrome/service/cloud_print/cloud_print_helpers.h b/chrome/service/cloud_print/cloud_print_helpers.h
index a180d2a..7bfaddb 100644
--- a/chrome/service/cloud_print/cloud_print_helpers.h
+++ b/chrome/service/cloud_print/cloud_print_helpers.h
@@ -16,7 +16,8 @@
// Helper methods for the cloud print proxy code.
GURL GetUrlForJobStatusUpdate(const GURL& cloud_print_server_url,
const std::string& job_id,
- PrintJobStatus status);
+ PrintJobStatus status,
+ int connector_code);
GURL GetUrlForJobStatusUpdate(const GURL& cloud_print_server_url,
const std::string& job_id,
diff --git a/chrome/service/cloud_print/cloud_print_helpers_unittest.cc b/chrome/service/cloud_print/cloud_print_helpers_unittest.cc
index baa8903..258e40b 100644
--- a/chrome/service/cloud_print/cloud_print_helpers_unittest.cc
+++ b/chrome/service/cloud_print/cloud_print_helpers_unittest.cc
@@ -19,10 +19,11 @@
if (expected_url_base[expected_url_base.length() - 1] != '/')
expected_url_base += "/";
- EXPECT_EQ(base::StringPrintf("%scontrol?jobid=87654321&status=ERROR",
+ EXPECT_EQ(base::StringPrintf(
+ "%scontrol?jobid=87654321&status=ERROR&connector_code=1",
expected_url_base.c_str()),
GetUrlForJobStatusUpdate(server_base_url, "87654321",
- PRINT_JOB_STATUS_ERROR).spec());
+ PRINT_JOB_STATUS_ERROR, 1).spec());
PrintJobDetails details;
details.status = PRINT_JOB_STATUS_IN_PROGRESS;
diff --git a/chrome/service/cloud_print/cloud_print_proxy.cc b/chrome/service/cloud_print/cloud_print_proxy.cc
index 24af3dc..eb22186 100644
--- a/chrome/service/cloud_print/cloud_print_proxy.cc
+++ b/chrome/service/cloud_print/cloud_print_proxy.cc
@@ -254,6 +254,12 @@
wipeout_->UnregisterPrinters(auth_token, printer_ids);
}
+void CloudPrintProxy::OnXmppPingUpdated(int ping_timeout) {
+ DCHECK(CalledOnValidThread());
+ service_prefs_->SetInt(prefs::kCloudPrintXmppPingTimeout, ping_timeout);
+ service_prefs_->WritePrefs();
+}
+
void CloudPrintProxy::OnUnregisterPrintersComplete() {
wipeout_.reset();
// Finish disabling cloud print for this user.
diff --git a/chrome/service/cloud_print/cloud_print_proxy.h b/chrome/service/cloud_print/cloud_print_proxy.h
index 507eb9e..71c2d66 100644
--- a/chrome/service/cloud_print/cloud_print_proxy.h
+++ b/chrome/service/cloud_print/cloud_print_proxy.h
@@ -68,6 +68,7 @@
virtual void OnUnregisterPrinters(
const std::string& auth_token,
const std::list<std::string>& printer_ids) OVERRIDE;
+ virtual void OnXmppPingUpdated(int ping_timeout) OVERRIDE;
// CloudPrintWipeout::Client implementation.
virtual void OnUnregisterPrintersComplete() OVERRIDE;
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
index 0125d71..db8a4d9 100644
--- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc
+++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
@@ -74,6 +74,7 @@
// CloudPrintConnector::Client implementation.
virtual void OnAuthFailed() OVERRIDE;
+ virtual void OnXmppPingUpdated(int ping_timeout) OVERRIDE;
// notifier::PushClientObserver implementation.
virtual void OnNotificationsEnabled() OVERRIDE;
@@ -103,12 +104,13 @@
void NotifyPrintSystemUnavailable();
void NotifyUnregisterPrinters(const std::string& auth_token,
const std::list<std::string>& printer_ids);
+ void NotifyXmppPingUpdated(int ping_timeout);
// Init XMPP channel
void InitNotifications(const std::string& robot_email,
const std::string& access_token);
- void HandlePrinterNotification(const std::string& printer_id);
+ void HandlePrinterNotification(const std::string& notification);
void PollForJobs();
// Schedules a task to poll for jobs. Does nothing if a task is already
// scheduled.
@@ -320,6 +322,13 @@
auth_->RefreshAccessToken();
}
+void CloudPrintProxyBackend::Core::OnXmppPingUpdated(int ping_timeout) {
+ settings_.SetXmppPingTimeoutSec(ping_timeout);
+ backend_->frontend_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&Core::NotifyXmppPingUpdated, this, ping_timeout));
+}
+
void CloudPrintProxyBackend::Core::InitNotifications(
const std::string& robot_email,
const std::string& access_token) {
@@ -375,10 +384,20 @@
}
void CloudPrintProxyBackend::Core::HandlePrinterNotification(
- const std::string& printer_id) {
+ const std::string& notification) {
DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
- VLOG(1) << "CP_CONNECTOR: Handle printer notification, id: " << printer_id;
- connector_->CheckForJobs(kJobFetchReasonNotified, printer_id);
+
+ size_t pos = notification.rfind(kNotificationUpdateSettings);
+ if (pos == std::string::npos) {
+ VLOG(1) << "CP_CONNECTOR: Handle printer notification, id: "
+ << notification;
+ connector_->CheckForJobs(kJobFetchReasonNotified, notification);
+ } else {
+ DCHECK(pos == notification.length() - strlen(kNotificationUpdateSettings));
+ std::string printer_id = notification.substr(0, pos);
+ VLOG(1) << "CP_CONNECTOR: Update printer settings, id: " << printer_id;
+ connector_->UpdatePrinterSettings(printer_id);
+ }
}
void CloudPrintProxyBackend::Core::PollForJobs() {
@@ -429,9 +448,8 @@
}
void CloudPrintProxyBackend::Core::ScheduleXmppPing() {
- if (!settings_.xmpp_ping_enabled())
- return;
-
+ // settings_.xmpp_ping_enabled() is obsolete, we are now control
+ // XMPP pings from Cloud Print server.
if (!xmpp_ping_scheduled_) {
base::TimeDelta interval = base::TimeDelta::FromSeconds(
base::RandInt(settings_.xmpp_ping_timeout_sec() * 0.9,
@@ -486,6 +504,11 @@
backend_->frontend_->OnUnregisterPrinters(auth_token, printer_ids);
}
+void CloudPrintProxyBackend::Core::NotifyXmppPingUpdated(int ping_timeout) {
+ DCHECK(base::MessageLoop::current() == backend_->frontend_loop_);
+ backend_->frontend_->OnXmppPingUpdated(ping_timeout);
+}
+
void CloudPrintProxyBackend::Core::OnNotificationsEnabled() {
DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
notifications_enabled_ = true;
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.h b/chrome/service/cloud_print/cloud_print_proxy_backend.h
index 403ea18..217f842 100644
--- a/chrome/service/cloud_print/cloud_print_proxy_backend.h
+++ b/chrome/service/cloud_print/cloud_print_proxy_backend.h
@@ -44,6 +44,8 @@
virtual void OnUnregisterPrinters(
const std::string& auth_token,
const std::list<std::string>& printer_ids) = 0;
+ // Update and store service settings.
+ virtual void OnXmppPingUpdated(int ping_timeout) = 0;
protected:
// Don't delete through SyncFrontend interface.
diff --git a/chrome/service/cloud_print/connector_settings.cc b/chrome/service/cloud_print/connector_settings.cc
index f97a7ec..c2137e4 100644
--- a/chrome/service/cloud_print/connector_settings.cc
+++ b/chrome/service/cloud_print/connector_settings.cc
@@ -116,10 +116,10 @@
void ConnectorSettings::SetXmppPingTimeoutSec(int timeout) {
xmpp_ping_timeout_sec_ = timeout;
- if (xmpp_ping_timeout_sec_ < kMinimumXmppPingTimeoutSecs) {
+ if (xmpp_ping_timeout_sec_ < kMinXmppPingTimeoutSecs) {
LOG(WARNING) <<
"CP_CONNECTOR: XMPP ping timeout is less then minimal value";
- xmpp_ping_timeout_sec_ = kMinimumXmppPingTimeoutSecs;
+ xmpp_ping_timeout_sec_ = kMinXmppPingTimeoutSecs;
}
}
diff --git a/chrome/service/cloud_print/connector_settings.h b/chrome/service/cloud_print/connector_settings.h
index ec811a4..18ce5af 100644
--- a/chrome/service/cloud_print/connector_settings.h
+++ b/chrome/service/cloud_print/connector_settings.h
@@ -55,6 +55,8 @@
bool ShouldConnect(const std::string& printer_name) const;
+ void SetXmppPingTimeoutSec(int timeout);
+
private:
friend class ConnectorSettingsTest;
FRIEND_TEST_ALL_PREFIXES(ConnectorSettingsTest, SettersTest);
@@ -63,8 +65,6 @@
xmpp_ping_enabled_ = enabled;
}
- void SetXmppPingTimeoutSec(int timeout);
-
// Cloud Print server url.
GURL server_url_;
diff --git a/chrome/service/cloud_print/connector_settings_unittest.cc b/chrome/service/cloud_print/connector_settings_unittest.cc
index 9586aa7..6645150 100644
--- a/chrome/service/cloud_print/connector_settings_unittest.cc
+++ b/chrome/service/cloud_print/connector_settings_unittest.cc
@@ -146,7 +146,7 @@
// Set invalid settings, and check correct defaults.
settings.SetXmppPingTimeoutSec(1);
- EXPECT_EQ(settings.xmpp_ping_timeout_sec(), kMinimumXmppPingTimeoutSecs);
+ EXPECT_EQ(settings.xmpp_ping_timeout_sec(), kMinXmppPingTimeoutSecs);
}
} // namespace cloud_print
diff --git a/chrome/service/cloud_print/print_system_cups.cc b/chrome/service/cloud_print/print_system_cups.cc
index 18c4d4c..1758bd7 100644
--- a/chrome/service/cloud_print/print_system_cups.cc
+++ b/chrome/service/cloud_print/print_system_cups.cc
@@ -37,10 +37,6 @@
namespace {
-// CUPS specific options.
-const char kCUPSPrinterInfoOpt[] = "printer-info";
-const char kCUPSPrinterStateOpt[] = "printer-state";
-
// Print system config options.
const char kCUPSPrintServerURLs[] = "print_server_urls";
const char kCUPSUpdateTimeoutMs[] = "update_timeout_ms";
@@ -52,9 +48,6 @@
const char kCUPSDefaultSupportedTypes[] =
"application/pdf,application/postscript,image/jpeg,image/png,image/gif";
-// Default port for IPP print servers.
-const int kDefaultIPPServerPort = 631;
-
// Time interval to check for printer's updates.
const int kCheckForPrinterUpdatesMinutes = 5;
diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc
index 22371b8..6a4f1bb 100644
--- a/chrome/service/cloud_print/printer_job_handler.cc
+++ b/chrome/service/cloud_print/printer_job_handler.cc
@@ -26,6 +26,10 @@
namespace cloud_print {
+PrinterJobHandler::PrinterInfoFromCloud::PrinterInfoFromCloud()
+ : current_xmpp_timeout(0), pending_xmpp_timeout(0) {
+}
+
PrinterJobHandler::PrinterJobHandler(
const printing::PrinterBasicInfo& printer_info,
const PrinterInfoFromCloud& printer_info_cloud,
@@ -304,7 +308,7 @@
accept_headers);
} else {
// The print ticket was not valid. We are done here.
- FailedFetchingJobData();
+ ValidatePrintTicketFailed();
}
return CloudPrintURLFetcher::STOP_PROCESSING;
}
@@ -477,7 +481,7 @@
request_ = CloudPrintURLFetcher::Create();
request_->StartGetRequest(
GetUrlForJobStatusUpdate(cloud_print_server_url_, job_details_.job_id_,
- status),
+ status, error),
this, kCloudPrintAPIMaxRetryCount, std::string());
}
@@ -569,12 +573,12 @@
return (job_check_pending_ || printer_update_pending_);
}
-void PrinterJobHandler::FailedFetchingJobData() {
+void PrinterJobHandler::ValidatePrintTicketFailed() {
if (!shutting_down_) {
- LOG(ERROR) << "CP_CONNECTOR: Failed fetching job data"
+ LOG(ERROR) << "CP_CONNECTOR: Failed validating print ticket"
<< ", printer name: " << printer_info_.printer_name
<< ", job id: " << job_details_.job_id_;
- JobFailed(INVALID_JOB_DATA);
+ JobFailed(VALIDATE_PRINT_TICKET_FAILED);
}
}
@@ -636,6 +640,16 @@
base::StringPrintf("%d", printer_info.printer_status), mime_boundary,
std::string(), &post_data);
}
+
+ // Add local_settings with a current XMPP ping interval.
+ if (printer_info_cloud_.pending_xmpp_timeout != 0) {
+ DCHECK(kMinXmppPingTimeoutSecs <= printer_info_cloud_.pending_xmpp_timeout);
+ net::AddMultipartValueForUpload(kPrinterLocalSettingsValue,
+ base::StringPrintf(kUpdateLocalSettingsXmppPingFormat,
+ printer_info_cloud_.current_xmpp_timeout),
+ mime_boundary, std::string(), &post_data);
+ }
+
printer_info_ = printer_info;
if (!post_data.empty()) {
net::AddMultipartFinalDelimiterForUpload(mime_boundary, &post_data);
diff --git a/chrome/service/cloud_print/printer_job_handler.h b/chrome/service/cloud_print/printer_job_handler.h
index fc74e77..10c74ed 100644
--- a/chrome/service/cloud_print/printer_job_handler.h
+++ b/chrome/service/cloud_print/printer_job_handler.h
@@ -85,6 +85,10 @@
std::string printer_id;
std::string caps_hash;
std::string tags_hash;
+ int current_xmpp_timeout;
+ int pending_xmpp_timeout;
+
+ PrinterInfoFromCloud();
};
// Begin public interface
@@ -153,7 +157,7 @@
enum PrintJobError {
SUCCESS,
JOB_DOWNLOAD_FAILED,
- INVALID_JOB_DATA,
+ VALIDATE_PRINT_TICKET_FAILED,
PRINT_FAILED,
};
@@ -233,7 +237,7 @@
// Returns false if printer info is up to date and no updating is needed.
bool UpdatePrinterInfo();
bool HavePendingTasks();
- void FailedFetchingJobData();
+ void ValidatePrintTicketFailed();
// Callback that asynchronously receives printer caps and defaults.
void OnReceivePrinterCaps(
@@ -283,6 +287,9 @@
bool job_check_pending_;
bool printer_update_pending_;
+ // Number of seconds between XMPP pings (for server registration)
+ int xmpp_ping_interval_;
+
// Some task in the state machine is in progress.
bool task_in_progress_;
scoped_refptr<PrintSystem::PrinterWatcher> printer_watcher_;
diff --git a/chrome/service/cloud_print/printer_job_handler_unittest.cc b/chrome/service/cloud_print/printer_job_handler_unittest.cc
index 13736d3..a41b3e8 100644
--- a/chrome/service/cloud_print/printer_job_handler_unittest.cc
+++ b/chrome/service/cloud_print/printer_job_handler_unittest.cc
@@ -231,7 +231,8 @@
std::string InProgressURI(int job_num) {
return GetUrlForJobStatusUpdate(GURL(kExampleCloudPrintServerURL),
StringPrintf(kExampleJobID, job_num),
- PRINT_JOB_STATUS_IN_PROGRESS).spec();
+ PRINT_JOB_STATUS_IN_PROGRESS,
+ 0).spec();
}
std::string StatusResponse(int job_num, const char* status_string) {
@@ -474,6 +475,8 @@
info_from_cloud_.tags_hash = GetHashOfPrinterInfo(basic_info_);
info_from_cloud_.caps_hash = base::MD5String(kExamplePrinterCapabilities);
+ info_from_cloud_.current_xmpp_timeout = 300;
+ info_from_cloud_.pending_xmpp_timeout = 0;
caps_and_defaults_.printer_capabilities = kExamplePrinterCapabilities;
caps_and_defaults_.caps_mime_type = kExampleCapsMimeType;
diff --git a/chrome/test/automation/automation_json_requests.cc b/chrome/test/automation/automation_json_requests.cc
deleted file mode 100644
index 4c0ad42..0000000
--- a/chrome/test/automation/automation_json_requests.cc
+++ /dev/null
@@ -1,945 +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/automation/automation_json_requests.h"
-
-#include "base/basictypes.h"
-#include "base/files/file_path.h"
-#include "base/format_macros.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_string_value_serializer.h"
-#include "base/json/json_writer.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/test_timeouts.h"
-#include "base/time/time.h"
-#include "base/values.h"
-#include "chrome/common/automation_messages.h"
-#include "chrome/test/automation/automation_proxy.h"
-
-using automation::Error;
-using automation::ErrorCode;
-using base::DictionaryValue;
-using base::ListValue;
-
-namespace {
-
-bool SendAutomationJSONRequest(AutomationMessageSender* sender,
- const DictionaryValue& request_dict,
- DictionaryValue* reply_dict,
- Error* error) {
- std::string request, reply;
- base::JSONWriter::Write(&request_dict, &request);
- std::string command;
- request_dict.GetString("command", &command);
- LOG(INFO) << "Sending '" << command << "' command.";
-
- base::Time before_sending = base::Time::Now();
- bool success = false;
- if (!SendAutomationJSONRequestWithDefaultTimeout(
- sender, request, &reply, &success)) {
- *error = Error(base::StringPrintf(
- "Chrome did not respond to '%s'. Elapsed time was %" PRId64 " ms.",
- command.c_str(),
- (base::Time::Now() - before_sending).InMilliseconds()));
- LOG(INFO) << error->message();
- return false;
- }
- scoped_ptr<Value> value(
- base::JSONReader::Read(reply, base::JSON_ALLOW_TRAILING_COMMAS));
- if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) {
- *error = Error("JSON request did not return a dictionary");
- LOG(ERROR) << "JSON request did not return dict: " << command << "\n";
- return false;
- }
- DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
- if (!success) {
- std::string error_msg;
- dict->GetString("error", &error_msg);
- int int_code = automation::kUnknownError;
- dict->GetInteger("code", &int_code);
- ErrorCode code = static_cast<ErrorCode>(int_code);
- *error = Error(code, error_msg);
- LOG(INFO) << "JSON request failed: " << command << "\n"
- << " with error: " << error_msg;
- return false;
- }
- reply_dict->MergeDictionary(dict);
- return true;
-}
-
-} // namespace
-
-WebKeyEvent::WebKeyEvent(automation::KeyEventTypes type,
- ui::KeyboardCode key_code,
- const std::string& unmodified_text,
- const std::string& modified_text,
- int modifiers)
- : type(type),
- key_code(key_code),
- unmodified_text(unmodified_text),
- modified_text(modified_text),
- modifiers(modifiers) {}
-
-WebMouseEvent::WebMouseEvent(automation::MouseEventType type,
- automation::MouseButton button,
- int x,
- int y,
- int click_count,
- int modifiers)
- : type(type),
- button(button),
- x(x),
- y(y),
- click_count(click_count),
- modifiers(modifiers) {}
-
-// static
-WebViewId WebViewId::ForView(const AutomationId& view_id) {
- WebViewId id;
- id.old_style_ = false;
- id.id_ = view_id;
- return id;
-}
-
-// static
-WebViewId WebViewId::ForOldStyleTab(int tab_id) {
- WebViewId id;
- id.old_style_ = true;
- id.tab_id_ = tab_id;
- return id;
-}
-
-WebViewId::WebViewId() : old_style_(true) {}
-
-void WebViewId::UpdateDictionary(DictionaryValue* dict,
- const std::string& view_id_key) const {
- if (old_style_) {
- dict->SetInteger("id", tab_id_);
- } else {
- dict->Set(view_id_key, id_.ToValue());
- }
-}
-
-bool WebViewId::IsValid() const {
- if (old_style_)
- return tab_id_ != 0;
- else
- return id_.is_valid();
-}
-
-AutomationId WebViewId::GetId() const {
- if (old_style_)
- return AutomationId(AutomationId::kTypeTab, base::IntToString(tab_id_));
- else
- return id_;
-}
-
-bool WebViewId::IsTab() const {
- return old_style_ || id_.type() == AutomationId::kTypeTab;
-}
-
-int WebViewId::tab_id() const {
- return tab_id_;
-}
-
-bool WebViewId::old_style() const {
- return old_style_;
-}
-
-// static
-WebViewLocator WebViewLocator::ForIndexPair(int browser_index, int tab_index) {
- WebViewLocator locator;
- locator.type_ = kTypeIndexPair;
- locator.locator_.index_pair.browser_index = browser_index;
- locator.locator_.index_pair.tab_index = tab_index;
- return locator;
-}
-
-// static
-WebViewLocator WebViewLocator::ForViewId(const AutomationId& view_id) {
- WebViewLocator locator;
- locator.type_ = kTypeViewId;
- locator.locator_.view_id = view_id;
- return locator;
-}
-
-WebViewLocator::WebViewLocator() {}
-
-WebViewLocator::~WebViewLocator() {}
-
-void WebViewLocator::UpdateDictionary(
- DictionaryValue* dict, const std::string& view_id_key) const {
- if (type_ == kTypeIndexPair) {
- dict->SetInteger("windex", locator_.index_pair.browser_index);
- dict->SetInteger("tab_index", locator_.index_pair.tab_index);
- } else if (type_ == kTypeViewId) {
- dict->Set(view_id_key, locator_.view_id.ToValue());
- }
-}
-
-int WebViewLocator::browser_index() const {
- return locator_.index_pair.browser_index;
-}
-
-int WebViewLocator::tab_index() const {
- return locator_.index_pair.tab_index;
-}
-
-WebViewLocator::Locator::Locator() {}
-
-WebViewLocator::Locator::~Locator() {}
-
-WebViewInfo::WebViewInfo(const WebViewId& view_id,
- const std::string& extension_id)
- : view_id(view_id),
- extension_id(extension_id) {}
-
-WebViewInfo::~WebViewInfo() {}
-
-bool SendAutomationJSONRequest(AutomationMessageSender* sender,
- const std::string& request,
- int timeout_ms,
- std::string* reply,
- bool* success) {
- return sender->Send(new AutomationMsg_SendJSONRequest(
- -1, request, reply, success), timeout_ms);
-}
-
-bool SendAutomationJSONRequestWithDefaultTimeout(
- AutomationMessageSender* sender,
- const std::string& request,
- std::string* reply,
- bool* success) {
- return sender->Send(new AutomationMsg_SendJSONRequest(
- -1, request, reply, success));
-}
-
-bool SendGetIndicesFromTabIdJSONRequest(
- AutomationMessageSender* sender,
- int tab_id,
- int* browser_index,
- int* tab_index,
- Error* error) {
- DictionaryValue request_dict;
- request_dict.SetString("command", "GetIndicesFromTab");
- request_dict.SetInteger("tab_id", tab_id);
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict, error))
- return false;
- if (!reply_dict.GetInteger("windex", browser_index))
- return false;
- if (!reply_dict.GetInteger("tab_index", tab_index))
- return false;
- return true;
-}
-
-bool SendGetIndicesFromTabHandleJSONRequest(
- AutomationMessageSender* sender,
- int tab_handle,
- int* browser_index,
- int* tab_index,
- Error* error) {
- DictionaryValue request_dict;
- request_dict.SetString("command", "GetIndicesFromTab");
- request_dict.SetInteger("tab_handle", tab_handle);
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict, error))
- return false;
- if (!reply_dict.GetInteger("windex", browser_index))
- return false;
- if (!reply_dict.GetInteger("tab_index", tab_index))
- return false;
- return true;
-}
-
-bool SendNavigateToURLJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const std::string& url,
- int navigation_count,
- AutomationMsg_NavigationResponseValues* nav_response,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "NavigateToURL");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetString("url", url);
- dict.SetInteger("navigation_count", navigation_count);
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- // We don't expect a navigation result for asynchronous navigations.
- if (navigation_count == 0)
- return true;
- int response = 0;
- if (!reply_dict.GetInteger("result", &response))
- return false;
- *nav_response = static_cast<AutomationMsg_NavigationResponseValues>(response);
- return true;
-}
-
-bool SendExecuteJavascriptJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const std::string& frame_xpath,
- const std::string& javascript,
- scoped_ptr<Value>* result,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "ExecuteJavascript");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetString("frame_xpath", frame_xpath);
- dict.SetString("javascript", javascript);
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
-
- std::string json;
- if (!reply_dict.GetString("result", &json)) {
- LOG(ERROR) << "Executed javascript but received no 'result'";
- return false;
- }
- // Wrap |json| in an array before deserializing because valid JSON has an
- // array or an object as the root.
- json.insert(0, "[");
- json.append("]");
-
- JSONStringValueSerializer deserializer(json);
- Value* value = deserializer.Deserialize(NULL, NULL);
- if (!value || !value->IsType(Value::TYPE_LIST)) {
- LOG(ERROR) << "Unable to deserialize returned JSON";
- return false;
- }
- scoped_ptr<ListValue> list(static_cast<ListValue*>(value));
- return list->Remove(0, result);
-}
-
-bool SendGoForwardJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "GoForward");
- locator.UpdateDictionary(&dict, "auto_id");
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendGoBackJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "GoBack");
- locator.UpdateDictionary(&dict, "auto_id");
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendReloadJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "Reload");
- locator.UpdateDictionary(&dict, "auto_id");
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendCaptureEntirePageJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const base::FilePath& path,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "CaptureEntirePage");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetString("path", path.value());
- DictionaryValue reply_dict;
-
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-#if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
-bool SendHeapProfilerDumpJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const std::string& reason,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "HeapProfilerDump");
- dict.SetString("process_type", "renderer");
- dict.SetString("reason", reason);
- locator.UpdateDictionary(&dict, "auto_id");
- DictionaryValue reply_dict;
-
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-#endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
-
-bool SendGetCookiesJSONRequest(
- AutomationMessageSender* sender,
- const std::string& url,
- scoped_ptr<ListValue>* cookies,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "GetCookies");
- dict.SetString("url", url);
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- scoped_ptr<Value> cookies_value;
- if (!reply_dict.Remove("cookies", &cookies_value))
- return false;
- if (!cookies_value->IsType(Value::TYPE_LIST))
- return false;
- cookies->reset(static_cast<ListValue*>(cookies_value.release()));
- return true;
-}
-
-bool SendDeleteCookieJSONRequest(
- AutomationMessageSender* sender,
- const std::string& url,
- const std::string& cookie_name,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "DeleteCookie");
- dict.SetString("url", url);
- dict.SetString("name", cookie_name);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendSetCookieJSONRequest(
- AutomationMessageSender* sender,
- const std::string& url,
- DictionaryValue* cookie_dict,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "SetCookie");
- dict.SetString("url", url);
- dict.Set("cookie", cookie_dict->DeepCopy());
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendGetTabIdsJSONRequest(
- AutomationMessageSender* sender,
- std::vector<WebViewInfo>* views,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "GetTabIds");
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- ListValue* id_list;
- if (reply_dict.GetList("ids", &id_list)) {
- for (size_t i = 0; i < id_list->GetSize(); ++i) {
- int id;
- if (!id_list->GetInteger(i, &id)) {
- *error = Error("Returned id in 'tab_ids' is not an integer");
- return false;
- }
- views->push_back(WebViewInfo(
- WebViewId::ForOldStyleTab(id), std::string()));
- }
- }
- return true;
-}
-
-bool SendGetWebViewsJSONRequest(
- AutomationMessageSender* sender,
- std::vector<WebViewInfo>* views,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "GetViews");
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- ListValue* views_list;
- if (!reply_dict.GetList("views", &views_list)) {
- *error = Error("Returned 'views' key is missing or invalid");
- return false;
- }
- for (size_t i = 0; i < views_list->GetSize(); ++i) {
- DictionaryValue* view_dict;
- if (!views_list->GetDictionary(i, &view_dict)) {
- *error = Error("Returned 'views' key contains non-dictionary values");
- return false;
- }
- AutomationId view_id;
- std::string error_msg;
- if (!AutomationId::FromValueInDictionary(
- view_dict, "auto_id", &view_id, &error_msg)) {
- *error = Error(error_msg);
- return false;
- }
- std::string extension_id;
- view_dict->GetString("extension_id", &extension_id);
- views->push_back(WebViewInfo(
- WebViewId::ForView(view_id), extension_id));
- }
- return true;
-}
-
-bool SendIsTabIdValidJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& view_id,
- bool* is_valid,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "IsTabIdValid");
- view_id.UpdateDictionary(&dict, "tab_id");
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- return reply_dict.GetBoolean("is_valid", is_valid);
-}
-
-bool SendDoesAutomationObjectExistJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& view_id,
- bool* does_exist,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "DoesAutomationObjectExist");
- view_id.UpdateDictionary(&dict, "auto_id");
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- return reply_dict.GetBoolean("does_exist", does_exist);
-}
-
-bool SendCloseViewJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "CloseTab");
- locator.UpdateDictionary(&dict, "auto_id");
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendMouseMoveJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "WebkitMouseMove");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("x", x);
- dict.SetInteger("y", y);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendMouseClickJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- automation::MouseButton button,
- int x,
- int y,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "WebkitMouseClick");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("button", button);
- dict.SetInteger("x", x);
- dict.SetInteger("y", y);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendMouseDragJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int start_x,
- int start_y,
- int end_x,
- int end_y,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "WebkitMouseDrag");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("start_x", start_x);
- dict.SetInteger("start_y", start_y);
- dict.SetInteger("end_x", end_x);
- dict.SetInteger("end_y", end_y);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendMouseButtonDownJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "WebkitMouseButtonDown");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("x", x);
- dict.SetInteger("y", y);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendMouseButtonUpJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "WebkitMouseButtonUp");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("x", x);
- dict.SetInteger("y", y);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendMouseDoubleClickJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "WebkitMouseDoubleClick");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("x", x);
- dict.SetInteger("y", y);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendWebKeyEventJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const WebKeyEvent& key_event,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "SendWebkitKeyEvent");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("type", key_event.type);
- dict.SetInteger("nativeKeyCode", key_event.key_code);
- dict.SetInteger("windowsKeyCode", key_event.key_code);
- dict.SetString("unmodifiedText", key_event.unmodified_text);
- dict.SetString("text", key_event.modified_text);
- dict.SetInteger("modifiers", key_event.modifiers);
- dict.SetBoolean("isSystemKey", false);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendNativeKeyEventJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- ui::KeyboardCode key_code,
- int modifiers,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "SendOSLevelKeyEventToTab");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("keyCode", key_code);
- dict.SetInteger("modifiers", modifiers);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendWebMouseEventJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const WebMouseEvent& mouse_event,
- automation::Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "ProcessWebMouseEvent");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("type", mouse_event.type);
- dict.SetInteger("button", mouse_event.button);
- dict.SetInteger("x", mouse_event.x);
- dict.SetInteger("y", mouse_event.y);
- dict.SetInteger("click_count", mouse_event.click_count);
- dict.SetInteger("modifiers", mouse_event.modifiers);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendDragAndDropFilePathsJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- const std::vector<base::FilePath::StringType>& paths,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "DragAndDropFilePaths");
- locator.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("x", x);
- dict.SetInteger("y", y);
-
- ListValue* list_value = new ListValue();
- for (size_t path_index = 0; path_index < paths.size(); ++path_index) {
- list_value->Append(new base::StringValue(paths[path_index]));
- }
- dict.Set("paths", list_value);
-
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendSetViewBoundsJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& id,
- int x,
- int y,
- int width,
- int height,
- automation::Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "SetViewBounds");
- id.UpdateDictionary(&dict, "auto_id");
- dict.SetInteger("bounds.x", x);
- dict.SetInteger("bounds.y", y);
- dict.SetInteger("bounds.width", width);
- dict.SetInteger("bounds.height", height);
-
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendMaximizeJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& id,
- automation::Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "MaximizeView");
- id.UpdateDictionary(&dict, "auto_id");
-
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendGetAppModalDialogMessageJSONRequest(
- AutomationMessageSender* sender,
- std::string* message,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "GetAppModalDialogMessage");
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- return reply_dict.GetString("message", message);
-}
-
-bool SendAcceptOrDismissAppModalDialogJSONRequest(
- AutomationMessageSender* sender,
- bool accept,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "AcceptOrDismissAppModalDialog");
- dict.SetBoolean("accept", accept);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendAcceptPromptAppModalDialogJSONRequest(
- AutomationMessageSender* sender,
- const std::string& prompt_text,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "AcceptOrDismissAppModalDialog");
- dict.SetBoolean("accept", true);
- dict.SetString("prompt_text", prompt_text);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendWaitForAllViewsToStopLoadingJSONRequestDeprecated(
- AutomationMessageSender* sender,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "WaitForAllTabsToStopLoading");
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendGetChromeDriverAutomationVersion(
- AutomationMessageSender* sender,
- int* version,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "GetChromeDriverAutomationVersion");
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- return reply_dict.GetInteger("version", version);
-}
-
-bool SendInstallExtensionJSONRequest(
- AutomationMessageSender* sender,
- const base::FilePath& path,
- bool with_ui,
- std::string* extension_id,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "InstallExtension");
- dict.SetString("path", path.value());
- dict.SetBoolean("with_ui", with_ui);
- // TODO(kkania): Set correct auto_id instead of hardcoding windex.
- dict.SetInteger("windex", 0);
- dict.SetInteger("tab_index", 0);
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- if (!reply_dict.GetString("id", extension_id)) {
- *error = Error("Missing or invalid 'id'");
- return false;
- }
- return true;
-}
-
-bool SendGetExtensionsInfoJSONRequest(
- AutomationMessageSender* sender,
- ListValue* extensions_list,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "GetExtensionsInfo");
- // TODO(kkania): Set correct auto_id instead of hardcoding windex.
- dict.SetInteger("windex", 0);
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- ListValue* extensions_list_swap;
- if (!reply_dict.GetList("extensions", &extensions_list_swap)) {
- *error = Error("Missing or invalid 'extensions'");
- return false;
- }
- extensions_list->Swap(extensions_list_swap);
- return true;
-}
-
-bool SendIsPageActionVisibleJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& tab_id,
- const std::string& extension_id,
- bool* is_visible,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "IsPageActionVisible");
- tab_id.UpdateDictionary(&dict, "auto_id");
- dict.SetString("extension_id", extension_id);
- // TODO(kkania): Set correct auto_id instead of hardcoding windex.
- dict.SetInteger("windex", 0);
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- if (!reply_dict.GetBoolean("is_visible", is_visible)) {
- *error = Error("Missing or invalid 'is_visible'");
- return false;
- }
- return true;
-}
-
-bool SendSetExtensionStateJSONRequest(
- AutomationMessageSender* sender,
- const std::string& extension_id,
- bool enable,
- bool allow_in_incognito,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "SetExtensionStateById");
- dict.SetString("id", extension_id);
- dict.SetBoolean("enable", enable);
- dict.SetBoolean("allow_in_incognito", allow_in_incognito);
- // TODO(kkania): Set correct auto_id instead of hardcoding windex.
- dict.SetInteger("windex", 0);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendClickExtensionButtonJSONRequest(
- AutomationMessageSender* sender,
- const std::string& extension_id,
- bool browser_action,
- Error* error) {
- DictionaryValue dict;
- if (browser_action)
- dict.SetString("command", "TriggerBrowserActionById");
- else
- dict.SetString("command", "TriggerPageActionById");
- dict.SetString("id", extension_id);
- // TODO(kkania): Set correct auto_id instead of hardcoding windex.
- dict.SetInteger("windex", 0);
- dict.SetInteger("tab_index", 0);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendUninstallExtensionJSONRequest(
- AutomationMessageSender* sender,
- const std::string& extension_id,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "UninstallExtensionById");
- dict.SetString("id", extension_id);
- // TODO(kkania): Set correct auto_id instead of hardcoding windex.
- dict.SetInteger("windex", 0);
- DictionaryValue reply_dict;
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
- return false;
- bool success;
- if (!reply_dict.GetBoolean("success", &success)) {
- *error = Error("Missing or invalid 'success'");
- return false;
- }
- if (!success) {
- *error = Error("Extension uninstall not permitted");
- return false;
- }
- return true;
-}
-
-bool SendSetLocalStatePreferenceJSONRequest(
- AutomationMessageSender* sender,
- const std::string& pref,
- base::Value* value,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "SetLocalStatePrefs");
- dict.SetString("path", pref);
- dict.Set("value", value);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendSetPreferenceJSONRequest(
- AutomationMessageSender* sender,
- const std::string& pref,
- base::Value* value,
- Error* error) {
- DictionaryValue dict;
- dict.SetString("command", "SetPrefs");
- // TODO(kkania): Set correct auto_id instead of hardcoding windex.
- dict.SetInteger("windex", 0);
- dict.SetString("path", pref);
- dict.Set("value", value);
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
-}
-
-bool SendOverrideGeolocationJSONRequest(
- AutomationMessageSender* sender,
- const base::DictionaryValue* geolocation,
- Error* error) {
- scoped_ptr<DictionaryValue> dict(geolocation->DeepCopy());
- dict->SetString("command", "OverrideGeoposition");
- DictionaryValue reply_dict;
- return SendAutomationJSONRequest(sender, *dict.get(), &reply_dict, error);
-}
diff --git a/chrome/test/automation/automation_json_requests.h b/chrome/test/automation/automation_json_requests.h
deleted file mode 100644
index 8abd32a..0000000
--- a/chrome/test/automation/automation_json_requests.h
+++ /dev/null
@@ -1,539 +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_AUTOMATION_AUTOMATION_JSON_REQUESTS_H_
-#define CHROME_TEST_AUTOMATION_AUTOMATION_JSON_REQUESTS_H_
-
-#include <string>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_number_conversions.h"
-#include "chrome/common/automation_constants.h"
-#include "chrome/common/automation_id.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-class AutomationMessageSender;
-
-namespace base {
-class DictionaryValue;
-class FilePath;
-class ListValue;
-class Value;
-}
-
-struct WebKeyEvent {
- WebKeyEvent(automation::KeyEventTypes type,
- ui::KeyboardCode key_code,
- const std::string& unmodified_text,
- const std::string& modified_text,
- int modifiers);
-
- automation::KeyEventTypes type;
- ui::KeyboardCode key_code;
- std::string unmodified_text;
- std::string modified_text;
- int modifiers;
-};
-
-struct WebMouseEvent {
- WebMouseEvent(automation::MouseEventType type,
- automation::MouseButton button,
- int x,
- int y,
- int click_count,
- int modifiers);
-
- automation::MouseEventType type;
- automation::MouseButton button;
- int x;
- int y;
- int click_count;
- int modifiers;
-};
-
-// Uniquely identifies a particular WebView.
-// This is needed because Chrome used to accept just tab IDs, while
-// now it accepts IDs for other types of WebViews.
-// TOOD(kkania): Remove this abstraction once Chrome 16 is unsupported.
-class WebViewId {
- public:
- // Creates an ID for the given view ID.
- static WebViewId ForView(const AutomationId& view_id);
-
- // Creates an ID for the given tab ID.
- static WebViewId ForOldStyleTab(int tab_id);
-
- // Creates an invalid ID.
- WebViewId();
-
- // Updates the given dictionary to include this ID. If the ID refers to a
- // view ID, |view_id_key| will be the key modified in the dictionary.
- void UpdateDictionary(base::DictionaryValue* dictionary,
- const std::string& view_id_key) const;
-
- // Returns whether this ID is valid. Even if it is valid, the object it
- // refers to may not exist.
- bool IsValid() const;
-
- // Returns an |AutomationId| made from this ID.
- AutomationId GetId() const;
-
- // Returns whether this ID refers to a tab.
- bool IsTab() const;
-
- int tab_id() const;
-
- // The old style is to use a single integer ID for a tab. The new style is
- // to use an automation ID which may refer to a number of different object
- // types.
- bool old_style() const;
-
- private:
- // Whether this ID is an old-style integer tab ID.
- bool old_style_;
-
- AutomationId id_;
- int tab_id_;
-};
-
-// Used to locate a WebView. The same locator may locate different WebViews
-// at different times. This is needed because Chrome used to only accept
-// browser/tab indices, while the new Chrome accepts a unique ID.
-// TOOD(kkania): Simplify this once Chrome 16 is unsupported.
-class WebViewLocator {
- public:
- // Creates a locator for locating the given tab.
- static WebViewLocator ForIndexPair(int browser_index, int tab_index);
-
- // Creates a locator for locating the given view.
- static WebViewLocator ForViewId(const AutomationId& view_id);
-
- // Creates an invalid locator.
- WebViewLocator();
- ~WebViewLocator();
-
- // Updates the given dictionary to include the given locator information.
- // If this locator is a view ID, |view_id_key| will be the name of the key
- // to update.
- void UpdateDictionary(base::DictionaryValue* dict,
- const std::string& view_id_key) const;
-
- int browser_index() const;
- int tab_index() const;
-
- private:
- enum Type {
- kTypeIndexPair,
- kTypeViewId,
- };
-
- struct IndexPair {
- int browser_index;
- int tab_index;
- };
-
- struct Locator {
- Locator();
- ~Locator();
-
- IndexPair index_pair;
- AutomationId view_id;
- };
-
- Type type_;
- Locator locator_;
-};
-
-// Collection of info about a given WebView.
-struct WebViewInfo {
- WebViewInfo(const WebViewId& view_id,
- const std::string& extension_id);
- ~WebViewInfo();
-
- // The view's unique ID.
- WebViewId view_id;
-
- // If this view belongs to an extension, this ID will be set to it.
- std::string extension_id;
-};
-
-// Sends a JSON request to the chrome automation provider. Returns true
-// if the JSON request was successfully sent and the reply was received.
-// If true, |success| will be set to whether the JSON request was
-// completed successfully by the automation provider.
-bool SendAutomationJSONRequest(AutomationMessageSender* sender,
- const std::string& request,
- int timeout_ms,
- std::string* reply,
- bool* success) WARN_UNUSED_RESULT;
-
-// Same as above, but uses the given |AutomationMessageSender|'s default timeout
-// value.
-bool SendAutomationJSONRequestWithDefaultTimeout(
- AutomationMessageSender* sender,
- const std::string& request,
- std::string* reply,
- bool* success);
-
-// Requests the current browser and tab indices for the given tab ID.
-// Returns true on success.
-bool SendGetIndicesFromTabIdJSONRequest(
- AutomationMessageSender* sender,
- int tab_id,
- int* browser_index,
- int* tab_index,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the current browser and tab indices for the given |TabProxy|
-// handle. Returns true on success.
-bool SendGetIndicesFromTabHandleJSONRequest(
- AutomationMessageSender* sender,
- int tab_proxy_handle,
- int* browser_index,
- int* tab_index,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to navigate to the given url and wait for the given number of
-// navigations to complete. Returns true on success.
-bool SendNavigateToURLJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const std::string& url,
- int navigation_count,
- AutomationMsg_NavigationResponseValues* nav_response,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the given javascript to be executed in the frame specified by the
-// given xpath. Returns true on success. If true, |result| will be reset to the
-// result of the execution.
-bool SendExecuteJavascriptJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const std::string& frame_xpath,
- const std::string& javascript,
- scoped_ptr<base::Value>* result,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the specified view to go forward. Waits for the load to complete.
-// Returns true on success.
-bool SendGoForwardJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the specified view to go back. Waits for the load to complete.
-// Returns true on success.
-bool SendGoBackJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the specified view to reload. Waits for the load to complete.
-// Returns true on success.
-bool SendReloadJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Deprecated, no longer works with Chrome 29+.
-// Requests a snapshot of the entire page to be saved to the given path
-// in PNG format.
-// Returns true on success.
-bool SendCaptureEntirePageJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const base::FilePath& path,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-#if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
-// Deprecated, no longer works with Chrome 29+.
-// Requests a heap profile dump.
-// Returns true on success.
-bool SendHeapProfilerDumpJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const std::string& reason,
- automation::Error* error) WARN_UNUSED_RESULT;
-#endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
-
-// Requests all the cookies for the given URL. On success returns true and
-// caller takes ownership of |cookies|, which is a list of all the cookies in
-// dictionary format.
-bool SendGetCookiesJSONRequest(
- AutomationMessageSender* sender,
- const std::string& url,
- scoped_ptr<base::ListValue>* cookies,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests deletion of the cookie with the given name and URL. Returns true
-// on success.
-bool SendDeleteCookieJSONRequest(
- AutomationMessageSender* sender,
- const std::string& url,
- const std::string& cookie_name,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests setting the given cookie for the given URL. Returns true on
-// success. The caller retains ownership of |cookie_dict|.
-bool SendSetCookieJSONRequest(
- AutomationMessageSender* sender,
- const std::string& url,
- base::DictionaryValue* cookie_dict,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the IDs for all open tabs. Returns true on success.
-bool SendGetTabIdsJSONRequest(
- AutomationMessageSender* sender,
- std::vector<WebViewInfo>* views,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests info for all open views. Returns true on success.
-bool SendGetWebViewsJSONRequest(
- AutomationMessageSender* sender,
- std::vector<WebViewInfo>* views,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests whether the given tab ID is valid. Returns true on success.
-bool SendIsTabIdValidJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& view_id,
- bool* is_valid,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests whether the given automation ID refers to an actual automation
-// object. Returns true on success.
-bool SendDoesAutomationObjectExistJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& view_id,
- bool* does_exist,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to close the given view. Returns true on success.
-bool SendCloseViewJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to send the WebKit event for a mouse move to the given
-// coordinate in the specified view. Returns true on success.
-// Deprecated. TODO(kkania): Remove when chrome 17 is unsupported.
-bool SendMouseMoveJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to send the WebKit events for a mouse click at the given
-// coordinate in the specified view. Returns true on success.
-// Deprecated. TODO(kkania): Remove when chrome 17 is unsupported.
-bool SendMouseClickJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- automation::MouseButton button,
- int x,
- int y,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to send the WebKit events for a mouse drag from the start to end
-// coordinates given in the specified view. Returns true on success.
-// Deprecated. TODO(kkania): Remove when chrome 17 is unsupported.
-bool SendMouseDragJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int start_x,
- int start_y,
- int end_x,
- int end_y,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to send the WebKit event for a mouse button down at the given
-// coordinate in the specified view. Returns true on success.
-// Deprecated. TODO(kkania): Remove when chrome 17 is unsupported.
-bool SendMouseButtonDownJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to send the WebKit event for a mouse button up at the given
-// coordinate in the specified view. Returns true on success.
-// Deprecated. TODO(kkania): Remove when chrome 17 is unsupported.
-bool SendMouseButtonUpJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to send the WebKit event for a mouse double click at the given
-// coordinate in the specified view. Returns true on success.
-// Deprecated. TODO(kkania): Remove when chrome 17 is unsupported.
-bool SendMouseDoubleClickJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to send the WebKit event for the given |WebKeyEvent| in a
-// specified view. Returns true on success.
-bool SendWebKeyEventJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const WebKeyEvent& key_event,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to send the key event for the given keycode+modifiers to a
-// browser window containing the specified view. Returns true on success.
-bool SendNativeKeyEventJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- ui::KeyboardCode key_code,
- int modifiers,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Deprecated, no longer works with Chrome 29+.
-// Requests to send the WebKit event for the given |WebMouseEvent| in a
-// specified view. Returns true on success.
-bool SendWebMouseEventJSONRequestDeprecated(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- const WebMouseEvent& mouse_event,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to drag and drop the file paths at the given coordinate in the
-// specified view. Returns true on success.
-bool SendDragAndDropFilePathsJSONRequest(
- AutomationMessageSender* sender,
- const WebViewLocator& locator,
- int x,
- int y,
- const std::vector<base::FilePath::StringType>& paths,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to set the given view's bounds. Returns true on success.
-bool SendSetViewBoundsJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& id,
- int x,
- int y,
- int width,
- int height,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to maximize the given view. Returns true on success.
-bool SendMaximizeJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& id,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to get the active JavaScript modal dialog's message. Returns true
-// on success.
-bool SendGetAppModalDialogMessageJSONRequest(
- AutomationMessageSender* sender,
- std::string* message,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to accept or dismiss the active JavaScript modal dialog.
-// Returns true on success.
-bool SendAcceptOrDismissAppModalDialogJSONRequest(
- AutomationMessageSender* sender,
- bool accept,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to accept the active JavaScript modal dialog with the given prompt
-// text. Returns true on success.
-bool SendAcceptPromptAppModalDialogJSONRequest(
- AutomationMessageSender* sender,
- const std::string& prompt_text,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Deprecated, no longer works with Chrome 29+.
-// Requests to wait for all views to stop loading. Returns true on success.
-bool SendWaitForAllViewsToStopLoadingJSONRequestDeprecated(
- AutomationMessageSender* sender,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the version of ChromeDriver automation supported by the automation
-// server. Returns true on success.
-bool SendGetChromeDriverAutomationVersion(
- AutomationMessageSender* sender,
- int* version,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests that the given extension be installed. If |with_ui| is false,
-// the extension will be installed silently. Returns true on success.
-bool SendInstallExtensionJSONRequest(
- AutomationMessageSender* sender,
- const base::FilePath& path,
- bool with_ui,
- std::string* extension_id,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests info about all installed extensions. Returns true on success.
-bool SendGetExtensionsInfoJSONRequest(
- AutomationMessageSender* sender,
- base::ListValue* extensions_list,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests whether the given extension's page action is visible in the
-// given tab.
-bool SendIsPageActionVisibleJSONRequest(
- AutomationMessageSender* sender,
- const WebViewId& tab_id,
- const std::string& extension_id,
- bool* is_visible,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests a modification of the given extension state. Returns true on
-// success.
-bool SendSetExtensionStateJSONRequest(
- AutomationMessageSender* sender,
- const std::string& extension_id,
- bool enable,
- bool allow_in_incognito,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the given extension's action button be pressed. Returns true on
-// success.
-bool SendClickExtensionButtonJSONRequest(
- AutomationMessageSender* sender,
- const std::string& extension_id,
- bool browser_action,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the given extension be uninstalled. Returns true on success.
-bool SendUninstallExtensionJSONRequest(
- AutomationMessageSender* sender,
- const std::string& extension_id,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the local state preference to be set to the given value.
-// Ownership of |value| is taken by this function. Returns true on success.
-bool SendSetLocalStatePreferenceJSONRequest(
- AutomationMessageSender* sender,
- const std::string& pref,
- base::Value* value,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests the user preference to be set to the given value.
-// Ownership of |value| is taken by this function. Returns true on success.
-bool SendSetPreferenceJSONRequest(
- AutomationMessageSender* sender,
- const std::string& pref,
- base::Value* value,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-// Requests to override the user's geolocation. Returns true on success.
-bool SendOverrideGeolocationJSONRequest(
- AutomationMessageSender* sender,
- const base::DictionaryValue* geolocation,
- automation::Error* error) WARN_UNUSED_RESULT;
-
-#endif // CHROME_TEST_AUTOMATION_AUTOMATION_JSON_REQUESTS_H_
diff --git a/chrome/test/automation/automation_proxy.cc b/chrome/test/automation/automation_proxy.cc
index 63acdfd..1c8cdb2 100644
--- a/chrome/test/automation/automation_proxy.cc
+++ b/chrome/test/automation/automation_proxy.cc
@@ -15,7 +15,6 @@
#include "chrome/common/automation_constants.h"
#include "chrome/common/automation_messages.h"
#include "chrome/common/chrome_version_info.h"
-#include "chrome/test/automation/automation_json_requests.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
@@ -443,7 +442,8 @@
int timeout_ms,
std::string* response) {
bool result = false;
- if (!SendAutomationJSONRequest(this, request, timeout_ms, response, &result))
+ if (!Send(new AutomationMsg_SendJSONRequest(-1, request, response, &result),
+ timeout_ms))
return false;
return result;
}
diff --git a/chrome/test/automation/value_conversion_traits.cc b/chrome/test/automation/value_conversion_traits.cc
deleted file mode 100644
index 84e0d7f..0000000
--- a/chrome/test/automation/value_conversion_traits.cc
+++ /dev/null
@@ -1,99 +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/automation/value_conversion_traits.h"
-
-#include "base/values.h"
-
-using base::DictionaryValue;
-using base::ListValue;
-using base::Value;
-
-Value* ValueConversionTraits<int>::CreateValueFrom(int t) {
- return new base::FundamentalValue(t);
-}
-
-bool ValueConversionTraits<int>::SetFromValue(const Value* value, int* t) {
- return value->GetAsInteger(t);
-}
-
-bool ValueConversionTraits<int>::CanConvert(const Value* value) {
- int t;
- return SetFromValue(value, &t);
-}
-
-Value* ValueConversionTraits<bool>::CreateValueFrom(bool t) {
- return new base::FundamentalValue(t);
-}
-
-bool ValueConversionTraits<bool>::SetFromValue(const Value* value, bool* t) {
- return value->GetAsBoolean(t);
-}
-
-bool ValueConversionTraits<bool>::CanConvert(const Value* value) {
- bool t;
- return SetFromValue(value, &t);
-}
-
-Value* ValueConversionTraits<std::string>::CreateValueFrom(
- const std::string& t) {
- return new base::StringValue(t);
-}
-
-bool ValueConversionTraits<std::string>::SetFromValue(
- const Value* value, std::string* t) {
- return value->GetAsString(t);
-}
-
-bool ValueConversionTraits<std::string>::CanConvert(const Value* value) {
- std::string t;
- return SetFromValue(value, &t);
-}
-
-Value* ValueConversionTraits<Value*>::CreateValueFrom(const Value* t) {
- return t->DeepCopy();
-}
-
-bool ValueConversionTraits<Value*>::SetFromValue(
- const Value* value, Value** t) {
- *t = value->DeepCopy();
- return true;
-}
-
-bool ValueConversionTraits<Value*>::CanConvert(const Value* value) {
- return true;
-}
-
-Value* ValueConversionTraits<ListValue*>::CreateValueFrom(const ListValue* t) {
- return t->DeepCopy();
-}
-
-bool ValueConversionTraits<ListValue*>::SetFromValue(const Value* value,
- ListValue** t) {
- if (!value->IsType(Value::TYPE_LIST))
- return false;
- *t = static_cast<const ListValue*>(value)->DeepCopy();
- return true;
-}
-
-bool ValueConversionTraits<ListValue*>::CanConvert(const Value* value) {
- return value->IsType(Value::TYPE_LIST);
-}
-
-Value* ValueConversionTraits<DictionaryValue*>::CreateValueFrom(
- const DictionaryValue* t) {
- return t->DeepCopy();
-}
-
-bool ValueConversionTraits<DictionaryValue*>::SetFromValue(
- const Value* value, DictionaryValue** t) {
- if (!value->IsType(Value::TYPE_DICTIONARY))
- return false;
- *t = static_cast<const DictionaryValue*>(value)->DeepCopy();
- return true;
-}
-
-bool ValueConversionTraits<DictionaryValue*>::CanConvert(const Value* value) {
- return value->IsType(Value::TYPE_DICTIONARY);
-}
diff --git a/chrome/test/automation/value_conversion_traits.h b/chrome/test/automation/value_conversion_traits.h
deleted file mode 100644
index ade6d04..0000000
--- a/chrome/test/automation/value_conversion_traits.h
+++ /dev/null
@@ -1,77 +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_AUTOMATION_VALUE_CONVERSION_TRAITS_H_
-#define CHROME_TEST_AUTOMATION_VALUE_CONVERSION_TRAITS_H_
-
-#include <string>
-
-namespace base {
-class DictionaryValue;
-class ListValue;
-class Value;
-}
-
-// ValueConversionTraits contains functions for converting between a base::Value
-// and a particular type. See particular function descriptions below.
-template <typename T>
-struct ValueConversionTraits {
- // Create a value from |t|. Will not return NULL.
- // static base::Value* CreateValueFrom(const T& t);
-
- // Attempts to set |t| from the given value. Returns true on success.
- // |t| will not be modified unless successful.
- // static bool SetFromValue(const base::Value* value, T* t);
-
- // Returns whether |value| can be converted to type |T|.
- // If true, |SetFromValue| will succeed.
- // static bool CanConvert(const base::Value* value);
-};
-
-template <>
-struct ValueConversionTraits<int> {
- static base::Value* CreateValueFrom(int t);
- static bool SetFromValue(const base::Value* value, int* t);
- static bool CanConvert(const base::Value* value);
-};
-
-template <>
-struct ValueConversionTraits<bool> {
- static base::Value* CreateValueFrom(bool t);
- static bool SetFromValue(const base::Value* value, bool* t);
- static bool CanConvert(const base::Value* value);
-};
-
-template <>
-struct ValueConversionTraits<std::string> {
- static base::Value* CreateValueFrom(const std::string& t);
- static bool SetFromValue(const base::Value* value, std::string* t);
- static bool CanConvert(const base::Value* value);
-};
-
-// The conversion will involve deep copying, not just casting.
-template <>
-struct ValueConversionTraits<base::Value*> {
- static base::Value* CreateValueFrom(const base::Value* t);
- static bool SetFromValue(const base::Value* value, base::Value** t);
- static bool CanConvert(const base::Value* value);
-};
-
-// The conversion will involve deep copying, not just casting.
-template <>
-struct ValueConversionTraits<base::ListValue*> {
- static base::Value* CreateValueFrom(const base::ListValue* t);
- static bool SetFromValue(const base::Value* value, base::ListValue** t);
- static bool CanConvert(const base::Value* value);
-};
-
-// The conversion will involve deep copying, not just casting.
-template <>
-struct ValueConversionTraits<base::DictionaryValue*> {
- static base::Value* CreateValueFrom(const base::DictionaryValue* t);
- static bool SetFromValue(const base::Value* value, base::DictionaryValue** t);
- static bool CanConvert(const base::Value* value);
-};
-
-#endif // CHROME_TEST_AUTOMATION_VALUE_CONVERSION_TRAITS_H_
diff --git a/chrome/test/automation/value_conversion_util.h b/chrome/test/automation/value_conversion_util.h
deleted file mode 100644
index 8e282d1..0000000
--- a/chrome/test/automation/value_conversion_util.h
+++ /dev/null
@@ -1,103 +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_AUTOMATION_VALUE_CONVERSION_UTIL_H_
-#define CHROME_TEST_AUTOMATION_VALUE_CONVERSION_UTIL_H_
-
-#include <string>
-
-#include "base/values.h"
-#include "chrome/test/automation/value_conversion_traits.h"
-
-// Creates a value from the given parameter. Will not return NULL.
-template <typename T>
-base::Value* CreateValueFrom(const T& t) {
- return ValueConversionTraits<T>::CreateValueFrom(t);
-}
-
-// Sets |t| from the given value. Returns true on success. |t| will not be
-// modified unless successful.
-template <typename T>
-bool SetFromValue(const base::Value* value, T* t) {
- return ValueConversionTraits<T>::SetFromValue(value, t);
-}
-
-// Creates a list value containing the converted value from the the given
-// parameter.
-template <typename T>
-base::ListValue* CreateListValueFrom(const T& t) {
- base::ListValue* list = new base::ListValue();
- list->Append(CreateValueFrom(t));
- return list;
-}
-
-// Same as above, but with more arguments.
-template <typename T1, typename T2>
-base::ListValue* CreateListValueFrom(const T1& t1, const T2& t2) {
- base::ListValue* list = new base::ListValue();
- list->Append(CreateValueFrom(t1));
- list->Append(CreateValueFrom(t2));
- return list;
-}
-
-// Same as above, but with more arguments.
-template <typename T1, typename T2, typename T3>
-base::ListValue* CreateListValueFrom(const T1& t1, const T2& t2, const T3& t3) {
- base::ListValue* list = new base::ListValue();
- list->Append(CreateValueFrom(t1));
- list->Append(CreateValueFrom(t2));
- list->Append(CreateValueFrom(t3));
- return list;
-}
-
-// Sets |t| from the first element in the given list. Returns true on success.
-// |t| will not be modified unless successful.
-template <typename T>
-bool SetFromListValue(const base::ListValue* list, T* t) {
- if (list->GetSize() != 1)
- return false;
-
- if (!ValueConversionTraits<T>::CanConvert(*list->begin()))
- return false;
-
- CHECK(SetFromValue(*list->begin(), t));
- return true;
-}
-
-// Same as above, but with more arguments.
-template <typename T1, typename T2>
-bool SetFromListValue(const base::ListValue* list, T1* t1, T2* t2) {
- if (list->GetSize() != 2)
- return false;
-
- if (!ValueConversionTraits<T1>::CanConvert(*list->begin()))
- return false;
- if (!ValueConversionTraits<T2>::CanConvert(*(list->begin() + 1)))
- return false;
-
- CHECK(SetFromValue(*list->begin(), t1));
- CHECK(SetFromValue(*(list->begin() + 1), t2));
- return true;
-}
-
-// Same as above, but with more arguments.
-template <typename T1, typename T2, typename T3>
-bool SetFromListValue(const base::ListValue* list, T1* t1, T2* t2, T3* t3) {
- if (list->GetSize() != 3)
- return false;
-
- if (!ValueConversionTraits<T1>::CanConvert(*list->begin()))
- return false;
- if (!ValueConversionTraits<T2>::CanConvert(*(list->begin() + 1)))
- return false;
- if (!ValueConversionTraits<T3>::CanConvert(*(list->begin() + 2)))
- return false;
-
- CHECK(SetFromValue(*list->begin(), t1));
- CHECK(SetFromValue(*(list->begin() + 1), t2));
- CHECK(SetFromValue(*(list->begin() + 2), t3));
- return true;
-}
-
-#endif // CHROME_TEST_AUTOMATION_VALUE_CONVERSION_UTIL_H_
diff --git a/chrome/test/base/chrome_test_suite.cc b/chrome/test/base/chrome_test_suite.cc
index cdb3378..4721f47 100644
--- a/chrome/test/base/chrome_test_suite.cc
+++ b/chrome/test/base/chrome_test_suite.cc
@@ -27,9 +27,6 @@
#include "chrome/utility/chrome_content_utility_client.h"
#include "content/public/test/test_launcher.h"
#include "extensions/common/extension_paths.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/dns/mock_host_resolver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/resource/resource_handle.h"
@@ -85,51 +82,6 @@
#endif // defined(OS_CHROMEOS)
}
-// In many cases it may be not obvious that a test makes a real DNS lookup.
-// We generally don't want to rely on external DNS servers for our tests,
-// so this host resolver procedure catches external queries and returns a failed
-// lookup result.
-class LocalHostResolverProc : public net::HostResolverProc {
- public:
- LocalHostResolverProc() : HostResolverProc(NULL) {}
-
- virtual int Resolve(const std::string& host,
- net::AddressFamily address_family,
- net::HostResolverFlags host_resolver_flags,
- net::AddressList* addrlist,
- int* os_error) OVERRIDE {
- const char* kLocalHostNames[] = {"localhost", "127.0.0.1", "::1"};
- bool local = false;
-
- if (host == net::GetHostName()) {
- local = true;
- } else {
- for (size_t i = 0; i < arraysize(kLocalHostNames); i++)
- if (host == kLocalHostNames[i]) {
- local = true;
- break;
- }
- }
-
- // To avoid depending on external resources and to reduce (if not preclude)
- // network interactions from tests, we simulate failure for non-local DNS
- // queries, rather than perform them.
- // If you really need to make an external DNS query, use
- // net::RuleBasedHostResolverProc and its AllowDirectLookup method.
- if (!local) {
- DVLOG(1) << "To avoid external dependencies, simulating failure for "
- "external DNS lookup of " << host;
- return net::ERR_NOT_IMPLEMENTED;
- }
-
- return ResolveUsingPrevious(host, address_family, host_resolver_flags,
- addrlist, os_error);
- }
-
- private:
- virtual ~LocalHostResolverProc() {}
-};
-
class ChromeTestSuiteInitializer : public testing::EmptyTestEventListener {
public:
ChromeTestSuiteInitializer() {
@@ -148,8 +100,6 @@
utility_content_client_.reset(new chrome::ChromeContentUtilityClient());
content::SetUtilityClientForTesting(utility_content_client_.get());
#endif
-
- SetUpHostResolver();
}
virtual void OnTestEnd(const testing::TestInfo& test_info) OVERRIDE {
@@ -167,22 +117,9 @@
#endif
content_client_.reset();
content::SetContentClient(NULL);
-
- TearDownHostResolver();
}
private:
- void SetUpHostResolver() {
- host_resolver_proc_ = new LocalHostResolverProc;
- scoped_host_resolver_proc_.reset(
- new net::ScopedDefaultHostResolverProc(host_resolver_proc_.get()));
- }
-
- void TearDownHostResolver() {
- scoped_host_resolver_proc_.reset();
- host_resolver_proc_ = NULL;
- }
-
scoped_ptr<chrome::ChromeContentClient> content_client_;
// TODO(ios): Bring this back once ChromeContentBrowserClient is building.
#if !defined(OS_IOS)
@@ -190,9 +127,6 @@
scoped_ptr<chrome::ChromeContentUtilityClient> utility_content_client_;
#endif
- scoped_refptr<LocalHostResolverProc> host_resolver_proc_;
- scoped_ptr<net::ScopedDefaultHostResolverProc> scoped_host_resolver_proc_;
-
DISALLOW_COPY_AND_ASSIGN(ChromeTestSuiteInitializer);
};
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 977051f..a685768 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -48,7 +48,6 @@
#include "content/public/test/test_browser_thread.h"
#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"
@@ -182,15 +181,6 @@
file_util::CreateDirectory(log_dir);
#endif // defined(OS_CHROMEOS)
- host_resolver_ = new net::RuleBasedHostResolverProc(NULL);
-
- // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
- // We don't want the test code to use it.
- host_resolver_->AddSimulatedFailure("wpad");
-
- net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
- host_resolver_.get());
-
#if defined(OS_MACOSX)
// On Mac, without the following autorelease pool, code which is directly
// executed (as opposed to executed inside a message loop) would autorelease
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h
index 8545846..185a238 100644
--- a/chrome/test/base/in_process_browser_test.h
+++ b/chrome/test/base/in_process_browser_test.h
@@ -36,10 +36,6 @@
class ContentRendererClient;
}
-namespace net {
-class RuleBasedHostResolverProc;
-}
-
// Base class for tests wanting to bring up a browser in the unit test process.
// Writing tests with InProcessBrowserTest is slightly different than that of
// other tests. This is necessitated by InProcessBrowserTest running a message
@@ -162,12 +158,6 @@
CommandLine GetCommandLineForRelaunch();
#endif
- // Returns the host resolver being used for the tests. Subclasses might want
- // to configure it inside tests.
- net::RuleBasedHostResolverProc* host_resolver() {
- return host_resolver_.get();
- }
-
#if defined(OS_MACOSX)
// Returns the autorelease pool in use inside RunTestOnMainThreadLoop().
base::mac::ScopedNSAutoreleasePool* AutoreleasePool() const {
@@ -199,9 +189,6 @@
// Browser created from CreateBrowser.
Browser* browser_;
- // Host resolver to use during the test.
- scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_;
-
// Temporary user data directory. Used only when a user data directory is not
// specified in the command line.
base::ScopedTempDir temp_user_data_dir_;
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index f2e3957..ff97b10 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -45,6 +45,10 @@
virtual void UpdateDevTools() OVERRIDE {}
virtual void UpdateLoadingAnimations(bool should_animate) OVERRIDE {}
virtual void SetStarredState(bool is_starred) OVERRIDE {}
+ virtual void OnActiveTabChanged(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason) OVERRIDE {}
virtual void ZoomChangedForActiveTab(bool can_show_bubble) OVERRIDE {}
virtual gfx::Rect GetRestoredBounds() const OVERRIDE;
virtual ui::WindowShowState GetRestoredState() const OVERRIDE;
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index f928f39..1cb4d99 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -344,6 +344,8 @@
settings_service->Init(store);
store->SetInitializationCompleted();
#endif
+
+ profile_name_ = "testing_profile";
}
void TestingProfile::FinishInit() {
@@ -550,7 +552,7 @@
}
std::string TestingProfile::GetProfileName() {
- return std::string("testing_profile");
+ return profile_name_;
}
bool TestingProfile::IsOffTheRecord() const {
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index 71de4a6..d57d5de 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -311,6 +311,10 @@
virtual PrefService* GetOffTheRecordPrefs() OVERRIDE;
+ void set_profile_name(const std::string& profile_name) {
+ profile_name_ = profile_name;
+ }
+
protected:
base::Time start_time_;
scoped_ptr<PrefServiceSyncable> prefs_;
@@ -380,6 +384,8 @@
// Weak pointer to a delegate for indicating that a profile was created.
Delegate* delegate_;
+
+ std::string profile_name_;
};
#endif // CHROME_TEST_BASE_TESTING_PROFILE_H_
diff --git a/chrome/test/base/v8_unit_test.cc b/chrome/test/base/v8_unit_test.cc
index 5523c48..92a9b42 100644
--- a/chrome/test/base/v8_unit_test.cc
+++ b/chrome/test/base/v8_unit_test.cc
@@ -144,8 +144,7 @@
ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &accessibilityAuditPath));
accessibilityAuditPath = accessibilityAuditPath.AppendASCII("third_party");
accessibilityAuditPath =
- accessibilityAuditPath.AppendASCII("accessibility-developer-tools");
- accessibilityAuditPath = accessibilityAuditPath.AppendASCII("gen");
+ accessibilityAuditPath.AppendASCII("accessibility-audit");
accessibilityAuditPath = accessibilityAuditPath.AppendASCII("axs_testing.js");
AddLibrary(accessibilityAuditPath);
diff --git a/chrome/test/base/web_ui_browsertest.cc b/chrome/test/base/web_ui_browsertest.cc
index a32720c..28d5d9e 100644
--- a/chrome/test/base/web_ui_browsertest.cc
+++ b/chrome/test/base/web_ui_browsertest.cc
@@ -54,7 +54,7 @@
namespace {
const base::FilePath::CharType kA11yAuditLibraryJSPath[] = FILE_PATH_LITERAL(
- "third_party/accessibility-developer-tools/gen/axs_testing.js");
+ "third_party/accessibility-audit/axs_testing.js");
const base::FilePath::CharType kMockJSPath[] =
FILE_PATH_LITERAL("chrome/third_party/mock4js/mock4js.js");
const base::FilePath::CharType kWebUILibraryJS[] =
diff --git a/chrome/test/chromedriver/README.txt b/chrome/test/chromedriver/README.txt
index 43126c4..eaddce6 100644
--- a/chrome/test/chromedriver/README.txt
+++ b/chrome/test/chromedriver/README.txt
@@ -4,12 +4,12 @@
ChromeDriver is an implementation of the WebDriver standard,
which allows users to automate testing of their website across browsers.
-See the user site at http://code.google.com/p/chromedriver.
+See the user site at https://sites.google.com/a/chromium.org/chromedriver/
=====Getting started=====
-Build ChromeDriver by building the 'chromedriver2_server' target. This will
+Build ChromeDriver by building the 'chromedriver' target. This will
create an executable binary in the build folder named
-'chromedriver2_server[.exe]'.
+'chromedriver[.exe]'.
Once built, ChromeDriver can be used interactively with python.
@@ -17,7 +17,7 @@
$ python
>>> import server
>>> import chromedriver
->>> cd_server = server.Server('/path/to/chromedriver2_server/executable')
+>>> cd_server = server.Server('/path/to/chromedriver/executable')
>>> driver = chromedriver.ChromeDriver(cd_server.GetUrl())
>>> driver.Load('http://www.google.com')
>>> driver.Quit()
@@ -28,8 +28,7 @@
To use ChromeDriver2 with Chrome on Android pass the Android package name in the
chromeOptions.androidPackage capability when creating the driver. The path to
adb_commands.py and the adb tool from the Android SDK must be set in PATH. For
-more detailed instructions see the wiki:
- https://code.google.com/p/chromedriver/wiki/ChromeDriver2forAndroid
+more detailed instructions see the user site.
=====Architecture=====
ChromeDriver is shipped separately from Chrome. It controls Chrome out of
@@ -84,12 +83,12 @@
http://build.chromium.org/p/chromium.chromedriver/waterfall
There are 4 test suites for verifying ChromeDriver's correctness:
-1) chromedriver2_unittests (chrome/chrome_tests.gypi)
+1) chromedriver_unittests (chrome/chrome_tests.gypi)
This is the unittest target, which runs on the main waterfall on win/mac/linux
and can close the tree. It is also run on the commit queue and try bots by
default. Tests should take a few milliseconds and be very stable.
-2) chromedriver2_tests (chrome/chrome_tests.gypi)
+2) chromedriver_tests (chrome/chrome_tests.gypi)
This is a collection of C++ medium sized tests which can be run optionally
on the trybots.
diff --git a/chrome/test/chromedriver/chrome/chrome.h b/chrome/test/chromedriver/chrome/chrome.h
index ef4ce83..2433fad 100644
--- a/chrome/test/chromedriver/chrome/chrome.h
+++ b/chrome/test/chromedriver/chrome/chrome.h
@@ -28,6 +28,8 @@
virtual int GetBuildNo() = 0;
+ virtual bool HasCrashedWebView() = 0;
+
// Return ids of opened WebViews in the same order as they are opened.
virtual Status GetWebViewIds(std::list<std::string>* web_view_ids) = 0;
diff --git a/chrome/test/chromedriver/chrome/chrome_android_impl.cc b/chrome/test/chromedriver/chrome/chrome_android_impl.cc
index a489b3e..0bddb4a 100644
--- a/chrome/test/chromedriver/chrome/chrome_android_impl.cc
+++ b/chrome/test/chromedriver/chrome/chrome_android_impl.cc
@@ -7,12 +7,16 @@
#include "chrome/test/chromedriver/chrome/device_manager.h"
#include "chrome/test/chromedriver/chrome/devtools_http_client.h"
#include "chrome/test/chromedriver/chrome/status.h"
+#include "chrome/test/chromedriver/net/port_server.h"
ChromeAndroidImpl::ChromeAndroidImpl(
scoped_ptr<DevToolsHttpClient> client,
ScopedVector<DevToolsEventListener>& devtools_event_listeners,
+ scoped_ptr<PortReservation> port_reservation,
scoped_ptr<Device> device)
- : ChromeImpl(client.Pass(), devtools_event_listeners),
+ : ChromeImpl(client.Pass(),
+ devtools_event_listeners,
+ port_reservation.Pass()),
device_(device.Pass()) {}
ChromeAndroidImpl::~ChromeAndroidImpl() {}
@@ -25,7 +29,7 @@
return "ANDROID";
}
-Status ChromeAndroidImpl::Quit() {
+Status ChromeAndroidImpl::QuitImpl() {
return device_->StopApp();
}
diff --git a/chrome/test/chromedriver/chrome/chrome_android_impl.h b/chrome/test/chromedriver/chrome/chrome_android_impl.h
index 8cd1d12..43ed71a 100644
--- a/chrome/test/chromedriver/chrome/chrome_android_impl.h
+++ b/chrome/test/chromedriver/chrome/chrome_android_impl.h
@@ -19,13 +19,16 @@
ChromeAndroidImpl(
scoped_ptr<DevToolsHttpClient> client,
ScopedVector<DevToolsEventListener>& devtools_event_listeners,
+ scoped_ptr<PortReservation> port_reservation,
scoped_ptr<Device> device);
virtual ~ChromeAndroidImpl();
// Overridden from Chrome:
virtual Type GetType() OVERRIDE;
virtual std::string GetOperatingSystemName() OVERRIDE;
- virtual Status Quit() OVERRIDE;
+
+ // Overridden from ChromeImpl:
+ virtual Status QuitImpl() OVERRIDE;
private:
scoped_ptr<Device> device_;
diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
index f15b895..717e43f 100644
--- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
+++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
@@ -16,6 +16,7 @@
#include "chrome/test/chromedriver/chrome/devtools_http_client.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome/web_view_impl.h"
+#include "chrome/test/chromedriver/net/port_server.h"
#if defined(OS_POSIX)
#include <errno.h>
@@ -63,13 +64,14 @@
ChromeDesktopImpl::ChromeDesktopImpl(
scoped_ptr<DevToolsHttpClient> client,
ScopedVector<DevToolsEventListener>& devtools_event_listeners,
+ scoped_ptr<PortReservation> port_reservation,
base::ProcessHandle process,
base::ScopedTempDir* user_data_dir,
base::ScopedTempDir* extension_dir)
: ChromeImpl(client.Pass(),
- devtools_event_listeners),
- process_(process),
- quit_(false) {
+ devtools_event_listeners,
+ port_reservation.Pass()),
+ process_(process) {
if (user_data_dir->IsValid())
CHECK(user_data_dir_.Set(user_data_dir->Take()));
if (extension_dir->IsValid())
@@ -149,8 +151,7 @@
return base::SysInfo::OperatingSystemName();
}
-Status ChromeDesktopImpl::Quit() {
- quit_ = true;
+Status ChromeDesktopImpl::QuitImpl() {
if (!KillProcess(process_))
return Status(kUnknownError, "cannot kill Chrome");
return Status(kOk);
diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.h b/chrome/test/chromedriver/chrome/chrome_desktop_impl.h
index 5e6783c..ab4e393 100644
--- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.h
+++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.h
@@ -27,6 +27,7 @@
ChromeDesktopImpl(
scoped_ptr<DevToolsHttpClient> client,
ScopedVector<DevToolsEventListener>& devtools_event_listeners,
+ scoped_ptr<PortReservation> port_reservation,
base::ProcessHandle process,
base::ScopedTempDir* user_data_dir,
base::ScopedTempDir* extension_dir);
@@ -43,11 +44,12 @@
virtual Status GetAutomationExtension(
AutomationExtension** extension) OVERRIDE;
virtual std::string GetOperatingSystemName() OVERRIDE;
- virtual Status Quit() OVERRIDE;
+
+ // Overridden from ChromeImpl:
+ virtual Status QuitImpl() OVERRIDE;
private:
base::ProcessHandle process_;
- bool quit_;
base::ScopedTempDir user_data_dir_;
base::ScopedTempDir extension_dir_;
diff --git a/chrome/test/chromedriver/chrome/chrome_existing_impl.cc b/chrome/test/chromedriver/chrome/chrome_existing_impl.cc
index 120f2df..af23106 100644
--- a/chrome/test/chromedriver/chrome/chrome_existing_impl.cc
+++ b/chrome/test/chromedriver/chrome/chrome_existing_impl.cc
@@ -5,11 +5,14 @@
#include "chrome/test/chromedriver/chrome/chrome_existing_impl.h"
#include "chrome/test/chromedriver/chrome/devtools_http_client.h"
#include "chrome/test/chromedriver/chrome/status.h"
+#include "chrome/test/chromedriver/net/port_server.h"
ChromeExistingImpl::ChromeExistingImpl(
scoped_ptr<DevToolsHttpClient> client,
ScopedVector<DevToolsEventListener>& devtools_event_listeners)
- : ChromeImpl(client.Pass(), devtools_event_listeners) {}
+ : ChromeImpl(client.Pass(),
+ devtools_event_listeners,
+ scoped_ptr<PortReservation>()) {}
ChromeExistingImpl::~ChromeExistingImpl() {}
@@ -21,7 +24,7 @@
return std::string();
}
-Status ChromeExistingImpl::Quit() {
+Status ChromeExistingImpl::QuitImpl() {
return Status(kOk);
}
diff --git a/chrome/test/chromedriver/chrome/chrome_existing_impl.h b/chrome/test/chromedriver/chrome/chrome_existing_impl.h
index 218f336..2a04e50 100644
--- a/chrome/test/chromedriver/chrome/chrome_existing_impl.h
+++ b/chrome/test/chromedriver/chrome/chrome_existing_impl.h
@@ -23,7 +23,9 @@
// Overridden from Chrome.
virtual Type GetType() OVERRIDE;
virtual std::string GetOperatingSystemName() OVERRIDE;
- virtual Status Quit() OVERRIDE;
+
+ // Overridden from ChromeImpl.
+ virtual Status QuitImpl() OVERRIDE;
};
#endif // CHROME_TEST_CHROMEDRIVER_CHROME_CHROME_EXISTING_IMPL_H_
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.cc b/chrome/test/chromedriver/chrome/chrome_impl.cc
index a7b3595..772e1e3 100644
--- a/chrome/test/chromedriver/chrome/chrome_impl.cc
+++ b/chrome/test/chromedriver/chrome/chrome_impl.cc
@@ -9,8 +9,12 @@
#include "chrome/test/chromedriver/chrome/devtools_http_client.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome/web_view_impl.h"
+#include "chrome/test/chromedriver/net/port_server.h"
-ChromeImpl::~ChromeImpl() {}
+ChromeImpl::~ChromeImpl() {
+ if (!quit_)
+ port_reservation_->Leak();
+}
std::string ChromeImpl::GetVersion() {
return devtools_http_client_->version();
@@ -20,6 +24,15 @@
return devtools_http_client_->build_no();
}
+bool ChromeImpl::HasCrashedWebView() {
+ for (WebViewList::iterator it = web_views_.begin();
+ it != web_views_.end(); ++it) {
+ if ((*it)->WasCrashed())
+ return true;
+ }
+ return false;
+}
+
Status ChromeImpl::GetWebViewIds(std::list<std::string>* web_view_ids) {
WebViewsInfo views_info;
Status status = devtools_http_client_->GetWebViewsInfo(&views_info);
@@ -106,9 +119,19 @@
return Status(kUnknownError, "automation extension not supported");
}
+Status ChromeImpl::Quit() {
+ Status status = QuitImpl();
+ if (status.IsOk())
+ quit_ = true;
+ return status;
+}
+
ChromeImpl::ChromeImpl(
scoped_ptr<DevToolsHttpClient> client,
- ScopedVector<DevToolsEventListener>& devtools_event_listeners)
- : devtools_http_client_(client.Pass()) {
+ ScopedVector<DevToolsEventListener>& devtools_event_listeners,
+ scoped_ptr<PortReservation> port_reservation)
+ : quit_(false),
+ devtools_http_client_(client.Pass()),
+ port_reservation_(port_reservation.Pass()) {
devtools_event_listeners_.swap(devtools_event_listeners);
}
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.h b/chrome/test/chromedriver/chrome/chrome_impl.h
index 03adc38..ce23ed2 100644
--- a/chrome/test/chromedriver/chrome/chrome_impl.h
+++ b/chrome/test/chromedriver/chrome/chrome_impl.h
@@ -18,6 +18,7 @@
class DevToolsEventListener;
class DevToolsHttpClient;
class JavaScriptDialogManager;
+class PortReservation;
class Status;
class WebView;
class WebViewImpl;
@@ -29,6 +30,7 @@
// Overridden from Chrome:
virtual std::string GetVersion() OVERRIDE;
virtual int GetBuildNo() OVERRIDE;
+ virtual bool HasCrashedWebView() OVERRIDE;
virtual Status GetWebViewIds(std::list<std::string>* web_view_ids) OVERRIDE;
virtual Status GetWebViewById(const std::string& id,
WebView** web_view) OVERRIDE;
@@ -36,12 +38,17 @@
virtual Status ActivateWebView(const std::string& id) OVERRIDE;
virtual Status GetAutomationExtension(
AutomationExtension** extension) OVERRIDE;
+ virtual Status Quit() OVERRIDE;
protected:
ChromeImpl(
scoped_ptr<DevToolsHttpClient> client,
- ScopedVector<DevToolsEventListener>& devtools_event_listeners);
+ ScopedVector<DevToolsEventListener>& devtools_event_listeners,
+ scoped_ptr<PortReservation> port_reservation);
+ virtual Status QuitImpl() = 0;
+
+ bool quit_;
scoped_ptr<DevToolsHttpClient> devtools_http_client_;
private:
@@ -50,6 +57,7 @@
// Web views in this list are in the same order as they are opened.
WebViewList web_views_;
ScopedVector<DevToolsEventListener> devtools_event_listeners_;
+ scoped_ptr<PortReservation> port_reservation_;
};
#endif // CHROME_TEST_CHROMEDRIVER_CHROME_CHROME_IMPL_H_
diff --git a/chrome/test/chromedriver/chrome/devtools_client.h b/chrome/test/chromedriver/chrome/devtools_client.h
index 05f5dfc..990f187 100644
--- a/chrome/test/chromedriver/chrome/devtools_client.h
+++ b/chrome/test/chromedriver/chrome/devtools_client.h
@@ -27,6 +27,8 @@
virtual const std::string& GetId() = 0;
+ virtual bool WasCrashed() = 0;
+
// Connect to DevTools if the DevToolsClient is disconnected.
virtual Status ConnectIfNecessary() = 0;
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.cc b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
index 1dbb808..b3e8e0e 100644
--- a/chrome/test/chromedriver/chrome/devtools_client_impl.cc
+++ b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
@@ -74,6 +74,7 @@
const FrontendCloserFunc& frontend_closer_func)
: socket_(factory.Run().Pass()),
url_(url),
+ crashed_(false),
id_(id),
frontend_closer_func_(frontend_closer_func),
parser_func_(base::Bind(&internal::ParseInspectorMessage)),
@@ -89,6 +90,7 @@
const ParserFunc& parser_func)
: socket_(factory.Run().Pass()),
url_(url),
+ crashed_(false),
id_(id),
frontend_closer_func_(frontend_closer_func),
parser_func_(parser_func),
@@ -107,6 +109,10 @@
return id_;
}
+bool DevToolsClientImpl::WasCrashed() {
+ return crashed_;
+}
+
Status DevToolsClientImpl::ConnectIfNecessary() {
if (stack_count_)
return Status(kUnknownError, "cannot connect when nested");
@@ -256,6 +262,9 @@
if (expected_id != -1 && response_info_map_[expected_id]->state != kWaiting)
return Status(kOk);
+ if (crashed_)
+ return Status(kTabCrashed);
+
std::string message;
switch (socket_->ReceiveNextMessage(&message, timeout)) {
case SyncWebSocket::kOk:
@@ -304,8 +313,10 @@
return status;
if (event.method == "Inspector.detached")
return Status(kDisconnected, "received Inspector.detached event");
- if (event.method == "Inspector.targetCrashed")
- return Status(kDisconnected, "page crashed");
+ if (event.method == "Inspector.targetCrashed") {
+ crashed_ = true;
+ return Status(kTabCrashed);
+ }
if (event.method == "Page.javascriptDialogOpening") {
// A command may have opened the dialog, which will block the response.
// To find out which one (if any), do a round trip with a simple command
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.h b/chrome/test/chromedriver/chrome/devtools_client_impl.h
index cd33f53..d26de29 100644
--- a/chrome/test/chromedriver/chrome/devtools_client_impl.h
+++ b/chrome/test/chromedriver/chrome/devtools_client_impl.h
@@ -76,6 +76,7 @@
// Overridden from DevToolsClient:
virtual const std::string& GetId() OVERRIDE;
+ virtual bool WasCrashed() OVERRIDE;
virtual Status ConnectIfNecessary() OVERRIDE;
virtual Status SendCommand(const std::string& method,
const base::DictionaryValue& params) OVERRIDE;
@@ -125,6 +126,7 @@
scoped_ptr<SyncWebSocket> socket_;
GURL url_;
+ bool crashed_;
const std::string id_;
FrontendCloserFunc frontend_closer_func_;
ParserFunc parser_func_;
diff --git a/chrome/test/chromedriver/chrome/status.cc b/chrome/test/chromedriver/chrome/status.cc
index df5e6b0..4eaaf58 100644
--- a/chrome/test/chromedriver/chrome/status.cc
+++ b/chrome/test/chromedriver/chrome/status.cc
@@ -57,6 +57,8 @@
return "disconnected";
case kForbidden:
return "forbidden";
+ case kTabCrashed:
+ return "tab crashed";
default:
return "<unknown>";
}
diff --git a/chrome/test/chromedriver/chrome/status.h b/chrome/test/chromedriver/chrome/status.h
index 37ef92f..ce64765 100644
--- a/chrome/test/chromedriver/chrome/status.h
+++ b/chrome/test/chromedriver/chrome/status.h
@@ -33,6 +33,7 @@
kNoSuchExecutionContext,
kDisconnected,
kForbidden = 103,
+ kTabCrashed,
};
// Represents a WebDriver status, which may be an error or ok.
diff --git a/chrome/test/chromedriver/chrome/stub_chrome.cc b/chrome/test/chromedriver/chrome/stub_chrome.cc
index 4f8fc45..7e5888b 100644
--- a/chrome/test/chromedriver/chrome/stub_chrome.cc
+++ b/chrome/test/chromedriver/chrome/stub_chrome.cc
@@ -22,6 +22,10 @@
return 9999;
}
+bool StubChrome::HasCrashedWebView() {
+ return false;
+}
+
Status StubChrome::GetWebViewIds(std::list<std::string>* web_view_ids) {
return Status(kOk);
}
diff --git a/chrome/test/chromedriver/chrome/stub_chrome.h b/chrome/test/chromedriver/chrome/stub_chrome.h
index e4e4628..af0bd06 100644
--- a/chrome/test/chromedriver/chrome/stub_chrome.h
+++ b/chrome/test/chromedriver/chrome/stub_chrome.h
@@ -22,6 +22,7 @@
virtual Type GetType() OVERRIDE;
virtual std::string GetVersion() OVERRIDE;
virtual int GetBuildNo() OVERRIDE;
+ virtual bool HasCrashedWebView() OVERRIDE;
virtual Status GetWebViewIds(std::list<std::string>* web_view_ids) OVERRIDE;
virtual Status GetWebViewById(const std::string& id,
WebView** web_view) OVERRIDE;
diff --git a/chrome/test/chromedriver/chrome/stub_devtools_client.cc b/chrome/test/chromedriver/chrome/stub_devtools_client.cc
index 4eb0af1..78bff72 100644
--- a/chrome/test/chromedriver/chrome/stub_devtools_client.cc
+++ b/chrome/test/chromedriver/chrome/stub_devtools_client.cc
@@ -17,6 +17,10 @@
return id_;
}
+bool StubDevToolsClient::WasCrashed() {
+ return false;
+}
+
Status StubDevToolsClient::ConnectIfNecessary() {
return Status(kOk);
}
diff --git a/chrome/test/chromedriver/chrome/stub_devtools_client.h b/chrome/test/chromedriver/chrome/stub_devtools_client.h
index 12fdba0..911854c 100644
--- a/chrome/test/chromedriver/chrome/stub_devtools_client.h
+++ b/chrome/test/chromedriver/chrome/stub_devtools_client.h
@@ -26,6 +26,7 @@
// Overridden from DevToolsClient:
virtual const std::string& GetId() OVERRIDE;
+ virtual bool WasCrashed() OVERRIDE;
virtual Status ConnectIfNecessary() OVERRIDE;
virtual Status SendCommand(const std::string& method,
const base::DictionaryValue& params) OVERRIDE;
diff --git a/chrome/test/chromedriver/chrome/stub_web_view.cc b/chrome/test/chromedriver/chrome/stub_web_view.cc
index c97d31a..3a914e5 100644
--- a/chrome/test/chromedriver/chrome/stub_web_view.cc
+++ b/chrome/test/chromedriver/chrome/stub_web_view.cc
@@ -16,6 +16,10 @@
return id_;
}
+bool StubWebView::WasCrashed() {
+ return false;
+}
+
Status StubWebView::ConnectIfNecessary() {
return Status(kOk);
}
diff --git a/chrome/test/chromedriver/chrome/stub_web_view.h b/chrome/test/chromedriver/chrome/stub_web_view.h
index 0a75c49..27c9a6b 100644
--- a/chrome/test/chromedriver/chrome/stub_web_view.h
+++ b/chrome/test/chromedriver/chrome/stub_web_view.h
@@ -19,6 +19,7 @@
// Overridden from WebView:
virtual std::string GetId() OVERRIDE;
+ virtual bool WasCrashed() OVERRIDE;
virtual Status ConnectIfNecessary() OVERRIDE;
virtual Status HandleReceivedEvents() OVERRIDE;
virtual Status Load(const std::string& url) OVERRIDE;
diff --git a/chrome/test/chromedriver/chrome/web_view.h b/chrome/test/chromedriver/chrome/web_view.h
index a86c90b..d84304a 100644
--- a/chrome/test/chromedriver/chrome/web_view.h
+++ b/chrome/test/chromedriver/chrome/web_view.h
@@ -34,6 +34,9 @@
// Return the id for this WebView.
virtual std::string GetId() = 0;
+ // Return true if the web view was crashed.
+ virtual bool WasCrashed() = 0;
+
// Make DevToolsCient connect to DevTools if it is disconnected.
virtual Status ConnectIfNecessary() = 0;
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc
index 929d824..69a73ae 100644
--- a/chrome/test/chromedriver/chrome/web_view_impl.cc
+++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -130,6 +130,10 @@
return id_;
}
+bool WebViewImpl::WasCrashed() {
+ return client_->WasCrashed();
+}
+
Status WebViewImpl::ConnectIfNecessary() {
return client_->ConnectIfNecessary();
}
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.h b/chrome/test/chromedriver/chrome/web_view_impl.h
index bbfaf67..57e00cc 100644
--- a/chrome/test/chromedriver/chrome/web_view_impl.h
+++ b/chrome/test/chromedriver/chrome/web_view_impl.h
@@ -38,6 +38,7 @@
// Overridden from WebView:
virtual std::string GetId() OVERRIDE;
+ virtual bool WasCrashed() OVERRIDE;
virtual Status ConnectIfNecessary() OVERRIDE;
virtual Status HandleReceivedEvents() OVERRIDE;
virtual Status Load(const std::string& url) OVERRIDE;
diff --git a/chrome/test/chromedriver/chrome/web_view_impl_unittest.cc b/chrome/test/chromedriver/chrome/web_view_impl_unittest.cc
index 483c6de..cd952a7 100644
--- a/chrome/test/chromedriver/chrome/web_view_impl_unittest.cc
+++ b/chrome/test/chromedriver/chrome/web_view_impl_unittest.cc
@@ -32,6 +32,9 @@
virtual const std::string& GetId() OVERRIDE {
return id_;
}
+ virtual bool WasCrashed() OVERRIDE {
+ return false;
+ }
virtual Status ConnectIfNecessary() OVERRIDE {
return Status(kOk);
}
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc
index f941f78..7bd7b11 100644
--- a/chrome/test/chromedriver/chrome_launcher.cc
+++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -38,6 +38,7 @@
#include "chrome/test/chromedriver/chrome/web_view.h"
#include "chrome/test/chromedriver/chrome/zip.h"
#include "chrome/test/chromedriver/net/net_util.h"
+#include "chrome/test/chromedriver/net/port_server.h"
#include "chrome/test/chromedriver/net/url_request_context_getter.h"
#include "crypto/sha2.h"
@@ -197,6 +198,7 @@
Status LaunchDesktopChrome(
URLRequestContextGetter* context_getter,
int port,
+ scoped_ptr<PortReservation> port_reservation,
const SyncWebSocketFactory& socket_factory,
const Capabilities& capabilities,
ScopedVector<DevToolsEventListener>& devtools_event_listeners,
@@ -274,6 +276,7 @@
scoped_ptr<ChromeDesktopImpl> chrome_desktop(
new ChromeDesktopImpl(devtools_client.Pass(),
devtools_event_listeners,
+ port_reservation.Pass(),
process,
&user_data_dir,
&extension_dir));
@@ -296,6 +299,7 @@
Status LaunchAndroidChrome(
URLRequestContextGetter* context_getter,
int port,
+ scoped_ptr<PortReservation> port_reservation,
const SyncWebSocketFactory& socket_factory,
const Capabilities& capabilities,
ScopedVector<DevToolsEventListener>& devtools_event_listeners,
@@ -334,8 +338,10 @@
if (status.IsError())
return status;
- chrome->reset(new ChromeAndroidImpl(
- devtools_client.Pass(), devtools_event_listeners, device.Pass()));
+ chrome->reset(new ChromeAndroidImpl(devtools_client.Pass(),
+ devtools_event_listeners,
+ port_reservation.Pass(),
+ device.Pass()));
return Status(kOk);
}
@@ -345,6 +351,7 @@
URLRequestContextGetter* context_getter,
const SyncWebSocketFactory& socket_factory,
DeviceManager* device_manager,
+ PortServer* port_server,
const Capabilities& capabilities,
ScopedVector<DevToolsEventListener>& devtools_event_listeners,
scoped_ptr<Chrome>* chrome) {
@@ -354,18 +361,36 @@
capabilities, devtools_event_listeners, chrome);
}
- int port;
- if (!FindOpenPort(&port))
- return Status(kUnknownError, "failed to find an open port for Chrome");
+ int port = 0;
+ scoped_ptr<PortReservation> port_reservation;
+ if (port_server) {
+ Status status = port_server->ReservePort(&port, &port_reservation);
+ if (status.IsError()) {
+ return Status(
+ kUnknownError, "failed to reserve port from port server", status);
+ }
+ } else {
+ if (!FindOpenPort(&port))
+ return Status(kUnknownError, "failed to find an open port for Chrome");
+ }
if (capabilities.IsAndroid()) {
- return LaunchAndroidChrome(
- context_getter, port, socket_factory, capabilities,
- devtools_event_listeners, device_manager, chrome);
+ return LaunchAndroidChrome(context_getter,
+ port,
+ port_reservation.Pass(),
+ socket_factory,
+ capabilities,
+ devtools_event_listeners,
+ device_manager,
+ chrome);
} else {
- return LaunchDesktopChrome(
- context_getter, port, socket_factory, capabilities,
- devtools_event_listeners, chrome);
+ return LaunchDesktopChrome(context_getter,
+ port,
+ port_reservation.Pass(),
+ socket_factory,
+ capabilities,
+ devtools_event_listeners,
+ chrome);
}
}
diff --git a/chrome/test/chromedriver/chrome_launcher.h b/chrome/test/chromedriver/chrome_launcher.h
index ec6e56d..e20d8f7 100644
--- a/chrome/test/chromedriver/chrome_launcher.h
+++ b/chrome/test/chromedriver/chrome_launcher.h
@@ -24,6 +24,7 @@
class Chrome;
class DeviceManager;
+class PortServer;
class Status;
class URLRequestContextGetter;
@@ -31,6 +32,7 @@
URLRequestContextGetter* context_getter,
const SyncWebSocketFactory& socket_factory,
DeviceManager* device_manager,
+ PortServer* port_server,
const Capabilities& capabilities,
ScopedVector<DevToolsEventListener>& devtools_event_listeners,
scoped_ptr<Chrome>* chrome);
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc
index c4ddb5b..d00a1be 100644
--- a/chrome/test/chromedriver/commands.cc
+++ b/chrome/test/chromedriver/commands.cc
@@ -151,8 +151,20 @@
}
scoped_ptr<base::Value> value;
Status status = command.Run(session, *params, &value);
- if (status.IsError() && session->chrome)
+
+ if (status.IsError() && session->chrome) {
+ if (!session->quit && session->chrome->HasCrashedWebView()) {
+ session->quit = true;
+ std::string message("session deleted because of page crash");
+ if (!session->detach) {
+ Status quit_status = session->chrome->Quit();
+ if (quit_status.IsError())
+ message += ", but failed to kill browser:" + quit_status.message();
+ }
+ status = Status(kUnknownError, message, status);
+ }
status.AddDetails("Session info: chrome=" + session->chrome->GetVersion());
+ }
if (IsVLogOn(0)) {
std::string result;
diff --git a/chrome/test/chromedriver/keycode_text_conversion_x.cc b/chrome/test/chromedriver/keycode_text_conversion_x.cc
index 349c431..c489e07 100644
--- a/chrome/test/chromedriver/keycode_text_conversion_x.cc
+++ b/chrome/test/chromedriver/keycode_text_conversion_x.cc
@@ -190,7 +190,7 @@
XEvent event;
memset(&event, 0, sizeof(XEvent));
XKeyEvent* key_event = &event.xkey;
- Display* display = ui::GetXDisplay();
+ XDisplay* display = gfx::GetXDisplay();
if (!display) {
*error_msg =
"an X display is required for keycode conversions, consider using Xvfb";
diff --git a/chrome/test/chromedriver/net/DEPS b/chrome/test/chromedriver/net/DEPS
index 4ffb644..9183c7c 100644
--- a/chrome/test/chromedriver/net/DEPS
+++ b/chrome/test/chromedriver/net/DEPS
@@ -2,5 +2,6 @@
# These files should not depend on chromedriver code.
"-chrome/test/chromedriver",
+ "+chrome/test/chromedriver/chrome/status.h",
"+chrome/test/chromedriver/net",
]
diff --git a/chrome/test/chromedriver/net/adb_client_socket.cc b/chrome/test/chromedriver/net/adb_client_socket.cc
index 2f2e50d..3e68a21 100644
--- a/chrome/test/chromedriver/net/adb_client_socket.cc
+++ b/chrome/test/chromedriver/net/adb_client_socket.cc
@@ -18,7 +18,6 @@
namespace {
const int kBufferSize = 16 * 1024;
-const int kResponseBufferSize = 16;
const char kOkayResponse[] = "OKAY";
const char kHostTransportCommand[] = "host:transport:%s";
const char kLocalAbstractCommand[] = "localabstract:%s";
diff --git a/chrome/test/chromedriver/net/port_server.cc b/chrome/test/chromedriver/net/port_server.cc
new file mode 100644
index 0000000..6b7648a
--- /dev/null
+++ b/chrome/test/chromedriver/net/port_server.cc
@@ -0,0 +1,130 @@
+// 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/net/port_server.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/process/process_handle.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/sync_socket.h"
+#include "chrome/test/chromedriver/chrome/status.h"
+#include "net/base/sys_addrinfo.h"
+
+#if defined(OS_LINUX)
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
+
+PortReservation::PortReservation(const base::Closure& on_free_func, int port)
+ : on_free_func_(on_free_func), port_(port) {}
+
+PortReservation::~PortReservation() {
+ if (!on_free_func_.is_null())
+ on_free_func_.Run();
+}
+
+void PortReservation::Leak() {
+ LOG(ERROR) << "Port leaked: " << port_;
+ on_free_func_.Reset();
+}
+
+PortServer::PortServer(const std::string& path) : path_(path) {
+ CHECK(path_.size() && path_[0] == 0)
+ << "path must be for Linux abstract namespace";
+}
+
+PortServer::~PortServer() {}
+
+Status PortServer::ReservePort(int* port,
+ scoped_ptr<PortReservation>* reservation) {
+ int port_to_use = 0;
+ {
+ base::AutoLock lock(free_lock_);
+ if (free_.size()) {
+ port_to_use = free_.front();
+ free_.pop_front();
+ }
+ }
+ if (!port_to_use) {
+ Status status = RequestPort(&port_to_use);
+ if (status.IsError())
+ return status;
+ }
+ *port = port_to_use;
+ reservation->reset(new PortReservation(
+ base::Bind(&PortServer::ReleasePort, base::Unretained(this), port_to_use),
+ port_to_use));
+ return Status(kOk);
+}
+
+Status PortServer::RequestPort(int* port) {
+ // The client sends its PID + \n, and the server responds with a port + \n,
+ // which is valid for the lifetime of the referred process.
+#if defined(OS_LINUX)
+ int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock_fd < 0)
+ return Status(kUnknownError, "unable to create socket");
+ base::SyncSocket sock(sock_fd);
+ struct timeval tv;
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+ if (setsockopt(sock_fd,
+ SOL_SOCKET,
+ SO_RCVTIMEO,
+ reinterpret_cast<char*>(&tv),
+ sizeof(tv)) < 0 ||
+ setsockopt(sock_fd,
+ SOL_SOCKET,
+ SO_SNDTIMEO,
+ reinterpret_cast<char*>(&tv),
+ sizeof(tv)) < 0) {
+ return Status(kUnknownError, "unable to set socket timeout");
+ }
+
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ memcpy(addr.sun_path, &path_[0], path_.length());
+ if (connect(sock.handle(),
+ reinterpret_cast<struct sockaddr*>(&addr),
+ sizeof(sa_family_t) + path_.length())) {
+ return Status(kUnknownError, "unable to connect");
+ }
+
+ int proc_id = static_cast<int>(base::GetCurrentProcId());
+ std::string request = base::IntToString(proc_id);
+ request += "\n";
+ VLOG(0) << "PORTSERVER REQUEST " << request;
+ if (sock.Send(request.c_str(), request.length()) != request.length())
+ return Status(kUnknownError, "failed to send portserver request");
+
+ std::string response;
+ do {
+ char c = 0;
+ size_t rv = sock.Receive(&c, 1);
+ if (!rv)
+ break;
+ response.push_back(c);
+ } while (sock.Peek());
+ if (response.empty())
+ return Status(kUnknownError, "failed to receive portserver response");
+ VLOG(0) << "PORTSERVER RESPONSE " << response;
+
+ int new_port = 0;
+ if (*response.rbegin() != '\n' ||
+ !base::StringToInt(response.substr(0, response.length() - 1), &new_port))
+ return Status(kUnknownError, "failed to parse portserver response");
+ *port = new_port;
+ return Status(kOk);
+#else
+ return Status(kUnknownError, "not implemented for this platform");
+#endif
+}
+
+void PortServer::ReleasePort(int port) {
+ base::AutoLock lock(free_lock_);
+ free_.push_back(port);
+}
diff --git a/chrome/test/chromedriver/net/port_server.h b/chrome/test/chromedriver/net/port_server.h
new file mode 100644
index 0000000..318bc5c
--- /dev/null
+++ b/chrome/test/chromedriver/net/port_server.h
@@ -0,0 +1,51 @@
+// 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_NET_PORT_SERVER_H_
+#define CHROME_TEST_CHROMEDRIVER_NET_PORT_SERVER_H_
+
+#include <list>
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+
+class Status;
+
+class PortReservation {
+ public:
+ PortReservation(const base::Closure& on_free_func, int port);
+ ~PortReservation();
+
+ void Leak();
+
+ private:
+ base::Closure on_free_func_;
+ int port_;
+};
+
+// Communicates with a port reservation management server.
+class PortServer {
+ public:
+ // Construct a port server that communicates via the unix domain socket with
+ // the given path. Must use the Linux abstract namespace.
+ explicit PortServer(const std::string& path);
+ ~PortServer();
+
+ Status ReservePort(int* port, scoped_ptr<PortReservation>* reservation);
+
+ private:
+ Status RequestPort(int* port);
+ void ReleasePort(int port);
+
+ std::string path_;
+
+ base::Lock free_lock_;
+ std::list<int> free_;
+};
+
+bool SetSocketTimeout(const base::TimeDelta& timeout);
+
+#endif // CHROME_TEST_CHROMEDRIVER_NET_PORT_SERVER_H_
diff --git a/chrome/test/chromedriver/net/port_server_unittest.cc b/chrome/test/chromedriver/net/port_server_unittest.cc
new file mode 100644
index 0000000..9f30f73
--- /dev/null
+++ b/chrome/test/chromedriver/net/port_server_unittest.cc
@@ -0,0 +1,189 @@
+// 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 <string>
+
+#include "base/bind.h"
+#include "base/guid.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop.h"
+#include "base/sync_socket.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "base/time/time.h"
+#include "chrome/test/chromedriver/chrome/status.h"
+#include "chrome/test/chromedriver/net/port_server.h"
+#include "net/base/sys_addrinfo.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_LINUX)
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
+
+namespace {
+
+void SetOnCall(bool* called) {
+ *called = true;
+}
+
+} // namespace
+
+TEST(PortReservationTest, Normal) {
+ bool called = false;
+ {
+ PortReservation r(base::Bind(&SetOnCall, &called), 100);
+ }
+ ASSERT_TRUE(called);
+}
+
+TEST(PortReservationTest, Leak) {
+ bool called = false;
+ {
+ PortReservation r(base::Bind(&SetOnCall, &called), 100);
+ r.Leak();
+ }
+ ASSERT_FALSE(called);
+}
+
+TEST(PortReservationTest, MultipleLeaks) {
+ bool called = false;
+ {
+ PortReservation r(base::Bind(&SetOnCall, &called), 100);
+ r.Leak();
+ r.Leak();
+ }
+ ASSERT_FALSE(called);
+}
+
+#if defined(OS_LINUX)
+namespace {
+
+void RunServerOnThread(const std::string& path,
+ const std::string& response,
+ base::WaitableEvent* listen_event,
+ std::string* request) {
+ int server_sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ ASSERT_GE(server_sock_fd, 0);
+ ASSERT_GE(fcntl(server_sock_fd, F_SETFL, O_NONBLOCK), 0);
+ base::SyncSocket server_sock(server_sock_fd);
+
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ memcpy(addr.sun_path, &path[0], path.length());
+ ASSERT_EQ(0,
+ bind(server_sock_fd,
+ reinterpret_cast<struct sockaddr*>(&addr),
+ sizeof(sa_family_t) + path.length()));
+ ASSERT_EQ(0, listen(server_sock_fd, 1));
+ listen_event->Signal();
+
+ struct sockaddr_un cli_addr;
+ socklen_t clilen = sizeof(cli_addr);
+ base::TimeTicks deadline =
+ base::TimeTicks::Now() + base::TimeDelta::FromSeconds(2);
+ int client_sock_fd = -1;
+ while (base::TimeTicks::Now() < deadline && client_sock_fd < 0) {
+ client_sock_fd = accept(
+ server_sock_fd, reinterpret_cast<struct sockaddr*>(&cli_addr), &clilen);
+ }
+ ASSERT_GE(client_sock_fd, 0);
+ base::SyncSocket sock(client_sock_fd);
+ do {
+ char c = 0;
+ size_t rv = sock.Receive(&c, 1);
+ if (!rv)
+ break;
+ request->push_back(c);
+ } while (sock.Peek());
+ sock.Send(response.c_str(), response.length());
+}
+
+std::string GenerateRandomPath() {
+ std::string path = base::GenerateGUID();
+ if (!path.empty()) {
+ std::string pre_path;
+ pre_path.push_back(0); // Linux abstract namespace.
+ path = pre_path + path;
+ }
+ return path;
+}
+
+} // namespace
+
+class PortServerTest : public testing::Test {
+ public:
+ PortServerTest() : thread_("server") {
+ EXPECT_TRUE(thread_.Start());
+ }
+
+ void RunServer(const std::string& path,
+ const std::string& response,
+ std::string* request) {
+ base::WaitableEvent listen_event(false, false);
+ thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &RunServerOnThread, path, response, &listen_event, request));
+ ASSERT_TRUE(listen_event.TimedWait(base::TimeDelta::FromSeconds(5)));
+ }
+
+ private:
+ base::Thread thread_;
+};
+
+TEST_F(PortServerTest, Reserve) {
+ std::string path = GenerateRandomPath();
+ PortServer server(path);
+
+ std::string request;
+ RunServer(path, "12345\n", &request);
+
+ int port = 0;
+ scoped_ptr<PortReservation> reservation;
+ Status status = server.ReservePort(&port, &reservation);
+ ASSERT_EQ(kOk, status.code()) << status.message();
+ ASSERT_EQ(port, 12345);
+}
+
+TEST_F(PortServerTest, ReserveResetReserve) {
+ std::string path = GenerateRandomPath();
+ PortServer server(path);
+
+ std::string request;
+ RunServer(path, "12345\n", &request);
+
+ int port = 0;
+ scoped_ptr<PortReservation> reservation;
+ Status status = server.ReservePort(&port, &reservation);
+ ASSERT_EQ(kOk, status.code()) << status.message();
+ ASSERT_EQ(port, 12345);
+
+ reservation.reset();
+ status = server.ReservePort(&port, &reservation);
+ ASSERT_EQ(kOk, status.code()) << status.message();
+ ASSERT_EQ(port, 12345);
+}
+
+TEST_F(PortServerTest, ReserveReserve) {
+ std::string path = GenerateRandomPath();
+ PortServer server(path);
+
+ std::string request;
+ RunServer(path, "12345\n", &request);
+
+ int port = 0;
+ scoped_ptr<PortReservation> reservation;
+ Status status = server.ReservePort(&port, &reservation);
+ ASSERT_EQ(kOk, status.code()) << status.message();
+ ASSERT_EQ(port, 12345);
+
+ RunServer(path, "12346\n", &request);
+ status = server.ReservePort(&port, &reservation);
+ ASSERT_EQ(kOk, status.code()) << status.message();
+ ASSERT_EQ(port, 12346);
+}
+#endif
diff --git a/chrome/test/chromedriver/run_buildbot_steps.py b/chrome/test/chromedriver/run_buildbot_steps.py
index ddc05fd..03cf8fc 100755
--- a/chrome/test/chromedriver/run_buildbot_steps.py
+++ b/chrome/test/chromedriver/run_buildbot_steps.py
@@ -28,7 +28,7 @@
_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
GS_ARCHIVE_BUCKET = 'gs://chromedriver-prebuilts'
-GS_ZIP_PREFIX = 'chromedriver2_prebuilts'
+GS_ZIP_PREFIX = 'chromedriver_prebuilts'
GS_RC_BUCKET = 'gs://chromedriver-rc'
GS_RELEASE_PATH = GS_RC_BUCKET + '/releases'
RC_LOG_FORMAT = '%s_log.json'
@@ -50,8 +50,8 @@
def ArchivePrebuilts(revision):
"""Uploads the prebuilts to google storage."""
util.MarkBuildStepStart('archive')
- prebuilts = ['chromedriver2_server',
- 'chromedriver2_unittests', 'chromedriver2_tests']
+ prebuilts = ['chromedriver',
+ 'chromedriver_unittests', 'chromedriver_tests']
build_dir = chrome_paths.GetBuildDir(prebuilts[0:1])
zip_name = '%s_r%s.zip' % (GS_ZIP_PREFIX, revision)
temp_dir = util.MakeTempDir()
@@ -70,7 +70,7 @@
util.MarkBuildStepStart('Download chromedriver prebuilts')
temp_dir = util.MakeTempDir()
- zip_path = os.path.join(temp_dir, 'chromedriver2_prebuilts.zip')
+ zip_path = os.path.join(temp_dir, 'chromedriver_prebuilts.zip')
if gsutil_download.DownloadLatestFile(GS_ARCHIVE_BUCKET, GS_ZIP_PREFIX,
zip_path):
util.MarkBuildStepError()
@@ -81,7 +81,7 @@
f.extractall(build_dir)
f.close()
# Workaround for Python bug: http://bugs.python.org/issue15795
- os.chmod(os.path.join(build_dir, 'chromedriver2_server'), 0700)
+ os.chmod(os.path.join(build_dir, 'chromedriver'), 0700)
def GetDownloads():
@@ -245,8 +245,8 @@
assert platform != 'android'
version = GetVersion()
if not ReleaseCandidateExists(platform):
- rc_file = _ConstructReleaseCandidate(platform, revision)
util.MarkBuildStepStart('upload release candidate')
+ rc_file = _ConstructReleaseCandidate(platform, revision)
if slave_utils.GSUtilCopyFile(rc_file, GS_RC_BUCKET):
util.MarkBuildStepError()
else:
@@ -275,13 +275,10 @@
"""Constructs a release candidate zip from the current build."""
zip_name = RC_ZIP_FORMAT % (platform, GetVersion(), revision)
if util.IsWindows():
- server_orig_name = 'chromedriver2_server.exe'
server_name = 'chromedriver.exe'
else:
- server_orig_name = 'chromedriver2_server'
server_name = 'chromedriver'
- server = os.path.join(chrome_paths.GetBuildDir([server_orig_name]),
- server_orig_name)
+ server = os.path.join(chrome_paths.GetBuildDir([server_name]), server_name)
print 'Zipping ChromeDriver server', server
temp_dir = util.MakeTempDir()
@@ -391,8 +388,9 @@
help='Comma separated list of application package names, '
'if running tests on Android.')
parser.add_option(
- '-r', '--revision', type='int', default=None,
- help='Chromium revision')
+ '-r', '--revision', type='int', help='Chromium revision')
+ parser.add_option('', '--update-log', action='store_true',
+ help='Update the test results log (only applicable to Android)')
options, _ = parser.parse_args()
bitness = '32'
@@ -407,11 +405,12 @@
CleanTmpDir()
if platform == 'android':
+ if not options.revision and options.update_log:
+ parser.error('Must supply a --revision with --update-log')
DownloadPrebuilts()
else:
if not options.revision:
parser.error('Must supply a --revision')
-
if platform == 'linux64':
ArchivePrebuilts(options.revision)
@@ -427,7 +426,9 @@
passed = (util.RunCommand(cmd) == 0)
if platform == 'android':
- UpdateTestResultsLog(platform, options.revision, passed)
+ if options.update_log:
+ util.MarkBuildStepStart('update test result log')
+ UpdateTestResultsLog(platform, options.revision, passed)
elif passed:
_MaybeUpdateReleaseCandidate(platform, options.revision)
_MaybeRelease(platform)
diff --git a/chrome/test/chromedriver/server/chromedriver_server.cc b/chrome/test/chromedriver/server/chromedriver_server.cc
index 355c629..a920379 100644
--- a/chrome/test/chromedriver/server/chromedriver_server.cc
+++ b/chrome/test/chromedriver/server/chromedriver_server.cc
@@ -23,6 +23,7 @@
#include "base/threading/thread.h"
#include "base/threading/thread_local.h"
#include "chrome/test/chromedriver/logging.h"
+#include "chrome/test/chromedriver/net/port_server.h"
#include "chrome/test/chromedriver/server/http_handler.h"
#include "chrome/test/chromedriver/version.h"
#include "net/base/ip_endpoint.h"
@@ -134,7 +135,10 @@
lazy_tls_server.Pointer()->Set(temp_server.release());
}
-void RunServer(int port, const std::string& url_base, int adb_port) {
+void RunServer(int port,
+ const std::string& url_base,
+ int adb_port,
+ scoped_ptr<PortServer> port_server) {
base::Thread io_thread("ChromeDriver IO");
CHECK(io_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
@@ -144,7 +148,8 @@
HttpHandler handler(cmd_run_loop.QuitClosure(),
io_thread.message_loop_proxy(),
url_base,
- adb_port);
+ adb_port,
+ port_server.Pass());
HttpRequestHandlerFunc handle_request_func =
base::Bind(&HandleRequestOnCmdThread, &handler);
@@ -177,6 +182,7 @@
int port = 9515;
int adb_port = 5037;
std::string url_base;
+ scoped_ptr<PortServer> port_server;
if (cmd_line->HasSwitch("h") || cmd_line->HasSwitch("help")) {
std::string options;
const char* kOptionAndDescriptions[] = {
@@ -187,6 +193,7 @@
"verbose", "log verbosely",
"silent", "log nothing",
"url-base", "base URL path prefix for commands, e.g. wd/url",
+ "port-server", "address of server to contact for reserving a port",
};
for (size_t i = 0; i < arraysize(kOptionAndDescriptions) - 1; i += 2) {
options += base::StringPrintf(
@@ -209,6 +216,22 @@
return 1;
}
}
+ if (cmd_line->HasSwitch("port-server")) {
+#if defined(OS_LINUX)
+ std::string address = cmd_line->GetSwitchValueASCII("port-server");
+ if (address.empty() || address[0] != '@') {
+ printf("Invalid port-server. Exiting...\n");
+ return 1;
+ }
+ std::string path;
+ // First character of path is \0 to use Linux's abstract namespace.
+ path.push_back(0);
+ path += address.substr(1);
+ port_server.reset(new PortServer(path));
+#else
+ printf("Warning: port-server not implemented for this platform.\n");
+#endif
+ }
if (cmd_line->HasSwitch("url-base"))
url_base = cmd_line->GetSwitchValueASCII("url-base");
if (url_base.empty() || url_base[0] != '/')
@@ -225,7 +248,6 @@
printf("Unable to initialize logging. Exiting...\n");
return 1;
}
-
- RunServer(port, url_base, adb_port);
+ RunServer(port, url_base, adb_port, port_server.Pass());
return 0;
}
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc
index 79c2faa..fe03647 100644
--- a/chrome/test/chromedriver/server/http_handler.cc
+++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -21,6 +21,7 @@
#include "chrome/test/chromedriver/chrome/adb_impl.h"
#include "chrome/test/chromedriver/chrome/device_manager.h"
#include "chrome/test/chromedriver/chrome/status.h"
+#include "chrome/test/chromedriver/net/port_server.h"
#include "chrome/test/chromedriver/net/url_request_context_getter.h"
#include "chrome/test/chromedriver/session.h"
#include "chrome/test/chromedriver/session_thread_map.h"
@@ -65,7 +66,8 @@
const base::Closure& quit_func,
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const std::string& url_base,
- int adb_port)
+ int adb_port,
+ scoped_ptr<PortServer> port_server)
: quit_func_(quit_func),
url_base_(url_base),
received_shutdown_(false),
@@ -77,6 +79,7 @@
socket_factory_ = CreateSyncWebSocketFactory(context_getter_.get());
adb_.reset(new AdbImpl(io_task_runner, adb_port));
device_manager_.reset(new DeviceManager(adb_.get()));
+ port_server_ = port_server.Pass();
CommandMapping commands[] = {
CommandMapping(
@@ -84,12 +87,13 @@
internal::kNewSessionPathPattern,
base::Bind(&ExecuteCreateSession,
&session_thread_map_,
- WrapToCommand("InitSession",
- base::Bind(&ExecuteInitSession,
- InitSessionParams(
- context_getter_,
- socket_factory_,
- device_manager_.get()))))),
+ WrapToCommand(
+ "InitSession",
+ base::Bind(&ExecuteInitSession,
+ InitSessionParams(context_getter_,
+ socket_factory_,
+ device_manager_.get(),
+ port_server_.get()))))),
CommandMapping(kGet,
"session/:sessionId",
WrapToCommand("GetSessionCapabilities",
diff --git a/chrome/test/chromedriver/server/http_handler.h b/chrome/test/chromedriver/server/http_handler.h
index 50d6b20..7b6943d 100644
--- a/chrome/test/chromedriver/server/http_handler.h
+++ b/chrome/test/chromedriver/server/http_handler.h
@@ -35,6 +35,7 @@
class Adb;
class DeviceManager;
+class PortServer;
class URLRequestContextGetter;
enum HttpMethod {
@@ -63,7 +64,8 @@
HttpHandler(const base::Closure& quit_func,
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const std::string& url_base,
- int adb_port);
+ int adb_port,
+ scoped_ptr<PortServer> port_server);
~HttpHandler();
void Handle(const net::HttpServerRequestInfo& request,
@@ -106,6 +108,7 @@
scoped_ptr<CommandMap> command_map_;
scoped_ptr<Adb> adb_;
scoped_ptr<DeviceManager> device_manager_;
+ scoped_ptr<PortServer> port_server_;
base::WeakPtrFactory<HttpHandler> weak_ptr_factory_;
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc
index c523dab..b2cd1b9 100644
--- a/chrome/test/chromedriver/session_commands.cc
+++ b/chrome/test/chromedriver/session_commands.cc
@@ -55,10 +55,12 @@
InitSessionParams::InitSessionParams(
scoped_refptr<URLRequestContextGetter> context_getter,
const SyncWebSocketFactory& socket_factory,
- DeviceManager* device_manager)
+ DeviceManager* device_manager,
+ PortServer* port_server)
: context_getter(context_getter),
socket_factory(socket_factory),
- device_manager(device_manager) {}
+ device_manager(device_manager),
+ port_server(port_server) {}
InitSessionParams::~InitSessionParams() {}
@@ -119,6 +121,7 @@
status = LaunchChrome(bound_params.context_getter.get(),
bound_params.socket_factory,
bound_params.device_manager,
+ bound_params.port_server,
capabilities,
devtools_event_listeners,
&session->chrome);
@@ -158,12 +161,11 @@
Session* session,
const base::DictionaryValue& params,
scoped_ptr<base::Value>* value) {
- if (allow_detach && session->detach) {
+ session->quit = true;
+ if (allow_detach && session->detach)
return Status(kOk);
- } else {
- session->quit = true;
+ else
return session->chrome->Quit();
- }
}
Status ExecuteGetSessionCapabilities(
diff --git a/chrome/test/chromedriver/session_commands.h b/chrome/test/chromedriver/session_commands.h
index 1c5be1c..bf10bb6 100644
--- a/chrome/test/chromedriver/session_commands.h
+++ b/chrome/test/chromedriver/session_commands.h
@@ -18,6 +18,7 @@
}
class DeviceManager;
+class PortServer;
struct Session;
class Status;
class URLRequestContextGetter;
@@ -25,12 +26,14 @@
struct InitSessionParams {
InitSessionParams(scoped_refptr<URLRequestContextGetter> context_getter,
const SyncWebSocketFactory& socket_factory,
- DeviceManager* device_manager);
+ DeviceManager* device_manager,
+ PortServer* port_server);
~InitSessionParams();
scoped_refptr<URLRequestContextGetter> context_getter;
SyncWebSocketFactory socket_factory;
DeviceManager* device_manager;
+ PortServer* port_server;
};
// Initializes a session.
diff --git a/chrome/test/chromedriver/test/run_all_tests.py b/chrome/test/chromedriver/test/run_all_tests.py
index cd0255e..4267731 100755
--- a/chrome/test/chromedriver/test/run_all_tests.py
+++ b/chrome/test/chromedriver/test/run_all_tests.py
@@ -107,7 +107,7 @@
def RunCppTests(cpp_tests):
- util.MarkBuildStepStart('chromedriver2_tests')
+ util.MarkBuildStepStart('chromedriver_tests')
code = util.RunCommand([cpp_tests])
if code:
util.MarkBuildStepError()
@@ -136,8 +136,8 @@
exe_postfix = ''
if util.IsWindows():
exe_postfix = '.exe'
- cpp_tests_name = 'chromedriver2_tests' + exe_postfix
- server_name = 'chromedriver2_server' + exe_postfix
+ cpp_tests_name = 'chromedriver_tests' + exe_postfix
+ server_name = 'chromedriver' + exe_postfix
required_build_outputs = [server_name]
if not options.android_packages:
diff --git a/chrome/test/functional/ispy/ispy_core/__init__.py b/chrome/test/functional/ispy/__init__.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/__init__.py
rename to chrome/test/functional/ispy/__init__.py
diff --git a/chrome/test/functional/ispy/ispy_core/app.yaml b/chrome/test/functional/ispy/app.yaml
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/app.yaml
rename to chrome/test/functional/ispy/app.yaml
diff --git a/chrome/test/functional/ispy/ispy_core/handlers/__init__.py b/chrome/test/functional/ispy/handlers/__init__.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/handlers/__init__.py
rename to chrome/test/functional/ispy/handlers/__init__.py
diff --git a/chrome/test/functional/ispy/ispy_core/handlers/command_handler.py b/chrome/test/functional/ispy/handlers/command_handler.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/handlers/command_handler.py
rename to chrome/test/functional/ispy/handlers/command_handler.py
diff --git a/chrome/test/functional/ispy/ispy_core/handlers/debug_view_handler.py b/chrome/test/functional/ispy/handlers/debug_view_handler.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/handlers/debug_view_handler.py
rename to chrome/test/functional/ispy/handlers/debug_view_handler.py
diff --git a/chrome/test/functional/ispy/ispy_core/handlers/image_handler.py b/chrome/test/functional/ispy/handlers/image_handler.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/handlers/image_handler.py
rename to chrome/test/functional/ispy/handlers/image_handler.py
diff --git a/chrome/test/functional/ispy/ispy_core/handlers/main_view_handler.py b/chrome/test/functional/ispy/handlers/main_view_handler.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/handlers/main_view_handler.py
rename to chrome/test/functional/ispy/handlers/main_view_handler.py
diff --git a/chrome/test/functional/ispy/ispy_core/handlers/update_mask_handler.py b/chrome/test/functional/ispy/handlers/update_mask_handler.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/handlers/update_mask_handler.py
rename to chrome/test/functional/ispy/handlers/update_mask_handler.py
diff --git a/chrome/test/functional/ispy/ispy_core/ispy_auth_constants.py b/chrome/test/functional/ispy/ispy_auth_constants.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/ispy_auth_constants.py
rename to chrome/test/functional/ispy/ispy_auth_constants.py
diff --git a/chrome/test/functional/ispy/ispy_core/main.py b/chrome/test/functional/ispy/main.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/main.py
rename to chrome/test/functional/ispy/main.py
diff --git a/chrome/test/functional/ispy/ispy_core/run_tests.py b/chrome/test/functional/ispy/run_tests.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/run_tests.py
rename to chrome/test/functional/ispy/run_tests.py
diff --git a/chrome/test/functional/ispy/ispy_core/tests/__init__.py b/chrome/test/functional/ispy/tests/__init__.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tests/__init__.py
rename to chrome/test/functional/ispy/tests/__init__.py
diff --git a/chrome/test/functional/ispy/ispy_core/tests/rendering_test_manager/__init__.py b/chrome/test/functional/ispy/tests/rendering_test_manager/__init__.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tests/rendering_test_manager/__init__.py
rename to chrome/test/functional/ispy/tests/rendering_test_manager/__init__.py
diff --git a/chrome/test/functional/ispy/ispy_core/tests/rendering_test_manager/cloud_bucket.py b/chrome/test/functional/ispy/tests/rendering_test_manager/cloud_bucket.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tests/rendering_test_manager/cloud_bucket.py
rename to chrome/test/functional/ispy/tests/rendering_test_manager/cloud_bucket.py
diff --git a/chrome/test/functional/ispy/ispy_core/tests/rendering_test_manager/cloud_bucket_impl.py b/chrome/test/functional/ispy/tests/rendering_test_manager/cloud_bucket_impl.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tests/rendering_test_manager/cloud_bucket_impl.py
rename to chrome/test/functional/ispy/tests/rendering_test_manager/cloud_bucket_impl.py
diff --git a/chrome/test/functional/ispy/ispy_core/tests/rendering_test_manager/mock_cloud_bucket.py b/chrome/test/functional/ispy/tests/rendering_test_manager/mock_cloud_bucket.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tests/rendering_test_manager/mock_cloud_bucket.py
rename to chrome/test/functional/ispy/tests/rendering_test_manager/mock_cloud_bucket.py
diff --git a/chrome/test/functional/ispy/ispy_core/tools/__init__.py b/chrome/test/functional/ispy/tools/__init__.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tools/__init__.py
rename to chrome/test/functional/ispy/tools/__init__.py
diff --git a/chrome/test/functional/ispy/ispy_core/tools/api_command_runner.py b/chrome/test/functional/ispy/tools/api_command_runner.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tools/api_command_runner.py
rename to chrome/test/functional/ispy/tools/api_command_runner.py
diff --git a/chrome/test/functional/ispy/ispy_core/tools/api_command_runner_functionaltest.py b/chrome/test/functional/ispy/tools/api_command_runner_functionaltest.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tools/api_command_runner_functionaltest.py
rename to chrome/test/functional/ispy/tools/api_command_runner_functionaltest.py
diff --git a/chrome/test/functional/ispy/ispy_core/tools/image_tools.py b/chrome/test/functional/ispy/tools/image_tools.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tools/image_tools.py
rename to chrome/test/functional/ispy/tools/image_tools.py
diff --git a/chrome/test/functional/ispy/ispy_core/tools/image_tools_unittest.py b/chrome/test/functional/ispy/tools/image_tools_unittest.py
similarity index 99%
rename from chrome/test/functional/ispy/ispy_core/tools/image_tools_unittest.py
rename to chrome/test/functional/ispy/tools/image_tools_unittest.py
index 52e4825..7d52c49 100644
--- a/chrome/test/functional/ispy/ispy_core/tools/image_tools_unittest.py
+++ b/chrome/test/functional/ispy/tools/image_tools_unittest.py
@@ -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/test/functional/ispy/ispy_core/tools/rendering_test_manager.py b/chrome/test/functional/ispy/tools/rendering_test_manager.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tools/rendering_test_manager.py
rename to chrome/test/functional/ispy/tools/rendering_test_manager.py
diff --git a/chrome/test/functional/ispy/ispy_core/tools/rendering_test_manager_unittest.py b/chrome/test/functional/ispy/tools/rendering_test_manager_unittest.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tools/rendering_test_manager_unittest.py
rename to chrome/test/functional/ispy/tools/rendering_test_manager_unittest.py
diff --git a/chrome/test/functional/ispy/ispy_core/tools/reverse_port_forwarder.py b/chrome/test/functional/ispy/tools/reverse_port_forwarder.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/tools/reverse_port_forwarder.py
rename to chrome/test/functional/ispy/tools/reverse_port_forwarder.py
diff --git a/chrome/test/functional/ispy/ispy_core/views/__init__.py b/chrome/test/functional/ispy/views/__init__.py
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/views/__init__.py
rename to chrome/test/functional/ispy/views/__init__.py
diff --git a/chrome/test/functional/ispy/ispy_core/views/debug_view.html b/chrome/test/functional/ispy/views/debug_view.html
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/views/debug_view.html
rename to chrome/test/functional/ispy/views/debug_view.html
diff --git a/chrome/test/functional/ispy/ispy_core/views/diff_view.html b/chrome/test/functional/ispy/views/diff_view.html
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/views/diff_view.html
rename to chrome/test/functional/ispy/views/diff_view.html
diff --git a/chrome/test/functional/ispy/ispy_core/views/list_view.html b/chrome/test/functional/ispy/views/list_view.html
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/views/list_view.html
rename to chrome/test/functional/ispy/views/list_view.html
diff --git a/chrome/test/functional/ispy/ispy_core/views/main_view.html b/chrome/test/functional/ispy/views/main_view.html
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/views/main_view.html
rename to chrome/test/functional/ispy/views/main_view.html
diff --git a/chrome/test/functional/ispy/ispy_core/wait_on_ajax.js b/chrome/test/functional/ispy/wait_on_ajax.js
similarity index 100%
rename from chrome/test/functional/ispy/ispy_core/wait_on_ajax.js
rename to chrome/test/functional/ispy/wait_on_ajax.js
diff --git a/chrome/test/mini_installer/config/chrome_system_installed.prop b/chrome/test/mini_installer/config/chrome_system_installed.prop
index 436516e..a1bd479 100644
--- a/chrome/test/mini_installer/config/chrome_system_installed.prop
+++ b/chrome/test/mini_installer/config/chrome_system_installed.prop
@@ -24,6 +24,10 @@
},
"Version": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"}
}
+ },
+ "HKEY_LOCAL_MACHINE\\Software\\Classes\\$CHROME_SHORT_NAME": {
+ "condition": "$WINDOWS_VERSION >= $VERSION_WIN8",
+ "exists": true
}
}
}
diff --git a/chrome/test/mini_installer/config/chrome_system_not_installed.prop b/chrome/test/mini_installer/config/chrome_system_not_installed.prop
index d57401c..f1e25e1 100644
--- a/chrome/test/mini_installer/config/chrome_system_not_installed.prop
+++ b/chrome/test/mini_installer/config/chrome_system_not_installed.prop
@@ -5,6 +5,9 @@
"RegistryEntries": {
"HKEY_LOCAL_MACHINE\\$CHROME_UPDATE_REGISTRY_SUBKEY": {"exists": false},
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME":
- {"exists": false}
+ {"exists": false},
+ "HKEY_LOCAL_MACHINE\\Software\\Classes\\$CHROME_SHORT_NAME": {
+ "exists": false
+ }
}
}
diff --git a/chrome/test/mini_installer/config/chrome_user_installed.prop b/chrome/test/mini_installer/config/chrome_user_installed.prop
index 684947e..993ddc4 100644
--- a/chrome/test/mini_installer/config/chrome_user_installed.prop
+++ b/chrome/test/mini_installer/config/chrome_user_installed.prop
@@ -24,6 +24,10 @@
},
"Version": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"}
}
+ },
+ "HKEY_CURRENT_USER\\Software\\Classes\\$CHROME_SHORT_NAME$USER_SPECIFIC_REGISTRY_SUFFIX": {
+ "condition": "$WINDOWS_VERSION >= $VERSION_WIN8",
+ "exists": true
}
}
}
diff --git a/chrome/test/mini_installer/config/chrome_user_not_installed.prop b/chrome/test/mini_installer/config/chrome_user_not_installed.prop
index 28e8042..6313f92 100644
--- a/chrome/test/mini_installer/config/chrome_user_not_installed.prop
+++ b/chrome/test/mini_installer/config/chrome_user_not_installed.prop
@@ -6,6 +6,9 @@
"HKEY_CURRENT_USER\\$CHROME_UPDATE_REGISTRY_SUBKEY\\Commands":
{"exists": false},
"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME":
- {"exists": false}
+ {"exists": false},
+ "HKEY_CURRENT_USER\\Software\\Classes\\$CHROME_SHORT_NAME$USER_SPECIFIC_REGISTRY_SUFFIX": {
+ "exists": false
+ }
}
}
diff --git a/chrome/test/mini_installer/file_verifier.py b/chrome/test/mini_installer/file_verifier.py
index e6a8021..5e62446 100644
--- a/chrome/test/mini_installer/file_verifier.py
+++ b/chrome/test/mini_installer/file_verifier.py
@@ -4,23 +4,28 @@
import os
+import verifier
-def VerifyFiles(files, variable_expander):
- """Verifies that the current files match the expectation dictionaries.
- This method will throw an AssertionError if file state doesn't match the
- provided expectation.
+class FileVerifier(verifier.Verifier):
+ """Verifies that the current files match the expectation dictionaries."""
- Args:
- files: A dictionary whose keys are file paths and values are expectation
- dictionaries. An expectation dictionary is a dictionary with the
- following key and value:
- 'exists' a boolean indicating whether the file should exist.
- variable_expander: A VariableExpander object.
- """
- for file_path, expectation in files.iteritems():
- file_expanded_path = variable_expander.Expand(file_path)
- file_exists = os.path.exists(file_expanded_path)
+ def _VerifyExpectation(self, expectation_name, expectation,
+ variable_expander):
+ """Overridden from verifier.Verifier.
+
+ This method will throw an AssertionError if file state doesn't match the
+ |expectation|.
+
+ Args:
+ expectation_name: Path to the file being verified. It is expanded using
+ Expand.
+ expectation: A dictionary with the following key and value:
+ 'exists' a boolean indicating whether the file should exist.
+ variable_expander: A VariableExpander object.
+ """
+ file_path = variable_expander.Expand(expectation_name)
+ file_exists = os.path.exists(file_path)
assert expectation['exists'] == file_exists, \
- ('File %s exists' % file_expanded_path) if file_exists else \
- ('File %s is missing' % file_expanded_path)
+ ('File %s exists' % file_path) if file_exists else \
+ ('File %s is missing' % file_path)
diff --git a/chrome/test/mini_installer/launch_chrome.py b/chrome/test/mini_installer/launch_chrome.py
index 311a06b..9f8cd6e 100644
--- a/chrome/test/mini_installer/launch_chrome.py
+++ b/chrome/test/mini_installer/launch_chrome.py
@@ -8,9 +8,9 @@
"""
import optparse
-import subprocess
import sys
import time
+import win32process
import chrome_helper
@@ -30,7 +30,7 @@
while time.time() - start_time < 30:
if chrome_helper.WindowExists([process_id], class_pattern):
return True
- time.sleep(0)
+ time.sleep(0.1)
return False
@@ -42,8 +42,12 @@
parser.error('Incorrect number of arguments.')
chrome_path = args[0]
- process = subprocess.Popen(chrome_path)
- if not WaitForWindow(process.pid, 'Chrome_WidgetWin_'):
+ # Use CreateProcess rather than subprocess.Popen to avoid side effects such as
+ # handle interitance.
+ _, _, process_id, _ = win32process.CreateProcess(None, chrome_path, None,
+ None, 0, 0, None, None,
+ win32process.STARTUPINFO())
+ if not WaitForWindow(process_id, 'Chrome_WidgetWin_'):
raise Exception('Could not launch Chrome.')
return 0
diff --git a/chrome/test/mini_installer/process_verifier.py b/chrome/test/mini_installer/process_verifier.py
index be92704..adf1e1d 100644
--- a/chrome/test/mini_installer/process_verifier.py
+++ b/chrome/test/mini_installer/process_verifier.py
@@ -3,29 +3,31 @@
# found in the LICENSE file.
import chrome_helper
+import verifier
-def VerifyProcesses(processes, variable_expander):
- """Verifies that the running processes match the expectation dictionaries.
+class ProcessVerifier(verifier.Verifier):
+ """Verifies that the running processes match the expectation dictionaries."""
- This method will throw an AssertionError if process state doesn't match the
- provided expectation.
+ def _VerifyExpectation(self, expectation_name, expectation,
+ variable_expander):
+ """Overridden from verifier.Verifier.
- Args:
- processes: A dictionary whose keys are paths to processes and values are
- expectation dictionaries. An expectation dictionary is a dictionary with
- the following key and value:
- 'running' a boolean indicating whether the process should be
- running.
- variable_expander: A VariableExpander object.
- """
- # Create a list of paths of all running processes.
- running_process_paths = [path for (_, path) in
- chrome_helper.GetProcessIDAndPathPairs()]
+ This method will throw an AssertionError if process state doesn't match the
+ |expectation|.
- for process_path, expectation in processes.iteritems():
- process_expanded_path = variable_expander.Expand(process_path)
- is_running = process_expanded_path in running_process_paths
+ Args:
+ expectation_name: Path to the process being verified. It is expanded using
+ Expand.
+ expectation: A dictionary with the following key and value:
+ 'running' a boolean indicating whether the process should be running.
+ variable_expander: A VariableExpander object.
+ """
+ # Create a list of paths of all running processes.
+ running_process_paths = [path for (_, path) in
+ chrome_helper.GetProcessIDAndPathPairs()]
+ process_path = variable_expander.Expand(expectation_name)
+ is_running = process_path in running_process_paths
assert expectation['running'] == is_running, \
- ('Process %s is running' % process_expanded_path) if is_running else \
- ('Process %s is not running' % process_expanded_path)
+ ('Process %s is running' % process_path) if is_running else \
+ ('Process %s is not running' % process_path)
diff --git a/chrome/test/mini_installer/quit_chrome.py b/chrome/test/mini_installer/quit_chrome.py
index 96321b7..90e3e6e 100644
--- a/chrome/test/mini_installer/quit_chrome.py
+++ b/chrome/test/mini_installer/quit_chrome.py
@@ -42,7 +42,7 @@
# It's normal that some window handles have become invalid.
if error.args[0] != winerror.ERROR_INVALID_WINDOW_HANDLE:
raise
- time.sleep(0)
+ time.sleep(0.1)
return False
diff --git a/chrome/test/mini_installer/registry_verifier.py b/chrome/test/mini_installer/registry_verifier.py
index 283f5cc..98ff97c 100644
--- a/chrome/test/mini_installer/registry_verifier.py
+++ b/chrome/test/mini_installer/registry_verifier.py
@@ -4,105 +4,98 @@
import _winreg
-
-def VerifyRegistryEntries(entries, variable_expander):
- """Verifies that the current registry matches the specified criteria.
-
- Args:
- entries: A dictionary whose keys are registry keys and values are
- expectation dictionaries.
- variable_expander: A VariableExpander object.
- """
- for key, expectation in entries.iteritems():
- VerifyRegistryEntry(key, expectation, variable_expander)
+import verifier
-def RootKeyConstant(root_key):
- """Converts a root registry key string into a _winreg.HKEY_* constant."""
- root_key_mapping = {
- 'HKEY_CLASSES_ROOT': _winreg.HKEY_CLASSES_ROOT,
- 'HKEY_CURRENT_USER': _winreg.HKEY_CURRENT_USER,
- 'HKEY_LOCAL_MACHINE': _winreg.HKEY_LOCAL_MACHINE,
- 'HKEY_USERS': _winreg.HKEY_USERS,
- }
- if root_key not in root_key_mapping:
- raise KeyError("Unknown root registry key '%s'" % root_key)
- return root_key_mapping[root_key]
+class RegistryVerifier(verifier.Verifier):
+ """Verifies that the current registry matches the specified criteria."""
+ def _RootKeyConstant(self, root_key):
+ """Converts a root registry key string into a _winreg.HKEY_* constant."""
+ root_key_mapping = {
+ 'HKEY_CLASSES_ROOT': _winreg.HKEY_CLASSES_ROOT,
+ 'HKEY_CURRENT_USER': _winreg.HKEY_CURRENT_USER,
+ 'HKEY_LOCAL_MACHINE': _winreg.HKEY_LOCAL_MACHINE,
+ 'HKEY_USERS': _winreg.HKEY_USERS,
+ }
+ if root_key not in root_key_mapping:
+ raise KeyError("Unknown root registry key '%s'" % root_key)
+ return root_key_mapping[root_key]
-def ValueTypeConstant(value_type):
- """Converts a registry value type string into a _winreg.REG_* constant."""
- value_type_mapping = {
- 'BINARY': _winreg.REG_BINARY,
- 'DWORD': _winreg.REG_DWORD,
- 'DWORD_LITTLE_ENDIAN': _winreg.REG_DWORD_LITTLE_ENDIAN,
- 'DWORD_BIG_ENDIAN': _winreg.REG_DWORD_BIG_ENDIAN,
- 'EXPAND_SZ': _winreg.REG_EXPAND_SZ,
- 'LINK': _winreg.REG_LINK,
- 'MULTI_SZ': _winreg.REG_MULTI_SZ,
- 'NONE': _winreg.REG_NONE,
- 'SZ': _winreg.REG_SZ,
- }
- if value_type not in value_type_mapping:
- raise KeyError("Unknown registry value type '%s'" % value_type)
- return value_type_mapping[value_type]
+ def _ValueTypeConstant(self, value_type):
+ """Converts a registry value type string into a _winreg.REG_* constant."""
+ value_type_mapping = {
+ 'BINARY': _winreg.REG_BINARY,
+ 'DWORD': _winreg.REG_DWORD,
+ 'DWORD_LITTLE_ENDIAN': _winreg.REG_DWORD_LITTLE_ENDIAN,
+ 'DWORD_BIG_ENDIAN': _winreg.REG_DWORD_BIG_ENDIAN,
+ 'EXPAND_SZ': _winreg.REG_EXPAND_SZ,
+ 'LINK': _winreg.REG_LINK,
+ 'MULTI_SZ': _winreg.REG_MULTI_SZ,
+ 'NONE': _winreg.REG_NONE,
+ 'SZ': _winreg.REG_SZ,
+ }
+ if value_type not in value_type_mapping:
+ raise KeyError("Unknown registry value type '%s'" % value_type)
+ return value_type_mapping[value_type]
+ def _VerifyExpectation(self, expectation_name, expectation,
+ variable_expander):
+ """Overridden from verifier.Verifier.
-def VerifyRegistryEntry(key, expectation, variable_expander):
- """Verifies a registry key according to the |expectation|.
+ Verifies a registry key according to the |expectation|.
- The |expectation| specifies whether or not the registry key should exist
- (under 'exists') and optionally specifies expected 'values' for the key.
-
- Args:
- key: Name of the registry key. It is expanded using Expand.
- expectation: A dictionary with the following keys and values:
- 'exists' a boolean indicating whether the registry key should exist.
- 'values' (optional) a dictionary where each key is a registry value and
- its associated value is a dictionary with the following key and
- values:
- 'type' a string indicating the type of the registry value.
- 'data' the associated data of the registry value. If it is a
- string, it is expanded using Expand.
- variable_expander: A VariableExpander object.
- """
- expanded_key = variable_expander.Expand(key)
- root_key, sub_key = expanded_key.split('\\', 1)
- try:
- # Query the Windows registry for the registry key. It will throw a
- # WindowsError if the key doesn't exist.
- key_handle = _winreg.OpenKey(RootKeyConstant(root_key), sub_key, 0,
- _winreg.KEY_QUERY_VALUE)
- except WindowsError:
- # Key doesn't exist. See that it matches the expectation.
- assert not expectation['exists'], ('Registry key %s is missing' %
- expanded_key)
- return
- # The key exists, see that it matches the expectation.
- assert expectation['exists'], ('Registry key %s exists' % expanded_key)
-
- # Verify the expected values.
- if 'values' not in expectation:
- return
- for value, value_expectation in expectation['values'].iteritems():
- # Query the value. It will throw a WindowsError if the value doesn't exist.
+ Args:
+ expectation_name: The registry key being verified. It is expanded using
+ Expand.
+ expectation: A dictionary with the following keys and values:
+ 'exists' a boolean indicating whether the registry key should exist.
+ 'values' (optional) a dictionary where each key is a registry value
+ and its associated value is a dictionary with the following key
+ and values:
+ 'type' a string indicating the type of the registry value.
+ 'data' the associated data of the registry value. If it is a
+ string, it is expanded using Expand.
+ variable_expander: A VariableExpander object.
+ """
+ key = variable_expander.Expand(expectation_name)
+ root_key, sub_key = key.split('\\', 1)
try:
- data, value_type = _winreg.QueryValueEx(key_handle, value)
+ # Query the Windows registry for the registry key. It will throw a
+ # WindowsError if the key doesn't exist.
+ key_handle = _winreg.OpenKey(self._RootKeyConstant(root_key), sub_key, 0,
+ _winreg.KEY_QUERY_VALUE)
except WindowsError:
- raise KeyError("Value '%s' of registry key %s is missing" % (
- value, expanded_key))
+ # Key doesn't exist. See that it matches the expectation.
+ assert not expectation['exists'], ('Registry key %s is missing' %
+ key)
+ return
+ # The key exists, see that it matches the expectation.
+ assert expectation['exists'], ('Registry key %s exists' % key)
- # Verify the type of the value.
- expected_value_type = value_expectation['type']
- assert ValueTypeConstant(expected_value_type) == value_type, \
- "Value '%s' of registry key %s has unexpected type '%s'" % (
- value, expanded_key, expected_value_type)
+ # Verify the expected values.
+ if 'values' not in expectation:
+ return
+ for value, value_expectation in expectation['values'].iteritems():
+ # Query the value. It will throw a WindowsError if the value doesn't
+ # exist.
+ try:
+ data, value_type = _winreg.QueryValueEx(key_handle, value)
+ except WindowsError:
+ raise KeyError("Value '%s' of registry key %s is missing" % (
+ value, key))
- # Verify the associated data of the value.
- expected_data = value_expectation['data']
- if isinstance(expected_data, basestring):
- expected_data = variable_expander.Expand(expected_data)
- assert expected_data == data, \
- ("Value '%s' of registry key %s has unexpected data.\n"
- " Expected: %s\n"
- " Actual: %s" % (value, expanded_key, expected_data, data))
+ # Verify the type of the value.
+ expected_value_type = value_expectation['type']
+ assert self._ValueTypeConstant(expected_value_type) == value_type, \
+ "Value '%s' of registry key %s has unexpected type '%s'" % (
+ value, key, expected_value_type)
+
+ # Verify the associated data of the value.
+ expected_data = value_expectation['data']
+ if isinstance(expected_data, basestring):
+ expected_data = variable_expander.Expand(expected_data)
+ assert expected_data == data, \
+ ("Value '%s' of registry key %s has unexpected data.\n"
+ " Expected: %s\n"
+ " Actual: %s" % (value, key, expected_data, data))
diff --git a/chrome/test/mini_installer/test_installer.py b/chrome/test/mini_installer/test_installer.py
index a54382b..a0cc722 100644
--- a/chrome/test/mini_installer/test_installer.py
+++ b/chrome/test/mini_installer/test_installer.py
@@ -17,7 +17,7 @@
import unittest
from variable_expander import VariableExpander
-import verifier
+import verifier_runner
class Config:
@@ -52,6 +52,7 @@
self._test = test
self._config = config
self._variable_expander = variable_expander
+ self._verifier_runner = verifier_runner.VerifierRunner()
self._clean_on_teardown = True
def __str__(self):
@@ -107,7 +108,8 @@
state: A state name.
"""
try:
- verifier.Verify(self._config.states[state], self._variable_expander)
+ self._verifier_runner.VerifyAll(self._config.states[state],
+ self._variable_expander)
except AssertionError as e:
# If an AssertionError occurs, we intercept it and add the state name
# to the error message so that we know where the test fails.
diff --git a/chrome/test/mini_installer/variable_expander.py b/chrome/test/mini_installer/variable_expander.py
index 5fc34b5..3233d73 100644
--- a/chrome/test/mini_installer/variable_expander.py
+++ b/chrome/test/mini_installer/variable_expander.py
@@ -75,6 +75,9 @@
* $CHROME_HTML_PROG_ID: 'ChromeHTML' (or 'ChromiumHTM').
* $USER_SPECIFIC_REGISTRY_SUFFIX: the output from the function
_GetUserSpecificRegistrySuffix().
+ * $WINDOWS_VERSION: a 2-tuple representing the current Windows version.
+ * $VERSION_[XP/SERVER_2003/VISTA/WIN7/WIN8/WIN8_1]: a 2-tuple
+ representing the version of the corresponding OS.
Args:
mini_installer_path: The path to mini_installer.exe.
@@ -87,6 +90,10 @@
local_appdata_path = shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA,
None, 0)
user_specific_registry_suffix = _GetUserSpecificRegistrySuffix()
+ windows_major_ver, windows_minor_ver, _, _, _ = win32api.GetVersionEx()
+ # This string will be converted to a tuple once injected in eval() through
+ # conditional checks. Tuples are compared lexicographically.
+ windows_version = '(%s, %s)' % (windows_major_ver, windows_minor_ver)
if mini_installer_product_name == 'Google Chrome':
chrome_short_name = 'Chrome'
chrome_long_name = 'Google Chrome'
@@ -115,6 +122,13 @@
'CHROME_UPDATE_REGISTRY_SUBKEY': chrome_update_registry_subkey,
'CHROME_HTML_PROG_ID': chrome_html_prog_id,
'USER_SPECIFIC_REGISTRY_SUFFIX': user_specific_registry_suffix,
+ 'WINDOWS_VERSION': windows_version,
+ 'VERSION_XP': '(5, 1)',
+ 'VERSION_SERVER_2003': '(5, 2)',
+ 'VERSION_VISTA': '(6, 0)',
+ 'VERSION_WIN7': '(6, 1)',
+ 'VERSION_WIN8': '(6, 2)',
+ 'VERSION_WIN8_1': '(6, 3)',
}
def Expand(self, str):
diff --git a/chrome/test/mini_installer/verifier.py b/chrome/test/mini_installer/verifier.py
index 5830350..f3e930e 100644
--- a/chrome/test/mini_installer/verifier.py
+++ b/chrome/test/mini_installer/verifier.py
@@ -2,29 +2,51 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import file_verifier
-import process_verifier
-import registry_verifier
+class Verifier:
+ """Verifies that the current machine states match the expectation."""
-def Verify(property, variable_expander):
- """Verifies that the current machine states match the property dictionary.
+ def VerifyInput(self, verifier_input, variable_expander):
+ """Verifies that the current machine states match |verifier_input|.
- A property dictionary is a dictionary where each key is a verifier's name and
- the associated value is the input to that verifier. For details about the
- input format for each verifier, take a look at http://goo.gl/1P85WL
+ Args:
+ verifier_input: An input to the verifier. It is a dictionary where each
+ key is an expectation name and the associated value is an expectation
+ dictionary. The expectation dictionary may contain an optional
+ 'condition' property, a string that determines whether the expectation
+ should be verified. Each subclass can specify a different expectation
+ name and expectation dictionary.
+ variable_expander: A VariableExpander object.
+ """
+ for expectation_name, expectation in verifier_input.iteritems():
+ if 'condition' in expectation:
+ condition = variable_expander.Expand(expectation['condition'])
+ if not self._EvaluateCondition(condition):
+ continue
+ self._VerifyExpectation(expectation_name, expectation, variable_expander)
- Args:
- property: A property dictionary.
- variable_expander: A VariableExpander object.
- """
- for verifier_name, value in property.iteritems():
- if verifier_name == 'Files':
- file_verifier.VerifyFiles(value, variable_expander)
- elif verifier_name == 'Processes':
- process_verifier.VerifyProcesses(value, variable_expander)
- elif verifier_name == 'RegistryEntries':
- registry_verifier.VerifyRegistryEntries(value, variable_expander)
- else:
- # TODO(sukolsak): Implement other verifiers
- raise KeyError('Unknown verifier %s' % verifier_name)
+ def _VerifyExpectation(self, expectation_name, expectation,
+ variable_expander):
+ """Verifies that the current machine states match |verifier_input|.
+
+ This is an abstract method for subclasses to override.
+
+ Args:
+ expectation_name: An expectation name. Each subclass can specify a
+ different expectation name format.
+ expectation: An expectation dictionary. Each subclass can specify a
+ different expectation dictionary format.
+ variable_expander: A VariableExpander object.
+ """
+ raise NotImplementedError()
+
+ def _EvaluateCondition(self, condition):
+ """Evaluates |condition| using eval().
+
+ Args:
+ condition: A condition string.
+
+ Returns:
+ The result of the evaluated condition.
+ """
+ return eval(condition, {'__builtins__': None}, None)
diff --git a/chrome/test/mini_installer/verifier_runner.py b/chrome/test/mini_installer/verifier_runner.py
new file mode 100644
index 0000000..41023d1
--- /dev/null
+++ b/chrome/test/mini_installer/verifier_runner.py
@@ -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.
+
+import file_verifier
+import process_verifier
+import registry_verifier
+
+
+class VerifierRunner:
+ """Runs all Verifiers."""
+
+ def __init__(self):
+ """Constructor."""
+ # TODO(sukolsak): Implement other verifiers
+ self._verifiers = {
+ 'Files': file_verifier.FileVerifier(),
+ 'Processes': process_verifier.ProcessVerifier(),
+ 'RegistryEntries': registry_verifier.RegistryVerifier(),
+ }
+
+ def VerifyAll(self, property, variable_expander):
+ """Verifies that the current machine states match the property dictionary.
+
+ A property dictionary is a dictionary where each key is a verifier's name
+ and the associated value is the input to that verifier. For details about
+ the input format for each verifier, take a look at http://goo.gl/1P85WL
+
+ Args:
+ property: A property dictionary.
+ variable_expander: A VariableExpander object.
+ """
+ for verifier_name, verifier_input in property.iteritems():
+ if verifier_name not in self._verifiers:
+ raise KeyError('Unknown verifier %s' % verifier_name)
+ self._verifiers[verifier_name].VerifyInput(verifier_input,
+ variable_expander)
diff --git a/chrome/test/perf/rendering/throughput_tests.cc b/chrome/test/perf/rendering/throughput_tests.cc
index 98b7c92..abcbe93 100644
--- a/chrome/test/perf/rendering/throughput_tests.cc
+++ b/chrome/test/perf/rendering/throughput_tests.cc
@@ -193,9 +193,7 @@
command_line->AppendSwitch(switches::kDisableGpuVsync);
command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
// Enable or disable GPU acceleration.
- if (use_gpu_) {
- command_line->AppendSwitch(switches::kForceCompositingMode);
- } else {
+ if (!use_gpu_) {
command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index 7dadd5c..307b432 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -324,6 +324,8 @@
LIST_TEST(TCPSocket_Connect)
LIST_TEST(TCPSocket_ReadWrite)
LIST_TEST(TCPSocket_SetOption)
+ LIST_TEST(TCPSocket_Listen)
+ LIST_TEST(TCPSocket_Backlog)
);
}
IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, TCPSocket) {
@@ -331,6 +333,8 @@
LIST_TEST(TCPSocket_Connect)
LIST_TEST(TCPSocket_ReadWrite)
LIST_TEST(TCPSocket_SetOption)
+ LIST_TEST(TCPSocket_Listen)
+ LIST_TEST(TCPSocket_Backlog)
);
}
IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(TCPSocket)) {
@@ -338,6 +342,8 @@
LIST_TEST(TCPSocket_Connect)
LIST_TEST(TCPSocket_ReadWrite)
LIST_TEST(TCPSocket_SetOption)
+ LIST_TEST(TCPSocket_Listen)
+ LIST_TEST(TCPSocket_Backlog)
);
}
IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, TCPSocket) {
@@ -345,6 +351,8 @@
LIST_TEST(TCPSocket_Connect)
LIST_TEST(TCPSocket_ReadWrite)
LIST_TEST(TCPSocket_SetOption)
+ LIST_TEST(TCPSocket_Listen)
+ LIST_TEST(TCPSocket_Backlog)
);
}
@@ -630,9 +638,7 @@
TEST_PPAPI_OUT_OF_PROCESS_VIA_HTTP(URLRequest_AppendDataToBody)
TEST_PPAPI_NACL(URLRequest_AppendDataToBody)
TEST_PPAPI_IN_PROCESS_VIA_HTTP(URLRequest_AppendFileToBody)
-#if !defined(OS_MACOSX) // TODO(teravest): http://crbug.com/280570
TEST_PPAPI_OUT_OF_PROCESS_VIA_HTTP(URLRequest_AppendFileToBody)
-#endif
TEST_PPAPI_NACL(URLRequest_AppendFileToBody)
TEST_PPAPI_IN_PROCESS_VIA_HTTP(URLRequest_Stress)
TEST_PPAPI_OUT_OF_PROCESS_VIA_HTTP(URLRequest_Stress)
@@ -774,9 +780,7 @@
LIST_TEST(FileIO_NotAllowMixedReadWrite)
LIST_TEST(FileIO_ReadWriteSetLength)
LIST_TEST(FileIO_ReadToArrayWriteSetLength)
-#if !defined(OS_MACOSX) // TODO(teravest): http://crbug.com/280570
LIST_TEST(FileIO_TouchQuery)
-#endif
LIST_TEST(FileIO_WillWriteWillSetLength)
LIST_TEST(FileIO_RequestOSFileHandle)
LIST_TEST(FileIO_RequestOSFileHandleWithOpenExclusive)
@@ -1067,30 +1071,30 @@
// NetworkMonitor tests.
IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, NetworkMonitor) {
RunTestViaHTTP(
- LIST_TEST(NetworkMonitorPrivate_Basic)
- LIST_TEST(NetworkMonitorPrivate_2Monitors)
- LIST_TEST(NetworkMonitorPrivate_DeleteInCallback)
+ LIST_TEST(NetworkMonitor_Basic)
+ LIST_TEST(NetworkMonitor_2Monitors)
+ LIST_TEST(NetworkMonitor_DeleteInCallback)
);
}
IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, NetworkMonitor) {
RunTestViaHTTP(
- LIST_TEST(NetworkMonitorPrivate_Basic)
- LIST_TEST(NetworkMonitorPrivate_2Monitors)
- LIST_TEST(NetworkMonitorPrivate_DeleteInCallback)
+ LIST_TEST(NetworkMonitor_Basic)
+ LIST_TEST(NetworkMonitor_2Monitors)
+ LIST_TEST(NetworkMonitor_DeleteInCallback)
);
}
IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(NetworkMonitor)) {
RunTestViaHTTP(
- LIST_TEST(NetworkMonitorPrivate_Basic)
- LIST_TEST(NetworkMonitorPrivate_2Monitors)
- LIST_TEST(NetworkMonitorPrivate_DeleteInCallback)
+ LIST_TEST(NetworkMonitor_Basic)
+ LIST_TEST(NetworkMonitor_2Monitors)
+ LIST_TEST(NetworkMonitor_DeleteInCallback)
);
}
IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, NetworkMonitor) {
RunTestViaHTTP(
- LIST_TEST(NetworkMonitorPrivate_Basic)
- LIST_TEST(NetworkMonitorPrivate_2Monitors)
- LIST_TEST(NetworkMonitorPrivate_DeleteInCallback)
+ LIST_TEST(NetworkMonitor_Basic)
+ LIST_TEST(NetworkMonitor_2Monitors)
+ LIST_TEST(NetworkMonitor_DeleteInCallback)
);
}
diff --git a/chrome/test/reliability/automated_ui_test_base.cc b/chrome/test/reliability/automated_ui_test_base.cc
deleted file mode 100644
index 95b84a9..0000000
--- a/chrome/test/reliability/automated_ui_test_base.cc
+++ /dev/null
@@ -1,234 +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/reliability/automated_ui_test_base.h"
-
-#include "base/test/test_timeouts.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/ui/view_ids.h"
-#include "chrome/test/automation/automation_proxy.h"
-#include "chrome/test/automation/browser_proxy.h"
-#include "chrome/test/automation/tab_proxy.h"
-#include "chrome/test/automation/window_proxy.h"
-#include "chrome/test/ui/ui_test.h"
-#include "ui/events/event_constants.h"
-#include "ui/gfx/point.h"
-#include "ui/gfx/rect.h"
-
-AutomatedUITestBase::AutomatedUITestBase() {}
-
-AutomatedUITestBase::~AutomatedUITestBase() {}
-
-void AutomatedUITestBase::LogErrorMessage(const std::string& error) {
-}
-
-void AutomatedUITestBase::LogWarningMessage(const std::string& warning) {
-}
-
-void AutomatedUITestBase::LogInfoMessage(const std::string& info) {
-}
-
-void AutomatedUITestBase::SetUp() {
- UITest::SetUp();
- set_active_browser(automation()->GetBrowserWindow(0).get());
-}
-
-bool AutomatedUITestBase::BackButton() {
- return RunCommand(IDC_BACK);
-}
-
-bool AutomatedUITestBase::CloseActiveTab() {
- BrowserProxy* browser = active_browser();
- int tab_count;
- if (!browser->GetTabCount(&tab_count)) {
- LogErrorMessage("get_tab_count_failed");
- return false;
- }
-
- if (tab_count > 1) {
- return RunCommand(IDC_CLOSE_TAB);
- } else if (tab_count == 1) {
- // Synchronously close the window if it is not the last window.
- return CloseActiveWindow();
- } else {
- LogInfoMessage("invalid_tab_count");
- return false;
- }
-}
-
-bool AutomatedUITestBase::CloseActiveWindow() {
- int browser_windows_count = 0;
- if (!automation()->GetNormalBrowserWindowCount(&browser_windows_count))
- return false;
- // Avoid quitting the application by not closing the last window.
- if (browser_windows_count < 2)
- return false;
- bool application_closed;
- CloseBrowser(active_browser(), &application_closed);
- if (application_closed) {
- LogErrorMessage("Application closed unexpectedly.");
- return false;
- }
- for (int i = 0; i < browser_windows_count - 1; ++i) {
- scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(i));
- Browser::Type type;
- if (browser->GetType(&type) && type == Browser::TYPE_TABBED) {
- set_active_browser(browser.get());
- return true;
- }
- }
-
- LogErrorMessage("Can't find browser window.");
- return false;
-}
-
-bool AutomatedUITestBase::DuplicateTab() {
- return RunCommand(IDC_DUPLICATE_TAB);
-}
-
-bool AutomatedUITestBase::FindInPage() {
- if (!RunCommandAsync(IDC_FIND))
- return false;
-
- return WaitForFindWindowVisibilityChange(active_browser(), true);
-}
-
-bool AutomatedUITestBase::ForwardButton() {
- return RunCommand(IDC_FORWARD);
-}
-
-bool AutomatedUITestBase::GoOffTheRecord() {
- return RunCommand(IDC_NEW_INCOGNITO_WINDOW);
-}
-
-bool AutomatedUITestBase::Home() {
- return RunCommand(IDC_HOME);
-}
-
-bool AutomatedUITestBase::OpenAndActivateNewBrowserWindow(
- scoped_refptr<BrowserProxy>* previous_browser) {
- if (!automation()->OpenNewBrowserWindow(Browser::TYPE_TABBED,
- true /* SW_SHOWNORMAL */)) {
- LogWarningMessage("failed_to_open_new_browser_window");
- return false;
- }
- int num_browser_windows;
- if (!automation()->GetBrowserWindowCount(&num_browser_windows)) {
- LogErrorMessage("failed_to_get_browser_window_count");
- return false;
- }
- // Get the most recently opened browser window and activate the tab
- // in order to activate this browser window.
- scoped_refptr<BrowserProxy> browser(
- automation()->GetBrowserWindow(num_browser_windows - 1));
- if (browser.get() == NULL) {
- LogErrorMessage("browser_window_not_found");
- return false;
- }
- if (!browser->ActivateTab(0)) {
- LogWarningMessage("failed_to_activate_tab");
- return false;
- }
-
- if (previous_browser) {
- DCHECK(previous_browser->get() == NULL);
- active_browser_.swap(*previous_browser);
- }
-
- active_browser_.swap(browser);
- return true;
-}
-
-bool AutomatedUITestBase::Navigate(const GURL& url) {
- scoped_refptr<TabProxy> tab(GetActiveTab());
- if (tab.get() == NULL) {
- LogErrorMessage("active_tab_not_found");
- return false;
- }
- AutomationMsg_NavigationResponseValues result = tab->NavigateToURL(url);
- if (result != AUTOMATION_MSG_NAVIGATION_SUCCESS) {
- LogErrorMessage("navigation_failed");
- return false;
- }
-
- return true;
-}
-
-bool AutomatedUITestBase::NewTab() {
- // Apply accelerator and wait for a new tab to open, if either
- // fails, return false. Apply Accelerator takes care of logging its failure.
- return RunCommand(IDC_NEW_TAB);
-}
-
-bool AutomatedUITestBase::ReloadPage() {
- return RunCommand(IDC_RELOAD);
-}
-
-bool AutomatedUITestBase::RestoreTab() {
- return RunCommand(IDC_RESTORE_TAB);
-}
-
-bool AutomatedUITestBase::SelectNextTab() {
- return RunCommand(IDC_SELECT_NEXT_TAB);
-}
-
-bool AutomatedUITestBase::SelectPreviousTab() {
- return RunCommand(IDC_SELECT_PREVIOUS_TAB);
-}
-
-bool AutomatedUITestBase::ShowDownloads() {
- return RunCommand(IDC_SHOW_DOWNLOADS);
-}
-
-bool AutomatedUITestBase::ShowHistory() {
- return RunCommand(IDC_SHOW_HISTORY);
-}
-
-bool AutomatedUITestBase::RunCommandAsync(int browser_command) {
- BrowserProxy* browser = active_browser();
- if (NULL == browser) {
- LogErrorMessage("browser_window_not_found");
- return false;
- }
-
- if (!browser->RunCommandAsync(browser_command)) {
- LogWarningMessage("failure_running_browser_command");
- return false;
- }
- return true;
-}
-
-bool AutomatedUITestBase::RunCommand(int browser_command) {
- BrowserProxy* browser = active_browser();
- if (NULL == browser) {
- LogErrorMessage("browser_window_not_found");
- return false;
- }
-
- if (!browser->RunCommand(browser_command)) {
- LogWarningMessage("failure_running_browser_command");
- return false;
- }
- return true;
-}
-
-scoped_refptr<TabProxy> AutomatedUITestBase::GetActiveTab() {
- BrowserProxy* browser = active_browser();
- if (browser == NULL) {
- LogErrorMessage("browser_window_not_found");
- return NULL;
- }
-
- return browser->GetActiveTab();
-}
-
-scoped_refptr<WindowProxy> AutomatedUITestBase::GetAndActivateWindowForBrowser(
- BrowserProxy* browser) {
- if (!browser->BringToFront()) {
- LogWarningMessage("failed_to_bring_window_to_front");
- return NULL;
- }
-
- return browser->GetWindow();
-}
diff --git a/chrome/test/reliability/automated_ui_test_base.h b/chrome/test/reliability/automated_ui_test_base.h
deleted file mode 100644
index fce6773..0000000
--- a/chrome/test/reliability/automated_ui_test_base.h
+++ /dev/null
@@ -1,142 +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_RELIABILITY_AUTOMATED_UI_TEST_BASE_H_
-#define CHROME_TEST_RELIABILITY_AUTOMATED_UI_TEST_BASE_H_
-
-#include <string>
-
-#include "chrome/test/ui/ui_test.h"
-
-class WindowProxy;
-
-class AutomatedUITestBase : public UITest {
- protected:
- AutomatedUITestBase();
- virtual ~AutomatedUITestBase();
-
- virtual void SetUp() OVERRIDE;
-
- virtual void LogErrorMessage(const std::string &error);
- virtual void LogWarningMessage(const std::string &warning);
- virtual void LogInfoMessage(const std::string &info);
-
- // Actions
-
- // NOTE: This list is sorted alphabetically.
- // All functions are synchronous unless specified with Async.
-
- // Go back in active tab.
- // Returns true if successful, false otherwise.
- bool BackButton();
-
- // Close the selected tab in the current browser window. The function will
- // not try close the tab if it is the only tab of the last normal window, so
- // the application is not got closed.
- // Returns true if the tab is closed, false otherwise.
- bool CloseActiveTab();
-
- // Close the current browser window if it is not the only window left.
- // (Closing the last window will get application closed.)
- // Returns true if the window is closed, false otherwise.
- bool CloseActiveWindow();
-
- // Duplicates the current tab.
- // Returns true if a duplicated tab is added.
- bool DuplicateTab();
-
- // Activates "find in page" on the current page. Returns true on success.
- bool FindInPage();
-
- // Go forward in active tab.
- // Returns true if successful, false otherwise.
- bool ForwardButton();
-
- // Opens an OffTheRecord browser window.
- bool GoOffTheRecord();
-
- // Navigates to the Home page.
- // Returns true if call to activate the accelerator is successful.
- bool Home();
-
- // Navigates the activate tab to given url.
- bool Navigate(const GURL& url);
-
- // Opens a new tab in the active window using an accelerator.
- // Returns true if a new tab is successfully opened.
- bool NewTab();
-
- // Opens a new browser window by calling automation()->OpenNewBrowserWindow.
- // Then activates the tab opened in the new window.
- // Returns true if window is successfully created.
- // If optional parameter previous_browser is passed in, it is set to be the
- // previous browser window when new window is successfully created, and the
- // caller owns previous_browser.
- bool OpenAndActivateNewBrowserWindow(
- scoped_refptr<BrowserProxy>* previous_browser);
-
- // Reload the active tab.
- // Returns true if successful, false otherwise.
- bool ReloadPage();
-
- // Restores a previously closed tab.
- // Returns true if the tab is successfully restored.
- bool RestoreTab();
-
- // Activates the next tab on the active browser window.
- // Returns true on success.
- bool SelectNextTab();
-
- // Activates the previous tab on the active browser window.
- // Returns true on success.
- bool SelectPreviousTab();
-
- // Opens the Downloads page in the current active browser window.
- // Returns true on success.
- bool ShowDownloads();
-
- // Opens the History page in the current active browser window.
- // Returns true on success.
- bool ShowHistory();
-
- // Runs the specified browser command in the current active browser.
- // See Browser::ExecuteCommandWithDisposition() for the list of commands.
- // Returns true if the call is successfully dispatched.
- // Possible failures include the active window is not a browser window or
- // the message to apply the accelerator fails.
- bool RunCommandAsync(int browser_command);
-
- // Runs the specified browser command in the current active browser, wait
- // and return until the command has finished executing.
- // See Browser::ExecuteCommandWithDisposition() for the list of commands.
- // Returns true if the call is successfully dispatched and executed.
- // Possible failures include the active window is not a browser window, or
- // the message to apply the accelerator fails, or the command execution
- // fails.
- bool RunCommand(int browser_command);
-
- void set_active_browser(BrowserProxy* browser) {
- active_browser_ = browser;
- }
- BrowserProxy* active_browser() const { return active_browser_.get(); }
-
- // Get the selected tab within the current active browser window, then
- // create a corresponding TabProxy and transfer the ownership to caller.
- // If success return the pointer to the newly created TabProxy and the
- // caller owns the TabProxy. Return NULL otherwise.
- scoped_refptr<TabProxy> GetActiveTab();
-
- // Returns the WindowProxy associated with the given BrowserProxy
- // (transferring ownership of the pointer to the caller) and brings that
- // window to the top.
- scoped_refptr<WindowProxy> GetAndActivateWindowForBrowser(
- BrowserProxy* browser);
-
- private:
- scoped_refptr<BrowserProxy> active_browser_;
-
- DISALLOW_COPY_AND_ASSIGN(AutomatedUITestBase);
-};
-
-#endif // CHROME_TEST_RELIABILITY_AUTOMATED_UI_TEST_BASE_H_
diff --git a/chrome/test/reliability/automated_ui_tests.cc b/chrome/test/reliability/automated_ui_tests.cc
deleted file mode 100644
index 5348e60..0000000
--- a/chrome/test/reliability/automated_ui_tests.cc
+++ /dev/null
@@ -1,765 +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 <fstream>
-#include <string>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/file_util.h"
-#include "base/file_version_info.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/i18n/time_formatting.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/platform_thread.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"
-#include "chrome/test/automation/automation_proxy.h"
-#include "chrome/test/automation/browser_proxy.h"
-#include "chrome/test/automation/tab_proxy.h"
-#include "chrome/test/automation/window_proxy.h"
-#include "chrome/test/reliability/automated_ui_tests.h"
-#include "chrome/test/ui/ui_test.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "url/gurl.h"
-
-#if defined(TOOLKIT_VIEWS)
-#include "ui/views/view.h"
-#endif
-
-namespace {
-
-const char kReproSwitch[] = "key";
-
-const char kReproRepeatSwitch[] = "num-reproductions";
-
-const char kInputFilePathSwitch[] = "input";
-
-const char kOutputFilePathSwitch[] = "output";
-
-const char kDebugModeSwitch[] = "debug";
-
-const char kWaitSwitch[] = "wait-after-action";
-
-const char kTestLogFilePathSwitch[] = "testlog";
-
-const base::FilePath::CharType* const kDefaultInputFilePath =
-FILE_PATH_LITERAL("automated_ui_tests.txt");
-
-const base::FilePath::CharType* const kDefaultOutputFilePath =
-FILE_PATH_LITERAL("automated_ui_tests_error_report.txt");
-
-const base::FilePath::CharType* const kDefaultTestLogFilePath =
-FILE_PATH_LITERAL("automated_ui_tests_log.txt");
-
-const int kDebuggingTimeoutMsec = 5000;
-
-// How many commands to run when testing a dialog box.
-const int kTestDialogActionsToRun = 7;
-
-// String name of local chrome dll for looking up file information.
-const wchar_t kChromeDll[] = L"chrome.dll";
-
-void SilentRuntimeReportHandler(const std::string& str) {
-}
-
-base::FilePath GetInputFilePath() {
- const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
- if (parsed_command_line.HasSwitch(kInputFilePathSwitch)) {
- return parsed_command_line.GetSwitchValuePath(kInputFilePathSwitch);
- } else {
- return base::FilePath(kDefaultInputFilePath);
- }
-}
-
-base::FilePath GetOutputFilePath() {
- const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
- if (parsed_command_line.HasSwitch(kOutputFilePathSwitch)) {
- return parsed_command_line.GetSwitchValuePath(kOutputFilePathSwitch);
- } else {
- return base::FilePath(kDefaultOutputFilePath);
- }
-}
-
-base::FilePath GetTestLogFilePath() {
- const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
- if (parsed_command_line.HasSwitch(kTestLogFilePathSwitch)) {
- return parsed_command_line.GetSwitchValuePath(kTestLogFilePathSwitch);
- } else {
- return base::FilePath(kDefaultTestLogFilePath);
- }
-}
-
-std::string GetChromeRevision() {
- // Get Chrome version
- std::string last_change;
-#if defined(OS_WIN)
- // Check file version info for chrome dll.
- scoped_ptr<FileVersionInfo> file_info;
- file_info.reset(
- FileVersionInfo::CreateFileVersionInfo(base::FilePath(kChromeDll)));
- last_change = WideToASCII(file_info->last_change());
-#elif defined(OS_POSIX)
- chrome::VersionInfo version_info;
- last_change = version_info.LastChange();
-#endif // !defined(OS_WIN)
- return last_change;
-}
-
-void InitTestLog(base::Time start_time) {
- base::FilePath path = GetTestLogFilePath();
- std::ofstream test_log_file;
- if (!path.empty())
- test_log_file.open(path.value().c_str(), std::ios::out);
-
- const std::string time =
- UTF16ToASCII(base::TimeFormatFriendlyDateAndTime(start_time));
-
- test_log_file << "Last Change: " << GetChromeRevision() << std::endl;
- test_log_file << "Test Start: " << time << std::endl;
- test_log_file.close();
-}
-
-void AppendToTestLog(const std::string& append_string) {
- base::FilePath path = GetTestLogFilePath();
- std::ofstream test_log_file;
- if (!path.empty()) {
- test_log_file.open(path.value().c_str(),
- std::ios::out | std::ios_base::app);
- }
-
- test_log_file << append_string << std::endl;
- test_log_file.close();
-}
-
-double CalculateTestDuration(base::Time start_time) {
- base::Time time_now = base::Time::Now();
- return time_now.ToDoubleT() - start_time.ToDoubleT();
-}
-
-} // namespace
-
-// This subset of commands is used to test dialog boxes, which aren't likely
-// to respond to most other commands.
-const std::string kTestDialogPossibleActions[] = {
- // See FuzzyTestDialog for details on why Enter and SpaceBar must appear first
- // in this list.
- "PressEnterKey",
- "PressSpaceBar",
- "PressTabKey",
- "DownArrow"
-};
-
-// The list of dialogs that can be shown.
-const std::string kDialogs[] = {
- "About",
- "Options",
- "TaskManager",
- "JavaScriptConsole",
- "ClearBrowsingData",
- "ImportSettings",
- "EditSearchEngines",
- "ViewPasswords"
-};
-
-AutomatedUITest::AutomatedUITest()
- : test_start_time_(base::Time::NowFromSystemTime()),
- total_crashes_(0),
- debug_logging_enabled_(false),
- post_action_delay_(0) {
- show_window_ = true;
- const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
- if (parsed_command_line.HasSwitch(kDebugModeSwitch))
- debug_logging_enabled_ = true;
- if (parsed_command_line.HasSwitch(kWaitSwitch)) {
- std::string str = parsed_command_line.GetSwitchValueASCII(kWaitSwitch);
- if (str.empty()) {
- post_action_delay_ = 1;
- } else {
- base::StringToInt(str, &post_action_delay_);
- }
- }
- scoped_ptr<base::Environment> env(base::Environment::Create());
- if (env->HasVar(env_vars::kHeadless))
- logging::SetLogReportHandler(SilentRuntimeReportHandler);
-}
-
-AutomatedUITest::~AutomatedUITest() {}
-
-void AutomatedUITest::RunReproduction() {
- const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
-
- InitTestLog(test_start_time_);
- xml_writer_.StartWriting();
- xml_writer_.StartElement("Report");
- std::string action_string =
- parsed_command_line.GetSwitchValueASCII(kReproSwitch);
-
- int64 num_reproductions = 1;
- if (parsed_command_line.HasSwitch(kReproRepeatSwitch)) {
- base::StringToInt64(
- parsed_command_line.GetSwitchValueASCII(kReproRepeatSwitch),
- &num_reproductions);
- }
- std::vector<std::string> actions;
- base::SplitString(action_string, ',', &actions);
- bool did_crash = false;
- bool command_complete = false;
-
- for (int64 i = 0; i < num_reproductions && !did_crash; ++i) {
- bool did_teardown = false;
- xml_writer_.StartElement("Executed");
- for (size_t j = 0; j < actions.size(); ++j) {
- DoAction(actions[j]);
- if (DidCrash(true)) {
- did_crash = true;
- if (j >= (actions.size() - 1))
- command_complete = true;
- break;
- }
- if (LowerCaseEqualsASCII(actions[j], "teardown"))
- did_teardown = true;
- }
-
- // Force proper teardown after each run, if it didn't already happen. But
- // don't teardown after crashes.
- if (!did_teardown && !did_crash)
- DoAction("TearDown");
-
- xml_writer_.EndElement(); // End "Executed" element.
- }
-
- if (did_crash) {
- base::FilePath crash_dump = GetMostRecentCrashDump();
- base::FilePath::StringType result =
- FILE_PATH_LITERAL("*** Crash dump produced. ")
- FILE_PATH_LITERAL("See result file for more details. Dump = ");
- result.append(crash_dump.value());
- result.append(FILE_PATH_LITERAL(" ***\n"));
- printf("%s", result.c_str());
- LogCrashResult(crash_dump, command_complete);
- EXPECT_TRUE(false) << "Crash detected.";
- } else {
- printf("*** No crashes. See result file for more details. ***\n");
- LogSuccessResult();
- }
-
- AppendToTestLog(base::StringPrintf("total_duration_seconds=%f",
- CalculateTestDuration(test_start_time_)));
- WriteReportToFile();
-}
-
-
-void AutomatedUITest::RunAutomatedUITest() {
- InitTestLog(test_start_time_);
-
- ASSERT_TRUE(InitXMLReader()) << "Error initializing XMLReader";
- xml_writer_.StartWriting();
- xml_writer_.StartElement("Report");
-
- while (init_reader_.Read()) {
- init_reader_.SkipToElement();
- std::string node_name = init_reader_.NodeName();
- if (LowerCaseEqualsASCII(node_name, "command")) {
- bool no_errors = true;
- xml_writer_.StartElement("Executed");
- std::string command_number;
- if (init_reader_.NodeAttribute("number", &command_number)) {
- xml_writer_.AddAttribute("command_number", command_number);
- }
- xml_writer_.StopIndenting();
-
- // Starts the browser, logging it as an action.
- DoAction("SetUp");
-
- // Record the depth of the root of the command subtree, then advance to
- // the first element in preparation for parsing.
- int start_depth = init_reader_.Depth();
- ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
- init_reader_.SkipToElement();
-
- // Check for a crash right after startup.
- if (DidCrash(true)) {
- LogCrashResult(GetMostRecentCrashDump(), false);
- // Try and start up again.
- CloseBrowserAndServer();
- LaunchBrowserAndServer();
- set_active_browser(automation()->GetBrowserWindow(0).get());
- if (DidCrash(true)) {
- no_errors = false;
- // We crashed again, so skip to the end of the this command.
- while (init_reader_.Depth() != start_depth) {
- ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
- }
- } else {
- // We didn't crash, so end the old element, logging a crash for that.
- // Then start a new element to log this command.
- xml_writer_.StartIndenting();
- xml_writer_.EndElement();
- xml_writer_.StartElement("Executed");
- xml_writer_.AddAttribute("command_number", command_number);
- xml_writer_.StopIndenting();
- xml_writer_.StartElement("SetUp");
- xml_writer_.EndElement();
- }
- }
- // Parse the command, performing the specified actions and checking
- // for a crash after each one.
- while (init_reader_.Depth() != start_depth) {
- node_name = init_reader_.NodeName();
-
- DoAction(node_name);
-
- // Advance to the next element
- ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
- init_reader_.SkipToElement();
- if (DidCrash(true)) {
- no_errors = false;
- // This was the last action if we've returned to the initial depth
- // of the command subtree.
- bool wasLastAction = init_reader_.Depth() == start_depth;
- LogCrashResult(GetMostRecentCrashDump(), wasLastAction);
- // Skip to the beginning of the next command.
- while (init_reader_.Depth() != start_depth) {
- ASSERT_TRUE(init_reader_.Read()) << "Malformed XML file.";
- }
- }
- }
-
- if (no_errors) {
- // If there were no previous crashes, log our tear down and check for
- // a crash, log success for the entire command if this doesn't crash.
- DoAction("TearDown");
- if (DidCrash(true))
- LogCrashResult(GetMostRecentCrashDump(), true);
- else
- LogSuccessResult();
- } else {
- // If there was a previous crash, just tear down without logging, so
- // that we know what the last command was before we crashed.
- CloseBrowserAndServer();
- }
-
- xml_writer_.StartIndenting();
- xml_writer_.EndElement(); // End "Executed" element.
- }
- }
-
- AppendToTestLog(base::StringPrintf("total_duration_seconds=%f",
- CalculateTestDuration(test_start_time_)));
-
- // The test is finished so write our report.
- WriteReportToFile();
-}
-
-bool AutomatedUITest::DoAction(const std::string& action) {
- bool did_complete_action = false;
- xml_writer_.StartElement(action);
- if (debug_logging_enabled_)
- AppendToOutputFile(action);
-
- if (LowerCaseEqualsASCII(action, "about")) {
- did_complete_action = OpenAboutDialog();
- } else if (LowerCaseEqualsASCII(action, "back")) {
- did_complete_action = BackButton();
- } else if (LowerCaseEqualsASCII(action, "changeencoding")) {
- did_complete_action = ChangeEncoding();
- } else if (LowerCaseEqualsASCII(action, "closetab")) {
- did_complete_action = CloseActiveTab();
- } else if (LowerCaseEqualsASCII(action, "clearbrowsingdata")) {
- did_complete_action = OpenClearBrowsingDataDialog();
- } else if (LowerCaseEqualsASCII(action, "crash")) {
- did_complete_action = ForceCrash();
- } else if (LowerCaseEqualsASCII(action, "dialog")) {
- did_complete_action = ExerciseDialog();
- } else if (LowerCaseEqualsASCII(action, "downloads")) {
- did_complete_action = ShowDownloads();
- } else if (LowerCaseEqualsASCII(action, "duplicatetab")) {
- did_complete_action = DuplicateTab();
- } else if (LowerCaseEqualsASCII(action, "editsearchengines")) {
- did_complete_action = OpenEditSearchEnginesDialog();
- } else if (LowerCaseEqualsASCII(action, "findinpage")) {
- did_complete_action = FindInPage();
- } else if (LowerCaseEqualsASCII(action, "forward")) {
- did_complete_action = ForwardButton();
- } else if (LowerCaseEqualsASCII(action, "goofftherecord")) {
- did_complete_action = GoOffTheRecord();
- } else if (LowerCaseEqualsASCII(action, "history")) {
- did_complete_action = ShowHistory();
- } else if (LowerCaseEqualsASCII(action, "home")) {
- did_complete_action = Home();
- } else if (LowerCaseEqualsASCII(action, "importsettings")) {
- did_complete_action = OpenImportSettingsDialog();
- } else if (LowerCaseEqualsASCII(action, "javascriptconsole")) {
- did_complete_action = JavaScriptConsole();
- } else if (LowerCaseEqualsASCII(action, "navigate")) {
- std::string url = content::kAboutBlankURL;
- if (init_reader_.NodeAttribute("url", &url)) {
- xml_writer_.AddAttribute("url", url);
- }
- GURL test_url(url);
- did_complete_action = Navigate(test_url);
- } else if (LowerCaseEqualsASCII(action, "newtab")) {
- did_complete_action = NewTab();
- } else if (LowerCaseEqualsASCII(action, "openwindow")) {
- did_complete_action = OpenAndActivateNewBrowserWindow(NULL);
- } else if (LowerCaseEqualsASCII(action, "options")) {
- did_complete_action = Options();
- } else if (LowerCaseEqualsASCII(action, "reload")) {
- did_complete_action = ReloadPage();
- } else if (LowerCaseEqualsASCII(action, "restoretab")) {
- did_complete_action = RestoreTab();
- } else if (LowerCaseEqualsASCII(action, "selectnexttab")) {
- did_complete_action = SelectNextTab();
- } else if (LowerCaseEqualsASCII(action, "selectprevtab")) {
- did_complete_action = SelectPreviousTab();
- } else if (LowerCaseEqualsASCII(action, "setup")) {
- AutomatedUITestBase::SetUp();
- did_complete_action = true;
- } else if (LowerCaseEqualsASCII(action, "sleep")) {
- // This is for debugging, it probably shouldn't be used real tests.
- base::PlatformThread::Sleep(
- base::TimeDelta::FromMilliseconds(kDebuggingTimeoutMsec));
- did_complete_action = true;
- } else if (LowerCaseEqualsASCII(action, "star")) {
- did_complete_action = StarPage();
- } else if (LowerCaseEqualsASCII(action, "taskmanager")) {
- did_complete_action = OpenTaskManagerDialog();
- } else if (LowerCaseEqualsASCII(action, "teardown")) {
- CloseBrowserAndServer();
- did_complete_action = true;
- } else if (LowerCaseEqualsASCII(action, "testaboutchrome")) {
- did_complete_action = TestAboutChrome();
- } else if (LowerCaseEqualsASCII(action, "testclearbrowsingdata")) {
- did_complete_action = TestClearBrowsingData();
- } else if (LowerCaseEqualsASCII(action, "testeditsearchengines")) {
- did_complete_action = TestEditSearchEngines();
- } else if (LowerCaseEqualsASCII(action, "testimportsettings")) {
- did_complete_action = TestImportSettings();
- } else if (LowerCaseEqualsASCII(action, "testoptions")) {
- did_complete_action = TestOptions();
- } else if (LowerCaseEqualsASCII(action, "testtaskmanager")) {
- did_complete_action = TestTaskManager();
- } else if (LowerCaseEqualsASCII(action, "testviewpasswords")) {
- did_complete_action = TestViewPasswords();
- } else if (LowerCaseEqualsASCII(action, "viewpasswords")) {
- did_complete_action = OpenViewPasswordsDialog();
- } else if (LowerCaseEqualsASCII(action, "viewsource")) {
- did_complete_action = ViewSource();
- } else if (LowerCaseEqualsASCII(action, "zoomplus")) {
- did_complete_action = ZoomPlus();
- } else if (LowerCaseEqualsASCII(action, "zoomminus")) {
- did_complete_action = ZoomMinus();
- } else {
- NOTREACHED() << "Unknown command passed into DoAction: "
- << action.c_str();
- }
-
- EXPECT_TRUE(did_complete_action) << action;
-
- if (!did_complete_action)
- xml_writer_.AddAttribute("failed_to_complete", "yes");
- xml_writer_.EndElement();
-
- if (post_action_delay_) {
- base::PlatformThread::Sleep(
- base::TimeDelta::FromSeconds(post_action_delay_));
- }
-
- return did_complete_action;
-}
-
-bool AutomatedUITest::ChangeEncoding() {
- // Get the encoding list that is used to populate the UI (encoding menu)
- std::string cur_locale = g_browser_process->GetApplicationLocale();
- const std::vector<CharacterEncoding::EncodingInfo>* encodings =
- CharacterEncoding::GetCurrentDisplayEncodings(
- cur_locale, "ISO-8859-1,windows-1252", std::string());
- DCHECK(encodings);
- DCHECK(!encodings->empty());
- unsigned len = static_cast<unsigned>(encodings->size());
-
- // The vector will contain mostly IDC values for encoding commands plus a few
- // menu separators (0 values). If we hit a separator we just retry.
- int index = base::RandInt(0, len);
- while ((*encodings)[index].encoding_id == 0) {
- index = base::RandInt(0, len);
- }
-
- return RunCommandAsync((*encodings)[index].encoding_id);
-}
-
-bool AutomatedUITest::JavaScriptConsole() {
- return RunCommandAsync(IDC_DEV_TOOLS);
-}
-
-bool AutomatedUITest::OpenAboutDialog() {
- return RunCommandAsync(IDC_ABOUT);
-}
-
-bool AutomatedUITest::OpenClearBrowsingDataDialog() {
- return RunCommandAsync(IDC_CLEAR_BROWSING_DATA);
-}
-
-bool AutomatedUITest::OpenEditSearchEnginesDialog() {
- return RunCommandAsync(IDC_EDIT_SEARCH_ENGINES);
-}
-
-bool AutomatedUITest::OpenImportSettingsDialog() {
- return RunCommandAsync(IDC_IMPORT_SETTINGS);
-}
-
-bool AutomatedUITest::OpenTaskManagerDialog() {
- return RunCommandAsync(IDC_TASK_MANAGER);
-}
-
-bool AutomatedUITest::OpenViewPasswordsDialog() {
- return RunCommandAsync(IDC_VIEW_PASSWORDS);
-}
-
-bool AutomatedUITest::Options() {
- return RunCommandAsync(IDC_OPTIONS);
-}
-
-bool AutomatedUITest::StarPage() {
- return RunCommandAsync(IDC_BOOKMARK_PAGE);
-}
-
-bool AutomatedUITest::ViewSource() {
- return RunCommandAsync(IDC_VIEW_SOURCE);
-}
-
-bool AutomatedUITest::ZoomMinus() {
- return RunCommandAsync(IDC_ZOOM_MINUS);
-}
-
-bool AutomatedUITest::ZoomPlus() {
- return RunCommandAsync(IDC_ZOOM_PLUS);
-}
-
-bool AutomatedUITest::TestAboutChrome() {
- DoAction("About");
- return FuzzyTestDialog(kTestDialogActionsToRun);
-}
-
-bool AutomatedUITest::TestClearBrowsingData() {
- DoAction("ClearBrowsingData");
- return FuzzyTestDialog(kTestDialogActionsToRun);
-}
-
-bool AutomatedUITest::TestEditSearchEngines() {
- DoAction("EditSearchEngines");
- return FuzzyTestDialog(kTestDialogActionsToRun);
-}
-
-bool AutomatedUITest::TestImportSettings() {
- DoAction("ImportSettings");
- return FuzzyTestDialog(kTestDialogActionsToRun);
-}
-
-bool AutomatedUITest::TestTaskManager() {
- DoAction("TaskManager");
- return FuzzyTestDialog(kTestDialogActionsToRun);
-}
-
-bool AutomatedUITest::TestOptions() {
- DoAction("Options");
- return FuzzyTestDialog(kTestDialogActionsToRun);
-}
-
-bool AutomatedUITest::TestViewPasswords() {
- DoAction("ViewPasswords");
- return FuzzyTestDialog(kTestDialogActionsToRun);
-}
-
-bool AutomatedUITest::ExerciseDialog() {
- int index = base::RandInt(0, arraysize(kDialogs) - 1);
- return DoAction(kDialogs[index]) && FuzzyTestDialog(kTestDialogActionsToRun);
-}
-
-bool AutomatedUITest::FuzzyTestDialog(int num_actions) {
- bool return_value = true;
-
- for (int i = 0; i < num_actions; i++) {
- // We want to make sure the first action performed on the dialog is not
- // Space or Enter because focus is likely on the Close button. Both Space
- // and Enter would close the dialog without performing more actions. We
- // rely on the fact that those two actions are first in the array and set
- // the lower bound to 2 if i == 0 to skip those two actions.
- int action_index = base::RandInt(i == 0 ? 2 : 0,
- arraysize(kTestDialogPossibleActions)
- - 1);
- return_value = return_value &&
- DoAction(kTestDialogPossibleActions[action_index]);
- if (DidCrash(false))
- break;
- }
- return DoAction("PressEscapeKey") && return_value;
-}
-
-bool AutomatedUITest::ForceCrash() {
- scoped_refptr<TabProxy> tab(GetActiveTab());
- GURL test_url(content::kChromeUICrashURL);
- AutomationMsg_NavigationResponseValues result = tab->NavigateToURL(test_url);
- if (result != AUTOMATION_MSG_NAVIGATION_SUCCESS) {
- AddErrorAttribute("navigation_failed");
- return false;
- }
- return true;
-}
-
-bool AutomatedUITest::InitXMLReader() {
- base::FilePath input_path = GetInputFilePath();
-
- if (!base::ReadFileToString(input_path, &xml_init_file_))
- return false;
- return init_reader_.Load(xml_init_file_);
-}
-
-bool AutomatedUITest::WriteReportToFile() {
- base::FilePath path = GetOutputFilePath();
- std::ofstream error_file;
- if (!path.empty())
- error_file.open(path.value().c_str(), std::ios::out);
-
- // Closes all open elements and free the writer. This is required
- // in order to retrieve the contents of the buffer.
- xml_writer_.StopWriting();
- error_file << xml_writer_.GetWrittenString();
- error_file.close();
- return true;
-}
-
-void AutomatedUITest::AppendToOutputFile(const std::string& append_string) {
- base::FilePath path = GetOutputFilePath();
- std::ofstream error_file;
- if (!path.empty())
- error_file.open(path.value().c_str(), std::ios::out | std::ios_base::app);
-
- error_file << append_string << " ";
- error_file.close();
-}
-
-void AutomatedUITest::LogCrashResult(const base::FilePath& crash_dump,
- bool command_completed) {
- xml_writer_.StartElement("result");
- xml_writer_.AddAttribute("test_log_path",
- GetTestLogFilePath().MaybeAsASCII());
- xml_writer_.AddAttribute("revision", GetChromeRevision());
- xml_writer_.StartElement("crash");
-#if defined(OS_WIN)
- xml_writer_.AddAttribute("crash_dump", WideToASCII(crash_dump.value()));
-#else
- xml_writer_.AddAttribute("crash_dump", crash_dump.value());
-#endif
- if (command_completed)
- xml_writer_.AddAttribute("command_completed", "yes");
- else
- xml_writer_.AddAttribute("command_completed", "no");
- xml_writer_.EndElement();
- xml_writer_.EndElement();
-}
-
-void AutomatedUITest::LogSuccessResult() {
- xml_writer_.StartElement("result");
- xml_writer_.AddAttribute("test_log_path",
- GetTestLogFilePath().MaybeAsASCII());
- xml_writer_.AddAttribute("revision", GetChromeRevision());
- xml_writer_.StartElement("success");
- xml_writer_.EndElement();
- xml_writer_.EndElement();
-}
-
-void AutomatedUITest::AddInfoAttribute(const std::string& info) {
- xml_writer_.AddAttribute("info", info);
-}
-
-void AutomatedUITest::AddWarningAttribute(const std::string& warning) {
- xml_writer_.AddAttribute("warning", warning);
-}
-
-void AutomatedUITest::AddErrorAttribute(const std::string& error) {
- xml_writer_.AddAttribute("error", error);
-}
-
-void AutomatedUITest::LogErrorMessage(const std::string& error) {
- AddErrorAttribute(error);
-}
-
-void AutomatedUITest::LogWarningMessage(const std::string& warning) {
- AddWarningAttribute(warning);
-}
-
-void AutomatedUITest::LogInfoMessage(const std::string& info) {
- AddWarningAttribute(info);
-}
-
-base::FilePath AutomatedUITest::GetMostRecentCrashDump() {
- base::FilePath crash_dump_path;
- base::FilePath most_recent_file_name;
- PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dump_path);
- base::Time most_recent_file_time;
-
- bool first_file = true;
-
- base::FileEnumerator enumerator(crash_dump_path,
- false, // not recursive
- base::FileEnumerator::FILES);
- for (base::FilePath path = enumerator.Next(); !path.value().empty();
- path = enumerator.Next()) {
- base::PlatformFileInfo file_info;
- file_util::GetFileInfo(path, &file_info);
- if (first_file) {
- most_recent_file_time = file_info.last_modified;
- most_recent_file_name = path.BaseName();
- first_file = false;
- } else if (file_info.last_modified >= most_recent_file_time) {
- most_recent_file_time = file_info.last_modified;
- most_recent_file_name = path.BaseName();
- }
- }
- if (most_recent_file_name.empty()) {
- return base::FilePath();
- } else {
- crash_dump_path = crash_dump_path.Append(most_recent_file_name);
- return crash_dump_path;
- }
-}
-
-bool AutomatedUITest::DidCrash(bool update_total_crashes) {
- int actual_crashes = GetCrashCount();
-
- // If there are more crash dumps than the total dumps which we have recorded
- // then this is a new crash.
- if (actual_crashes > total_crashes_) {
- if (update_total_crashes)
- total_crashes_ = actual_crashes;
- return true;
- } else {
- return false;
- }
-}
-
-TEST_F(AutomatedUITest, TheOneAndOnlyTest) {
- const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
- if (parsed_command_line.HasSwitch(kReproSwitch))
- RunReproduction();
- else
- RunAutomatedUITest();
-}
diff --git a/chrome/test/reliability/automated_ui_tests.h b/chrome/test/reliability/automated_ui_tests.h
deleted file mode 100644
index 4cb6055..0000000
--- a/chrome/test/reliability/automated_ui_tests.h
+++ /dev/null
@@ -1,362 +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_RELIABILITY_AUTOMATED_UI_TESTS_H_
-#define CHROME_TEST_RELIABILITY_AUTOMATED_UI_TESTS_H_
-
-// This takes an input file of commands, which consist of a series of
-// actions, and runs every command, reporting the status of each one
-// to an output file once all the commands have been run.
-//
-// The input file should be an XML file that has a root of any name followed
-// by a series of elements named "command" with child elements representing
-// the various actions, in order, to be performed during each command. A
-// command element can optionally include an "number" attribute to identify it.
-//
-// Example:
-// <CommandList>
-// <command number="1"><NewTab/><Navigate/><OpenWindow/><Navigate/><Back/>
-// </command>
-// <command number="2"><NewTab/><Navigate/><Navigate/><Back/><Forward/>
-// </command>
-// <command number="3"><CloseTab/><OpenWindow/><NewTab/><Navigate/><CloseTab/>
-// </command>
-// </CommandList>
-//
-// When the test is finished it will output results to the output file,
-// overwriting any previous version of this file. The output file is an
-// XML file which reports on each command, indicating whether it successfully
-// ran and if there were any errors.
-//
-// Example: (actual output will probably contain more actions per command):
-// <Report>
-// <Executed command_number="1"><NewTab/><Navigate/><result><success/>
-// </result> </Executed>
-// <Executed command_number="2"><Back/><Forward/><result><success/></result>
-// </Executed>
-// <Executed command_number="3"><CloseTab/><result>
-// <crash crash_dump="C:\a_crash.txt" command_completed="no"/></result>
-// </Executed>
-// </Report>
-//
-// A "crash" result will have two attributes, crash_dump, which points
-// to the full path of crash dump associated with this crash, and
-// command_completed which indicates whether or not the last
-// action recorded was the final action of the command.
-//
-// Furthermore, each individual action may contain additional attributes
-// to log non-fatal failures. If the attribute 'failed_to_complete="yes"'
-// is present, then the action did not complete. If that attribute is present,
-// an info, warning, or error attribute will also be present, and will contain
-// a string describing the error. The presence of info means the failure was
-// expected, probably due to a state making the action impossible to perform
-// like trying to close the last remaining window. Warnings usually mean the
-// action couldn't complete for an unknown and unexpected reason, but that the
-// test state is probably fine. Errors are like warnings, but they mean the test
-// state is probably incorrect, and more failures are likely to be caused by
-// the same problem.
-//
-// Example of some failed actions:
-// <CloseTab failed_to_complete="yes" info="would_have_exited_application"/>
-// <Reload failed_to_complete="yes" warning="failed_to_apply_accelerator"/>
-// <Star failed_to_complete="yes" error="browser_window_not_found"/>
-//
-//
-// Switches
-// --input : Specifies the input file, must be an absolute directory.
-// Default is "C:\automated_ui_tests.txt"
-//
-// --output : Specifies the output file, must be an absolute directory.
-// Default is "C:\automated_ui_tests_error_report.txt"
-//
-//
-// Test reproduction options:
-//
-// If you're trying to reproduce the results from crash reports use the
-// following switches
-//
-// --key : Specifies, via a comma delimited list, what actions to run. Examples:
-// --key=SetUp,ZoomPlus,Forward,History,Navigate,Back,TearDown
-// --key=SetUp,ZoomPlus
-// Note, the second key doesn't include a TearDown, that will
-// automatically be added if the result doesn't crash.
-//
-// --num-reproductions : Specifies the number of reproductions to run, the
-// default is 1. Suggested use: run without this flag
-// to see if we reproduce a crash, then run with the flag
-// if there isn't a crash, to see if it might be a rare
-// race condition that causes the crash.
-//
-//
-// Debugging options:
-//
-// --debug : Will append each action that is performed to the output file, as
-// soon as the action is performed. If the program finishes, this file
-// will be overwritten with the normal results. This flag is used to
-// help debug the tests if they are crashing before they get a chance
-// to write their results to file.
-//
-// --wait-after-action : waits the specified amount of time (1s by default)
-// after each action. Useful for debugging.
-
-#include <string>
-
-#include "chrome/test/reliability/automated_ui_test_base.h"
-#include "chrome/test/ui/ui_test.h"
-#include "third_party/libxml/chromium/libxml_utils.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-namespace base {
-class Time;
-}
-
-class AutomatedUITest : public AutomatedUITestBase {
- protected:
- AutomatedUITest();
- virtual ~AutomatedUITest();
-
- // Runs a reproduction of one set of actions, reporting whether they crash
- // or not.
- void RunReproduction();
-
- // Runs automated UI tests which are read from the input file.
- // Reports crashes to the output file.
- void RunAutomatedUITest();
-
- // Attempts to perform an action based on the input string. See below for
- // possible actions. Returns true if the action completes, false otherwise.
- bool DoAction(const std::string& action);
-
- // Actions ------------------------------------------------------------------
-
- // NOTE: This list is sorted alphabetically, so that we can easily detect
- // missing actions.
-
- // Changes the encoding of the page (the encoding is selected at random
- // from a list of encodings).
- // Returns true if call to activate the accelerator is successful.
- // XML element: <ChangeEncoding/>
- bool ChangeEncoding();
-
- // Opens one of the dialogs (chosen randomly) and exercises it.
- // XML element: <Dialog/>
- bool ExerciseDialog();
-
- // Opens the JavaScriptConsole window. While it isn't modal, it takes focus
- // from the current browser window, so most of the test can't continue until
- // it is dismissed.
- // XML element: <JavaScriptConsole/>
- bool JavaScriptConsole();
-
- // Opens the About dialog. This dialog is modal so a majority of the test
- // can't be completed until it is dismissed.
- // XML element: <About/>
- bool OpenAboutDialog();
-
- // Opens the Clear Browsing Data dialog, this dialog is modal so a majority of
- // the test can't be completed until it is dismissed.
- // XML element: <ClearBrowsingData/>
- bool OpenClearBrowsingDataDialog();
-
- // Opens the Search Engines dialog. While it isn't modal, it takes focus from
- // the current browser window, so most of the test can't continue until it is
- // dismissed.
- // XML element: <EditSearchEngines/>
- bool OpenEditSearchEnginesDialog();
-
- // Opens the Import Settings dialog, this dialog is modal so a majority of
- // the test can't be completed until it is dismissed.
- // XML element: <ImportSettings/>
- bool OpenImportSettingsDialog();
-
- // Opens the Task Manager dialog. While it isn't modal, it takes focus from
- // the current browser window, so most of the test can't continue until it is
- // dismissed.
- // XML element: <TaskManager/>
- bool OpenTaskManagerDialog();
-
- // Opens the View Passwords dialog, this dialog is modal so a majority of
- // the test can't be completed until it is dismissed.
- // XML element: <ViewPasswords/>
- bool OpenViewPasswordsDialog();
-
- // Opens the Options dialog. While it isn't modal, it takes focus from
- // the current browser window, so most of the test can't continue until it is
- // dismissed.
- // XML element: <Options/>
- bool Options();
-
- // Stars the current page. This opens a dialog that may or may not be
- // dismissed.
- // XML element: <Star/>
- bool StarPage();
-
- // Views source of the current page.
- // Returns true if call to activate the accelerator is successful.
- // XML element: <ViewSource/>
- bool ViewSource();
-
- // Decreases the text size on the current active tab.
- // XML element: <ZoomMinus/>
- bool ZoomMinus();
-
- // Increases the text size on the current active tab.
- // XML element: <ZoomPlus/>
- bool ZoomPlus();
-
- // Test Dialog Actions ******************************************************
- // These are a special set of actions that perform multiple actions on a
- // specified dialog. They run kTestDialogActionsToRun actions randomly
- // chosen from test_dialog_possible_actions_ after opening the dialog. They
- // then always end with a PressEscapeKey action, to attempt to close the
- // dialog.
- //
- // The randomly performed actions are logged as child elements of the
- // TestDialog action. For example (for kTestDialogActionsToRun = 4):
- // <TestEditKeywords> <PressTabKey/><PressEnterKey/><DownArrow/>
- // <DownArrow/><PressEscapeKey/> </TestEditKeywords>
-
- // Opens About dialog and runs random actions on it.
- // XML element: <TestAboutChrome/>
- bool TestAboutChrome();
-
- // Opens Clear Browsing Data dialog and runs random actions on it.
- // XML element: <TestClearBrowsingData/>
- bool TestClearBrowsingData();
-
- // Opens Edit Keywords dialog and runs random actions on it.
- // XML element: <TestEditSearchEngines/>
- bool TestEditSearchEngines();
-
- // Opens Import Settings dialog and runs random actions on it.
- // XML element: <TestImportSettings/>
- bool TestImportSettings();
-
- // Opens Options dialog and runs random actions on it.
- // XML element: <TestOptions/>
- bool TestOptions();
-
- // Opens Task Manager and runs random actions on it.
- // This has the possibility of killing both the browser and renderer
- // processes, which will cause non-fatal errors for the remaining actions
- // in this command.
- // XML element: <TestTaskManager/>
- bool TestTaskManager();
-
- // Opens View Passwords dialog and runs random actions on it.
- // XML element: <TestViewPasswords/>
- bool TestViewPasswords();
-
- // End Test Dialog Actions **************************************************
-
- // Runs a limited set of actions designed to test dialogs. Will run
- // |num_actions| from the set defined in test_dialog_possible_actions_.
- bool FuzzyTestDialog(int num_actions);
-
- // Navigates to about:crash.
- // XML element: <Crash/>
- bool ForceCrash();
-
- // Utility functions --------------------------------------------------------
-
- // Opens init file, reads it into the reader, and closes the file.
- // Returns false if there are any errors.
- bool InitXMLReader();
-
- // Closes the xml_writer and outputs the contents of its buffer to
- // the output file.
- bool WriteReportToFile();
-
- // Appends the provided string to the output file.
- void AppendToOutputFile(const std::string& append_string);
-
- // Logs a crash to the xml_writer in the form of:
- // <result><crash crash_dump="|crash_dump|" command_completed="yes/no"/>
- // </result>
- // crash_dump - Location of crash dump if applicable.
- // command_completed - True if all actions in the command were completed
- // before the crash occured.
- void LogCrashResult(const base::FilePath& crash_dump,
- bool command_completed);
-
- // Logs a successful command to the xml_writer in the form of:
- // <result><success/><result/>
- void LogSuccessResult();
-
- // Adds the attribute "reason=|reason|" to the current element.
- // Used to log the reason for a given failure while performing an action.
- void LogActionFailureReason(const std::string& reason);
-
- // Adds the attribute 'info="|info|"' to the current element. Used when an
- // action could not complete for a non-serious issue. Usually because the
- // state of the test wouldn't allow for a particular action.
- void AddInfoAttribute(const std::string& info);
-
- // Adds the attribute "warning=|warning|" to the current element. Used when
- // an action could not complete because of a potentially troublesome issue.
- void AddWarningAttribute(const std::string& warning);
-
- // Adds the attribute "error=|error|" to the current element. Used when an
- // action could not complete due to an unexpected problem which might
- // invalidate the results of the entire command (not just the action).
- // This is usually used when the testing environment isn't acting as we'd
- // expect. For example, no chrome windows are focused, or key presses aren't
- // being registered.
- void AddErrorAttribute(const std::string& error);
-
- // Returns the full path of the crash dump. This is likely to be the
- // .txt file, not the actual crash dump. Although they do share
- // a common name.
- base::FilePath GetMostRecentCrashDump();
-
- // Returns true if the test has produced any new crash logs.
- // A "new" crash log is one that was produced since DidCrash was last called
- // with |update_total_crashes| set to true.
- bool DidCrash(bool update_total_crashes);
-
- // Override the message logging in AutomatedUITestBase.
- virtual void LogErrorMessage(const std::string& error) OVERRIDE;
- virtual void LogWarningMessage(const std::string& warning) OVERRIDE;
- virtual void LogInfoMessage(const std::string& info) OVERRIDE;
-
- // Overridden so that UI Test doesn't set up when the tests start.
- // We use DoAction("SetUp") to set up, because it logs it and makes
- // it easier to check for crashes when we start the browser.
- virtual void SetUp() OVERRIDE {}
-
- // Overridden so that UI Test doesn't close the browser (which is already
- // closed) at the end of the test.
- // We use DoAction("TearDown") to tear down, because it logs it and makes
- // it easier to check for crashes when we close the browser.
- virtual void TearDown() OVERRIDE {}
-
- private:
- // Parses the init file.
- XmlReader init_reader_;
-
- // Builds the output file.
- XmlWriter xml_writer_;
-
- // Time the test was started. Used to find crash dumps.
- base::Time test_start_time_;
-
- // Number of times the browser has crashed during this run.
- // Used to check for new crashes.
- int total_crashes_;
-
- // Used to init the init_reader_. It must exist as long as the reader does.
- std::string xml_init_file_;
-
- // If true, appends the commands to the output file as they are executed.
- // Used for debugging when automated_ui_tests.cc crashes before it outputs
- // results.
- bool debug_logging_enabled_;
-
- // A delay in second we wait for after each action. Useful for debugging.
- int post_action_delay_;
-
- DISALLOW_COPY_AND_ASSIGN(AutomatedUITest);
-};
-
-#endif // CHROME_TEST_RELIABILITY_AUTOMATED_UI_TESTS_H_
diff --git a/chrome/test/reliability/page_load_test.cc b/chrome/test/reliability/page_load_test.cc
deleted file mode 100644
index 9321537..0000000
--- a/chrome/test/reliability/page_load_test.cc
+++ /dev/null
@@ -1,796 +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 provides reliablity test which runs under UI test framework. The
-// test is intended to run within QEMU environment.
-//
-// Usage 1: reliability_test
-// Upon invocation, it visits a hard coded list of sample URLs. This is mainly
-// used by buildbot, to verify reliability_test itself runs ok.
-//
-// Usage 2: reliability_test --site=url --startpage=start --endpage=end [...]
-// Upon invocation, it visits a list of URLs constructed as
-// "http://url/page?id=k". (start <= k <= end).
-//
-// Usage 3: reliability_test --list=file --startline=start --endline=end [...]
-// Upon invocation, it visits each of the URLs on line numbers between start
-// and end, inclusive, stored in the input file. The line number starts from 1.
-//
-// If both "--site" and "--list" are provided, the "--site" set of arguments
-// are ignored.
-//
-// Optional Switches:
-// --iterations=num: goes through the list of URLs constructed in usage 2 or 3
-// num times.
-// --continuousload: continuously visits the list of URLs without restarting
-// browser for each page load.
-// --memoryusage: prints out memory usage when visiting each page.
-// --endurl=url: visits the specified url in the end.
-// --logfile=filepath: saves the visit log to the specified path.
-// --noclearprofile: do not clear profile dir before firing up each time.
-// --savedebuglog: save Chrome, V8, and test debug log for each page loaded.
-// --searchdumpsbypid: Look for crash dumps by browser process id.
-// "crash_dir/pid/"
-
-#include <fstream>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/file_util.h"
-#include "base/file_version_info.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/i18n/time_formatting.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/path_service.h"
-#include "base/prefs/json_pref_store.h"
-#include "base/prefs/pref_registry_simple.h"
-#include "base/prefs/pref_service.h"
-#include "base/process/kill.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/test/test_file_util.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "chrome/browser/prefs/pref_service_mock_builder.h"
-#include "chrome/common/automation_messages.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/chrome_version_info.h"
-#include "chrome/common/logging_chrome.h"
-#include "chrome/common/net/url_fixer_upper.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/render_messages.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/test/automation/automation_proxy.h"
-#include "chrome/test/automation/browser_proxy.h"
-#include "chrome/test/automation/tab_proxy.h"
-#include "chrome/test/automation/window_proxy.h"
-#include "chrome/test/ui/ui_test.h"
-#include "net/base/net_util.h"
-#include "v8/include/v8-testing.h"
-
-namespace {
-
-// See comments at the beginning of the file for the definition of switches.
-const char kSiteSwitch[] = "site";
-const char kStartPageSwitch[] = "startpage";
-const char kEndPageSwitch[] = "endpage";
-const char kListSwitch[] = "list";
-const char kStartIndexSwitch[] = "startline";
-const char kEndIndexSwitch[] = "endline";
-const char kIterationSwitch[] = "iterations";
-const char kContinuousLoadSwitch[] = "continuousload";
-const char kMemoryUsageSwitch[] = "memoryusage";
-const char kEndURLSwitch[] = "endurl";
-const char kLogFileSwitch[] = "logfile";
-const char kNoPageDownSwitch[] = "nopagedown";
-const char kNoClearProfileSwitch[] = "noclearprofile";
-const char kSaveDebugLogSwitch[] = "savedebuglog";
-const char kStressOptSwitch[] = "stress-opt";
-const char kStressDeoptSwitch[] = "stress-deopt";
-
-const char kDefaultServerUrl[] = "http://urllist.com";
-std::string g_server_url;
-const char kTestPage1[] = "page1.html";
-const char kTestPage2[] = "page2.html";
-
-// These are copied from v8 definitions as we cannot include them.
-const char kV8LogFileSwitch[] = "logfile";
-const char kV8LogFileDefaultName[] = "v8.log";
-
-// String name of local chrome dll for looking up file information.
-const wchar_t kChromeDll[] = L"chrome.dll";
-
-bool g_append_page_id = false;
-int32 g_start_page;
-int32 g_end_page;
-base::FilePath g_url_file_path;
-int32 g_start_index = 1;
-int32 g_end_index = kint32max;
-int32 g_iterations = 1;
-bool g_memory_usage = false;
-bool g_continuous_load = false;
-bool g_browser_existing = false;
-bool g_clear_profile = true;
-std::string g_end_url;
-base::FilePath g_log_file_path;
-bool g_save_debug_log = false;
-base::FilePath g_chrome_log_path;
-base::FilePath g_v8_log_path;
-base::FilePath g_test_log_path;
-bool g_stand_alone = false;
-bool g_stress_opt = false;
-bool g_stress_deopt = false;
-
-void ReportHandler(const std::string& str) {
- // Ignore report events.
-}
-
-void SetPageRange(const CommandLine& parsed_command_line) {
- // If calling into this function, we are running as a standalone program.
- g_stand_alone = true;
-
- // Since we use --enable-dcheck for reliability tests, suppress the error
- // dialog in the test process.
- logging::SetLogReportHandler(ReportHandler);
-
- if (parsed_command_line.HasSwitch(kStartPageSwitch)) {
- ASSERT_TRUE(parsed_command_line.HasSwitch(kEndPageSwitch));
- ASSERT_TRUE(
- base::StringToInt(parsed_command_line.GetSwitchValueASCII(
- kStartPageSwitch),
- &g_start_page));
- ASSERT_TRUE(
- base::StringToInt(parsed_command_line.GetSwitchValueASCII(
- kEndPageSwitch),
- &g_end_page));
- ASSERT_TRUE(g_start_page > 0 && g_end_page > 0);
- ASSERT_TRUE(g_start_page < g_end_page);
- g_append_page_id = true;
- } else {
- ASSERT_FALSE(parsed_command_line.HasSwitch(kEndPageSwitch));
- }
-
- if (parsed_command_line.HasSwitch(kSiteSwitch)) {
- g_server_url = parsed_command_line.GetSwitchValueASCII(kSiteSwitch);
- }
-
- if (parsed_command_line.HasSwitch(kStartIndexSwitch)) {
- ASSERT_TRUE(
- base::StringToInt(parsed_command_line.GetSwitchValueASCII(
- kStartIndexSwitch),
- &g_start_index));
- ASSERT_GT(g_start_index, 0);
- }
-
- if (parsed_command_line.HasSwitch(kEndIndexSwitch)) {
- ASSERT_TRUE(
- base::StringToInt(parsed_command_line.GetSwitchValueASCII(
- kEndIndexSwitch),
- &g_end_index));
- ASSERT_GT(g_end_index, 0);
- }
-
- ASSERT_TRUE(g_end_index >= g_start_index);
-
- if (parsed_command_line.HasSwitch(kListSwitch))
- g_url_file_path = parsed_command_line.GetSwitchValuePath(kListSwitch);
-
- if (parsed_command_line.HasSwitch(kIterationSwitch)) {
- ASSERT_TRUE(
- base::StringToInt(parsed_command_line.GetSwitchValueASCII(
- kIterationSwitch),
- &g_iterations));
- ASSERT_GT(g_iterations, 0);
- }
-
- if (parsed_command_line.HasSwitch(kMemoryUsageSwitch))
- g_memory_usage = true;
-
- if (parsed_command_line.HasSwitch(kContinuousLoadSwitch))
- g_continuous_load = true;
-
- if (parsed_command_line.HasSwitch(kEndURLSwitch))
- g_end_url = parsed_command_line.GetSwitchValueASCII(kEndURLSwitch);
-
- if (parsed_command_line.HasSwitch(kLogFileSwitch))
- g_log_file_path = parsed_command_line.GetSwitchValuePath(kLogFileSwitch);
-
- if (parsed_command_line.HasSwitch(kNoClearProfileSwitch))
- g_clear_profile = false;
-
- if (parsed_command_line.HasSwitch(kSaveDebugLogSwitch)) {
- g_save_debug_log = true;
- g_chrome_log_path = logging::GetLogFileName();
- // We won't get v8 log unless --no-sandbox is specified.
- if (parsed_command_line.HasSwitch(switches::kNoSandbox)) {
- PathService::Get(base::DIR_CURRENT, &g_v8_log_path);
- g_v8_log_path = g_v8_log_path.AppendASCII(kV8LogFileDefaultName);
- // The command line switch may override the default v8 log path.
- if (parsed_command_line.HasSwitch(switches::kJavaScriptFlags)) {
- CommandLine v8_command_line(
- parsed_command_line.GetSwitchValuePath(switches::kJavaScriptFlags));
- if (v8_command_line.HasSwitch(kV8LogFileSwitch)) {
- g_v8_log_path = base::MakeAbsoluteFilePath(
- v8_command_line.GetSwitchValuePath(kV8LogFileSwitch));
- }
- }
- }
- }
-
- if (parsed_command_line.HasSwitch(kStressOptSwitch)) {
- g_stress_opt = true;
- }
- if (parsed_command_line.HasSwitch(kStressDeoptSwitch)) {
- g_stress_deopt = true;
- }
-}
-
-class PageLoadTest : public UITest {
- public:
- enum NavigationResult {
- NAVIGATION_ERROR = 0,
- NAVIGATION_SUCCESS,
- NAVIGATION_AUTH_NEEDED,
- NAVIGATION_TIME_OUT,
- };
-
- typedef struct {
- // These are results from the test automation that drives Chrome
- NavigationResult result;
- int crash_dump_count;
- // These are stability metrics recorded by Chrome itself
- bool browser_clean_exit;
- int browser_launch_count;
- int page_load_count;
- int browser_crash_count;
- int renderer_crash_count;
- int plugin_crash_count;
- } NavigationMetrics;
-
- PageLoadTest() {
- show_window_ = true;
- SetPageRange(*CommandLine::ForCurrentProcess());
- }
-
- void EnsureBrowserAndServer() {
- if (!g_browser_existing) {
- LaunchBrowserAndServer();
- g_browser_existing = true;
- }
- }
-
- // Load a URL in a browser tab and perform a couple of page down events.
- // url_string: The URL to navigate to. Accept URL as std::string here
- // because the url may also act as a test id and needs to
- // be logged in its original format even if invalid.
- // log_file: Log file for test results and possible crash dump
- // files. This file does not need to be opened in which
- // case nothing is logged.
- // metrics_output: Return metrics for the page load.
- // keep_browser: Set to true if the browser should be kept open after
- // loading the page.
- // log_only_errors: Set to true if only errors should be logged otherwise
- // successful navigations will also be logged.
- bool NavigateToURLLogResult(const std::string& url_string,
- std::ofstream& log_file,
- NavigationMetrics* metrics_output,
- bool keep_browser,
- bool log_only_error) {
- GURL url(url_string);
- NavigationMetrics metrics = {NAVIGATION_ERROR};
- std::ofstream test_log;
-
- // Create a test log.
- g_test_log_path = base::FilePath(FILE_PATH_LITERAL("test_log.log"));
- test_log.open(g_test_log_path.value().c_str());
-
- // Get the version of Chrome we're running.
- std::string last_change;
-#if defined(OS_WIN)
- // Check file version info for chrome dll.
- scoped_ptr<FileVersionInfo> file_info;
- file_info.reset(
- FileVersionInfo::CreateFileVersionInfo(base::FilePath(kChromeDll)));
- last_change = WideToASCII(file_info->last_change());
-#elif defined(OS_POSIX)
- // TODO(fmeawad): On Mac, the version retrieved here belongs to the test
- // module and not the chrome binary, need to be changed to chrome binary
- // instead.
- chrome::VersionInfo version_info;
- last_change = version_info.LastChange();
-#endif // !defined(OS_WIN)
- test_log << "Last Change: ";
- test_log << last_change << std::endl;
-
- // Log timestamp for test start.
- base::Time time_now = base::Time::Now();
- double time_start = time_now.ToDoubleT();
- test_log << "Test Start: ";
- test_log << base::TimeFormatFriendlyDateAndTime(time_now) << std::endl;
-
- // Make sure the browser is running.
- EnsureBrowserAndServer();
-
- // Log Browser Launched time.
- time_now = base::Time::Now();
- test_log << "browser_launched_seconds=";
- test_log << (time_now.ToDoubleT() - time_start) << std::endl;
-
- int result = AUTOMATION_MSG_NAVIGATION_ERROR;
- // This is essentially what NavigateToURL does except we don't fire
- // assertion when page loading fails. We log the result instead.
- {
- // TabProxy should be released before Browser is closed.
- scoped_refptr<TabProxy> tab_proxy(GetActiveTab());
- if (tab_proxy.get())
- result = tab_proxy->NavigateToURL(url);
- }
-
- // Log navigate complete time.
- time_now = base::Time::Now();
- test_log << "navigate_complete_seconds=";
- test_log << (time_now.ToDoubleT() - time_start) << std::endl;
-
- if (!keep_browser) {
- CloseBrowserAndServer();
- g_browser_existing = false;
- }
-
- // Log end of test time.
- time_now = base::Time::Now();
- test_log << "total_duration_seconds=";
- test_log << (time_now.ToDoubleT() - time_start) << std::endl;
-
- // Get navigation result and metrics, and optionally write to the log file
- // provided. The log format is:
- // <url> <navigation_result> <browser_crash_count> <renderer_crash_count>
- // <plugin_crash_count> <crash_dump_count> [chrome_log=<path>
- // v8_log=<path>] crash_dump=<path>
- switch (result) {
- case AUTOMATION_MSG_NAVIGATION_ERROR:
- metrics.result = NAVIGATION_ERROR;
- break;
- case AUTOMATION_MSG_NAVIGATION_SUCCESS:
- metrics.result = NAVIGATION_SUCCESS;
- break;
- case AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED:
- metrics.result = NAVIGATION_AUTH_NEEDED;
- break;
- default:
- metrics.result = NAVIGATION_ERROR;
- break;
- }
-
- // Get crash dumps - don't delete them if logging.
- std::vector<base::FilePath> new_crash_dumps;
- CollectNewCrashDumps(new_crash_dumps, &metrics, !log_file.is_open());
-
- bool do_log = log_file.is_open() &&
- (!log_only_error ||
- metrics.result != NAVIGATION_SUCCESS ||
- !new_crash_dumps.empty());
- if (do_log) {
- log_file << url_string;
- switch (metrics.result) {
- case NAVIGATION_ERROR:
- log_file << " error";
- break;
- case NAVIGATION_SUCCESS:
- log_file << " success";
- break;
- case NAVIGATION_AUTH_NEEDED:
- log_file << " auth_needed";
- break;
- case NAVIGATION_TIME_OUT:
- log_file << " timeout";
- break;
- default:
- break;
- }
- }
-
-#if !defined(OS_MACOSX) // Not used by mac chromebot.
- // Get stability metrics recorded by Chrome itself.
- GetStabilityMetrics(&metrics);
-#endif
-
- if (do_log) {
- log_file << " " << metrics.browser_crash_count \
- // The renderer crash count is flaky due to 1183283.
- // Ignore the count since we also catch crash by
- // crash_dump_count.
- << " " << 0 \
- << " " << metrics.plugin_crash_count \
- << " " << metrics.crash_dump_count;
- }
-
- // Close test log.
- test_log.close();
-
- if (do_log && g_save_debug_log && !g_continuous_load)
- SaveDebugLogs(log_file);
-
- // Log revision information for Chrome build under test.
- if (do_log)
- log_file << " " << "revision=" << last_change;
-
- if (do_log) {
- for (size_t i = 0; i < new_crash_dumps.size(); i++)
- log_file << " crash_dump=" << new_crash_dumps[i].value().c_str();
- }
-
- if (do_log)
- log_file << std::endl;
-
- if (metrics_output)
- *metrics_output = metrics;
-
- return do_log;
- }
-
- void NavigateThroughPageID(std::ofstream& log_file) {
- if (g_append_page_id) {
- // For usage 2
- for (int i = g_start_page; i <= g_end_page; ++i) {
- const char* server = g_server_url.empty() ? kDefaultServerUrl :
- g_server_url.c_str();
- std::string test_page_url(
- base::StringPrintf("%s/page?id=%d", server, i));
- NavigateToURLLogResult(
- test_page_url, log_file, NULL, g_continuous_load, false);
- }
- } else {
- // Don't run if running as a standalone program which is for distributed
- // testing, to avoid mistakenly hitting web sites with many instances.
- if (g_stand_alone)
- return;
- // For usage 1
- NavigationMetrics metrics;
-
- base::FilePath sample_data_dir = GetSampleDataDir();
- base::FilePath test_page_1 = sample_data_dir.AppendASCII(kTestPage1);
- base::FilePath test_page_2 = sample_data_dir.AppendASCII(kTestPage2);
-
- GURL test_url_1 = net::FilePathToFileURL(test_page_1);
- GURL test_url_2 = net::FilePathToFileURL(test_page_2);
-
- // Convert back to string so that all calls to navigate are the same.
- const std::string test_url_1_string = test_url_1.spec();
- const std::string test_url_2_string = test_url_2.spec();
-
- NavigateToURLLogResult(
- test_url_1_string, log_file, &metrics, g_continuous_load, false);
- // Verify everything is fine
- EXPECT_EQ(NAVIGATION_SUCCESS, metrics.result);
- EXPECT_EQ(0, metrics.crash_dump_count);
- EXPECT_TRUE(metrics.browser_clean_exit);
- EXPECT_EQ(1, metrics.browser_launch_count);
- // Both starting page and test_url_1 are loaded.
- EXPECT_EQ(2, metrics.page_load_count);
- EXPECT_EQ(0, metrics.browser_crash_count);
- EXPECT_EQ(0, metrics.renderer_crash_count);
- EXPECT_EQ(0, metrics.plugin_crash_count);
-
- // Go to "about:crash"
- NavigateToURLLogResult(content::kChromeUICrashURL,
- log_file,
- &metrics,
- g_continuous_load,
- false);
- // Found a crash dump
- EXPECT_EQ(1, metrics.crash_dump_count) << kFailedNoCrashService;
- // Browser did not crash, and exited cleanly.
- EXPECT_TRUE(metrics.browser_clean_exit);
- EXPECT_EQ(1, metrics.browser_launch_count);
- // Only the renderer should have crashed.
- EXPECT_EQ(0, metrics.browser_crash_count);
- EXPECT_EQ(1, metrics.renderer_crash_count);
- EXPECT_EQ(0, metrics.plugin_crash_count);
-
- NavigateToURLLogResult(
- test_url_2_string, log_file, &metrics, g_continuous_load, false);
- // The data on previous crash should be cleared and we should get
- // metrics for a successful page load.
- EXPECT_EQ(NAVIGATION_SUCCESS, metrics.result);
- EXPECT_EQ(0, metrics.crash_dump_count);
- EXPECT_TRUE(metrics.browser_clean_exit);
- EXPECT_EQ(1, metrics.browser_launch_count);
- EXPECT_EQ(0, metrics.browser_crash_count);
- EXPECT_EQ(0, metrics.renderer_crash_count);
- EXPECT_EQ(0, metrics.plugin_crash_count);
-
- // Verify metrics service does what we need when browser process crashes.
- LaunchBrowserAndServer();
- {
- // TabProxy should be released before Browser is closed.
- scoped_refptr<TabProxy> tab_proxy(GetActiveTab());
- EXPECT_TRUE(tab_proxy.get());
- if (tab_proxy.get()) {
- EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS,
- tab_proxy->NavigateToURL(GURL(test_url_1)));
- }
- }
- // Kill browser process.
- base::ProcessHandle browser_process = process();
- base::KillProcess(browser_process, 0, false);
-
- GetStabilityMetrics(&metrics);
- // This is not a clean shutdown.
- EXPECT_FALSE(metrics.browser_clean_exit);
- EXPECT_EQ(1, metrics.browser_crash_count);
- EXPECT_EQ(0, metrics.renderer_crash_count);
- EXPECT_EQ(0, metrics.plugin_crash_count);
- // Relaunch browser so UITest does not fire assertion during TearDown.
- LaunchBrowserAndServer();
- }
- }
-
- // For usage 3
- void NavigateThroughURLList(std::ofstream& log_file) {
- std::ifstream file(g_url_file_path.value().c_str());
- ASSERT_TRUE(file.is_open());
-
- for (int line_index = 1;
- line_index <= g_end_index && !file.eof();
- ++line_index) {
- std::string url_str;
- std::getline(file, url_str);
-
- if (file.fail())
- break;
-
- if (g_start_index <= line_index) {
- if (g_stress_opt || g_stress_deopt) {
- // Make sure the browser is running to communicate the stress
- // setting.
- EnsureBrowserAndServer();
- v8::Testing::StressType stress_type =
- g_stress_opt
- ? v8::Testing::kStressTypeOpt
- : v8::Testing::kStressTypeDeopt;
- scoped_refptr<TabProxy> tab_proxy(GetActiveTab());
- if (tab_proxy.get()) {
- tab_proxy->JavaScriptStressTestControl(
- kJavaScriptStressTestSetStressRunType, stress_type);
- }
-
- bool success = true;
- // Load each page a number of times and keep the same browser open
- // for these loads. This loop will end if an error is encountered
- // during one of the loads and the error logged.
- for (int i = 0;
- i < v8::Testing::GetStressRuns() && success;
- i++) {
- bool last_load = (i == (v8::Testing::GetStressRuns() - 1));
- bool keep_browser = !last_load || g_continuous_load;
- bool log_only_error = !last_load;
- NavigationMetrics metrics;
-
- scoped_refptr<TabProxy> tab_proxy(GetActiveTab());
- if (tab_proxy.get()) {
- tab_proxy->JavaScriptStressTestControl(
- kJavaScriptStressTestPrepareStressRun, i);
- }
- bool did_log_error;
- did_log_error = NavigateToURLLogResult(url_str,
- log_file,
- &metrics,
- keep_browser,
- log_only_error);
- success = metrics.result == NAVIGATION_SUCCESS && !did_log_error;
- }
- } else {
- NavigateToURLLogResult(
- url_str, log_file, NULL, g_continuous_load, false);
- }
- }
- }
-
- file.close();
- }
-
- protected:
- // Call the base class's SetUp method and initialize our own class members.
- virtual void SetUp() {
- // Set UI Test members before setting up browser.
- clear_profile_ = g_clear_profile;
-
- UITest::SetUp();
- g_browser_existing = true;
-
- // If 'BREAKPAD_DUMP_LOCATION' environment variable is set, use it instead.
- scoped_ptr<base::Environment> env(base::Environment::Create());
- std::string alternate_minidump_location;
- if (env->GetVar("BREAKPAD_DUMP_LOCATION", &alternate_minidump_location)) {
- crash_dumps_dir_path_ = base::FilePath::FromUTF8Unsafe(
- alternate_minidump_location);
- } else {
- PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dumps_dir_path_);
- }
-
- base::FileEnumerator enumerator(crash_dumps_dir_path_,
- false, // not recursive
- base::FileEnumerator::FILES);
- for (base::FilePath path = enumerator.Next(); !path.value().empty();
- path = enumerator.Next()) {
- if (path.MatchesExtension(FILE_PATH_LITERAL(".dmp")))
- crash_dumps_[path.BaseName()] = true;
- }
- }
-
- base::FilePath ConstructSavedDebugLogPath(
- const base::FilePath& debug_log_path,
- int index) {
- std::string suffix("_");
- suffix.append(base::IntToString(index));
- return debug_log_path.InsertBeforeExtensionASCII(suffix);
- }
-
- void SaveDebugLog(const base::FilePath& log_path, const std::wstring& log_id,
- std::ofstream& log_file, int index) {
- if (!log_path.empty()) {
- base::FilePath saved_log_file_path =
- ConstructSavedDebugLogPath(log_path, index);
- if (base::Move(log_path, saved_log_file_path)) {
- log_file << " " << log_id << "=" << saved_log_file_path.value();
- }
- }
- }
-
- // Rename the chrome and v8 debug log files if existing, and save the file
- // paths in the log_file provided.
- void SaveDebugLogs(std::ofstream& log_file) {
- static int url_count = 1;
- SaveDebugLog(g_chrome_log_path, L"chrome_log", log_file, url_count);
- SaveDebugLog(g_v8_log_path, L"v8_log", log_file, url_count);
- SaveDebugLog(g_test_log_path, L"test_log", log_file, url_count);
- url_count++;
- }
-
- // Delete a crash dump file.
- void DeleteCrashDump(base::FilePath crash_dump_file_name) {
- base::FilePath crash_dump_file_path(crash_dumps_dir_path_);
- crash_dump_file_path = crash_dump_file_path.Append(crash_dump_file_name);
- base::FilePath crash_text_file_path =
- crash_dump_file_path.ReplaceExtension(FILE_PATH_LITERAL("txt"));
-
- ASSERT_TRUE(file_util::DieFileDie(crash_dump_file_path, false));
- ASSERT_TRUE(file_util::DieFileDie(crash_text_file_path, false));
- }
-
- bool HasNewCrashDumps() {
- base::FileEnumerator enumerator(crash_dumps_dir_path_,
- false, // not recursive
- base::FileEnumerator::FILES);
- for (base::FilePath path = enumerator.Next(); !path.value().empty();
- path = enumerator.Next()) {
- if (path.MatchesExtension(FILE_PATH_LITERAL(".dmp")) &&
- !crash_dumps_[path.BaseName()]) {
- return true;
- }
- }
-
- return false;
- }
-
- // Check whether there are new .dmp files. Return the list and optionally
- // delete them afterwards.
- void CollectNewCrashDumps(std::vector<base::FilePath>& new_crash_dumps,
- NavigationMetrics* metrics,
- bool delete_dumps) {
- int num_dumps = 0;
- base::FileEnumerator enumerator(crash_dumps_dir_path_,
- false, // not recursive
- base::FileEnumerator::FILES);
- for (base::FilePath path = enumerator.Next(); !path.value().empty();
- path = enumerator.Next()) {
- if (path.MatchesExtension(FILE_PATH_LITERAL(".dmp")) &&
- !crash_dumps_[path.BaseName()]) {
- crash_dumps_[path.BaseName()] = true;
- base::FilePath crash_dump_file_path(crash_dumps_dir_path_);
- crash_dump_file_path = crash_dump_file_path.Append(path.BaseName());
- new_crash_dumps.push_back(crash_dump_file_path);
- if (delete_dumps)
- DeleteCrashDump(path.BaseName());
- num_dumps++;
- }
- }
- if (metrics)
- metrics->crash_dump_count = num_dumps;
- }
-
- // Get a PrefService whose contents correspond to the Local State file
- // that was saved by the app as it closed. The caller takes ownership of the
- // returned PrefService object.
- PrefService* GetLocalState(PrefRegistry* registry) {
- base::FilePath path = user_data_dir().Append(chrome::kLocalStateFilename);
- PrefServiceMockBuilder builder;
- builder.WithUserFilePrefs(
- path, base::MessageLoop::current()->message_loop_proxy().get());
- return builder.Create(registry);
- }
-
- void GetStabilityMetrics(NavigationMetrics* metrics) {
- if (!metrics)
- return;
- scoped_refptr<PrefRegistrySimple> registry = new PrefRegistrySimple();
- registry->RegisterBooleanPref(prefs::kStabilityExitedCleanly, false);
- registry->RegisterIntegerPref(prefs::kStabilityLaunchCount, -1);
- registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, -1);
- registry->RegisterIntegerPref(prefs::kStabilityCrashCount, 0);
- registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
-
- scoped_ptr<PrefService> local_state(GetLocalState(registry.get()));
- if (!local_state.get())
- return;
-
- metrics->browser_clean_exit =
- local_state->GetBoolean(prefs::kStabilityExitedCleanly);
- metrics->browser_launch_count =
- local_state->GetInteger(prefs::kStabilityLaunchCount);
- metrics->page_load_count =
- local_state->GetInteger(prefs::kStabilityPageLoadCount);
- metrics->browser_crash_count =
- local_state->GetInteger(prefs::kStabilityCrashCount);
- metrics->renderer_crash_count =
- local_state->GetInteger(prefs::kStabilityRendererCrashCount);
- // TODO(huanr)
- metrics->plugin_crash_count = 0;
-
- if (!metrics->browser_clean_exit)
- metrics->browser_crash_count++;
- }
-
- base::FilePath GetSampleDataDir() {
- base::FilePath test_dir;
- PathService::Get(chrome::DIR_TEST_DATA, &test_dir);
- test_dir = test_dir.AppendASCII("reliability");
- test_dir = test_dir.AppendASCII("sample_pages");
- return test_dir;
- }
-
- // The pathname of Chrome's crash dumps directory.
- base::FilePath crash_dumps_dir_path_;
-
- // The set of all the crash dumps we have seen. Each crash generates a
- // .dmp and a .txt file in the crash dumps directory. We only store the
- // .dmp files in this set.
- //
- // The set is implemented as a std::map. The key is the file name, and
- // the value is false (the file is not in the set) or true (the file is
- // in the set). The initial value for any key in std::map is 0 (false),
- // which in this case means a new file is not in the set initially,
- // exactly the semantics we want.
- std::map<base::FilePath, bool> crash_dumps_;
-};
-
-TEST_F(PageLoadTest, Reliability) {
- std::ofstream log_file;
-
- if (!g_log_file_path.empty()) {
- log_file.open(g_log_file_path.value().c_str());
- }
-
- for (int k = 0; k < g_iterations; ++k) {
- if (g_url_file_path.empty()) {
- NavigateThroughPageID(log_file);
- } else {
- NavigateThroughURLList(log_file);
- }
- }
-
- if (!g_end_url.empty()) {
- NavigateToURLLogResult(
- g_end_url, log_file, NULL, g_continuous_load, false);
- }
-
- log_file.close();
-}
-
-} // namespace
-
diff --git a/chrome/tools/automated_ui_test_tools/ui_action_generator.py b/chrome/tools/automated_ui_test_tools/ui_action_generator.py
deleted file mode 100755
index b455554..0000000
--- a/chrome/tools/automated_ui_test_tools/ui_action_generator.py
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""A simple main function to print ui action sequences.
-
-Action sequences are generated using chrome/test/functional/ui_model.py
-and are output in the format required by automated_ui_tests build target.
-
-Generate 100 command sequences to ui.txt:
-ui_action_generator.py -o ui.txt -c 100
-
-Generate 100 15-action-length sequences:
-ui_action_generator.py -c 100 -a 15
-
-Re-create command with seed 12345:
-ui_action_generator.py -s 12345
-"""
-
-import optparse
-import os
-import sys
-import xml.dom.minidom
-
-
-def _AddTestPath():
- """Add chrome/test/functional to path to find script dependancies."""
- script_dir = os.path.dirname(__file__)
- chrome_dir = os.path.join(script_dir, os.pardir, os.pardir)
- test_dir = os.path.join(chrome_dir, 'test', 'functional')
- sys.path += [test_dir]
-
-_AddTestPath()
-import ui_model
-
-
-def CreateUIActionList(actions_per_command, num_commands, given_seed=None):
- """Generate user-like pseudo-random action sequences.
-
- Args:
- actions_per_command: length of each ui action sequence.
- num_commands: number of sequences to generate.
- seed: optional rand seed for this list.
-
- Returns:
- XML format command list string, readable by automated_ui_tests.
- """
- doc = xml.dom.minidom.Document()
- command_list = doc.createElement('CommandList')
- doc.appendChild(command_list)
- for _ in xrange(num_commands):
- command = doc.createElement('command')
- command_list.appendChild(command)
- seed = ui_model.Seed(given_seed)
- command.setAttribute('seed', str(seed))
- browser = ui_model.BrowserState()
- for _ in xrange(actions_per_command):
- action = ui_model.GetRandomAction(browser)
- browser = ui_model.UpdateState(browser, action)
- action_tuple = action.split(';')
- action_element = doc.createElement(action_tuple[0])
- if len(action_tuple) == 2:
- action_element.setAttribute('url', action_tuple[1])
- command.appendChild(action_element)
- return doc.toprettyxml()
-
-
-def ParseCommandLine():
- """Returns the list of options and their values, and unparsed args.
- """
- parser = optparse.OptionParser()
- parser.add_option('-o', '--output', dest='output_file', type='string',
- action='store', default='ui_actions.txt',
- help='the file to output the command list to')
- parser.add_option('-c', '--num_commands', dest='num_commands',
- type='int', action='store', default=1,
- help='number of commands to output')
- parser.add_option('-a', '--actions-per-command', dest='actions_per_command',
- type='int', action='store', default=25,
- help='number of actions per command')
- parser.add_option('-s', '--seed', dest='seed', type='int', action='store',
- default=None, help='generate action sequence using a seed')
-
- return parser.parse_args()
-
-
-def main():
- """Generate command list and write it out in xml format.
-
- For use as input for automated_ui_tests build target.
- """
- options, args = ParseCommandLine()
- command_list = CreateUIActionList(options.actions_per_command,
- options.num_commands,
- options.seed)
- f = open(options.output_file, 'w')
- f.write(command_list)
- f.close()
- print command_list
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chrome/unit_tests.isolate b/chrome/unit_tests.isolate
index 8af8a9b..71bab21 100644
--- a/chrome/unit_tests.isolate
+++ b/chrome/unit_tests.isolate
@@ -13,6 +13,7 @@
['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', {
'variables': {
'isolate_dependency_tracked': [
+ '../third_party/accessibility-audit/axs_testing.js',
'<(PRODUCT_DIR)/resources.pak',
],
'isolate_dependency_untracked': [
@@ -20,7 +21,6 @@
'../components/test/data/',
'../extensions/test/data/',
'../net/data/',
- '../third_party/accessibility-developer-tools/gen/',
'../third_party/hunspell_dictionaries/',
'../third_party/zlib/google/test/data/',
'test/data/',
diff --git a/chrome/utility/importer/OWNERS b/chrome/utility/importer/OWNERS
index 66d2678..6238904 100644
--- a/chrome/utility/importer/OWNERS
+++ b/chrome/utility/importer/OWNERS
@@ -8,5 +8,4 @@
per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
diff --git a/chrome/utility/local_discovery/service_discovery_client_impl.cc b/chrome/utility/local_discovery/service_discovery_client_impl.cc
index e8fc595..05ec76d 100644
--- a/chrome/utility/local_discovery/service_discovery_client_impl.cc
+++ b/chrome/utility/local_discovery/service_discovery_client_impl.cc
@@ -31,7 +31,7 @@
const std::string& service_type,
const ServiceWatcher::UpdatedCallback& callback) {
return scoped_ptr<ServiceWatcher>(new ServiceWatcherImpl(
- service_type, callback, mdns_client_));
+ service_type, callback, mdns_client_));
}
scoped_ptr<ServiceResolver> ServiceDiscoveryClientImpl::CreateServiceResolver(
diff --git a/chrome/utility/local_discovery/service_discovery_message_handler.cc b/chrome/utility/local_discovery/service_discovery_message_handler.cc
index 5b0ab95..d559547 100644
--- a/chrome/utility/local_discovery/service_discovery_message_handler.cc
+++ b/chrome/utility/local_discovery/service_discovery_message_handler.cc
@@ -110,27 +110,10 @@
#endif // OS_WIN
-void SendServiceResolved(uint64 id, ServiceResolver::RequestStatus status,
- const ServiceDescription& description) {
- content::UtilityThread::Get()->Send(
- new LocalDiscoveryHostMsg_ResolverCallback(id, status, description));
+void SendHostMessageOnUtilityThread(IPC::Message* msg) {
+ content::UtilityThread::Get()->Send(msg);
}
-void SendServiceUpdated(uint64 id, ServiceWatcher::UpdateType update,
- const std::string& name) {
- content::UtilityThread::Get()->Send(
- new LocalDiscoveryHostMsg_WatcherCallback(id, update, name));
-}
-
-void SendLocalDomainResolved(uint64 id, bool success,
- const net::IPAddressNumber& address_ipv4,
- const net::IPAddressNumber& address_ipv6) {
- content::UtilityThread::Get()->Send(
- new LocalDiscoveryHostMsg_LocalDomainResolverCallback(
- id, success, address_ipv4, address_ipv6));
-}
-
-
std::string WatcherUpdateToString(ServiceWatcher::UpdateType update) {
switch (update) {
case ServiceWatcher::UPDATE_ADDED:
@@ -178,8 +161,10 @@
{
// Temporarily redirect network code to use pre-created sockets.
ScopedSocketFactorySetter socket_factory_setter;
- if (!mdns_client_->StartListening())
+ if (!mdns_client_->StartListening()) {
+ Send(new LocalDiscoveryHostMsg_Error());
return;
+ }
}
service_discovery_client_.reset(
@@ -387,7 +372,6 @@
service_watchers_.clear();
service_resolvers_.clear();
local_domain_resolvers_.clear();
-
service_discovery_client_.reset();
mdns_client_.reset();
}
@@ -398,8 +382,8 @@
const std::string& name) {
VLOG(1) << "OnServiceUpdated with id " << id << WatcherUpdateToString(update);
DCHECK(service_discovery_client_);
- utility_task_runner_->PostTask(FROM_HERE,
- base::Bind(&SendServiceUpdated, id, update, name));
+
+ Send(new LocalDiscoveryHostMsg_WatcherCallback(id, update, name));
}
void ServiceDiscoveryMessageHandler::OnServiceResolved(
@@ -410,8 +394,7 @@
<< ResolverStatusToString(status);
DCHECK(service_discovery_client_);
- utility_task_runner_->PostTask(FROM_HERE,
- base::Bind(&SendServiceResolved, id, status, description));
+ Send(new LocalDiscoveryHostMsg_ResolverCallback(id, status, description));
}
void ServiceDiscoveryMessageHandler::OnLocalDomainResolved(
@@ -419,19 +402,19 @@
bool success,
const net::IPAddressNumber& address_ipv4,
const net::IPAddressNumber& address_ipv6) {
- VLOG(1) << "OnLocalDomainResolved with id " << id;
-
- if (!address_ipv4.empty())
- VLOG(1) << "Local comain callback has valid ipv4 address with id " << id;
- if (!address_ipv6.empty())
- VLOG(1) << "Local comain callback has valid ipv6 address with id " << id;
+ VLOG(1) << "OnLocalDomainResolved with id=" << id
+ << ", IPv4=" << net::IPAddressToString(address_ipv4)
+ << ", IPv6=" << net::IPAddressToString(address_ipv6);
DCHECK(service_discovery_client_);
- utility_task_runner_->PostTask(FROM_HERE, base::Bind(&SendLocalDomainResolved,
- id, success,
- address_ipv4,
- address_ipv6));
+ Send(new LocalDiscoveryHostMsg_LocalDomainResolverCallback(
+ id, success, address_ipv4, address_ipv6));
}
+void ServiceDiscoveryMessageHandler::Send(IPC::Message* msg) {
+ utility_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&SendHostMessageOnUtilityThread,
+ msg));
+}
} // namespace local_discovery
diff --git a/chrome/utility/local_discovery/service_discovery_message_handler.h b/chrome/utility/local_discovery/service_discovery_message_handler.h
index 417db0f..c463448 100644
--- a/chrome/utility/local_discovery/service_discovery_message_handler.h
+++ b/chrome/utility/local_discovery/service_discovery_message_handler.h
@@ -93,6 +93,8 @@
const net::IPAddressNumber& address_ipv4,
const net::IPAddressNumber& address_ipv6);
+ void Send(IPC::Message* msg);
+
ServiceWatchers service_watchers_;
ServiceResolvers service_resolvers_;
LocalDomainResolvers local_domain_resolvers_;