diff --git a/chrome/android/java/src/org/chromium/chrome/browser/PasswordManagerHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/PasswordManagerHandler.java new file mode 100644 index 0000000..ead4749 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/PasswordManagerHandler.java
@@ -0,0 +1,64 @@ +// Copyright 2017 The Chromium 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; + +/** + * Interface for retrieving passwords and password exceptions (websites for which Chrome should not + * save password) from native code. + */ +public interface PasswordManagerHandler { + /** + * An interface which a client can use to listen to changes to password and password exception + * lists. + */ + public interface PasswordListObserver { + /** + * Called when passwords list is updated. + * @param count Number of entries in the password list. + */ + void passwordListAvailable(int count); + + /** + * Called when password exceptions list is updated. + * @param count Number of entries in the password exception list. + */ + void passwordExceptionListAvailable(int count); + } + + /** + * Called to start fetching password and exception lists. + */ + public void updatePasswordLists(); + + /** + * Get the saved password entry at index. + * + * @param index Index of Password. + * @return SavedPasswordEntry at index. + */ + public SavedPasswordEntry getSavedPasswordEntry(int index); + + /** + * Get saved password exception at index. + * + * @param index of exception + * @return Origin of password exception. + */ + public String getSavedPasswordException(int index); + + /** + * Remove saved password entry at index. + * + * @param index of password entry to remove. + */ + public void removeSavedPasswordEntry(int index); + + /** + * Remove saved exception entry at index. + * + * @param index of exception entry. + */ + public void removeSavedPasswordException(int index); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/PasswordUIView.java b/chrome/android/java/src/org/chromium/chrome/browser/PasswordUIView.java index b51ba809..2c0172d5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/PasswordUIView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/PasswordUIView.java
@@ -4,147 +4,77 @@ package org.chromium.chrome.browser; -import org.chromium.base.ObserverList; import org.chromium.base.annotations.CalledByNative; /** - * Class for retrieving passwords and password exceptions (websites for which Chrome should not save - * password) from native code. + * Production implementation of PasswordManagerHandler, making calls to native C++ code to retrieve + * the data. */ -public final class PasswordUIView { - - /** - * Class representing information about a saved password entry. - */ - public static final class SavedPasswordEntry { - private final String mUrl; - private final String mName; - private final String mPassword; - - private SavedPasswordEntry(String url, String name, String password) { - mUrl = url; - mName = name; - mPassword = password; - } - - public String getUrl() { - return mUrl; - } - - public String getUserName() { - return mName; - } - - public String getPassword() { - return mPassword; - } - } - +public final class PasswordUIView implements PasswordManagerHandler { @CalledByNative private static SavedPasswordEntry createSavedPasswordEntry( String url, String name, String password) { return new SavedPasswordEntry(url, name, password); } - /** - * Interface which client can use to listen to changes to password and password exception lists. - * Clients can register and unregister themselves with addObserver and removeObserver. - */ - public interface PasswordListObserver { - /** - * Called when passwords list is updated. - * @param count Number of entries in the password list. - */ - void passwordListAvailable(int count); - - /** - * Called when password exceptions list is updated. - * @param count Number of entries in the password exception list. - */ - void passwordExceptionListAvailable(int count); - } - - private ObserverList<PasswordListObserver> mObservers = - new ObserverList<PasswordListObserver>(); - // Pointer to native implementation, set to 0 in destroy(). private long mNativePasswordUIViewAndroid; + // This class has exactly one observer, set on construction and expected to last at least as + // long as this object (a good candidate is the owner of this object). + private final PasswordListObserver mObserver; + /** * Constructor creates the native object as well. Callers should call destroy() after usage. + * @param PasswordListObserver The only observer. */ - public PasswordUIView() { + public PasswordUIView(PasswordListObserver observer) { mNativePasswordUIViewAndroid = nativeInit(); + mObserver = observer; } @CalledByNative private void passwordListAvailable(int count) { - for (PasswordListObserver observer : mObservers) { - observer.passwordListAvailable(count); - } + mObserver.passwordListAvailable(count); } @CalledByNative private void passwordExceptionListAvailable(int count) { - for (PasswordListObserver observer : mObservers) { - observer.passwordExceptionListAvailable(count); - } + mObserver.passwordExceptionListAvailable(count); } - public void addObserver(PasswordListObserver observer) { - mObservers.addObserver(observer); - } - - public void removeObserver(PasswordListObserver observer) { - mObservers.removeObserver(observer); - } - - /** - * Calls native to refresh password and exception lists. Observers are notified when fetch to - * passwords is complete. - */ + // Calls native to refresh password and exception lists. The native code calls back into + // passwordListAvailable and passwordExceptionListAvailable. + @Override public void updatePasswordLists() { nativeUpdatePasswordLists(mNativePasswordUIViewAndroid); } - /** - * Get the saved password entry at index. - * - * @param index Index of Password. - * @return SavedPasswordEntry at index. - */ + @Override public SavedPasswordEntry getSavedPasswordEntry(int index) { return nativeGetSavedPasswordEntry(mNativePasswordUIViewAndroid, index); } - /** - * Get saved password exception at index. - * - * @param index of exception - * @return Origin of password exception. - */ + @Override public String getSavedPasswordException(int index) { return nativeGetSavedPasswordException(mNativePasswordUIViewAndroid, index); } - /** - * Remove saved password entry at index. - * - * @param index of password entry to remove. - */ + @Override public void removeSavedPasswordEntry(int index) { nativeHandleRemoveSavedPasswordEntry(mNativePasswordUIViewAndroid, index); } - /** - * Remove saved exception entry at index. - * - * @param index of exception entry. - */ + @Override public void removeSavedPasswordException(int index) { nativeHandleRemoveSavedPasswordException(mNativePasswordUIViewAndroid, index); } + /** + * Returns the URL for the website for managing one's passwords without the need to use Chrome + * with the user's profile signed in. + * @return The string with the URL. + */ public static String getAccountDashboardURL() { return nativeGetAccountDashboardURL(); } @@ -157,7 +87,6 @@ nativeDestroy(mNativePasswordUIViewAndroid); mNativePasswordUIViewAndroid = 0; } - mObservers.clear(); } private native long nativeInit(); @@ -165,8 +94,7 @@ private native void nativeUpdatePasswordLists(long nativePasswordUIViewAndroid); private native SavedPasswordEntry nativeGetSavedPasswordEntry( - long nativePasswordUIViewAndroid, - int index); + long nativePasswordUIViewAndroid, int index); private native String nativeGetSavedPasswordException(long nativePasswordUIViewAndroid, int index);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SavedPasswordEntry.java b/chrome/android/java/src/org/chromium/chrome/browser/SavedPasswordEntry.java new file mode 100644 index 0000000..032ba7d --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/SavedPasswordEntry.java
@@ -0,0 +1,38 @@ +// Copyright 2017 The Chromium 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; + +/** + * A class representing information about a saved password entry in Chrome's settngs. + * + * Note: This could be a nested class in the PasswordManagerHandler interface, but that would mean + * that PasswordUIView, which implements that interface and references SavedPasswordEntry in some of + * its JNI-registered methods, would need an explicit import of PasswordManagerHandler. That again + * would violate our presubmit checks, and https://crbug.com/424792 indicates that the preferred + * solution is to move the nested class to top-level. + */ +public final class SavedPasswordEntry { + private final String mUrl; + private final String mName; + private final String mPassword; + + public SavedPasswordEntry(String url, String name, String password) { + mUrl = url; + mName = name; + mPassword = password; + } + + public String getUrl() { + return mUrl; + } + + public String getUserName() { + return mName; + } + + public String getPassword() { + return mPassword; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java index eb8a82c..44781481 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
@@ -34,8 +34,8 @@ import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; +import org.chromium.chrome.browser.PasswordManagerHandler.PasswordListObserver; import org.chromium.chrome.browser.PasswordUIView; -import org.chromium.chrome.browser.PasswordUIView.PasswordListObserver; import org.chromium.chrome.browser.sync.ProfileSyncService; import org.chromium.components.sync.AndroidSyncSettings; import org.chromium.ui.text.SpanApplier; @@ -214,7 +214,6 @@ // Delete was clicked. private void removeItem() { - final PasswordUIView passwordUIView = new PasswordUIView(); final PasswordListObserver passwordDeleter = new PasswordListObserver() { @Override public void passwordListAvailable(int count) { @@ -222,8 +221,10 @@ RecordHistogram.recordEnumeratedHistogram( "PasswordManager.Android.PasswordCredentialEntry", PASSWORD_ENTRY_ACTION_DELETED, PASSWORD_ENTRY_ACTION_BOUNDARY); - passwordUIView.removeSavedPasswordEntry(mID); - passwordUIView.destroy(); + PasswordManagerHandlerProvider.getInstance() + .getPasswordManagerHandler() + .removeSavedPasswordEntry(mID); + PasswordManagerHandlerProvider.getInstance().removeObserver(this); Toast.makeText(getActivity().getApplicationContext(), R.string.deleted, Toast.LENGTH_SHORT) .show(); @@ -237,8 +238,10 @@ RecordHistogram.recordEnumeratedHistogram( "PasswordManager.Android.PasswordExceptionEntry", PASSWORD_ENTRY_ACTION_DELETED, PASSWORD_ENTRY_ACTION_BOUNDARY); - passwordUIView.removeSavedPasswordException(mID); - passwordUIView.destroy(); + PasswordManagerHandlerProvider.getInstance() + .getPasswordManagerHandler() + .removeSavedPasswordException(mID); + PasswordManagerHandlerProvider.getInstance().removeObserver(this); Toast.makeText(getActivity().getApplicationContext(), R.string.deleted, Toast.LENGTH_SHORT) .show(); @@ -247,8 +250,10 @@ } }; - passwordUIView.addObserver(passwordDeleter); - passwordUIView.updatePasswordLists(); + PasswordManagerHandlerProvider.getInstance().addObserver(passwordDeleter); + PasswordManagerHandlerProvider.getInstance() + .getPasswordManagerHandler() + .updatePasswordLists(); } private void hookupCopyUsernameButton(View usernameView) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordManagerHandlerProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordManagerHandlerProvider.java new file mode 100644 index 0000000..52341247 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordManagerHandlerProvider.java
@@ -0,0 +1,117 @@ +// Copyright 2017 The Chromium 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.preferences.password; + +import org.chromium.base.ObserverList; +import org.chromium.base.ThreadUtils; +import org.chromium.base.VisibleForTesting; +import org.chromium.chrome.browser.PasswordManagerHandler; +import org.chromium.chrome.browser.PasswordUIView; + +/** + * A provider for PasswordManagerHandler implementations, handling the choice of the proper one + * (production vs. testing), its lifetime and multiple observers. + * + * This class is used by the code responsible for Chrome's passwords settings. There can only be one + * instance of Chrome's passwords settings opened at a time (although more clients of + * PasswordManagerHandler can live as nested settings pages). Therefore, the provider can be just + * one. However, it cannot be just a collection of static data members and methods, because the + * managed PasswordManagerHandler instances need to refer to it as an observer. For that reason, the + * provider is a singleton. + */ +public class PasswordManagerHandlerProvider implements PasswordManagerHandler.PasswordListObserver { + private static final class LazyHolder { + private static final PasswordManagerHandlerProvider INSTANCE = + new PasswordManagerHandlerProvider(); + } + + /** Private constructor, use GetInstance() instead. */ + private PasswordManagerHandlerProvider() {} + + public static PasswordManagerHandlerProvider getInstance() { + return LazyHolder.INSTANCE; + } + + // The production implementation of PasswordManagerHandler is |sPasswordUIView|, instantiated on + // demand. Tests might want to override that by providing a fake implementation through + // setPasswordManagerHandlerForTest, which is then kept in |mTestPasswordManagerHandler|. + private PasswordUIView mPasswordUIView; + private PasswordManagerHandler mTestPasswordManagerHandler; + + // This class is itself a PasswordListObserver, listening directly to a PasswordManagerHandler + // implementation. But it also keeps a list of other observers, to which it forwards the events. + private final ObserverList<PasswordManagerHandler.PasswordListObserver> mObservers = + new ObserverList<PasswordManagerHandler.PasswordListObserver>(); + + /** + * Sets a testing implementation of PasswordManagerHandler to be used. It overrides the + * production one even if it exists. The caller needs to ensure that |this| becomes an observer + * of |passwordManagerHandler|. Also, this must not be called when there are already some + * observers in |mObservers|, because of special handling of the production implementation of + * PasswordManagerHandler on removing the last observer. + */ + @VisibleForTesting + public void setPasswordManagerHandlerForTest(PasswordManagerHandler passwordManagerHandler) { + ThreadUtils.assertOnUiThread(); + assert mObservers.isEmpty(); + mTestPasswordManagerHandler = passwordManagerHandler; + } + + /** + * A convenience function to choose between the production and test PasswordManagerHandler + * implementation. + */ + public PasswordManagerHandler getPasswordManagerHandler() { + ThreadUtils.assertOnUiThread(); + if (mTestPasswordManagerHandler != null) return mTestPasswordManagerHandler; + return mPasswordUIView; + } + + /** + * This method creates the production implementation of PasswordManagerHandler and saves it into + * mPasswordUIView. + */ + private void createPasswordManagerHandler() { + ThreadUtils.assertOnUiThread(); + assert mPasswordUIView == null; + mPasswordUIView = new PasswordUIView(this); + } + + /** + * Starts forwarding events from the PasswordManagerHandler implementation to |observer|. + */ + public void addObserver(PasswordManagerHandler.PasswordListObserver observer) { + ThreadUtils.assertOnUiThread(); + if (getPasswordManagerHandler() == null) createPasswordManagerHandler(); + mObservers.addObserver(observer); + } + + public void removeObserver(PasswordManagerHandler.PasswordListObserver observer) { + ThreadUtils.assertOnUiThread(); + mObservers.removeObserver(observer); + // If this was the last observer of the production implementation of PasswordManagerHandler, + // call destroy on it to close the connection to the native C++ code. + if (mObservers.isEmpty() && mTestPasswordManagerHandler == null) { + mPasswordUIView.destroy(); + mPasswordUIView = null; + } + } + + @Override + public void passwordListAvailable(int count) { + ThreadUtils.assertOnUiThread(); + for (PasswordManagerHandler.PasswordListObserver observer : mObservers) { + observer.passwordListAvailable(count); + } + } + + @Override + public void passwordExceptionListAvailable(int count) { + ThreadUtils.assertOnUiThread(); + for (PasswordManagerHandler.PasswordListObserver observer : mObservers) { + observer.passwordExceptionListAvailable(count); + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java index 296f5f8..4611618 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
@@ -21,8 +21,9 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.PasswordManagerHandler; import org.chromium.chrome.browser.PasswordUIView; -import org.chromium.chrome.browser.PasswordUIView.PasswordListObserver; +import org.chromium.chrome.browser.SavedPasswordEntry; import org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference; import org.chromium.chrome.browser.preferences.ChromeBasePreference; import org.chromium.chrome.browser.preferences.ChromeSwitchPreference; @@ -37,8 +38,9 @@ * The "Save passwords" screen in Settings, which allows the user to enable or disable password * saving, to view saved passwords (just the username and URL), and to delete saved passwords. */ -public class SavePasswordsPreferences extends PreferenceFragment - implements PasswordListObserver, Preference.OnPreferenceClickListener { +public class SavePasswordsPreferences + extends PreferenceFragment implements PasswordManagerHandler.PasswordListObserver, + Preference.OnPreferenceClickListener { // Keys for name/password dictionaries. public static final String PASSWORD_LIST_URL = "url"; public static final String PASSWORD_LIST_NAME = "name"; @@ -65,7 +67,6 @@ private static final int ORDER_EXCEPTIONS = 4; private static final int ORDER_SAVED_PASSWORDS_NO_TEXT = 5; - private final PasswordUIView mPasswordManagerHandler = new PasswordUIView(); private boolean mNoPasswords; private boolean mNoPasswordExceptions; private Preference mLinkPref; @@ -78,7 +79,7 @@ super.onCreate(savedInstanceState); getActivity().setTitle(R.string.prefs_saved_passwords); setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity())); - mPasswordManagerHandler.addObserver(this); + PasswordManagerHandlerProvider.getInstance().addObserver(this); if (ChromeFeatureList.isEnabled(EXPORT_PASSWORDS)) { setHasOptionsMenu(true); } @@ -123,7 +124,9 @@ getPreferenceScreen().removeAll(); createSavePasswordsSwitch(); createAutoSignInCheckbox(); - mPasswordManagerHandler.updatePasswordLists(); + PasswordManagerHandlerProvider.getInstance() + .getPasswordManagerHandler() + .updatePasswordLists(); } /** @@ -168,8 +171,9 @@ profileCategory.setOrder(ORDER_SAVED_PASSWORDS); getPreferenceScreen().addPreference(profileCategory); for (int i = 0; i < count; i++) { - PasswordUIView.SavedPasswordEntry saved = - mPasswordManagerHandler.getSavedPasswordEntry(i); + SavedPasswordEntry saved = PasswordManagerHandlerProvider.getInstance() + .getPasswordManagerHandler() + .getSavedPasswordEntry(i); PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getActivity()); String url = saved.getUrl(); String name = saved.getUserName(); @@ -205,7 +209,9 @@ profileCategory.setOrder(ORDER_EXCEPTIONS); getPreferenceScreen().addPreference(profileCategory); for (int i = 0; i < count; i++) { - String exception = mPasswordManagerHandler.getSavedPasswordException(i); + String exception = PasswordManagerHandlerProvider.getInstance() + .getPasswordManagerHandler() + .getSavedPasswordException(i); PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getActivity()); screen.setTitle(exception); screen.setOnPreferenceClickListener(this); @@ -225,7 +231,7 @@ @Override public void onDestroy() { super.onDestroy(); - mPasswordManagerHandler.destroy(); + PasswordManagerHandlerProvider.getInstance().removeObserver(this); } /**
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 8792d5b..123d912 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -56,9 +56,11 @@ "java/src/org/chromium/chrome/browser/NativePageHost.java", "java/src/org/chromium/chrome/browser/NavigationPopup.java", "java/src/org/chromium/chrome/browser/NearOomMonitor.java", + "java/src/org/chromium/chrome/browser/PasswordManagerHandler.java", "java/src/org/chromium/chrome/browser/PasswordUIView.java", "java/src/org/chromium/chrome/browser/PowerBroadcastReceiver.java", "java/src/org/chromium/chrome/browser/RepostFormWarningDialog.java", + "java/src/org/chromium/chrome/browser/SavedPasswordEntry.java", "java/src/org/chromium/chrome/browser/SearchGeolocationDisclosureTabHelper.java", "java/src/org/chromium/chrome/browser/ServiceTabLauncher.java", "java/src/org/chromium/chrome/browser/SingleTabActivity.java", @@ -967,11 +969,12 @@ "java/src/org/chromium/chrome/browser/preferences/languages/LanguageListBaseAdapter.java", "java/src/org/chromium/chrome/browser/preferences/languages/LanguageListPreference.java", "java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java", + "java/src/org/chromium/chrome/browser/preferences/password/PasswordManagerHandlerProvider.java", + "java/src/org/chromium/chrome/browser/preferences/password/PasswordReauthenticationFragment.java", + "java/src/org/chromium/chrome/browser/preferences/password/ReauthenticationManager.java", "java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java", "java/src/org/chromium/chrome/browser/preferences/privacy/BandwidthType.java", "java/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataBridge.java", - "java/src/org/chromium/chrome/browser/preferences/password/PasswordReauthenticationFragment.java", - "java/src/org/chromium/chrome/browser/preferences/password/ReauthenticationManager.java", "java/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataCounterBridge.java", "java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java", "java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesAdvanced.java",
diff --git a/chrome/browser/search/README.md b/chrome/browser/search/README.md new file mode 100644 index 0000000..bb545d2 --- /dev/null +++ b/chrome/browser/search/README.md
@@ -0,0 +1,147 @@ +New Tab Page (Desktop) +====================== + +On Desktop (ChromeOS, Windows, Mac, and Linux), there are multiple +variants of the **New Tab Page** (**NTP**). The variant is selected +according to the user’s **Default Search Engine** (**DSE**). All +variants are implemented as HTML/CSS/JS, but differ in where they are +hosted. + +* **Google**: either the **[Remote NTP][remote-ntp]** (as of + 2017-12-05, the default) or the **[Local NTP][local-ntp]**, with + Google branding (as of 2017-12-05, planned to replace the Remote NTP + and in experiments on Beta). + +* **Bing**, **Yandex**: a **[Third-Party NTP][third-party-ntp]**, + where the NTP is hosted on third-party servers but Chrome provides + some of the content via <iframe> elements. + +* **Other**: the **Local NTP** with no branding. + +As of 2017-12-05, Bing and Yandex have implemented third-party NTPs. The +full list is in [`prepopulated_engines.json`][engines], under the key +`"new_tab_url"`. + +All variants show up to 8 **NTP Tiles**. Each NTP tile represents a site +that Chrome believes the user is likely to want to visit. On Desktop, +NTP tiles have a title, a thumbnail, and an “X” button so that the user +can remove tiles that they don’t want. + +[remote-ntp]: #remote-ntp +[local-ntp]: #local-ntp +[third-party-ntp]: #third_party-ntp +[engines]: https://chromium.googlesource.com/chromium/src/+/master/components/search_engines/prepopulated_engines.json + +Variants +-------- + +### Local NTP + +#### Google branding + +##### One Google Bar + +The **One Google Bar** (**OGB**) is at the top of the NTP. The NTP +fetches the OGB from Google servers each time it loads. + +##### Google Logo + +The **Google Logo** is below the OGB. By default, it is the regular +Google logo. It can also be a **Doodle**, if a Google Doodle is running +for a particular combination of (today’s date, user’s country, user’s +birthday). + +###### No Doodle + +On a day when there is no Doodle (in the user’s current country), the +NTP shows the Google logo. It comes in two variants: + +* Colorful, if the user is using the default theme, or on any other + theme with a solid black (L=0%), white (L=100%), or gray (S=0%) + background color. +* White, if the user’s theme has a background image, or if the + background is a solid color, but not black, white, or gray. + +Also, even on days when there is a Doodle, if the user’s theme’s +background is not solid white, new NTPs show the Google logo by default. +In this case, an animated spinner advertises the Doodle. If the user +clicks on the spinner, then the NTP resets to the default theme and +shows the Doodle. + +###### Static Doodles + +A **Static Doodle** shows as a single static image. When clicked, it +triggers a navigation to the Doodle’s target URL. + +###### Animated Doodles + +An **Animated Doodle** initially shows a static **Call-to-Action** +(**CTA**) image, usually with a “play” icon. When clicked, it swaps out +the CTA image for an animated image. When clicked a second time, it +triggers a navigation to the Doodle’s target URL. + +###### Interactive Doodles + +An **Interactive Doodle** is embedded into the NTP as an `<iframe>`. +The framed content usually contains a CTA image, but this is opaque to +the containing NTP. + +The embedded Doodle can ask the containing NTP to resize the `<iframe>` +tag to enlarge the space available for the Doodle. To do this, it sends +a `postMessage()` call to `window.parent`. The event data supports these +parameters: + +* `cmd` (required string): must be `"resizeDoodle"`. +* `width` (optional string): a CSS width (with units) or `null`. + Because the Doodle cannot know the size of the outer page, only + `null` (default width) or values based on `"100%"` (`"100%"`, + `"calc(100% - 50px)"`) are recommended. +* `height` (optional string): a CSS height (with units) or `null` for + the default (`"200px"`). Must not be a percentage, but otherwise any + units are OK. +* `duration` (optional string): a CSS duration, such as `"130ms"` or + `"1s"`. If `null` or absent, `"0s"` (no transition) is assumed. + +For example: + + // Reset to initial width and height. + window.parent.postMessage({cmd: "resizeDoodle"}); + + // Transition smoothly to full-width, 350px tall. + window.parent.postMessage({ + cmd: "resizeDoodle", + width: "100%", + height: "350px", + duration: "1s", + }); + +##### Fakebox + +The **Fakebox** looks like a search bar, so that the NTP mimics the +appearance of the Google homepage. It’s not actually a real search bar, +and if the user interacts with it, the NTP moves keyboard focus and any +text to the Omnibox and hides the Fakebox. + +##### Promos + +Below the NTP tiles, there is space for a **Promo**. A Promo is +typically a short string, typically used for disasters (e.g. “Affected +by the Boston Molassacre? Find a relief center near you.”) or an +advertisement (e.g. “Try the all-new new Chromebook, with included +toaster oven.”). + +As of 2017-12-05, the Local NTP does not yet support Promos. + +#### Non-Google Local NTP + +A non-Google local NTP shows only NTP tiles, with no branding. The tiles +are centered within the page. + +### Remote NTP + +The Remote NTP is hosted on Google servers. It is intended for removal, +and is not documented here. + +### Third-Party NTP + +TODO(sfiera)
diff --git a/chrome/browser/sync/test/integration/bookmarks_helper.cc b/chrome/browser/sync/test/integration/bookmarks_helper.cc index 08ebdd52..c392f30 100644 --- a/chrome/browser/sync/test/integration/bookmarks_helper.cc +++ b/chrome/browser/sync/test/integration/bookmarks_helper.cc
@@ -87,13 +87,15 @@ } ~FaviconChangeObserver() override { model_->RemoveObserver(this); } void WaitForGetFavicon() { + DCHECK(!run_loop_.running()); wait_for_load_ = true; - content::RunMessageLoop(); + content::RunThisRunLoop(&run_loop_); ASSERT_TRUE(node_->is_favicon_loaded()); } void WaitForSetFavicon() { + DCHECK(!run_loop_.running()); wait_for_load_ = false; - content::RunMessageLoop(); + content::RunThisRunLoop(&run_loop_); } // bookmarks::BookmarkModelObserver: @@ -125,9 +127,9 @@ const BookmarkNode* node) override {} void BookmarkNodeFaviconChanged(BookmarkModel* model, const BookmarkNode* node) override { - if (model == model_ && node == node_) { + if (model == model_ && node == node_ && run_loop_.running()) { if (!wait_for_load_ || (wait_for_load_ && node->is_favicon_loaded())) - base::RunLoop::QuitCurrentWhenIdleDeprecated(); + run_loop_.Quit(); } } @@ -135,6 +137,7 @@ BookmarkModel* model_; const BookmarkNode* node_; bool wait_for_load_; + base::RunLoop run_loop_; DISALLOW_COPY_AND_ASSIGN(FaviconChangeObserver); };
diff --git a/chrome/browser/sync/test/integration/passwords_helper.cc b/chrome/browser/sync/test/integration/passwords_helper.cc index 6559ce5..22ef0fff 100644 --- a/chrome/browser/sync/test/integration/passwords_helper.cc +++ b/chrome/browser/sync/test/integration/passwords_helper.cc
@@ -49,15 +49,17 @@ void OnGetPasswordStoreResults( std::vector<std::unique_ptr<PasswordForm>> results) override { result_.swap(results); - // Quit the message loop to wake up passwords_helper::GetLogins. - base::RunLoop::QuitCurrentWhenIdleDeprecated(); + run_loop_.Quit(); } - std::vector<std::unique_ptr<PasswordForm>> result() { + std::vector<std::unique_ptr<PasswordForm>> WaitForResult() { + DCHECK(!run_loop_.running()); + content::RunThisRunLoop(&run_loop_); return std::move(result_); } private: + base::RunLoop run_loop_; std::vector<std::unique_ptr<PasswordForm>> result_; DISALLOW_COPY_AND_ASSIGN(PasswordStoreConsumerHelper); @@ -101,8 +103,7 @@ PasswordForm::SCHEME_HTML, kFakeSignonRealm, GURL()}; PasswordStoreConsumerHelper consumer; store->GetLogins(matcher_form, &consumer); - content::RunMessageLoop(); - return consumer.result(); + return consumer.WaitForResult(); } void RemoveLogin(PasswordStore* store, const PasswordForm& form) {
diff --git a/chrome/browser/sync/test/integration/status_change_checker.cc b/chrome/browser/sync/test/integration/status_change_checker.cc index 364ecb5..7194b0e 100644 --- a/chrome/browser/sync/test/integration/status_change_checker.cc +++ b/chrome/browser/sync/test/integration/status_change_checker.cc
@@ -8,7 +8,9 @@ #include "base/run_loop.h" #include "base/timer/timer.h" -StatusChangeChecker::StatusChangeChecker() : timed_out_(false) {} +StatusChangeChecker::StatusChangeChecker() + : run_loop_(base::RunLoop::Type::kNestableTasksAllowed), + timed_out_(false) {} StatusChangeChecker::~StatusChangeChecker() {} @@ -30,18 +32,9 @@ return base::TimeDelta::FromSeconds(45); } -void StatusChangeChecker::StartBlockingWait() { - base::OneShotTimer timer; - timer.Start(FROM_HERE, - GetTimeoutDuration(), - base::Bind(&StatusChangeChecker::OnTimeout, - base::Unretained(this))); - - base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).Run(); -} - void StatusChangeChecker::StopWaiting() { - base::RunLoop::QuitCurrentWhenIdleDeprecated(); + if (run_loop_.running()) + run_loop_.Quit(); } void StatusChangeChecker::CheckExitCondition() { @@ -52,6 +45,17 @@ } } +void StatusChangeChecker::StartBlockingWait() { + DCHECK(!run_loop_.running()); + + base::OneShotTimer timer; + timer.Start(FROM_HERE, GetTimeoutDuration(), + base::BindRepeating(&StatusChangeChecker::OnTimeout, + base::Unretained(this))); + + run_loop_.Run(); +} + void StatusChangeChecker::OnTimeout() { DVLOG(1) << "Await -> Timed out: " << GetDebugMessage(); timed_out_ = true;
diff --git a/chrome/browser/sync/test/integration/status_change_checker.h b/chrome/browser/sync/test/integration/status_change_checker.h index 1716b35..d78ca105 100644 --- a/chrome/browser/sync/test/integration/status_change_checker.h +++ b/chrome/browser/sync/test/integration/status_change_checker.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/run_loop.h" #include "base/time/time.h" // Interface for a helper class that can pump the message loop while waiting @@ -45,14 +46,6 @@ // Timeout length when blocking. virtual base::TimeDelta GetTimeoutDuration(); - // Helper function to start running the nested run loop. - // - // Will exit if IsExitConditionSatisfied() returns true when called from - // CheckExitCondition(), if a timeout occurs, or if StopWaiting() is called. - // - // The timeout length is specified with GetTimeoutDuration(). - void StartBlockingWait(); - // Stop the nested running of the message loop started in StartBlockingWait(). void StopWaiting(); @@ -60,9 +53,19 @@ // true. void CheckExitCondition(); + private: + // Helper function to start running the nested run loop (run_loop_). + // + // Will exit if IsExitConditionSatisfied() returns true when called from + // CheckExitCondition(), if a timeout occurs, or if StopWaiting() is called. + // + // The timeout length is specified with GetTimeoutDuration(). + void StartBlockingWait(); + // Called when the blocking wait timeout is exceeded. void OnTimeout(); + base::RunLoop run_loop_; bool timed_out_; };
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 889729b0..d2f02e7 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -10171.0.0 \ No newline at end of file +10190.0.0 \ No newline at end of file
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 9be9762b..2c733eed 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -820,8 +820,6 @@ "media/webrtc/track_observer.cc", "media/webrtc/track_observer.h", "media/webrtc/two_keys_adapter_map.h", - "media/webrtc/video_codec_factory.cc", - "media/webrtc/video_codec_factory.h", "media/webrtc/webrtc_audio_sink.cc", "media/webrtc/webrtc_audio_sink.h", "media/webrtc/webrtc_media_stream_adapter.cc",
diff --git a/content/renderer/media/gpu/rtc_video_decoder.cc b/content/renderer/media/gpu/rtc_video_decoder.cc index 311227ae..d81d406 100644 --- a/content/renderer/media/gpu/rtc_video_decoder.cc +++ b/content/renderer/media/gpu/rtc_video_decoder.cc
@@ -133,6 +133,12 @@ return decoder; } +// static +void RTCVideoDecoder::Destroy(webrtc::VideoDecoder* decoder, + media::GpuVideoAcceleratorFactories* factories) { + factories->GetTaskRunner()->DeleteSoon(FROM_HERE, decoder); +} + int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings, int32_t /*numberOfCores*/) { DVLOG(2) << "InitDecode"; @@ -271,10 +277,6 @@ return WEBRTC_VIDEO_CODEC_OK; } -const char* RTCVideoDecoder::ImplementationName() const { - return "RTCVideoDecoder"; -} - int32_t RTCVideoDecoder::Release() { DVLOG(2) << "Release"; // Do not destroy VDA because WebRTC can call InitDecode and start decoding
diff --git a/content/renderer/media/gpu/rtc_video_decoder.h b/content/renderer/media/gpu/rtc_video_decoder.h index 23afb14..25a7eba2 100644 --- a/content/renderer/media/gpu/rtc_video_decoder.h +++ b/content/renderer/media/gpu/rtc_video_decoder.h
@@ -85,8 +85,6 @@ // this runs. int32_t Release() override; - const char* ImplementationName() const override; - // VideoDecodeAccelerator::Client implementation. void ProvidePictureBuffers(uint32_t count, media::VideoPixelFormat format,
diff --git a/content/renderer/media/gpu/rtc_video_decoder_factory.cc b/content/renderer/media/gpu/rtc_video_decoder_factory.cc index f1f0b7a..8df7c448 100644 --- a/content/renderer/media/gpu/rtc_video_decoder_factory.cc +++ b/content/renderer/media/gpu/rtc_video_decoder_factory.cc
@@ -6,89 +6,31 @@ #include <memory> -#include "base/memory/ptr_util.h" #include "content/renderer/media/gpu/rtc_video_decoder.h" #include "media/video/gpu_video_accelerator_factories.h" -#include "third_party/webrtc/api/video_codecs/sdp_video_format.h" namespace content { -namespace { - -// This extra indirection is needed so that we can delete the decoder on the -// correct thread. -class ScopedVideoDecoder : public webrtc::VideoDecoder { - public: - ScopedVideoDecoder( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - std::unique_ptr<webrtc::VideoDecoder> decoder) - : task_runner_(task_runner), decoder_(std::move(decoder)) {} - - int32_t InitDecode(const webrtc::VideoCodec* codec_settings, - int32_t number_of_cores) override { - return decoder_->InitDecode(codec_settings, number_of_cores); - } - int32_t RegisterDecodeCompleteCallback( - webrtc::DecodedImageCallback* callback) override { - return decoder_->RegisterDecodeCompleteCallback(callback); - } - int32_t Release() override { return decoder_->Release(); } - int32_t Decode(const webrtc::EncodedImage& input_image, - bool missing_frames, - const webrtc::RTPFragmentationHeader* fragmentation, - const webrtc::CodecSpecificInfo* codec_specific_info, - int64_t render_time_ms) override { - return decoder_->Decode(input_image, missing_frames, fragmentation, - codec_specific_info, render_time_ms); - } - bool PrefersLateDecoding() const override { - return decoder_->PrefersLateDecoding(); - } - const char* ImplementationName() const override { - return decoder_->ImplementationName(); - } - - // Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while - // this runs. - ~ScopedVideoDecoder() override { - task_runner_->DeleteSoon(FROM_HERE, decoder_.release()); - } - - private: - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - std::unique_ptr<webrtc::VideoDecoder> decoder_; -}; - -} // namespace - RTCVideoDecoderFactory::RTCVideoDecoderFactory( media::GpuVideoAcceleratorFactories* gpu_factories) : gpu_factories_(gpu_factories) { DVLOG(2) << __func__; } -std::vector<webrtc::SdpVideoFormat> -RTCVideoDecoderFactory::GetSupportedFormats() const { - // TODO(magjed): Implement this based on - // gpu_factories_->GetVideoDecodeAcceleratorSupportedProfiles(). This function - // is currently unused by WebRTC. - return std::vector<webrtc::SdpVideoFormat>(); -} - RTCVideoDecoderFactory::~RTCVideoDecoderFactory() { DVLOG(2) << __func__; } -std::unique_ptr<webrtc::VideoDecoder> -RTCVideoDecoderFactory::CreateVideoDecoder( - const webrtc::SdpVideoFormat& format) { +webrtc::VideoDecoder* RTCVideoDecoderFactory::CreateVideoDecoder( + webrtc::VideoCodecType type) { DVLOG(2) << __func__; - std::unique_ptr<webrtc::VideoDecoder> decoder = RTCVideoDecoder::Create( - webrtc::PayloadStringToCodecType(format.name), gpu_factories_); - // Make sure the decoder is destructed on the correct thread. - return decoder ? base::MakeUnique<ScopedVideoDecoder>( - gpu_factories_->GetTaskRunner(), std::move(decoder)) - : nullptr; + return RTCVideoDecoder::Create(type, gpu_factories_).release(); +} + +void RTCVideoDecoderFactory::DestroyVideoDecoder( + webrtc::VideoDecoder* decoder) { + DVLOG(2) << __func__; + RTCVideoDecoder::Destroy(decoder, gpu_factories_); } } // namespace content
diff --git a/content/renderer/media/gpu/rtc_video_decoder_factory.h b/content/renderer/media/gpu/rtc_video_decoder_factory.h index e9e0eea..7a4e45b 100644 --- a/content/renderer/media/gpu/rtc_video_decoder_factory.h +++ b/content/renderer/media/gpu/rtc_video_decoder_factory.h
@@ -8,7 +8,7 @@ #include "base/macros.h" #include "base/threading/thread.h" #include "content/common/content_export.h" -#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h" +#include "third_party/webrtc/media/engine/webrtcvideodecoderfactory.h" #include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h" namespace webrtc { @@ -23,7 +23,7 @@ // TODO(wuchengli): add unittest. class CONTENT_EXPORT RTCVideoDecoderFactory - : public webrtc::VideoDecoderFactory { + : public cricket::WebRtcVideoDecoderFactory { public: explicit RTCVideoDecoderFactory( media::GpuVideoAcceleratorFactories* gpu_factories); @@ -31,10 +31,12 @@ // Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while // this runs. - std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder( - const webrtc::SdpVideoFormat& format) override; + webrtc::VideoDecoder* CreateVideoDecoder( + webrtc::VideoCodecType type) override; - std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override; + // Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while + // this runs. + void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) override; private: media::GpuVideoAcceleratorFactories* gpu_factories_;
diff --git a/content/renderer/media/gpu/rtc_video_encoder.cc b/content/renderer/media/gpu/rtc_video_encoder.cc index f7e8366..8a2a2d3 100644 --- a/content/renderer/media/gpu/rtc_video_encoder.cc +++ b/content/renderer/media/gpu/rtc_video_encoder.cc
@@ -941,8 +941,4 @@ return true; } -const char* RTCVideoEncoder::ImplementationName() const { - return "RTCVideoEncoder"; -} - } // namespace content
diff --git a/content/renderer/media/gpu/rtc_video_encoder.h b/content/renderer/media/gpu/rtc_video_encoder.h index 155a3317..9612e025 100644 --- a/content/renderer/media/gpu/rtc_video_encoder.h +++ b/content/renderer/media/gpu/rtc_video_encoder.h
@@ -59,7 +59,6 @@ int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override; int32_t SetRates(uint32_t new_bit_rate, uint32_t frame_rate) override; bool SupportsNativeHandle() const override; - const char* ImplementationName() const override; private: class Impl;
diff --git a/content/renderer/media/gpu/rtc_video_encoder_factory.cc b/content/renderer/media/gpu/rtc_video_encoder_factory.cc index fc61ac2..152f7104 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_factory.cc +++ b/content/renderer/media/gpu/rtc_video_encoder_factory.cc
@@ -11,24 +11,23 @@ #include "content/renderer/media/gpu/rtc_video_encoder.h" #include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h" #include "media/video/gpu_video_accelerator_factories.h" -#include "third_party/webrtc/api/video_codecs/sdp_video_format.h" #include "third_party/webrtc/common_video/h264/profile_level_id.h" -#include "third_party/webrtc/media/base/codec.h" namespace content { namespace { // Translate from media::VideoEncodeAccelerator::SupportedProfile to -// webrtc::SdpVideoFormat, or return nothing if the profile isn't supported. -base::Optional<webrtc::SdpVideoFormat> VEAToWebRTCFormat( +// cricket::WebRtcVideoEncoderFactory::VideoCodec, or return nothing if the +// profile isn't supported. +base::Optional<cricket::VideoCodec> VEAToWebRTCCodec( const media::VideoEncodeAccelerator::SupportedProfile& profile) { DCHECK_EQ(profile.max_framerate_denominator, 1U); if (profile.profile >= media::VP8PROFILE_MIN && profile.profile <= media::VP8PROFILE_MAX) { if (base::FeatureList::IsEnabled(features::kWebRtcHWVP8Encoding)) { - return webrtc::SdpVideoFormat("VP8"); + return base::Optional<cricket::VideoCodec>(cricket::VideoCodec("VP8")); } } else if (profile.profile >= media::H264PROFILE_MIN && profile.profile <= media::H264PROFILE_MAX) { @@ -55,7 +54,7 @@ break; default: // Unsupported H264 profile in WebRTC. - return base::nullopt; + return base::Optional<cricket::VideoCodec>(); } const int width = profile.max_resolution.width(); @@ -68,22 +67,15 @@ const webrtc::H264::ProfileLevelId profile_level_id( h264_profile, h264_level.value_or(webrtc::H264::kLevel1)); - webrtc::SdpVideoFormat format("H264"); - format.parameters = { - {cricket::kH264FmtpProfileLevelId, - *webrtc::H264::ProfileLevelIdToString(profile_level_id)}, - {cricket::kH264FmtpLevelAsymmetryAllowed, "1"}, - {cricket::kH264FmtpPacketizationMode, "1"}}; - return format; + cricket::VideoCodec codec("H264"); + codec.SetParam(cricket::kH264FmtpProfileLevelId, + *webrtc::H264::ProfileLevelIdToString(profile_level_id)); + codec.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1"); + codec.SetParam(cricket::kH264FmtpPacketizationMode, "1"); + return base::Optional<cricket::VideoCodec>(codec); } } - return base::nullopt; -} - -bool IsSameFormat(const webrtc::SdpVideoFormat& format1, - const webrtc::SdpVideoFormat& format2) { - return cricket::IsSameCodec(format1.name, format2.parameters, format2.name, - format2.parameters); + return base::Optional<cricket::VideoCodec>(); } } // anonymous namespace @@ -94,45 +86,47 @@ const media::VideoEncodeAccelerator::SupportedProfiles& profiles = gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles(); for (const auto& profile : profiles) { - base::Optional<webrtc::SdpVideoFormat> format = VEAToWebRTCFormat(profile); - if (format) { - supported_formats_.push_back(std::move(*format)); + base::Optional<cricket::VideoCodec> codec = VEAToWebRTCCodec(profile); + if (codec) { + supported_codecs_.push_back(std::move(*codec)); profiles_.push_back(profile.profile); } } // There should be a 1:1 mapping between media::VideoCodecProfile and - // webrtc::SdpVideoFormat. - CHECK_EQ(profiles_.size(), supported_formats_.size()); + // cricket::VideoCodec. + CHECK_EQ(profiles_.size(), supported_codecs_.size()); } RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {} -std::unique_ptr<webrtc::VideoEncoder> -RTCVideoEncoderFactory::CreateVideoEncoder( - const webrtc::SdpVideoFormat& format) { - for (size_t i = 0; i < supported_formats_.size(); ++i) { - if (IsSameFormat(format, supported_formats_[i])) { - // There should be a 1:1 mapping between media::VideoCodecProfile and - // webrtc::SdpVideoFormat. - CHECK_EQ(profiles_.size(), supported_formats_.size()); - return base::MakeUnique<RTCVideoEncoder>(profiles_[i], gpu_factories_); +webrtc::VideoEncoder* RTCVideoEncoderFactory::CreateVideoEncoder( + const cricket::VideoCodec& codec) { + for (size_t i = 0; i < supported_codecs_.size(); ++i) { + if (!cricket::CodecNamesEq(codec.name, supported_codecs_[i].name)) + continue; + // Check H264 profile. + using webrtc::H264::ParseSdpProfileLevelId; + if (cricket::CodecNamesEq(codec.name.c_str(), cricket::kH264CodecName) && + ParseSdpProfileLevelId(codec.params)->profile != + ParseSdpProfileLevelId(supported_codecs_[i].params)->profile) { + continue; } + // There should be a 1:1 mapping between media::VideoCodecProfile and + // cricket::VideoCodec. + CHECK_EQ(profiles_.size(), supported_codecs_.size()); + return new RTCVideoEncoder(profiles_[i], gpu_factories_); } return nullptr; } -std::vector<webrtc::SdpVideoFormat> -RTCVideoEncoderFactory::GetSupportedFormats() const { - return supported_formats_; +const std::vector<cricket::VideoCodec>& +RTCVideoEncoderFactory::supported_codecs() const { + return supported_codecs_; } -webrtc::VideoEncoderFactory::CodecInfo -RTCVideoEncoderFactory::QueryVideoEncoder( - const webrtc::SdpVideoFormat& format) const { - CodecInfo info; - info.has_internal_source = false; - info.is_hardware_accelerated = true; - return info; +void RTCVideoEncoderFactory::DestroyVideoEncoder( + webrtc::VideoEncoder* encoder) { + delete encoder; } } // namespace content
diff --git a/content/renderer/media/gpu/rtc_video_encoder_factory.h b/content/renderer/media/gpu/rtc_video_encoder_factory.h index 904d82e..baf30df9 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_factory.h +++ b/content/renderer/media/gpu/rtc_video_encoder_factory.h
@@ -12,7 +12,7 @@ #include "base/memory/ref_counted.h" #include "content/common/content_export.h" #include "media/base/video_codecs.h" -#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h" +#include "third_party/webrtc/media/engine/webrtcvideoencoderfactory.h" namespace media { class GpuVideoAcceleratorFactories; @@ -23,27 +23,26 @@ // This class creates RTCVideoEncoder instances (each wrapping a // media::VideoEncodeAccelerator) on behalf of the WebRTC stack. class CONTENT_EXPORT RTCVideoEncoderFactory - : public webrtc::VideoEncoderFactory { + : public cricket::WebRtcVideoEncoderFactory { public: explicit RTCVideoEncoderFactory( media::GpuVideoAcceleratorFactories* gpu_factories); ~RTCVideoEncoderFactory() override; - // webrtc::VideoEncoderFactory implementation. - std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder( - const webrtc::SdpVideoFormat& format) override; - std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override; - webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder( - const webrtc::SdpVideoFormat& format) const override; + // cricket::WebRtcVideoEncoderFactory implementation. + webrtc::VideoEncoder* CreateVideoEncoder( + const cricket::VideoCodec& codec) override; + const std::vector<cricket::VideoCodec>& supported_codecs() const override; + void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override; private: media::GpuVideoAcceleratorFactories* gpu_factories_; - // List of supported webrtc::SdpVideoFormat. |profiles_| and - // |supported_formats_| have the same length and the profile for - // |supported_formats_[i]| is |profiles_[i]|. + // List of supported cricket::WebRtcVideoEncoderFactory::VideoCodec. + // |profiles_| and |supported_codecs_| have the same length and the profile + // for |supported_codecs_[i]| is |profiles_[i]|. std::vector<media::VideoCodecProfile> profiles_; - std::vector<webrtc::SdpVideoFormat> supported_formats_; + std::vector<cricket::VideoCodec> supported_codecs_; DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory); };
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc index d687fd4f..d8e343c 100644 --- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc +++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -31,12 +31,13 @@ #include "content/public/common/renderer_preferences.h" #include "content/public/common/webrtc_ip_handling_policy.h" #include "content/public/renderer/content_renderer_client.h" +#include "content/renderer/media/gpu/rtc_video_decoder_factory.h" +#include "content/renderer/media/gpu/rtc_video_encoder_factory.h" #include "content/renderer/media/media_stream_video_source.h" #include "content/renderer/media/media_stream_video_track.h" #include "content/renderer/media/rtc_peer_connection_handler.h" #include "content/renderer/media/webrtc/audio_codec_factory.h" #include "content/renderer/media/webrtc/stun_field_trial.h" -#include "content/renderer/media/webrtc/video_codec_factory.h" #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" #include "content/renderer/media/webrtc_audio_device_impl.h" #include "content/renderer/media/webrtc_logging.h" @@ -62,11 +63,18 @@ #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/webrtc/api/mediaconstraintsinterface.h" +#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h" +#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h" #include "third_party/webrtc/api/videosourceproxy.h" +#include "third_party/webrtc/media/engine/convert_legacy_video_factory.h" #include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h" #include "third_party/webrtc/rtc_base/refcountedobject.h" #include "third_party/webrtc/rtc_base/ssladapter.h" +#if defined(OS_ANDROID) +#include "media/base/android/media_codec_util.h" +#endif + namespace content { namespace { @@ -230,15 +238,35 @@ socket_factory_.reset( new IpcPacketSocketFactory(p2p_socket_dispatcher_.get())); - const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); + std::unique_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory; + std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory; + const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); + if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled()) { + if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding)) + decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories)); + + if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) { + encoder_factory.reset(new RTCVideoEncoderFactory(gpu_factories)); + } + } + +#if defined(OS_ANDROID) + if (!media::MediaCodecUtil::SupportsSetParameters()) + encoder_factory.reset(); +#endif + + // TODO(magjed): Update RTCVideoEncoderFactory/RTCVideoDecoderFactory to new + // interface and let Chromium be responsible in what order video codecs are + // listed, instead of using + // cricket::ConvertVideoEncoderFactory/cricket::ConvertVideoDecoderFactory. pc_factory_ = webrtc::CreatePeerConnectionFactory( worker_thread_ /* network thread */, worker_thread_, signaling_thread_, audio_device_.get(), CreateWebrtcAudioEncoderFactory(), CreateWebrtcAudioDecoderFactory(), - CreateWebrtcVideoEncoderFactory(gpu_factories), - CreateWebrtcVideoDecoderFactory(gpu_factories), nullptr /* audio_mixer */, - nullptr /* audio_processing */); + cricket::ConvertVideoEncoderFactory(std::move(encoder_factory)), + cricket::ConvertVideoDecoderFactory(std::move(decoder_factory)), + nullptr /* audio_mixer */, nullptr /* audio_processing */); CHECK(pc_factory_.get()); webrtc::PeerConnectionFactoryInterface::Options factory_options;
diff --git a/content/renderer/media/webrtc/video_codec_factory.cc b/content/renderer/media/webrtc/video_codec_factory.cc deleted file mode 100644 index 0c48ad2..0000000 --- a/content/renderer/media/webrtc/video_codec_factory.cc +++ /dev/null
@@ -1,201 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/video_codec_factory.h" - -#include "base/base_switches.h" -#include "base/command_line.h" -#include "base/memory/ptr_util.h" -#include "build/build_config.h" -#include "content/public/common/content_switches.h" -#include "content/renderer/media/gpu/rtc_video_decoder_factory.h" -#include "content/renderer/media/gpu/rtc_video_encoder_factory.h" -#include "third_party/webrtc/media/base/codec.h" -#include "third_party/webrtc/media/engine/internaldecoderfactory.h" -#include "third_party/webrtc/media/engine/internalencoderfactory.h" -#include "third_party/webrtc/media/engine/simulcast_encoder_adapter.h" -#include "third_party/webrtc/media/engine/videodecodersoftwarefallbackwrapper.h" -#include "third_party/webrtc/media/engine/videoencodersoftwarefallbackwrapper.h" -#include "third_party/webrtc/media/engine/vp8_encoder_simulcast_proxy.h" - -#if defined(OS_ANDROID) -#include "media/base/android/media_codec_util.h" -#endif - -namespace content { - -namespace { - -bool IsFormatSupported( - const std::vector<webrtc::SdpVideoFormat>& supported_formats, - const webrtc::SdpVideoFormat& format) { - for (const webrtc::SdpVideoFormat& supported_format : supported_formats) { - if (cricket::IsSameCodec(format.name, format.parameters, - supported_format.name, - supported_format.parameters)) { - return true; - } - } - return false; -} - -template <typename Factory> -bool IsFormatSupported(Factory* factory, const webrtc::SdpVideoFormat& format) { - return factory && IsFormatSupported(factory->GetSupportedFormats(), format); -} - -// Merge |formats1| and |formats2|, but avoid adding duplicate formats. -std::vector<webrtc::SdpVideoFormat> MergeFormats( - std::vector<webrtc::SdpVideoFormat> formats1, - std::vector<webrtc::SdpVideoFormat> formats2) { - for (const webrtc::SdpVideoFormat& format : formats2) { - // Don't add same format twice. - if (!IsFormatSupported(formats1, format)) - formats1.push_back(format); - } - return formats1; -} - -std::unique_ptr<webrtc::VideoDecoder> CreateDecoder( - webrtc::VideoDecoderFactory* factory, - const webrtc::SdpVideoFormat& format) { - return IsFormatSupported(factory, format) - ? factory->CreateVideoDecoder(format) - : nullptr; -} - -template <typename SoftwareWrapperClass, typename CoderClass> -std::unique_ptr<CoderClass> Wrap(std::unique_ptr<CoderClass> internal_coder, - std::unique_ptr<CoderClass> external_coder) { - if (internal_coder && external_coder) { - return base::MakeUnique<SoftwareWrapperClass>(std::move(internal_coder), - std::move(external_coder)); - } - return external_coder ? std::move(external_coder) : std::move(internal_coder); -} - -// This class combines an external factory with the internal factory and adds -// internal SW codecs, simulcast, and SW fallback wrappers. -class EncoderAdapter : public webrtc::VideoEncoderFactory { - public: - explicit EncoderAdapter( - std::unique_ptr<webrtc::VideoEncoderFactory> external_encoder_factory) - : external_encoder_factory_(std::move(external_encoder_factory)) {} - - webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder( - const webrtc::SdpVideoFormat& format) const override { - const webrtc::VideoEncoderFactory* factory = - IsFormatSupported(external_encoder_factory_.get(), format) - ? external_encoder_factory_.get() - : &internal_encoder_factory_; - return factory->QueryVideoEncoder(format); - } - - std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder( - const webrtc::SdpVideoFormat& format) override { - std::unique_ptr<webrtc::VideoEncoder> internal_encoder; - if (IsFormatSupported(internal_encoder_factory_.GetSupportedFormats(), - format)) { - internal_encoder = - cricket::CodecNamesEq(format.name.c_str(), cricket::kVp8CodecName) - ? base::MakeUnique<webrtc::VP8EncoderSimulcastProxy>( - &internal_encoder_factory_) - : internal_encoder_factory_.CreateVideoEncoder(format); - } - - std::unique_ptr<webrtc::VideoEncoder> external_encoder; - if (IsFormatSupported(external_encoder_factory_.get(), format)) { - external_encoder = - cricket::CodecNamesEq(format.name.c_str(), cricket::kVp8CodecName) - ? base::MakeUnique<webrtc::SimulcastEncoderAdapter>( - external_encoder_factory_.get()) - : external_encoder_factory_->CreateVideoEncoder(format); - } - - return Wrap<webrtc::VideoEncoderSoftwareFallbackWrapper>( - std::move(internal_encoder), std::move(external_encoder)); - } - - std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override { - std::vector<webrtc::SdpVideoFormat> internal_formats = - internal_encoder_factory_.GetSupportedFormats(); - return external_encoder_factory_ - ? MergeFormats(internal_formats, - external_encoder_factory_->GetSupportedFormats()) - : internal_formats; - } - - private: - webrtc::InternalEncoderFactory internal_encoder_factory_; - const std::unique_ptr<webrtc::VideoEncoderFactory> external_encoder_factory_; -}; - -// This class combines an external factory with the internal factory and adds -// internal SW codecs and SW fallback wrappers. -class DecoderAdapter : public webrtc::VideoDecoderFactory { - public: - explicit DecoderAdapter( - std::unique_ptr<webrtc::VideoDecoderFactory> external_decoder_factory) - : external_decoder_factory_(std::move(external_decoder_factory)) {} - - std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder( - const webrtc::SdpVideoFormat& format) override { - std::unique_ptr<webrtc::VideoDecoder> internal_decoder = - CreateDecoder(&internal_decoder_factory_, format); - - std::unique_ptr<webrtc::VideoDecoder> external_decoder = - CreateDecoder(external_decoder_factory_.get(), format); - - return Wrap<webrtc::VideoDecoderSoftwareFallbackWrapper>( - std::move(internal_decoder), std::move(external_decoder)); - } - - std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override { - std::vector<webrtc::SdpVideoFormat> internal_formats = - internal_decoder_factory_.GetSupportedFormats(); - return external_decoder_factory_ - ? MergeFormats(internal_formats, - external_decoder_factory_->GetSupportedFormats()) - : internal_formats; - } - - private: - webrtc::InternalDecoderFactory internal_decoder_factory_; - const std::unique_ptr<webrtc::VideoDecoderFactory> external_decoder_factory_; -}; - -} // namespace - -std::unique_ptr<webrtc::VideoEncoderFactory> CreateWebrtcVideoEncoderFactory( - media::GpuVideoAcceleratorFactories* gpu_factories) { - std::unique_ptr<webrtc::VideoEncoderFactory> encoder_factory; - - const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() && - !cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) { - encoder_factory.reset(new RTCVideoEncoderFactory(gpu_factories)); - } - -#if defined(OS_ANDROID) - if (!media::MediaCodecUtil::SupportsSetParameters()) - encoder_factory.reset(); -#endif - - return base::MakeUnique<EncoderAdapter>(std::move(encoder_factory)); -} - -std::unique_ptr<webrtc::VideoDecoderFactory> CreateWebrtcVideoDecoderFactory( - media::GpuVideoAcceleratorFactories* gpu_factories) { - std::unique_ptr<webrtc::VideoDecoderFactory> decoder_factory; - - const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() && - !cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding)) { - decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories)); - } - - return base::MakeUnique<DecoderAdapter>(std::move(decoder_factory)); -} - -} // namespace content
diff --git a/content/renderer/media/webrtc/video_codec_factory.h b/content/renderer/media/webrtc/video_codec_factory.h deleted file mode 100644 index 2935358..0000000 --- a/content/renderer/media/webrtc/video_codec_factory.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_VIDEO_CODEC_FACTORY_H_ -#define CONTENT_RENDERER_MEDIA_WEBRTC_VIDEO_CODEC_FACTORY_H_ - -#include "media/video/gpu_video_accelerator_factories.h" -#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h" -#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h" - -namespace content { - -std::unique_ptr<webrtc::VideoEncoderFactory> CreateWebrtcVideoEncoderFactory( - media::GpuVideoAcceleratorFactories* gpu_factories); -std::unique_ptr<webrtc::VideoDecoderFactory> CreateWebrtcVideoDecoderFactory( - media::GpuVideoAcceleratorFactories* gpu_factories); - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBRTC_VIDEO_CODEC_FACTORY_H_
diff --git a/device/u2f/OWNERS b/device/u2f/OWNERS new file mode 100644 index 0000000..bf052cb --- /dev/null +++ b/device/u2f/OWNERS
@@ -0,0 +1,3 @@ +jdoerrie@chromium.org + +# COMPONENT: Blink>WebAuthentication
diff --git a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html similarity index 94% rename from third_party/WebKit/LayoutTests/media/track/opera/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html rename to third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html index fa39685..e29f2b0 100644 --- a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html
@@ -1,7 +1,7 @@ <!doctype html> <title>HTMLMediaElement.crossOrigin</title> -<script src=../../../../../../resources/testharness.js></script> -<script src=../../../../../../resources/testharnessreport.js></script> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> <div id=log></div> <script> test(function(){
diff --git a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html b/third_party/WebKit/LayoutTests/media/track/opera/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html deleted file mode 100644 index 6893212a..0000000 --- a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html +++ /dev/null
@@ -1,107 +0,0 @@ -<!doctype html> -<title>HTMLMediaElement.addTextTrack</title> -<script src=../../../../../../resources/testharness.js></script> -<script src=../../../../../../resources/testharnessreport.js></script> -<div id=log></div> -<script> -var video = document.createElement('video'); -test(function(){ - assert_throws(new TypeError, function(){ - video.addTextTrack('foo'); - }); - assert_throws(new TypeError, function(){ - video.addTextTrack(undefined); - }); - assert_throws(new TypeError, function(){ - video.addTextTrack(null); - }); -}, document.title + ' bogus first arg'); - -test(function(){ - assert_throws(new TypeError, function(){ - video.addTextTrack('SUBTITLES'); - }); -}, document.title + ' uppercase first arg'); - -test(function(){ - var t = video.addTextTrack('subtitles'); - assert_equals(t.kind, 'subtitles'); - assert_equals(t.label, ''); - assert_equals(t.language, ''); - assert_equals(t.mode, 'hidden'); - assert_equals(t.cues.length, 0); -}, document.title + ' subtitles first arg'); - -test(function(){ - var t = video.addTextTrack('captions'); - assert_equals(t.kind, 'captions'); - assert_equals(t.label, ''); - assert_equals(t.language, ''); - assert_equals(t.mode, 'hidden'); - assert_equals(t.cues.length, 0); -}, document.title + ' captions first arg'); - -test(function(){ - var t = video.addTextTrack('descriptions'); - assert_equals(t.kind, 'descriptions'); - assert_equals(t.label, ''); - assert_equals(t.language, ''); - assert_equals(t.mode, 'hidden'); - assert_equals(t.cues.length, 0); -}, document.title + ' descriptions first arg'); - -test(function(){ - var t = video.addTextTrack('chapters'); - assert_equals(t.kind, 'chapters'); - assert_equals(t.label, ''); - assert_equals(t.language, ''); - assert_equals(t.mode, 'hidden'); - assert_equals(t.cues.length, 0); -}, document.title + ' chapters first arg'); - -test(function(){ - var t = video.addTextTrack('metadata'); - assert_equals(t.kind, 'metadata'); - assert_equals(t.label, ''); - assert_equals(t.language, ''); - assert_equals(t.mode, 'hidden'); - assert_equals(t.cues.length, 0); -}, document.title + ' metadata first arg'); - -test(function(){ - var t = video.addTextTrack('subtitles', undefined, undefined); - assert_equals(t.kind, 'subtitles'); - assert_equals(t.label, ''); - assert_equals(t.language, ''); - assert_equals(t.mode, 'hidden'); - assert_equals(t.cues.length, 0); -}, document.title + ' undefined second and third arg'); - -test(function(){ - var t = video.addTextTrack('subtitles', null, null); - assert_equals(t.kind, 'subtitles'); - assert_equals(t.label, 'null'); - assert_equals(t.language, 'null'); - assert_equals(t.mode, 'hidden'); - assert_equals(t.cues.length, 0); -}, document.title + ' null second and third arg'); - -test(function(){ - var t = video.addTextTrack('subtitles', 'foo', 'bar'); - assert_equals(t.kind, 'subtitles'); - assert_equals(t.label, 'foo'); - assert_equals(t.language, 'bar'); - assert_equals(t.mode, 'hidden'); - assert_equals(t.cues.length, 0); -}, document.title + ' foo and bar second and third arg'); - -test(function(){ - var t = video.addTextTrack('subtitles', 'foo'); - assert_equals(t.kind, 'subtitles'); - assert_equals(t.label, 'foo'); - assert_equals(t.language, ''); - assert_equals(t.mode, 'hidden'); - assert_equals(t.cues.length, 0); -}, document.title + ' foo second arg, third arg omitted'); - -</script>
diff --git a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/HTMLElement/HTMLMediaElement/textTracks.html b/third_party/WebKit/LayoutTests/media/track/opera/interfaces/HTMLElement/HTMLMediaElement/textTracks.html deleted file mode 100644 index c63d2f8..0000000 --- a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/HTMLElement/HTMLMediaElement/textTracks.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!doctype html> -<title>HTMLMediaElement.textTracks</title> -<script src=../../../../../../resources/testharness.js></script> -<script src=../../../../../../resources/testharnessreport.js></script> -<div id=log></div> -<script> -var video = document.createElement('video'); -test(function(){ - assert_equals(video.textTracks, video.textTracks); - assert_equals(video.textTracks.length, 0); -}); - -</script> \ No newline at end of file