diff --git a/DEPS b/DEPS index 4961c73b..c08423d 100644 --- a/DEPS +++ b/DEPS
@@ -39,7 +39,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '14184d5567b58085b6d8a6375796d405056f7f73', + 'skia_revision': '43f610f693d6d5db115d68ecde8e3fd52e725c6a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS index d28a6a2c..80348f5 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -275,10 +275,6 @@ 'filepath': 'net/cookies/|'\ 'chrome/browser/net/sqlite_persistent_cookie_store', }, - 'custom_handlers': { - 'filepath': 'chrome/browser/custom_handlers/|'\ - 'chrome/common/custom_handlers/', - }, 'custom_tabs': { 'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/customtabs/|'\ 'chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/', @@ -440,6 +436,9 @@ 'filepath': '_message.*.h|'\ '_messages.cc', }, + 'login': { + 'filepath': 'chrome/browser/ui/login' + }, 'libwebp': { 'filepath': 'third_party/libwebp' }, @@ -1244,7 +1243,8 @@ 'autofill': ['bondd+autofillwatch@chromium.org', 'estade+watch@chromium.org', 'jdonnelly+autofillwatch@chromium.org', - 'rouslan+autofill@chromium.org'], + 'rouslan+autofill@chromium.org', + 'vabr+watchlistautofill@chromium.org'], 'automation': ['robertshield@chromium.org'], 'background_sync': ['jkarlin+watch@chromium.org'], 'base': ['vmpstr+watch@chromium.org'], @@ -1316,7 +1316,6 @@ 'peter@chromium.org'], 'content_worker': ['blink-worker-reviews@chromium.org', 'kinuko+watch@chromium.org'], - 'custom_handlers': ['vabr+watchlist@chromium.org'], 'deep_memory_profiler': ['dmikurube@chromium.org'], 'device_bluetooth': ['scheib+watch@chromium.org'], 'device_sensors': ['timvolodine@chromium.org', @@ -1365,6 +1364,7 @@ 'jfweitz+watch@chromium.org', 'skanuj+watch@chromium.org'], 'ios_chrome': ['sdefresne+watch@chromium.org'], 'ipc': ['jam@chromium.org', 'darin-cc@chromium.org'], + 'login': ['vabr+watchlistlogin@chromium.org'], 'libwebp': ['urvang@chromium.org', 'jzern@chromium.org', 'skal@google.com', 'vikasa@google.com'], 'libvpx': ['tomfinegan@chromium.org', 'jzern@chromium.org', @@ -1420,7 +1420,7 @@ 'dcheng@chromium.org', 'jianli@chromium.org'], 'password_manager': ['mkwst+watchlist-passwords@chromium.org', 'gcasto+watchlist@chromium.org', - 'vabr+watchlist@chromium.org'], + 'vabr+watchlistpasswordmanager@chromium.org'], 'pepper_api': ['bradnelson+warch@chromium.org', 'piman+watch@chromium.org', 'ihf+watch@chromium.org', 'yusukes+watch@chromium.org', 'binji+watch@chromium.org',
diff --git a/android_webview/android_webview_tests.gypi b/android_webview/android_webview_tests.gypi index 14c90ca..a5af244 100644 --- a/android_webview/android_webview_tests.gypi +++ b/android_webview/android_webview_tests.gypi
@@ -11,6 +11,8 @@ 'android_webview_java', 'android_webview_pak', 'libdrawgl', + '../base/base.gyp:base_java_test_support', + '../components/components.gyp:policy_java_test_support' ], 'variables': { 'apk_name': 'AndroidWebView', @@ -96,6 +98,7 @@ 'type': 'none', 'dependencies': [ '../base/base.gyp:base_java_test_support', + '../components/components.gyp:policy_java_test_support', '../content/content_shell_and_tests.gyp:content_java_test_support', '../net/net.gyp:net_java_test_support', '../testing/android/on_device_instrumentation.gyp:broker_java',
diff --git a/android_webview/javatests/AndroidManifest.xml b/android_webview/javatests/AndroidManifest.xml index fb3db24..ed0ae66f 100644 --- a/android_webview/javatests/AndroidManifest.xml +++ b/android_webview/javatests/AndroidManifest.xml
@@ -5,7 +5,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.chromium.android_webview.test"> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" /> - <instrumentation android:name="org.chromium.base.test.BaseInstrumentationTestRunner" + <instrumentation android:name="org.chromium.android_webview.test.AwInstrumentationTestRunner" android:targetPackage="org.chromium.android_webview.shell" android:label="Tests for org.chromium.android_webview"/> <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
diff --git a/android_webview/javatests/DEPS b/android_webview/javatests/DEPS index e2a33b1f..24ccfae 100644 --- a/android_webview/javatests/DEPS +++ b/android_webview/javatests/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+components/external_video_surface/android/java", "+components/policy/android/java", + "+components/policy/android/javatests", "+content/public/android/java", "+content/public/test/android/javatests", ]
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java index 7c2629e..32bdae7 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java
@@ -4,10 +4,8 @@ package org.chromium.android_webview.test; -import android.os.Bundle; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; -import android.text.TextUtils; import android.util.Pair; import org.chromium.android_webview.AwContents; @@ -17,9 +15,13 @@ import org.chromium.base.test.util.Feature; import org.chromium.content.browser.test.util.TestCallbackHelperContainer; import org.chromium.net.test.util.TestWebServer; +import org.chromium.policy.AbstractAppRestrictionsProvider; import org.chromium.policy.CombinedPolicyProvider; +import org.chromium.policy.test.PolicyData; +import org.chromium.policy.test.annotations.Policies; import java.util.ArrayList; +import java.util.Arrays; /** Tests for the policy based URL filtering. */ public class PolicyUrlFilteringTest extends AwTestBase { @@ -28,7 +30,8 @@ private TestWebServer mWebServer; private String mFooTestUrl; private String mBarTestUrl; - private AwPolicyProvider mTestProvider; + private static final String sFooTestFilePath = "/foo.html"; + private static final String sFooWhitelistFilter = "localhost" + sFooTestFilePath; private static final String sBlacklistPolicyName = "com.android.browser:URLBlacklist"; private static final String sWhitelistPolicyName = "com.android.browser:URLWhitelist"; @@ -36,21 +39,14 @@ @Override public void setUp() throws Exception { super.setUp(); - setTestAwContentsClient(new TestAwContentsClient()); + mContentsClient = new TestAwContentsClient(); + mAwContents = createAwTestContainerViewOnMainSync(mContentsClient).getAwContents(); mWebServer = TestWebServer.start(); - mFooTestUrl = mWebServer.setResponse("/foo.html", "<html><body>foo</body></html>", + mFooTestUrl = mWebServer.setResponse(sFooTestFilePath, "<html><body>foo</body></html>", new ArrayList<Pair<String, String>>()); mBarTestUrl = mWebServer.setResponse("/bar.html", "<html><body>bar</body></html>", new ArrayList<Pair<String, String>>()); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mTestProvider = new AwPolicyProvider(getActivity().getApplicationContext()); - CombinedPolicyProvider.get().registerProvider(mTestProvider); - } - }); - getInstrumentation().waitForIdleSync(); } @@ -60,97 +56,83 @@ super.tearDown(); } - private void setTestAwContentsClient(TestAwContentsClient contentsClient) throws Exception { - mContentsClient = contentsClient; - final AwTestContainerView testContainerView = - createAwTestContainerViewOnMainSync(mContentsClient); - mAwContents = testContainerView.getAwContents(); - } - // Tests transforming the bundle to native policies, reloading the policies and blocking // the navigation. @MediumTest @Feature({"AndroidWebView", "Policy"}) public void testBlacklistedUrl() throws Throwable { - TestCallbackHelperContainer.OnReceivedErrorHelper onReceivedErrorHelper = - mContentsClient.getOnReceivedErrorHelper(); - TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = - mContentsClient.getOnPageFinishedHelper(); + final AwPolicyProvider testProvider = + new AwPolicyProvider(getActivity().getApplicationContext()); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + CombinedPolicyProvider.get().registerProvider(testProvider); + } + }); - loadUrlSync(mAwContents, onPageFinishedHelper, mFooTestUrl); - assertEquals(mFooTestUrl, onPageFinishedHelper.getUrl()); - assertEquals(0, onReceivedErrorHelper.getCallCount()); + navigateAndCheckOutcome(mFooTestUrl, 0); - setFilteringPolicy(new String[] {"localhost"}, new String[] {}); + setFilteringPolicy(testProvider, new String[] {"localhost"}, new String[] {}); - loadUrlSync(mAwContents, onPageFinishedHelper, mFooTestUrl); - assertEquals(mFooTestUrl, onPageFinishedHelper.getUrl()); - assertEquals(1, onReceivedErrorHelper.getCallCount()); - assertEquals(ErrorCodeConversionHelper.ERROR_CONNECT, onReceivedErrorHelper.getErrorCode()); + navigateAndCheckOutcome(mFooTestUrl, 1); + assertEquals(ErrorCodeConversionHelper.ERROR_CONNECT, + mContentsClient.getOnReceivedErrorHelper().getErrorCode()); } - // Tests transforming the bundle to native policies, reloading the policies and getting a - // successful navigation with a whitelist. + // Tests getting a successful navigation with a whitelist. @MediumTest @Feature({"AndroidWebView", "Policy"}) + @Policies.Add({ + @Policies.Item(key = sBlacklistPolicyName, stringArray = {"*"}), + @Policies.Item(key = sWhitelistPolicyName, stringArray = {sFooWhitelistFilter})}) public void testWhitelistedUrl() throws Throwable { - TestCallbackHelperContainer.OnReceivedErrorHelper onReceivedErrorHelper = - mContentsClient.getOnReceivedErrorHelper(); - TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = - mContentsClient.getOnPageFinishedHelper(); - setFilteringPolicy(new String[] {"*"}, new String[] {mFooTestUrl}); - - loadUrlSync(mAwContents, onPageFinishedHelper, mFooTestUrl); - assertEquals(mFooTestUrl, onPageFinishedHelper.getUrl()); - assertEquals(0, onReceivedErrorHelper.getCallCount()); + navigateAndCheckOutcome(mFooTestUrl, 0); // Make sure it goes through the blacklist - loadUrlSync(mAwContents, onPageFinishedHelper, mBarTestUrl); - assertEquals(mBarTestUrl, onPageFinishedHelper.getUrl()); - assertEquals(1, onReceivedErrorHelper.getCallCount()); - assertEquals(ErrorCodeConversionHelper.ERROR_CONNECT, onReceivedErrorHelper.getErrorCode()); + navigateAndCheckOutcome(mBarTestUrl, 1); + assertEquals(ErrorCodeConversionHelper.ERROR_CONNECT, + mContentsClient.getOnReceivedErrorHelper().getErrorCode()); } // Tests that bad policy values are properly handled @SmallTest @Feature({"AndroidWebView", "Policy"}) + @Policies.Add({ + @Policies.Item(key = sBlacklistPolicyName, string = "shouldBeAJsonArrayNotAString")}) public void testBadPolicyValue() throws Exception { - final Bundle newPolicies = new Bundle(); - newPolicies.putString(sBlacklistPolicyName, "shouldBeAJsonArrayNotAString"); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mTestProvider.notifySettingsAvailable(newPolicies); - } - }); - getInstrumentation().waitForIdleSync(); - - TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = - mContentsClient.getOnPageFinishedHelper(); - loadUrlSync(mAwContents, onPageFinishedHelper, mFooTestUrl); - + navigateAndCheckOutcome(mFooTestUrl, 0); // At the moment this test is written, a failure is a crash, a success is no crash. } - private void setFilteringPolicy(final String[] blacklistUrls, final String[] whitelistUrls) { - final Bundle newPolicies = new Bundle(); + /** + * Synchronously loads the provided URL and checks that the number or reported errors for the + * current context is the expected one. + */ + private void navigateAndCheckOutcome(String url, int expectedErrorCount) throws Exception { + TestCallbackHelperContainer.OnReceivedErrorHelper onReceivedErrorHelper = + mContentsClient.getOnReceivedErrorHelper(); + TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = + mContentsClient.getOnPageFinishedHelper(); - if (blacklistUrls != null && blacklistUrls.length > 0) { - String blacklistString = - String.format("[\"%s\"]", TextUtils.join("\",\"", blacklistUrls)); - newPolicies.putString(sBlacklistPolicyName, blacklistString); - } + loadUrlSync(mAwContents, onPageFinishedHelper, url); + assertEquals(url, onPageFinishedHelper.getUrl()); + assertEquals(expectedErrorCount, onReceivedErrorHelper.getCallCount()); + } - if (whitelistUrls != null && whitelistUrls.length > 0) { - String whitelistString = - String.format("[\"%s\"]", TextUtils.join("\",\"", whitelistUrls)); - newPolicies.putString(sWhitelistPolicyName, whitelistString); - } + private void setFilteringPolicy(final AwPolicyProvider testProvider, + final String[] blacklistUrls, final String[] whitelistUrls) { + final PolicyData[] policies = { + new PolicyData.StrArray(sBlacklistPolicyName, blacklistUrls), + new PolicyData.StrArray(sWhitelistPolicyName, whitelistUrls) + }; + + AbstractAppRestrictionsProvider.setTestRestrictions( + PolicyData.asBundle(Arrays.asList(policies))); ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mTestProvider.notifySettingsAvailable(newPolicies); + testProvider.refresh(); } });
diff --git a/android_webview/test/shell/DEPS b/android_webview/test/shell/DEPS index 0d019e1..2a76d5bd 100644 --- a/android_webview/test/shell/DEPS +++ b/android_webview/test/shell/DEPS
@@ -1,3 +1,4 @@ include_rules = [ + "+components/policy/android/javatests", "+content/public/android/java", ]
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java new file mode 100644 index 0000000..84f9ceb --- /dev/null +++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java
@@ -0,0 +1,22 @@ +// Copyright 2015 The Chromium 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.android_webview.test; + +import org.chromium.base.test.BaseInstrumentationTestRunner; +import org.chromium.base.test.BaseTestResult; +import org.chromium.policy.test.annotations.Policies; + +/** + * Instrumentation test runner that allows integrating features defined above base layer + * for webview testing. + */ +public class AwInstrumentationTestRunner extends BaseInstrumentationTestRunner { + @Override + protected void addTestHooks(BaseTestResult result) { + super.addTestHooks(result); + + result.addPreTestHook(Policies.getRegistrationHook()); + } +}
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index 3fad91e..8b61bca 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -237,7 +237,7 @@ // Determine where the library should be loaded from. String zipFilePath = null; String libFilePath = System.mapLibraryName(library); - if (linker.isInZipFile()) { + if (Linker.isInZipFile()) { // Load directly from the APK. zipFilePath = getLibraryApkPath(context); Log.i(TAG, "Loading " + library + " from within " + zipFilePath);
diff --git a/base/test/launcher/test_results_tracker.cc b/base/test/launcher/test_results_tracker.cc index 3c7faa32..b766fa6 100644 --- a/base/test/launcher/test_results_tracker.cc +++ b/base/test/launcher/test_results_tracker.cc
@@ -145,8 +145,7 @@ // to compare with regular test names, e.g. before or after disabling. all_tests_.insert(TestNameWithoutDisabledPrefix(test_name)); - test_locations_.insert(std::make_pair( - TestNameWithoutDisabledPrefix(test_name), CodeLocation(file, line))); + test_locations_.insert(std::make_pair(test_name, CodeLocation(file, line))); } void TestResultsTracker::AddDisabledTest(const std::string& test_name) {
diff --git a/build/android/play_services/config.json b/build/android/play_services/config.json index df669e92..f4f9c6e 100644 --- a/build/android/play_services/config.json +++ b/build/android/play_services/config.json
@@ -1,3 +1,3 @@ { - "version_number": 8115000 + "version_number": 8298000 }
diff --git a/build/android/play_services/google_play_services_library.zip.sha1 b/build/android/play_services/google_play_services_library.zip.sha1 index d6178e7b..113d55a 100644 --- a/build/android/play_services/google_play_services_library.zip.sha1 +++ b/build/android/play_services/google_play_services_library.zip.sha1
@@ -1 +1 @@ -d21c06dd47dfa502ce0d9ef9f466ef79a32dc833 \ No newline at end of file +07308d03b3a83f2985c52e5cfe2764220e19e223 \ No newline at end of file
diff --git a/chrome/android/java/res/layout/data_use_dialog.xml b/chrome/android/java/res/layout/data_use_dialog.xml index cfc6e17ec..63662c8 100644 --- a/chrome/android/java/res/layout/data_use_dialog.xml +++ b/chrome/android/java/res/layout/data_use_dialog.xml
@@ -3,16 +3,40 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" android:layout_width="match_parent" - android:paddingStart="18dp" - android:paddingTop="8dp" > + android:orientation="vertical" + android:paddingBottom="16dp" + android:paddingStart="16dp" + android:paddingTop="16dp" > + + <TextView + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginBottom="16dp" + android:layout_marginStart="8dp" + android:text="@string/data_use_tracking_ended_message" + android:textColor="@color/light_normal_color" + android:textSize="16sp" /> + + <TextView + android:id="@+id/learn_more" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:clickable="true" + android:layout_marginBottom="16dp" + android:layout_marginStart="8dp" + android:text="@string/learn_more" + android:textColor="@color/light_active_color" + android:textSize="16sp" /> <CheckBox android:id="@+id/data_use_checkbox" android:layout_height="wrap_content" - android:layout_width="match_parent" - android:text="@string/data_use_tracking_ended_checkbox_message" /> + android:layout_width="match_parent" + android:text="@string/data_use_tracking_ended_checkbox_message" + android:textColor="@color/light_normal_color" + android:textSize="16sp" /> -</FrameLayout> \ No newline at end of file +</LinearLayout> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/website_settings.xml b/chrome/android/java/res/layout/website_settings.xml index 4a7ecd3..9cc5ee339 100644 --- a/chrome/android/java/res/layout/website_settings.xml +++ b/chrome/android/java/res/layout/website_settings.xml
@@ -20,7 +20,7 @@ android:paddingEnd="@dimen/website_settings_popup_padding_sides" android:paddingStart="@dimen/website_settings_popup_padding_sides" > - <view class="org.chromium.chrome.browser.WebsiteSettingsPopup$ElidedUrlTextView" + <view class="org.chromium.chrome.browser.pageinfo.WebsiteSettingsPopup$ElidedUrlTextView" android:id="@+id/website_settings_url" android:layout_width="match_parent" android:layout_height="wrap_content"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java index 0e5c2d9..fc158b5e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -23,8 +23,6 @@ private static final String ENABLED_PARAM = "enabled"; private static final String ENABLED_VALUE = "true"; - static final String PROMO_ON_LIMITED_TAPS = "promo_on_limited_taps"; - static final String TAP_TRIGGERED_PROMO_LIMIT = "tap_triggered_promo_limit"; static final String PEEK_PROMO_FORCED = "peek_promo_forced"; static final String PEEK_PROMO_ENABLED = "peek_promo_enabled"; static final String PEEK_PROMO_MAX_SHOW_COUNT = "peek_promo_max_show_count"; @@ -36,9 +34,6 @@ @VisibleForTesting static final String TRANSLATION_ONEBOX_ENABLED = "translation_onebox_enabled"; - // Tap handling. - private static final int UNLIMITED_TAPS = -1; - // Cached values to avoid repeated and redundant JNI operations. private static Boolean sEnabled; private static Boolean sIsPeekPromoEnabled; @@ -96,19 +91,6 @@ } /** - * @return Whether the promo should be triggered by a limited number of taps. - */ - public static boolean isPromoLimitedByTapCounts() { - return getBooleanParam(PROMO_ON_LIMITED_TAPS); - } - - /** - * @return The maximum number of times the promo can be triggered by a tap, or - * {@code ContextualSearchUma#PROMO_TAPS_REMAINING_INVALID} if no value is present in the finch - * configuration. - */ - static int getPromoTapTriggeredLimit() { - return getIntParamValueOrDefault(TAP_TRIGGERED_PROMO_LIMIT, UNLIMITED_TAPS); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java index db237a37..5625c2c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -30,6 +30,7 @@ private static final Pattern CONTAINS_WHITESPACE_PATTERN = Pattern.compile("\\s"); private static final int REMAINING_NOT_APPLICABLE = -1; private static final int ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1000; + private static final int TAP_TRIGGERED_PROMO_LIMIT = 50; private static final int TAP_RESOLVE_LIMIT_FOR_DECIDED = 50; private static final int TAP_PREFETCH_LIMIT_FOR_DECIDED = 50; private static final int TAP_RESOLVE_LIMIT_FOR_UNDECIDED = 20; @@ -43,6 +44,7 @@ private boolean mDidOverrideDecidedStateForTesting; private boolean mDecidedStateForTesting; private boolean mDidResetCounters; + private Integer mTapTriggeredPromoLimitForTesting; private Integer mTapResolveLimitForDecided; private Integer mTapPrefetchLimitForDecided; private Integer mTapResolveLimitForUndecided; @@ -78,13 +80,20 @@ // Return a non-negative value if opt-out promo counter is enabled, and there's a limit. DisableablePromoTapCounter counter = getPromoTapCounter(); if (counter.isEnabled()) { - int limit = ContextualSearchFieldTrial.getPromoTapTriggeredLimit(); + int limit = getPromoTapTriggeredLimit(); if (limit >= 0) return Math.max(0, limit - counter.getCount()); } return REMAINING_NOT_APPLICABLE; } + private int getPromoTapTriggeredLimit() { + if (mTapTriggeredPromoLimitForTesting != null) { + return mTapTriggeredPromoLimitForTesting.intValue(); + } + return TAP_TRIGGERED_PROMO_LIMIT; + } + /** * @return the {@link DisableablePromoTapCounter}. */ @@ -97,8 +106,7 @@ */ boolean isTapSupported() { if (!isUserUndecided()) return true; - return !ContextualSearchFieldTrial.isPromoLimitedByTapCounts() - || getPromoTapsRemaining() != 0; + return getPromoTapsRemaining() != 0; } /** @@ -437,6 +445,14 @@ return ContextualSearchFieldTrial.isTranslationOneboxEnabled(); } + /** + * Sets the limit for the tap triggered promo. + */ + @VisibleForTesting + void setPromoTapTriggeredLimitForTesting(int limit) { + mTapTriggeredPromoLimitForTesting = limit; + } + @VisibleForTesting void setTapResolveLimitForDecidedForTesting(int limit) { mTapResolveLimitForDecided = limit;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datausage/DataUseTabUIManager.java b/chrome/android/java/src/org/chromium/chrome/browser/datausage/DataUseTabUIManager.java index 035a992..bfe8427 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/datausage/DataUseTabUIManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/datausage/DataUseTabUIManager.java
@@ -15,6 +15,7 @@ import android.widget.CheckBox; import org.chromium.chrome.R; +import org.chromium.chrome.browser.EmbedContentViewActivity; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.sessions.SessionTabHelper; import org.chromium.chrome.browser.tab.Tab; @@ -100,12 +101,19 @@ */ private static void startDataUseDialog(final Activity activity, final Tab tab, final String url, final int pageTransitionType, final String referrerUrl) { - View checkBoxView = View.inflate(activity, R.layout.data_use_dialog, null); - final CheckBox checkBox = (CheckBox) checkBoxView.findViewById(R.id.data_use_checkbox); + View dataUseDialogView = View.inflate(activity, R.layout.data_use_dialog, null); + final CheckBox checkBox = (CheckBox) dataUseDialogView.findViewById(R.id.data_use_checkbox); + View learnMore = dataUseDialogView.findViewById(R.id.learn_more); + learnMore.setOnClickListener(new android.view.View.OnClickListener() { + @Override + public void onClick(View v) { + EmbedContentViewActivity.show(activity, R.string.data_use_learn_more_title, + R.string.data_use_learn_more_link_url); + } + }); new AlertDialog.Builder(activity, R.style.AlertDialogTheme) .setTitle(R.string.data_use_tracking_ended_title) - .setMessage(R.string.data_use_tracking_ended_message) - .setView(checkBoxView) + .setView(dataUseDialogView) .setPositiveButton(R.string.data_use_tracking_ended_continue, new OnClickListener() { @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java index b6a71ccc2..f2f50a4f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java
@@ -114,9 +114,6 @@ } } - private static final int ROW_MAIN = 1; - private static final int ROW_OTHER = 2; - private final int mMargin; private final int mIconSize; private final int mMinWidth; @@ -414,48 +411,26 @@ placeChild(mCloseButton, Gravity.END); placeGroup(mMainGroup); - int customGroupWidth = 0; if (mCustomGroup != null) { - updateCustomGroupForRow(ROW_MAIN); - customGroupWidth = getWidthWithMargins(mCustomGroup); - } - - int buttonGroupWidth = 0; - if (mButtonGroup != null) { - updateButtonGroupForRow(ROW_MAIN); - buttonGroupWidth = getWidthWithMargins(mButtonGroup); - } - - boolean customGroupOnMainRow = customGroupWidth <= availableWidth(); - boolean buttonGroupOnMainRow = customGroupWidth + buttonGroupWidth <= availableWidth(); - - if (mCustomGroup != null) { - if (customGroupOnMainRow) { - mCustomGroup.gravity = (mButtonGroup != null && buttonGroupOnMainRow) - ? Gravity.START : Gravity.END; - } else { - startRow(); - updateCustomGroupForRow(ROW_OTHER); - } + startRow(); + updateCustomGroupLayoutProperties(); placeGroup(mCustomGroup); } if (mButtonGroup != null) { - if (!buttonGroupOnMainRow) { - startRow(); - updateButtonGroupForRow(ROW_OTHER); + startRow(); + updateButtonGroupLayoutProperties(); - // If the infobar consists of just a main row and a buttons row, the buttons must be - // at least 32dp below the bottom of the message text. - if (mCustomGroup == null && mMessageTextView != null) { - LayoutParams lp = (LayoutParams) mMessageTextView.getLayoutParams(); - int messageBottom = lp.top + mMessageTextView.getMeasuredHeight(); - mTop = Math.max(mTop, messageBottom + 2 * mMargin); - } + // If the infobar consists of just a main row and a buttons row, the buttons must be + // at least 32dp below the bottom of the message text. + if (mCustomGroup == null && mMessageTextView != null) { + LayoutParams lp = (LayoutParams) mMessageTextView.getLayoutParams(); + int messageBottom = lp.top + mMessageTextView.getMeasuredHeight(); + mTop = Math.max(mTop, messageBottom + 2 * mMargin); } placeGroup(mButtonGroup); - if (mCustomButton != null && !buttonGroupOnMainRow) { + if (mCustomButton != null) { // The custom button is start-aligned with the message view (unless that causes it // to overlap the primary button). LayoutParams primaryButtonLP = (LayoutParams) mPrimaryButton.getLayoutParams(); @@ -476,17 +451,6 @@ } startRow(); - - // If everything fits on a single row, center everything vertically. - if (buttonGroupOnMainRow) { - int layoutHeight = mBottom; - for (int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - int extraSpace = layoutHeight - child.getMeasuredHeight(); - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - lp.top = extraSpace / 2; - } - } } /** @@ -572,18 +536,15 @@ } /** - * The button group has different layout properties (margins, gravity, etc) when placed on the - * main row as opposed to on a separate row. This updates the layout properties of the button - * group to prepare for placing it on either the main row or a separate row. - * - * @param row One of ROW_MAIN or ROW_OTHER. + * Updates the layout properties (margins, gravity, etc) of the button group to prepare for + * placing it on its own row. */ - private void updateButtonGroupForRow(int row) { - int startEndMargin = row == ROW_MAIN ? mMargin : 0; + private void updateButtonGroupLayoutProperties() { + int startEndMargin = 0; mButtonGroup.setHorizontalMode(mMargin / 2, startEndMargin, startEndMargin); mButtonGroup.gravity = Gravity.END; - if (row == ROW_OTHER && mButtonGroup.views.length >= 2) { + if (mButtonGroup.views.length >= 2) { int extraWidth = availableWidth() - getWidthWithMargins(mButtonGroup); if (extraWidth < 0) { // Group is too wide to fit on a single row, so stack the group items vertically. @@ -594,21 +555,18 @@ ((LayoutParams) mTertiaryButton.getLayoutParams()).endMargin += extraWidth; } } - if (row == ROW_MAIN && mCustomButton != null) { - // Increase spacing between custom button and primary button. - ((LayoutParams) mCustomButton.getLayoutParams()).endMargin = mMargin; - } } /** - * Analagous to updateButtonGroupForRow(), but for the custom group istead of the button group. + * Analagous to updateButtonGroupLayoutProperties(), but for the custom group instead of the + * button group. */ - private void updateCustomGroupForRow(int row) { - int startEndMargin = row == ROW_MAIN ? mMargin : 0; + private void updateCustomGroupLayoutProperties() { + int startEndMargin = 0; mCustomGroup.setHorizontalMode(mMargin, startEndMargin, startEndMargin); mCustomGroup.gravity = Gravity.START; - if (row == ROW_OTHER && mCustomGroup.views.length == 2) { + if (mCustomGroup.views.length == 2) { int extraWidth = availableWidth() - getWidthWithMargins(mCustomGroup); if (extraWidth < 0) { // Group is too wide to fit on a single row, so stack the group items vertically. @@ -624,7 +582,7 @@ measureChildWithFixedWidth(view1, view1.getMeasuredWidth() + extraWidth1); } } - if (row == ROW_OTHER && mCustomGroup.views.length == 1) { + if (mCustomGroup.views.length == 1) { mCustomGroup.gravity = Gravity.FILL_HORIZONTAL; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/notifications/OWNERS index a1a35ba4..2fc004d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/OWNERS
@@ -1,2 +1,3 @@ miguelg@chromium.org +mvanouwerkerk@chromium.org peter@chromium.org \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/DataUseSnackbarController.java b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/DataUseSnackbarController.java index adacddf..eb295d86 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/DataUseSnackbarController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/DataUseSnackbarController.java
@@ -7,6 +7,7 @@ import android.content.Context; import org.chromium.chrome.R; +import org.chromium.chrome.browser.EmbedContentViewActivity; /** * The controller for two data use snackbars: @@ -34,14 +35,16 @@ public void showDataUseTrackingStartedBar() { mSnackbarManager.showSnackbar(Snackbar.make( mContext.getString(R.string.data_use_tracking_started_snackbar_message), this) - .setAction(mContext.getString(R.string.data_use_tracking_started_snackbar_action), + .setAction(mContext.getString(R.string.data_use_tracking_snackbar_action), null)); // TODO(megjablon): Add metrics. } public void showDataUseTrackingEndedBar() { mSnackbarManager.showSnackbar(Snackbar.make( - mContext.getString(R.string.data_use_tracking_ended_title), this)); + mContext.getString(R.string.data_use_tracking_ended_snackbar_message), this) + .setAction(mContext.getString(R.string.data_use_tracking_snackbar_action), + null)); // TODO(megjablon): Add metrics. } @@ -57,7 +60,9 @@ */ @Override public void onAction(Object actionData) { - // TODO(megjablon): Load the more page and add metrics. + // TODO(megjablon): Add metrics. + EmbedContentViewActivity.show(mContext, R.string.data_use_learn_more_title, + R.string.data_use_learn_more_link_url); } @Override
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 2bd8e571..bf7939b7 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -778,23 +778,32 @@ <!-- Data Use --> <message name="IDS_DATA_USE_TRACKING_STARTED_SNACKBAR_MESSAGE" desc="Message shown when data use tracking starts."> - Data use is being tracked + Data use is being tracked </message> - <message name="IDS_DATA_USE_TRACKING_STARTED_SNACKBAR_ACTION" desc="Button to learn more when data use tracking starts."> + <message name="IDS_DATA_USE_TRACKING_SNACKBAR_ACTION" desc="Button to learn more when data use tracking starts or ends."> More </message> - <message name="IDS_DATA_USE_TRACKING_ENDED_TITLE" desc="Message shown when data use tracking has ended. Used by both the snackbar and dialog."> + <message name="IDS_DATA_USE_TRACKING_ENDED_SNACKBAR_MESSAGE" desc="Message shown when data use tracking has ended."> Data use tracking has ended </message> + <message name="IDS_DATA_USE_TRACKING_ENDED_TITLE" desc="Message shown on the dialog when data use tracking has ended."> + Data use tracking ended + </message> <message name="IDS_DATA_USE_TRACKING_ENDED_MESSAGE" desc="Message shown on the dialog when data use tracking has ended."> Your data use will no longer be measured. </message> <message name="IDS_DATA_USE_TRACKING_ENDED_CHECKBOX_MESSAGE" desc="Message shown to opt out of seeing dialogs when data use tracking has ended."> - Don’t ask me again + Don’t show this again </message> <message name="IDS_DATA_USE_TRACKING_ENDED_CONTINUE" desc="Continue button for the dialog shown when data use tracking has ended. When clicked, the page resumes loading."> Continue </message> + <message name="IDS_DATA_USE_LEARN_MORE_TITLE" desc="Title for the 'Learn more' link in the the dialog shown when data use tracking has ended"> + Learn more + </message> + <message name="IDS_DATA_USE_LEARN_MORE_LINK_URL" desc="URL for the 'Learn more' link in the the dialog shown when data use tracking has ended"> + <!-- Intentionally empty. This is overridden downstream. --> + </message> <!-- About Chrome preferences --> <message name="IDS_PREFS_ABOUT_CHROME" desc="Title for the About Chrome page. [CHAR-LIMIT=32]">
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index 5f0b8bc..ea6d261 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -1616,12 +1616,10 @@ * @Feature({"ContextualSearch"}) */ @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - @CommandLineFlags.Add({ - ContextualSearchFieldTrial.PROMO_ON_LIMITED_TAPS + "=true", - ContextualSearchFieldTrial.TAP_TRIGGERED_PROMO_LIMIT + "=2"}) @FlakyTest public void testTapTriggeredPromoLimitForOptOut() throws InterruptedException, TimeoutException { + mPolicy.setPromoTapTriggeredLimitForTesting(2); mPolicy.overrideDecidedStateForTesting(false); clickWordNode("states"); @@ -1863,11 +1861,9 @@ * @Feature({"ContextualSearch"}) */ @Restriction({RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE}) - @CommandLineFlags.Add({ - ContextualSearchFieldTrial.PROMO_ON_LIMITED_TAPS + "=true", - ContextualSearchFieldTrial.TAP_TRIGGERED_PROMO_LIMIT + "=2"}) @FlakyTest public void testPromoTapCount() throws InterruptedException, TimeoutException { + mPolicy.setPromoTapTriggeredLimitForTesting(2); // Note that this tests the basic underlying counter used by // testTapTriggeredPromoLimitForOptOut. // TODO(donnd): consider removing either this test or testTapTriggeredPromoLimitForOptOut.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/invalidations/InvalidationControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/invalidations/InvalidationControllerTest.java index 2892093..93fdbbf 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/invalidations/InvalidationControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/invalidations/InvalidationControllerTest.java
@@ -22,6 +22,7 @@ import org.chromium.sync.notifier.InvalidationIntentProtocol; import org.chromium.sync.signin.ChromeSigninController; import org.chromium.sync.test.util.MockSyncContentResolverDelegate; +import org.chromium.testing.local.CustomShadowAsyncTask; import org.chromium.testing.local.LocalRobolectricTestRunner; import org.junit.Assert; import org.junit.Before; @@ -39,7 +40,7 @@ * Tests for the {@link InvalidationController}. */ @RunWith(LocalRobolectricTestRunner.class) -@Config(manifest = Config.NONE) +@Config(manifest = Config.NONE, shadows = {CustomShadowAsyncTask.class}) public class InvalidationControllerTest { /** * Stubbed out ProfileSyncService with a setter to control return value of
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index ad570f1..09407f9db 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h
@@ -246,9 +246,6 @@ #define IDC_TRANSLATE_ORIGINAL_LANGUAGE_BASE 42100 #define IDC_TRANSLATE_TARGET_LANGUAGE_BASE 42400 -// Speech input -#define IDC_TOGGLE_SPEECH_INPUT 42500 - // Identifiers for platform-specific items. // Placed in a common file to help insure they never collide. #define IDC_VIEW_MENU 44000 // OSX only
diff --git a/chrome/app/chrome_dll.rc b/chrome/app/chrome_dll.rc index c132fea..4dc8a15 100644 --- a/chrome/app/chrome_dll.rc +++ b/chrome/app/chrome_dll.rc
@@ -115,7 +115,6 @@ "M", IDC_SHOW_AVATAR_MENU, VIRTKEY, CONTROL, SHIFT VK_ESCAPE, IDC_STOP, VIRTKEY VK_ESCAPE, IDC_TASK_MANAGER, VIRTKEY, SHIFT - VK_OEM_PERIOD, IDC_TOGGLE_SPEECH_INPUT, VIRTKEY, CONTROL, SHIFT "U", IDC_VIEW_SOURCE, VIRTKEY, CONTROL VK_OEM_MINUS, IDC_ZOOM_MINUS, VIRTKEY, CONTROL VK_OEM_MINUS, IDC_ZOOM_MINUS, VIRTKEY, CONTROL, SHIFT
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 7108217..54a8f27 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -23,17 +23,11 @@ <message name="IDS_SETTINGS_HIGH_CONTRAST_LABEL" desc="Label for checkbox which enables high-contrast UI."> Use high contrast mode </message> - <message name="IDS_SETTINGS_STICKY_KEYS_LABEL" desc="Label for checkbox which enables sticky keys."> - Enable sticky keys + <message name="IDS_SETTINGS_STICKY_KEYS_LABEL" desc="Label for checkbox which enables sticky keys, with an explanation of the term 'sticky keys'."> + Enable sticky keys (to perform keyboard shortcuts by typing them sequentially) </message> - <message name="IDS_SETTINGS_STICKY_KEYS_SUBLABEL" desc="Sub-label describing what the term 'sticky keys' means."> - (to perform keyboard shortcuts by typing them sequentially) - </message> - <message name="IDS_SETTINGS_CHROMEVOX_LABEL" desc="Label for checkbox which enables ChromeVox"> - Enable ChromeVox - </message> - <message name="IDS_SETTINGS_CHROMEVOX_SUBLABEL" desc="Sub-label describingn what ChromeVox is."> - (spoken feedback) + <message name="IDS_SETTINGS_CHROMEVOX_LABEL" desc="Label for checkbox which enables ChromeVox, with a description of what ChromeVox is."> + Enable ChromeVox (spoken feedback) </message> <message name="IDS_SETTINGS_SCREEN_MAGNIFIER_LABEL" desc="Label for checkbox which enables the screen magnifier"> Enable screen magnifier
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_mic_search.png b/chrome/app/theme/default_100_percent/common/omnibox_mic_search.png deleted file mode 100644 index 90b98f1..0000000 --- a/chrome/app/theme/default_100_percent/common/omnibox_mic_search.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_mic_search.png b/chrome/app/theme/default_200_percent/common/omnibox_mic_search.png deleted file mode 100644 index 31ea0fdb..0000000 --- a/chrome/app/theme/default_200_percent/common/omnibox_mic_search.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/material_100_percent/common/omnibox_mic_search.png b/chrome/app/theme/material_100_percent/common/omnibox_mic_search.png deleted file mode 100644 index 8fb133a0..0000000 --- a/chrome/app/theme/material_100_percent/common/omnibox_mic_search.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/material_200_percent/common/omnibox_mic_search.png b/chrome/app/theme/material_200_percent/common/omnibox_mic_search.png deleted file mode 100644 index 4541c7d..0000000 --- a/chrome/app/theme/material_200_percent/common/omnibox_mic_search.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 2d9d1239..c39d828 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd
@@ -516,7 +516,6 @@ <if expr="not is_macosx and not is_ios"> <structure type="chrome_scaled_image" name="IDR_OMNIBOX_KEYWORD_HINT_TAB" file="common/omnibox_keyword_hint_tab.png" /> </if> - <structure type="chrome_scaled_image" name="IDR_OMNIBOX_MIC_SEARCH" file="common/omnibox_mic_search.png" /> <structure type="chrome_scaled_image" name="IDR_OMNIBOX_PDF_ICON" file="pdf.png" /> <structure type="chrome_scaled_image" name="IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_BOTTOM" file="common/omnibox_popup_border_and_shadow_bottom.png" /> <structure type="chrome_scaled_image" name="IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_BOTTOM_LEFT" file="common/omnibox_popup_border_and_shadow_bottom_left.png" />
diff --git a/chrome/browser/global_keyboard_shortcuts_mac.mm b/chrome/browser/global_keyboard_shortcuts_mac.mm index d9bd18d..aa2d3ee 100644 --- a/chrome/browser/global_keyboard_shortcuts_mac.mm +++ b/chrome/browser/global_keyboard_shortcuts_mac.mm
@@ -106,8 +106,6 @@ {false, false, false, false, kVK_Delete, 0, IDC_BACK}, {false, true, false, false, kVK_Delete, 0, IDC_FORWARD}, {true, true, false, false, 0, 'c', IDC_DEV_TOOLS_INSPECT}, - {true, true, false, false, kVK_ANSI_Period, 0, - IDC_TOGGLE_SPEECH_INPUT}, }; *num_entries = arraysize(keyboard_shortcuts);
diff --git a/chrome/browser/media/android/router/media_router_android.cc b/chrome/browser/media/android/router/media_router_android.cc index 614d4d9..02fcfb78 100644 --- a/chrome/browser/media/android/router/media_router_android.cc +++ b/chrome/browser/media/android/router/media_router_android.cc
@@ -312,6 +312,16 @@ NOTIMPLEMENTED(); } +void MediaRouterAndroid::RegisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) { + NOTIMPLEMENTED(); +} + +void MediaRouterAndroid::UnregisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) { + NOTIMPLEMENTED(); +} + void MediaRouterAndroid::OnSinksReceived( JNIEnv* env, jobject obj,
diff --git a/chrome/browser/media/android/router/media_router_android.h b/chrome/browser/media/android/router/media_router_android.h index b7d481b3..610a22b 100644 --- a/chrome/browser/media/android/router/media_router_android.h +++ b/chrome/browser/media/android/router/media_router_android.h
@@ -107,6 +107,10 @@ LocalMediaRoutesObserver* observer) override; void UnregisterLocalMediaRoutesObserver( LocalMediaRoutesObserver* observer) override; + void RegisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) override; + void UnregisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) override; base::android::ScopedJavaGlobalRef<jobject> java_media_router_;
diff --git a/chrome/browser/media/router/media_router.gypi b/chrome/browser/media/router/media_router.gypi index aed29aa..32089b1 100644 --- a/chrome/browser/media/router/media_router.gypi +++ b/chrome/browser/media/router/media_router.gypi
@@ -35,6 +35,8 @@ 'media_source.h', 'media_source_helper.cc', 'media_source_helper.h', + 'presentation_connection_state_observer.cc', + 'presentation_connection_state_observer.h', 'presentation_media_sinks_observer.cc', 'presentation_media_sinks_observer.h', 'presentation_service_delegate_impl.cc',
diff --git a/chrome/browser/media/router/media_router.h b/chrome/browser/media/router/media_router.h index f355c58..5836a9c3 100644 --- a/chrome/browser/media/router/media_router.h +++ b/chrome/browser/media/router/media_router.h
@@ -27,6 +27,7 @@ class LocalMediaRoutesObserver; class MediaRoutesObserver; class MediaSinksObserver; +class PresentationConnectionStateObserver; class PresentationSessionMessagesObserver; // Type of callback used in |CreateRoute()| and |JoinRoute()|. Callback is @@ -125,6 +126,7 @@ friend class LocalMediaRoutesObserver; friend class MediaSinksObserver; friend class MediaRoutesObserver; + friend class PresentationConnectionStateObserver; friend class PresentationSessionMessagesObserver; // The following functions are called by friend Observer classes above. @@ -189,6 +191,15 @@ // Removes the LocalMediaRoutesObserver |observer|. virtual void UnregisterLocalMediaRoutesObserver( LocalMediaRoutesObserver* observer) = 0; + + // Registers/unregisters a PresentationConnectionStateObserver to receive + // updates on state changes for a PresentationConnection. MediaRouter does + // not own |observer|. When |observer| is about to be destroyed, it must be + // unregistered from MediaRouter. + virtual void RegisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) = 0; + virtual void UnregisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) = 0; }; } // namespace media_router
diff --git a/chrome/browser/media/router/media_router.mojom b/chrome/browser/media/router/media_router.mojom index 2330a1e9..6289a2d 100644 --- a/chrome/browser/media/router/media_router.mojom +++ b/chrome/browser/media/router/media_router.mojom
@@ -201,6 +201,13 @@ AVAILABLE }; + // Keep in sync with content/public/browser/presentation_session.h. + enum PresentationConnectionState { + CONNECTED, + CLOSED, + TERMINATED + }; + // Registers a MediaRouteProvider with the MediaRouter. // Returns a string that uniquely identifies the Media Router browser // process. @@ -218,5 +225,10 @@ // Called when the overall availability of media sinks has been updated. OnSinkAvailabilityUpdated(SinkAvailability availability); + + // Called when the state of presentation connected to route |route_id| has + // changed to |state|. + OnPresentationConnectionStateChanged( + string route_id, PresentationConnectionState state); };
diff --git a/chrome/browser/media/router/media_router_mojo_impl.cc b/chrome/browser/media/router/media_router_mojo_impl.cc index d6bb508..e7bc9d3 100644 --- a/chrome/browser/media/router/media_router_mojo_impl.cc +++ b/chrome/browser/media/router/media_router_mojo_impl.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/media/router/media_router_type_converters.h" #include "chrome/browser/media/router/media_routes_observer.h" #include "chrome/browser/media/router/media_sinks_observer.h" +#include "chrome/browser/media/router/presentation_connection_state_observer.h" #include "chrome/browser/media/router/presentation_session_messages_observer.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "extensions/browser/process_manager.h" @@ -499,6 +500,40 @@ local_routes_observers_.RemoveObserver(observer); } +void MediaRouterMojoImpl::RegisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(observer); + + const MediaRoute::Id route_id = observer->route_id(); + auto* observers = presentation_connection_state_observers_.get(route_id); + if (!observers) { + observers = new PresentationConnectionStateObserverList; + presentation_connection_state_observers_.add(route_id, + make_scoped_ptr(observers)); + } + + if (observers->HasObserver(observer)) + return; + + observers->AddObserver(observer); +} + +void MediaRouterMojoImpl::UnregisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(observer); + + const MediaRoute::Id route_id = observer->route_id(); + auto* observers = presentation_connection_state_observers_.get(route_id); + if (!observers) + return; + + observers->RemoveObserver(observer); + if (!observers->might_have_observers()) + presentation_connection_state_observers_.erase(route_id); +} + void MediaRouterMojoImpl::DoCreateRoute( const MediaSource::Id& source_id, const MediaSink::Id& sink_id, @@ -644,6 +679,25 @@ } } +void MediaRouterMojoImpl::OnPresentationConnectionStateChanged( + const mojo::String& route_id, + interfaces::MediaRouter::PresentationConnectionState state) { + if (!interfaces::MediaRouter::PresentationConnectionState_IsValidValue( + state)) { + DLOG(WARNING) << "Unknown PresentationConnectionState value " << state; + return; + } + + auto* observers = presentation_connection_state_observers_.get(route_id); + if (!observers) + return; + + content::PresentationConnectionState converted_state = + mojo::PresentationConnectionStateFromMojo(state); + FOR_EACH_OBSERVER(PresentationConnectionStateObserver, *observers, + OnStateChanged(converted_state)); +} + void MediaRouterMojoImpl::DoOnPresentationSessionDetached( const MediaRoute::Id& route_id) { DVLOG_WITH_INSTANCE(1) << "DoOnPresentationSessionDetached " << route_id;
diff --git a/chrome/browser/media/router/media_router_mojo_impl.h b/chrome/browser/media/router/media_router_mojo_impl.h index 054223d..f2ce7c5 100644 --- a/chrome/browser/media/router/media_router_mojo_impl.h +++ b/chrome/browser/media/router/media_router_mojo_impl.h
@@ -199,6 +199,10 @@ LocalMediaRoutesObserver* observer) override; void UnregisterLocalMediaRoutesObserver( LocalMediaRoutesObserver* observer) override; + void RegisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) override; + void UnregisterPresentationConnectionStateObserver( + PresentationConnectionStateObserver* observer) override; // These calls invoke methods in the component extension via Mojo. void DoCreateRoute(const MediaSource::Id& source_id, @@ -249,6 +253,9 @@ void OnRoutesUpdated(mojo::Array<interfaces::MediaRoutePtr> routes) override; void OnSinkAvailabilityUpdated( interfaces::MediaRouter::SinkAvailability availability) override; + void OnPresentationConnectionStateChanged( + const mojo::String& route_id, + interfaces::MediaRouter::PresentationConnectionState state) override; // Converts the callback result of calling Mojo CreateRoute()/JoinRoute() // into a local callback. @@ -292,12 +299,19 @@ base::ScopedPtrHashMap<MediaRoute::Id, scoped_ptr<PresentationSessionMessagesObserverList>> messages_observers_; + // IDs of MediaRoutes being listened for messages. Note that this is // different from |message_observers_| because we might be waiting for // |OnRouteMessagesReceived()| to be invoked after all observers for that // route have been removed. std::set<MediaRoute::Id> route_ids_listening_for_messages_; + using PresentationConnectionStateObserverList = + base::ObserverList<PresentationConnectionStateObserver>; + base::ScopedPtrHashMap<MediaRoute::Id, + scoped_ptr<PresentationConnectionStateObserverList>> + presentation_connection_state_observers_; + IssueManager issue_manager_; // Binds |this| to a Mojo connection stub for interfaces::MediaRouter.
diff --git a/chrome/browser/media/router/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/media_router_mojo_impl_unittest.cc index be57f699..bb7b38f 100644 --- a/chrome/browser/media/router/media_router_mojo_impl_unittest.cc +++ b/chrome/browser/media/router/media_router_mojo_impl_unittest.cc
@@ -733,6 +733,28 @@ ProcessEventLoop(); } +TEST_F(MediaRouterMojoImplTest, PresentationConnectionStateObserver) { + using PresentationConnectionState = + interfaces::MediaRouter::PresentationConnectionState; + + MediaRoute::Id route_id("route-id"); + MockPresentationConnectionStateObserver observer(router(), route_id); + + EXPECT_CALL(observer, + OnStateChanged(content::PRESENTATION_CONNECTION_STATE_CLOSED)); + media_router_proxy_->OnPresentationConnectionStateChanged( + route_id, + PresentationConnectionState::PRESENTATION_CONNECTION_STATE_CLOSED); + ProcessEventLoop(); + + EXPECT_CALL(observer, OnStateChanged( + content::PRESENTATION_CONNECTION_STATE_TERMINATED)); + media_router_proxy_->OnPresentationConnectionStateChanged( + route_id, + PresentationConnectionState::PRESENTATION_CONNECTION_STATE_TERMINATED); + ProcessEventLoop(); +} + TEST_F(MediaRouterMojoImplTest, QueuedWhileAsleep) { EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id())) .Times(2)
diff --git a/chrome/browser/media/router/media_router_type_converters.cc b/chrome/browser/media/router/media_router_type_converters.cc index 493b613..627bf9de 100644 --- a/chrome/browser/media/router/media_router_type_converters.cc +++ b/chrome/browser/media/router/media_router_type_converters.cc
@@ -5,8 +5,11 @@ #include "chrome/browser/media/router/media_router_type_converters.h" using media_router::interfaces::IssuePtr; -using media_router::interfaces::MediaSinkPtr; using media_router::interfaces::MediaRoutePtr; +using media_router::interfaces::MediaSinkPtr; + +using PresentationConnectionState = + media_router::interfaces::MediaRouter::PresentationConnectionState; namespace mojo { @@ -126,4 +129,19 @@ input->is_blocking, input->help_url); } +content::PresentationConnectionState PresentationConnectionStateFromMojo( + PresentationConnectionState state) { + switch (state) { + case PresentationConnectionState::PRESENTATION_CONNECTION_STATE_CONNECTED: + return content::PRESENTATION_CONNECTION_STATE_CONNECTED; + case PresentationConnectionState::PRESENTATION_CONNECTION_STATE_CLOSED: + return content::PRESENTATION_CONNECTION_STATE_CLOSED; + case PresentationConnectionState::PRESENTATION_CONNECTION_STATE_TERMINATED: + return content::PRESENTATION_CONNECTION_STATE_TERMINATED; + default: + NOTREACHED() << "Unknown PresentationConnectionState " << state; + return content::PRESENTATION_CONNECTION_STATE_TERMINATED; + } +} + } // namespace mojo
diff --git a/chrome/browser/media/router/media_router_type_converters.h b/chrome/browser/media/router/media_router_type_converters.h index 5ef4cbe..8dc5dbe 100644 --- a/chrome/browser/media/router/media_router_type_converters.h +++ b/chrome/browser/media/router/media_router_type_converters.h
@@ -13,6 +13,7 @@ #include "chrome/browser/media/router/media_router.mojom.h" #include "chrome/browser/media/router/media_sink.h" #include "chrome/browser/media/router/media_source.h" +#include "content/public/browser/presentation_session.h" #include "mojo/common/common_type_converters.h" namespace mojo { @@ -62,6 +63,10 @@ const media_router::interfaces::IssuePtr& input); }; +// PresentationConnectionState conversion. +content::PresentationConnectionState PresentationConnectionStateFromMojo( + media_router::interfaces::MediaRouter::PresentationConnectionState state); + } // namespace mojo #endif // CHROME_BROWSER_MEDIA_ROUTER_MEDIA_ROUTER_TYPE_CONVERTERS_H_
diff --git a/chrome/browser/media/router/mock_media_router.h b/chrome/browser/media/router/mock_media_router.h index 37738192..01fa7b5 100644 --- a/chrome/browser/media/router/mock_media_router.h +++ b/chrome/browser/media/router/mock_media_router.h
@@ -72,6 +72,10 @@ void(LocalMediaRoutesObserver* observer)); MOCK_METHOD1(UnregisterLocalMediaRoutesObserver, void(LocalMediaRoutesObserver* observer)); + MOCK_METHOD1(RegisterPresentationConnectionStateObserver, + void(PresentationConnectionStateObserver* observer)); + MOCK_METHOD1(UnregisterPresentationConnectionStateObserver, + void(PresentationConnectionStateObserver* observer)); }; } // namespace media_router
diff --git a/chrome/browser/media/router/presentation_connection_state_observer.cc b/chrome/browser/media/router/presentation_connection_state_observer.cc new file mode 100644 index 0000000..47f342c --- /dev/null +++ b/chrome/browser/media/router/presentation_connection_state_observer.cc
@@ -0,0 +1,24 @@ +// Copyright 2015 The Chromium Authors. 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/router/presentation_connection_state_observer.h" + +#include "base/logging.h" +#include "chrome/browser/media/router/media_router.h" + +namespace media_router { + +PresentationConnectionStateObserver::PresentationConnectionStateObserver( + MediaRouter* router, + const MediaRoute::Id& route_id) + : router_(router), route_id_(route_id) { + DCHECK(router_); + router_->RegisterPresentationConnectionStateObserver(this); +} + +PresentationConnectionStateObserver::~PresentationConnectionStateObserver() { + router_->UnregisterPresentationConnectionStateObserver(this); +} + +} // namespace media_router
diff --git a/chrome/browser/media/router/presentation_connection_state_observer.h b/chrome/browser/media/router/presentation_connection_state_observer.h new file mode 100644 index 0000000..555f9fe --- /dev/null +++ b/chrome/browser/media/router/presentation_connection_state_observer.h
@@ -0,0 +1,40 @@ +// Copyright 2015 The Chromium 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_ROUTER_PRESENTATION_CONNECTION_STATE_OBSERVER_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_CONNECTION_STATE_OBSERVER_H_ + +#include "base/macros.h" +#include "chrome/browser/media/router/media_route.h" + +namespace media_router { + +class MediaRouter; + +// Base class for observing state changes on a PresentationConnection. +class PresentationConnectionStateObserver { + public: + // |router|: The MediaRouter instance to register this instance with. + // |route_id|: ID of MediaRoute connected to the PresentationConnection to + // be observed. + PresentationConnectionStateObserver(MediaRouter* router, + const MediaRoute::Id& route_id); + virtual ~PresentationConnectionStateObserver(); + + MediaRoute::Id route_id() const { return route_id_; } + + // Invoked when the state of PresentationConnection represented by |route_id_| + // has changed to |state|. + virtual void OnStateChanged(content::PresentationConnectionState state) {} + + private: + MediaRouter* const router_; + const MediaRoute::Id route_id_; + + DISALLOW_COPY_AND_ASSIGN(PresentationConnectionStateObserver); +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_CONNECTION_STATE_OBSERVER_H_
diff --git a/chrome/browser/media/router/test_helper.cc b/chrome/browser/media/router/test_helper.cc index e8d4807..1bba86fa 100644 --- a/chrome/browser/media/router/test_helper.cc +++ b/chrome/browser/media/router/test_helper.cc
@@ -28,4 +28,12 @@ MockEventPageTracker::~MockEventPageTracker() { } +MockPresentationConnectionStateObserver:: + MockPresentationConnectionStateObserver(MediaRouter* router, + const MediaRoute::Id& route_id) + : PresentationConnectionStateObserver(router, route_id) {} + +MockPresentationConnectionStateObserver:: + ~MockPresentationConnectionStateObserver() = default; + } // namespace media_router
diff --git a/chrome/browser/media/router/test_helper.h b/chrome/browser/media/router/test_helper.h index 1c5bf8d..24af92df 100644 --- a/chrome/browser/media/router/test_helper.h +++ b/chrome/browser/media/router/test_helper.h
@@ -13,6 +13,7 @@ #include "chrome/browser/media/router/media_router_mojo_impl.h" #include "chrome/browser/media/router/media_routes_observer.h" #include "chrome/browser/media/router/media_sinks_observer.h" +#include "chrome/browser/media/router/presentation_connection_state_observer.h" #include "extensions/browser/event_page_tracker.h" #include "testing/gmock/include/gmock/gmock.h" @@ -139,11 +140,22 @@ class MockMediaRoutesObserver : public MediaRoutesObserver { public: explicit MockMediaRoutesObserver(MediaRouter* router); - ~MockMediaRoutesObserver(); + ~MockMediaRoutesObserver() override; MOCK_METHOD1(OnRoutesUpdated, void(const std::vector<MediaRoute>& sinks)); }; +class MockPresentationConnectionStateObserver + : public PresentationConnectionStateObserver { + public: + MockPresentationConnectionStateObserver(MediaRouter* router, + const MediaRoute::Id& route_id); + ~MockPresentationConnectionStateObserver() override; + + MOCK_METHOD1(OnStateChanged, + void(content::PresentationConnectionState state)); +}; + class MockEventPageTracker : public extensions::EventPageTracker { public: MockEventPageTracker();
diff --git a/chrome/browser/memory/tab_manager.cc b/chrome/browser/memory/tab_manager.cc index 31a095e0..55fde20 100644 --- a/chrome/browser/memory/tab_manager.cc +++ b/chrome/browser/memory/tab_manager.cc
@@ -440,6 +440,15 @@ WebContents* web_contents = model->GetWebContentsAt(idx); + // Do not discard tabs that don't have a valid URL (most probably they have + // just been opened and dicarding them would lose the URL). + // TODO(georgesak): Look into a workaround to be able to kill the tab without + // losing the pending navigation. + if (!web_contents->GetLastCommittedURL().is_valid() || + web_contents->GetLastCommittedURL().is_empty()) { + return false; + } + // Do not discard tabs in which the user has entered text in a form, lest that // state gets lost. if (web_contents->GetPageImportanceSignals().had_form_interaction)
diff --git a/chrome/browser/memory/tab_manager_browsertest.cc b/chrome/browser/memory/tab_manager_browsertest.cc index e28ddde..9a13eaa 100644 --- a/chrome/browser/memory/tab_manager_browsertest.cc +++ b/chrome/browser/memory/tab_manager_browsertest.cc
@@ -216,6 +216,37 @@ EXPECT_TRUE(tab_manager->recent_tab_discard()); } +IN_PROC_BROWSER_TEST_F(TabManagerTest, InvalidOrEmptyURL) { + TabManager* tab_manager = g_browser_process->GetTabManager(); + ASSERT_TRUE(tab_manager); + + // Open two tabs. Wait for the foreground one to load but do not wait for the + // background one. + content::WindowedNotificationObserver load1( + content::NOTIFICATION_NAV_ENTRY_COMMITTED, + content::NotificationService::AllSources()); + OpenURLParams open1(GURL(chrome::kChromeUIAboutURL), content::Referrer(), + CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false); + browser()->OpenURL(open1); + load1.Wait(); + + content::WindowedNotificationObserver load2( + content::NOTIFICATION_NAV_ENTRY_COMMITTED, + content::NotificationService::AllSources()); + OpenURLParams open2(GURL(chrome::kChromeUICreditsURL), content::Referrer(), + NEW_BACKGROUND_TAB, ui::PAGE_TRANSITION_TYPED, false); + browser()->OpenURL(open2); + + ASSERT_EQ(2, browser()->tab_strip_model()->count()); + + // This shouldn't be able to discard a tab as the background tab has not yet + // started loading (its URL is not committed). + EXPECT_FALSE(tab_manager->DiscardTab()); + + // Wait for the background tab to load which then allows it to be discarded. + load2.Wait(); + EXPECT_TRUE(tab_manager->DiscardTab()); +} } // namespace memory #endif // OS_WIN || OS_CHROMEOS
diff --git a/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/chromevox/BUILD.gn index 105a1db..c3bce7e 100644 --- a/chrome/browser/resources/chromeos/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -31,10 +31,11 @@ ] if (chromevox_compress_js) { deps += [ - ":chromevox1_content_script", - ":chromevox1_kbexplorer_script", - ":chromevox1_options_script", - ":chromevox2_background_script", + ":chromevox_content_script", + ":chromevox_kbexplorer_script", + ":chromevox_options_script", + ":chromevox_background_script", + ":chromevox_panel_script", ] } else { deps += [ ":chromevox_deps_js" ] @@ -133,7 +134,7 @@ run_jsbundler("chromevox_copied_files") { mode = "copy" dest_dir = chromevox_out_dir - sources = chromevox_assets_gypi_values.chromevox_assets_chromevox + sources = chromevox_assets_gypi_values.chromevox_assets_images sources += chromevox_assets_gypi_values.chromevox_assets_chromevox_background_earcons sources += @@ -148,6 +149,7 @@ "chromevox/background/options.html", "chromevox/injected/api.js", "cvox2/background/background.html", + "cvox2/background/panel.html", ] if (chromevox_compress_js) { sources += [ "chromevox/injected/api_util.js" ] @@ -155,10 +157,11 @@ sources += chromevox_modules sources += [ "closure/closure_preinit.js", - chromevox_vars_gypi_values.chromevox1_content_script_loader_file, - chromevox_vars_gypi_values.chromevox1_kbexplorer_loader_file, - chromevox_vars_gypi_values.chromevox1_options_script_loader_file, - chromevox_vars_gypi_values.chromevox2_background_script_loader_file, + chromevox_vars_gypi_values.chromevox_content_script_loader_file, + chromevox_vars_gypi_values.chromevox_kbexplorer_loader_file, + chromevox_vars_gypi_values.chromevox_options_script_loader_file, + chromevox_vars_gypi_values.chromevox_background_script_loader_file, + chromevox_vars_gypi_values.chromevox_panel_script_loader_file, ] } if (!chromevox_compress_js) { @@ -256,33 +259,40 @@ } } - compress_js("chromevox1_content_script") { + compress_js("chromevox_content_script") { sources = [ - chromevox_vars_gypi_values.chromevox1_content_script_loader_file, + chromevox_vars_gypi_values.chromevox_content_script_loader_file, ] output_file = "$chromevox_out_dir/chromeVoxChromePageScript.js" } - compress_js("chromevox1_kbexplorer_script") { + compress_js("chromevox_kbexplorer_script") { sources = [ - chromevox_vars_gypi_values.chromevox1_kbexplorer_loader_file, + chromevox_vars_gypi_values.chromevox_kbexplorer_loader_file, ] output_file = "$chromevox_out_dir/chromeVoxKbExplorerScript.js" } - compress_js("chromevox1_options_script") { + compress_js("chromevox_options_script") { sources = [ - chromevox_vars_gypi_values.chromevox1_options_script_loader_file, + chromevox_vars_gypi_values.chromevox_options_script_loader_file, ] output_file = "$chromevox_out_dir/chromeVoxChromeOptionsScript.js" } - compress_js("chromevox2_background_script") { + compress_js("chromevox_background_script") { sources = [ - chromevox_vars_gypi_values.chromevox2_background_script_loader_file, + chromevox_vars_gypi_values.chromevox_background_script_loader_file, ] output_file = "$chromevox_out_dir/chromeVox2ChromeBackgroundScript.js" } + + compress_js("chromevox_panel_script") { + sources = [ + chromevox_vars_gypi_values.chromevox_panel_script_loader_file, + ] + output_file = "$chromevox_out_dir/chromeVoxPanelScript.js" + } } else { generate_deps_js("chromevox_deps_js") { sources = chromevox_modules + closure_library_modules
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox.gni b/chrome/browser/resources/chromeos/chromevox/chromevox.gni index 6a36df8d..2a4e8c8b 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox.gni +++ b/chrome/browser/resources/chromeos/chromevox/chromevox.gni
@@ -131,6 +131,8 @@ "cvox2/background/earcon_engine.js", "cvox2/background/next_earcons.js", "cvox2/background/output.js", + "cvox2/background/panel.js", + "cvox2/background/panel_command.js", "cvox2/background/tabs_automation_handler.js", "extensions/searchvox/abstract_result.js", "extensions/searchvox/constants.js",
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox.gyp b/chrome/browser/resources/chromeos/chromevox/chromevox.gyp index 94b33f1..9cdc4f5f 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox.gyp +++ b/chrome/browser/resources/chromeos/chromevox/chromevox.gyp
@@ -44,10 +44,11 @@ }], ['chromevox_compress_js==1', { 'dependencies': [ - 'chromevox1_content_script', - 'chromevox1_kbexplorer_script', - 'chromevox1_options_script', - 'chromevox2_background_script', + 'chromevox_content_script', + 'chromevox_kbexplorer_script', + 'chromevox_options_script', + 'chromevox_background_script', + 'chromevox_panel_script', ], }, { # chromevox_compress_js==0 'dependencies': [ @@ -72,6 +73,7 @@ 'destination': '<(chromevox_dest_dir)/cvox2/background', 'files': [ 'cvox2/background/background.html', + 'cvox2/background/panel.html', ], }, ], @@ -134,10 +136,11 @@ 'deps_js_output_file': '<(chromevox_dest_dir)/deps.js', }, 'sources': [ - '<(chromevox1_content_script_loader_file)', - '<(chromevox1_kbexplorer_loader_file)', - '<(chromevox1_options_script_loader_file)', - '<(chromevox2_background_script_loader_file)', + '<(chromevox_content_script_loader_file)', + '<(chromevox_kbexplorer_loader_file)', + '<(chromevox_options_script_loader_file)', + '<(chromevox_background_script_loader_file)', + '<(chromevox_panel_script_loader_file)', ], 'includes': ['generate_deps.gypi'], }, @@ -163,43 +166,52 @@ ['chromevox_compress_js==1', { 'targets': [ { - 'target_name': 'chromevox1_content_script', + 'target_name': 'chromevox_content_script', 'type': 'none', 'variables': { 'output_file': '<(chromevox_dest_dir)/chromeVoxChromePageScript.js', }, - 'sources': [ '<(chromevox1_content_script_loader_file)' ], + 'sources': [ '<(chromevox_content_script_loader_file)' ], 'includes': [ 'compress_js.gypi', ], }, { - 'target_name': 'chromevox1_options_script', + 'target_name': 'chromevox_options_script', 'type': 'none', 'variables': { 'output_file': '<(chromevox_dest_dir)/chromeVoxChromeOptionsScript.js', }, - 'sources': [ '<(chromevox1_options_script_loader_file)' ], + 'sources': [ '<(chromevox_options_script_loader_file)' ], 'includes': [ 'compress_js.gypi', ], }, { - 'target_name': 'chromevox1_kbexplorer_script', + 'target_name': 'chromevox_kbexplorer_script', 'type': 'none', 'variables': { 'output_file': '<(chromevox_dest_dir)/chromeVoxKbExplorerScript.js', }, - 'sources': [ '<(chromevox1_kbexplorer_loader_file)' ], + 'sources': [ '<(chromevox_kbexplorer_loader_file)' ], 'includes': [ 'compress_js.gypi', ], }, { - 'target_name': 'chromevox2_background_script', + 'target_name': 'chromevox_background_script', 'type': 'none', 'variables': { 'output_file': '<(chromevox_dest_dir)/chromeVox2ChromeBackgroundScript.js', }, 'sources': [ - '<(chromevox2_background_script_loader_file)', + '<(chromevox_background_script_loader_file)', ], 'includes': [ 'compress_js.gypi', ], }, + { + 'target_name': 'chromevox_panel_script', + 'type': 'none', + 'variables': { + 'output_file': '<(chromevox_dest_dir)/chromeVoxPanelScript.js', + }, + 'sources': [ '<(chromevox_panel_script_loader_file)' ], + 'includes': [ 'compress_js.gypi', ], + }, ], }, { # chromevox_compress_js==0 'targets': [ @@ -210,10 +222,11 @@ 'dest_dir': '<(chromevox_dest_dir)', }, 'sources': [ - '<(chromevox1_content_script_loader_file)', - '<(chromevox1_kbexplorer_loader_file)', - '<(chromevox1_options_script_loader_file)', - '<(chromevox2_background_script_loader_file)', + '<(chromevox_content_script_loader_file)', + '<(chromevox_kbexplorer_loader_file)', + '<(chromevox_options_script_loader_file)', + '<(chromevox_background_script_loader_file)', + '<(chromevox_panel_script_loader_file)', ], 'includes': [ 'copy_js.gypi', ], },
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/braille_captions_background.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/braille_captions_background.js index 2c7fa18..a38d3b7 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/braille_captions_background.js +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/braille_captions_background.js
@@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** @fileoverview Sends braille content to a content script if the braille - * captions feature is enabled. +/** @fileoverview If the braille captions feature is enabled, sends + * braille content to the Panel on Chrome OS, or a content script on + * other platforms. */ goog.provide('cvox.BrailleCaptionsBackground'); +goog.require('PanelCommand'); goog.require('cvox.BrailleDisplayState'); goog.require('cvox.ExtensionBridge'); @@ -65,11 +67,17 @@ brailleChars += String.fromCharCode( self.BRAILLE_UNICODE_BLOCK_START | byteBuf[i]); } - cvox.ExtensionBridge.send({ - message: 'BRAILLE_CAPTION', - text: text, - brailleChars: brailleChars - }); + + if (cvox.ChromeVox.isChromeOS) { + var data = {text: text, braille: brailleChars}; + (new PanelCommand(PanelCommandType.UPDATE_BRAILLE, data)).send(); + } else { + cvox.ExtensionBridge.send({ + message: 'BRAILLE_CAPTION', + text: text, + brailleChars: brailleChars + }); + } };
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json b/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json index 3aa7300..0164642 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json
@@ -3,42 +3,24 @@ { "command": "previousElement", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [37], - "metaKey": [true] + "keyCode": [37] } } }, { "command": "previousLine", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [38], - "metaKey": [true] + "keyCode": [38] } } }, { "command": "nextElement", "sequence": { - "keys": { - "keyCode": [39], - "metaKey": [true] - } - } - }, - { - "command": "nextLine", - "sequence": { - "keys": { - "keyCode": [40], - "metaKey": [true] - } - } - }, - { - "command": "nextCharacter", - "sequence": { "cvoxModifier": true, "keys": { "keyCode": [39] @@ -46,11 +28,31 @@ } }, { + "command": "nextLine", + "sequence": { + "cvoxModifier": true, + "keys": { + "keyCode": [40] + } + } + }, + { + "command": "nextCharacter", + "sequence": { + "cvoxModifier": true, + "keys": { + "keyCode": [39], + "shiftKey": [true] + } + } + }, + { "command": "previousCharacter", "sequence": { "cvoxModifier": true, "keys": { - "keyCode": [37] + "keyCode": [37], + "shiftKey": [true] } } }, @@ -60,7 +62,8 @@ "cvoxModifier": true, "keys": { "keyCode": [39], - "ctrlKey": [true] + "ctrlKey": [true], + "shiftKey": [true] } } }, @@ -70,25 +73,26 @@ "cvoxModifier": true, "keys": { "keyCode": [37], - "ctrlKey": [true] + "ctrlKey": [true], + "shiftKey": [true] } } }, { "command": "nextButton", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [66], - "metaKey": [true] + "keyCode": [66] } } }, { "command": "previousButton", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [66], - "metaKey": [true], "shiftKey": [true] } } @@ -96,18 +100,18 @@ { "command": "nextCheckBox", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [88], - "metaKey": [true] + "keyCode": [88] } } }, { "command": "previousCheckBox", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [88], - "metaKey": [true], "shiftKey": [true] } } @@ -115,18 +119,18 @@ { "command": "nextCombobox", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [67], - "metaKey": [true] + "keyCode": [67] } } }, { "command": "previousCombobox", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [67], - "metaKey": [true], "shiftKey": [true] } } @@ -134,18 +138,18 @@ { "command": "nextEditText", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [69], - "metaKey": [true] + "keyCode": [69] } } }, { "command": "previousEditText", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [69], - "metaKey": [true], "shiftKey": [true] } } @@ -153,18 +157,18 @@ { "command": "nextFormField", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [70], - "metaKey": [true] + "keyCode": [70] } } }, { "command": "previousFormField", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [70], - "metaKey": [true], "shiftKey": [true] } } @@ -172,18 +176,18 @@ { "command": "nextHeading", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [72], - "metaKey": [true] + "keyCode": [72] } } }, { "command": "previousHeading", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [72], - "metaKey": [true], "shiftKey": [true] } } @@ -191,18 +195,18 @@ { "command": "nextLink", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [67], - "metaKey": [true] + "keyCode": [67] } } }, { "command": "previousLink", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [76], - "metaKey": [true], "shiftKey": [true] } } @@ -210,18 +214,18 @@ { "command": "nextTable", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [84], - "metaKey": [true] + "keyCode": [84] } } }, { "command": "previousTable", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [84], - "metaKey": [true], "shiftKey": [true] } } @@ -229,18 +233,18 @@ { "command": "nextVisitedLink", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [86], - "metaKey": [true] + "keyCode": [86] } } }, { "command": "previousVisitedLink", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [86], - "metaKey": [true], "shiftKey": [true] } } @@ -248,9 +252,9 @@ { "command": "goToEnd", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [39], - "metaKey": [true], "ctrlKey": [true] } } @@ -258,9 +262,9 @@ { "command": "goToBeginning", "sequence": { + "cvoxModifier": true, "keys": { "keyCode": [37], - "metaKey": [true], "ctrlKey": [true] } } @@ -268,15 +272,6 @@ { "command": "doDefault", "sequence": { - "keys": { - "keyCode": [32], - "metaKey": [true] - } - } - }, - { - "command": "showContextMenu", - "sequence": { "cvoxModifier": true, "keys": { "keyCode": [32] @@ -284,11 +279,21 @@ } }, { + "command": "showContextMenu", + "sequence": { + "cvoxModifier": true, + "keys": { + "keyCode": [32], + "shitKey": [true] + } + } + }, + { "command": "continuousRead", "sequence": { + "cvoxModifier": true, "keys": { - "keyCode": [82], - "metaKey": [true] + "keyCode": [82] } } }, @@ -297,7 +302,8 @@ "sequence": { "cvoxModifier": true, "keys": { - "keyCode": [81] + "keyCode": [81], + "shitKey": [true] } } }
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox_assets.gypi b/chrome/browser/resources/chromeos/chromevox/chromevox_assets.gypi index 61c8479..f7a52346 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox_assets.gypi +++ b/chrome/browser/resources/chromeos/chromevox/chromevox_assets.gypi
@@ -4,11 +4,16 @@ { 'variables': { - 'chromevox_assets_chromevox': [ - 'chromevox/chromevox-128.png', - 'chromevox/chromevox-16.png', - 'chromevox/chromevox-19.png', - 'chromevox/chromevox-48.png', + 'chromevox_assets_images': [ + 'images/chromevox-128.png', + 'images/chromevox-16.png', + 'images/chromevox-19.png', + 'images/chromevox-48.png', + 'images/close-19.png', + 'images/close-hover-19.png', + 'images/options-19.png', + 'images/options-hover-19.png', + 'images/triangle-6.png', ], 'chromevox_assets_chromevox_background_earcons': [ 'chromevox/background/earcons/alert_modal.ogg', @@ -92,9 +97,9 @@ 'type': 'none', 'copies': [ { - 'destination': '<(chromevox_dest_dir)/chromevox', + 'destination': '<(chromevox_dest_dir)/images', 'files': [ - '<@(chromevox_assets_chromevox)', + '<@(chromevox_assets_images)', ], }, {
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox_vars.gypi b/chrome/browser/resources/chromeos/chromevox/chromevox_vars.gypi index c6997ce..59dfde51 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox_vars.gypi +++ b/chrome/browser/resources/chromeos/chromevox/chromevox_vars.gypi
@@ -6,10 +6,11 @@ { 'variables': { - 'chromevox1_content_script_loader_file': 'chromevox/injected/loader.js', - 'chromevox1_kbexplorer_loader_file': 'chromevox/background/kbexplorer_loader.js', - 'chromevox1_options_script_loader_file': 'chromevox/background/options_loader.js', - 'chromevox2_background_script_loader_file': 'cvox2/background/loader.js', + 'chromevox_content_script_loader_file': 'chromevox/injected/loader.js', + 'chromevox_kbexplorer_loader_file': 'chromevox/background/kbexplorer_loader.js', + 'chromevox_options_script_loader_file': 'chromevox/background/options_loader.js', + 'chromevox_background_script_loader_file': 'cvox2/background/loader.js', + 'chromevox_panel_script_loader_file': 'cvox2/background/panel_loader.js', 'chromevox_extension_key': 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDltVl1k15pjRzuZfMc3B69inxwm2bZeZ2O8/zFO+NluHnBm3GJ3fzdOoFGJd+M16I8p7zxxQyHeDMfWYASyCeB8XnUEDKjqNLQfCnncsANzHsYoEbYj2nEUML2P13b9q+AAvpCBpAJ4cZp81e9n1y/vbSXHE4385cgkKueItzikQIDAQAB', } }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js index 424cfda..f09e724 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -121,6 +121,14 @@ }).bind(this) }); + Object.defineProperty(cvox.ChromeVox, 'modKeyStr', { + get: function() { + return (this.mode_ == ChromeVoxMode.CLASSIC || this.mode_ == + ChromeVoxMode.COMPAT) ? + 'Search+Shift' : 'Search'; + }.bind(this) + }); + document.addEventListener( 'keydown', cvox.ChromeVoxKbHandler.basicKeyDownActionsListener, true); cvox.ChromeVoxKbHandler.commandHandler = this.onGotCommand.bind(this); @@ -353,8 +361,7 @@ } break; case 'showOptionsPage': - var optionsPage = {url: 'chromevox/background/options.html'}; - chrome.tabs.create(optionsPage); + chrome.runtime.openOptionsPage(); break; case 'toggleChromeVoxVersion': var newMode; @@ -412,6 +419,14 @@ }, /** + * Open the options page in a new tab. + */ + showOptionsPage: function() { + var optionsPage = {url: 'chromevox/background/options.html'}; + chrome.tabs.create(optionsPage); + }, + + /** * Handles a braille command. * @param {!cvox.BrailleKeyEvent} evt * @param {!cvox.NavBraille} content
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.html b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.html new file mode 100644 index 0000000..454e67c --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.html
@@ -0,0 +1,149 @@ +<!-- Copyright 2015 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> +<html> +<head> +<meta charset="utf-8"> +<title class="i18n" msgid="panel_title"></title> + +<link href='http://fonts.googleapis.com/css?family=Droid+Sans+Mono|Roboto:400,700,700italic' rel='stylesheet' type='text/css'> + +<script type="text/javascript" src="../../closure/base.js"></script> +<script type="text/javascript" src="../../deps.js"></script> +<script type="text/javascript" src="panel_loader.js"></script> +<script type="text/javascript" src="../../chromeVoxPanelScript.js"> +</script> +<style> + body { + padding: 0; + border: 0; + margin: 0; + height: 35px; + overflow: hidden; + } + #main { + position: fixed; + left: 0; + top: 0; + right: 0; + height: 35px; + background-color: #000; + display: flex; + } + button { + border: 0; + padding: 0; + margin: 0; + background-color: #000; + outline: none; + } + #menu { + min-width: 52px; + height: 35px; + } + #menu:hover { + background-color: #f69139; + } + #options_close { + min-width: 48px; + height: 35px; + } + #chromevox { + width: 19px; + height: 19px; + margin: 8px 0; + } + #triangle { + width: 6px; + height: 6px; + margin: 14px 0; + } + #options { + background-image: url('/images/options-19.png'); + width: 19px; + height: 19px; + margin: 8px 0; + } + #options:hover { + background-image: url('/images/options-hover-19.png'); + } + #close { + background-image: url('/images/close-19.png'); + width: 19px; + height: 19px; + } + #close:hover { + background-image: url('/images/close-hover-19.png'); + } + #caption { + color: #fff; + margin-left: 12px; + flex-grow: 1; + } + #speech-container { + height: 35px; + margin-left: 12px; + } + #speech { + height: 35px; + line-height: 35px; + font-family: 'Roboto', sans-serif; + font-size: 12pt; + overflow: hidden; + } + .usertext { + font-weight: 700; + font-style: italic; + } + #braille-container { + position: relative; + top: -35px; + height: 35px; + } + #braille-text { + height: 17px; + line-height: 17px; + font-family: 'Droid Sans Mono', Courier, monospace; + font-size: 12pt; + letter-spacing: 3.13px; + white-space: pre; + } + #braille-cells { + height: 17px; + line-height: 17px; + font-family: 'Droid Sans Mono', Courier, monospace; + font-size: 13pt; + white-space: pre; + } +</style> + +</head> + +<html> + +<body> +<div id="main"> + <div hidden id="menu_title" class="i18n" msgid="menu_title"></div> + <button id="menu" aria-labelledby="menu_title"> + <img id="chromevox" src="/images/chromevox-19.png"> + <img id="triangle" src="/images/triangle-6.png"> + </button> + <div id="caption"> + <div id="speech-container"> + <div id="speech"></div> + </div> + <div id="braille-container"> + <div id="braille-text"></div> + <div id="braille-cells"></div> + </div> + </div> + <div id="options_close"> + <div hidden id="options_title" class="i18n" msgid="options"></div> + <button id="options" aria-labelledby="options_title"></button> + <div hidden id="disable_chromevox_title" class="i18n" + msgid="disable_chromevox"></div> + <button id="close" aria-labelledby="disable_chromevox_title"></button> + </div> +</div> +</body> +</html>
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js new file mode 100644 index 0000000..286fc92 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js
@@ -0,0 +1,150 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview ChromeVox panel. + * + */ + +goog.provide('Panel'); + +goog.require('Msgs'); +goog.require('PanelCommand'); + +function $(id) { + return document.getElementById(id); +} + +/** + * Class to manage the panel. + * @constructor + */ +Panel = function() { +}; + +/** + * Initialize the panel. + */ +Panel.init = function() { + /** @type {Element} @private */ + this.speechContainer_ = $('speech-container'); + + /** @type {Element} @private */ + this.speechElement_ = $('speech'); + + /** @type {Element} @private */ + this.brailleContainer_ = $('braille-container'); + + /** @type {Element} @private */ + this.brailleTextElement_ = $('braille-text'); + + /** @type {Element} @private */ + this.brailleCellsElement_ = $('braille-cells'); + + Panel.updateFromPrefs(); + window.addEventListener('storage', function(event) { + if (event.key == 'brailleCaptions') { + Panel.updateFromPrefs(); + } + }, false); + + window.addEventListener('message', function(message) { + var command = JSON.parse(message.data); + Panel.exec(/** @type {PanelCommand} */(command)); + }, false); + + $('menu').addEventListener('click', Panel.onMenu, false); + $('options').addEventListener('click', Panel.onOptions, false); + $('close').addEventListener('click', Panel.onClose, false); + + Msgs.addTranslatedMessagesToDom(document); +}; + +/** + * Update the display based on prefs. + */ +Panel.updateFromPrefs = function() { + if (localStorage['brailleCaptions'] === String(true)) { + this.speechContainer_.style.visibility = 'hidden'; + this.brailleContainer_.style.visibility = 'visible'; + } else { + this.speechContainer_.style.visibility = 'visible'; + this.brailleContainer_.style.visibility = 'hidden'; + } +}; + +/** + * Execute a command to update the panel. + * + * @param {PanelCommand} command The command to execute. + */ +Panel.exec = function(command) { + /** + * Escape text so it can be safely added to HTML. + * @param {*} str Text to be added to HTML, will be cast to string. + * @return {string} The escaped string. + */ + function escapeForHtml(str) { + return String(str) + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/\>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/\//g, '/'); + } + + switch (command.type) { + case PanelCommandType.CLEAR_SPEECH: + this.speechElement_.innerHTML = ''; + break; + case PanelCommandType.ADD_NORMAL_SPEECH: + if (this.speechElement_.innerHTML != '') { + this.speechElement_.innerHTML += ' '; + } + this.speechElement_.innerHTML += '<span class="usertext">' + + escapeForHtml(command.data) + + '</span>'; + break; + case PanelCommandType.ADD_ANNOTATION_SPEECH: + if (this.speechElement_.innerHTML != '') { + this.speechElement_.innerHTML += ' '; + } + this.speechElement_.innerHTML += escapeForHtml(command.data); + break; + case PanelCommandType.UPDATE_BRAILLE: + this.brailleTextElement_.textContent = command.data.text; + this.brailleCellsElement_.textContent = command.data.braille; + break; + } +}; + +/** + * Open the ChromeVox Menu. + */ +Panel.onMenu = function() { + window.location = '#fullscreen'; + // TODO(dmazzoni): implement the menu UI here. +}; + +/** + * Open the ChromeVox Options. + */ +Panel.onOptions = function() { + var bkgnd = + chrome.extension.getBackgroundPage()['global']['backgroundObj']; + bkgnd['showOptionsPage'](); + window.location = '#'; +}; + +/** + * Exit ChromeVox. + */ +Panel.onClose = function() { + window.location = '#close'; +}; + +window.addEventListener('load', function() { + Panel.init(); +}, false);
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel_command.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel_command.js new file mode 100644 index 0000000..473a305 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel_command.js
@@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Commands to pass from the ChromeVox background page context + * to the ChromeVox Panel. + */ + +goog.provide('PanelCommand'); +goog.provide('PanelCommandType'); + +/** + * Create one command to pass to the ChromeVox Panel. + * @param {PanelCommandType} type The type of command. + * @param {string|{text: string, braille: string}=} opt_data + * Optional data associated with the command. + * @constructor + */ +PanelCommand = function(type, opt_data) { + this.type = type; + this.data = opt_data; +}; + +/** + * Send this command to the ChromeVox Panel window. + */ +PanelCommand.prototype.send = function() { + var views = chrome.extension.getViews(); + for (var i = 0; i < views.length; i++) { + if (views[i].location.href.indexOf('background/panel.html') > 0) { + views[i].postMessage(JSON.stringify(this), window.location.origin); + } + } +}; + +/** + * Possible panel commands. + * @enum {string} + */ +PanelCommandType = { + CLEAR_SPEECH: 'clear_speech', + ADD_NORMAL_SPEECH: 'add_normal_speech', + ADD_ANNOTATION_SPEECH: 'add_annotation_speech', + UPDATE_BRAILLE: 'update_braille', +};
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel_loader.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel_loader.js new file mode 100644 index 0000000..1d7156c --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel_loader.js
@@ -0,0 +1,10 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Loads the panel script. + * + */ + +goog.require('Panel');
diff --git a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js index 7edb8720..a70c7588 100644 --- a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js +++ b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
@@ -10,6 +10,7 @@ goog.provide('cvox.TtsBackground'); +goog.require('PanelCommand'); goog.require('cvox.AbstractTts'); goog.require('cvox.ChromeTtsBase'); goog.require('cvox.ChromeVox'); @@ -301,6 +302,9 @@ // make a note that we're going to stop speech. if (queueMode == cvox.QueueMode.FLUSH || queueMode == cvox.QueueMode.CATEGORY_FLUSH) { + (new PanelCommand( + PanelCommandType.CLEAR_SPEECH)).send(); + if (this.shouldCancel_(this.currentUtterance_, utterance, queueMode)) { this.cancelUtterance_(this.currentUtterance_); this.currentUtterance_ = null; @@ -320,6 +324,19 @@ // Next, add the new utterance to the queue. this.utteranceQueue_.push(utterance); + // Update the caption panel. + if (utterance.properties && + utterance.properties['pitch'] && + utterance.properties['pitch'] < this.ttsProperties['pitch']) { + (new PanelCommand( + PanelCommandType.ADD_ANNOTATION_SPEECH, + utterance.textString)).send(); + } else { + (new PanelCommand( + PanelCommandType.ADD_NORMAL_SPEECH, + utterance.textString)).send(); + } + // Now start speaking the next item in the queue. this.startSpeakingNextItemInQueue_(); }; @@ -499,6 +516,7 @@ this.utteranceQueue_.length = 0; + (new PanelCommand(PanelCommandType.CLEAR_SPEECH)).send(); chrome.tts.stop(); };
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/chromevox-128.png b/chrome/browser/resources/chromeos/chromevox/images/chromevox-128.png similarity index 100% rename from chrome/browser/resources/chromeos/chromevox/chromevox/chromevox-128.png rename to chrome/browser/resources/chromeos/chromevox/images/chromevox-128.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/chromevox-16.png b/chrome/browser/resources/chromeos/chromevox/images/chromevox-16.png similarity index 100% rename from chrome/browser/resources/chromeos/chromevox/chromevox/chromevox-16.png rename to chrome/browser/resources/chromeos/chromevox/images/chromevox-16.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/chromevox-19.png b/chrome/browser/resources/chromeos/chromevox/images/chromevox-19.png similarity index 100% rename from chrome/browser/resources/chromeos/chromevox/chromevox/chromevox-19.png rename to chrome/browser/resources/chromeos/chromevox/images/chromevox-19.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/chromevox-48.png b/chrome/browser/resources/chromeos/chromevox/images/chromevox-48.png similarity index 100% rename from chrome/browser/resources/chromeos/chromevox/chromevox/chromevox-48.png rename to chrome/browser/resources/chromeos/chromevox/images/chromevox-48.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/images/close-19.png b/chrome/browser/resources/chromeos/chromevox/images/close-19.png new file mode 100644 index 0000000..83a62c87 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/images/close-19.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/images/close-hover-19.png b/chrome/browser/resources/chromeos/chromevox/images/close-hover-19.png new file mode 100644 index 0000000..96cf00b8 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/images/close-hover-19.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/images/options-19.png b/chrome/browser/resources/chromeos/chromevox/images/options-19.png new file mode 100644 index 0000000..6187118 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/images/options-19.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/images/options-hover-19.png b/chrome/browser/resources/chromeos/chromevox/images/options-hover-19.png new file mode 100644 index 0000000..660cb7ec --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/images/options-hover-19.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/images/options.png b/chrome/browser/resources/chromeos/chromevox/images/options.png new file mode 100644 index 0000000..5b3fc68 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/images/options.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/images/triangle-6.png b/chrome/browser/resources/chromeos/chromevox/images/triangle-6.png new file mode 100644 index 0000000..f003a1d2 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/images/triangle-6.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2 b/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2 index ec3777e..5618c7fc 100644 --- a/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2 +++ b/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2
@@ -91,5 +91,10 @@ } }, "options_page": "chromevox/background/options.html", - "default_locale": "en" + "default_locale": "en", + "icons": { + "16": "images/chromevox-16.png", + "48": "images/chromevox-48.png", + "128": "images/chromevox-128.png" + } }
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index b46310f..d1b911c7 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -2397,6 +2397,20 @@ <message desc="Describes the volume up key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_UP_KEY"> volume up </message> + + <!-- Panel --> + <message desc="Title of the ChromeVox panel, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_TITLE"> + ChromeVox Panel + </message> + <message desc="Title of the button that opens up the ChromeVox menu." name="IDS_CHROMEVOX_MENU_TITLE"> + ChromeVox Menu + </message> + <message desc="Title of the button that opens up the ChromeVox menu." name="IDS_CHROMEVOX_OPTIONS"> + ChromeVox Options + </message> + <message desc="Title of the button that disables ChromeVox." name="IDS_CHROMEVOX_DISABLE_CHROMEVOX"> + Disable ChromeVox + </message> </messages> </release> </grit>
diff --git a/chrome/browser/resources/chromeos/chromevox/tools/check_chromevox.py b/chrome/browser/resources/chromeos/chromevox/tools/check_chromevox.py index bb5cb4d..1ff2f26 100755 --- a/chrome/browser/resources/chromeos/chromevox/tools/check_chromevox.py +++ b/chrome/browser/resources/chromeos/chromevox/tools/check_chromevox.py
@@ -61,6 +61,7 @@ [[CVoxPath('chromevox/background/options_loader.js')], _COMMON_EXTERNS], [[CVoxPath('chromevox/injected/loader.js')], _COMMON_EXTERNS], [[CVoxPath('cvox2/background/loader.js')], _COMMON_EXTERNS], + [[CVoxPath('cvox2/background/panel_loader.js')], _COMMON_EXTERNS], ]
diff --git a/chrome/browser/resources/chromeos/keyboard_overlay_data.js b/chrome/browser/resources/chromeos/keyboard_overlay_data.js index 771221a..f929a27 100644 --- a/chrome/browser/resources/chromeos/keyboard_overlay_data.js +++ b/chrome/browser/resources/chromeos/keyboard_overlay_data.js
@@ -15776,7 +15776,6 @@ '-<>CTRL<>SHIFT': 'keyboardOverlayZoomScreenOut', '-<>SEARCH': 'keyboardOverlayF11', '.<>ALT<>CTRL': 'keyboardOverlayNextUser', - '.<>CTRL<>SHIFT': 'keyboardOverlayToggleSpeechInput', '.<>SEARCH': 'keyboardOverlayInsert', '/<>ALT<>CTRL': 'keyboardOverlayViewKeyboardOverlay', '/<>ALT<>CTRL<>SHIFT': 'keyboardOverlayViewKeyboardOverlay',
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html index 5afc4c7..fbea6e3 100644 --- a/chrome/browser/resources/settings/a11y_page/a11y_page.html +++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -21,10 +21,10 @@ </settings-checkbox> <settings-checkbox pref="{{prefs.settings.a11y.sticky_keys_enabled}}" - i18n-values="label:stickyKeysLabel; subLabel:stickyKeysSublabel"> + i18n-values="label:stickyKeysLabel"> </settings-checkbox> <settings-checkbox pref="{{prefs.settings.accessibility}}" - i18n-values="label:chromeVoxLabel; subLabel:chromeVoxSublabel"> + i18n-values="label:chromeVoxLabel"> </settings-checkbox> <settings-checkbox i18n-values="label:screenMagnifierLabel" pref="{{prefs.settings.a11y.screen_magnifier}}">
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index 83ecc0b..c78428c8 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -778,9 +778,6 @@ case IDC_SHOW_SIGNIN: ShowBrowserSigninOrSettings(browser_, signin_metrics::SOURCE_MENU); break; - case IDC_TOGGLE_SPEECH_INPUT: - ToggleSpeechInput(browser_); - break; case IDC_DISTILL_PAGE: DistillCurrentPage(browser_); break; @@ -1036,9 +1033,6 @@ command_updater_.UpdateCommandEnabled(IDC_UPGRADE_DIALOG, true); command_updater_.UpdateCommandEnabled(IDC_VIEW_INCOMPATIBILITIES, true); - // Toggle speech input - command_updater_.UpdateCommandEnabled(IDC_TOGGLE_SPEECH_INPUT, true); - // Distill current page. command_updater_.UpdateCommandEnabled( IDC_DISTILL_PAGE, base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 12f21b3..8b7e06b 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -1131,15 +1131,6 @@ } } -void ToggleSpeechInput(Browser* browser) { - SearchTabHelper* search_tab_helper = - SearchTabHelper::FromWebContents( - browser->tab_strip_model()->GetActiveWebContents()); - // |search_tab_helper| can be null in unit tests. - if (search_tab_helper) - search_tab_helper->ToggleVoiceSearch(); -} - void DistillCurrentPage(Browser* browser) { DistillCurrentPageAndView(browser->tab_strip_model()->GetActiveWebContents()); }
diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h index 3b32291..153188d 100644 --- a/chrome/browser/ui/browser_commands.h +++ b/chrome/browser/ui/browser_commands.h
@@ -147,7 +147,6 @@ void ShowAvatarMenu(Browser* browser); void ShowFastUserSwitcher(Browser* browser); void OpenUpdateChromeDialog(Browser* browser); -void ToggleSpeechInput(Browser* browser); void DistillCurrentPage(Browser* browser); bool CanRequestTabletSite(content::WebContents* current_tab); bool IsRequestingTabletSite(Browser* browser);
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h index 692a360..b2adbb32 100644 --- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h +++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
@@ -17,7 +17,6 @@ #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" #include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.h" -#include "chrome/browser/ui/search/search_model_observer.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/ui/zoom/zoom_event_manager_observer.h" @@ -29,7 +28,6 @@ class LocationBarDecoration; class LocationIconDecoration; class ManagePasswordsDecoration; -class MicSearchDecoration; class PageActionDecoration; class Profile; class SelectedKeywordDecoration; @@ -45,7 +43,6 @@ class LocationBarViewMac : public LocationBar, public LocationBarTesting, public ChromeOmniboxEditController, - public SearchModelObserver, public ui_zoom::ZoomEventManagerObserver { public: LocationBarViewMac(AutocompleteTextField* field, @@ -172,10 +169,6 @@ return manage_passwords_decoration_.get(); } - // SearchModelObserver: - void ModelChanged(const SearchModel::State& old_state, - const SearchModel::State& new_state) override; - Browser* browser() const { return browser_; } // ZoomManagerObserver: @@ -219,10 +212,6 @@ // Returns whether any updates were made. bool UpdateZoomDecoration(bool default_zoom_changed); - // Updates the voice search decoration. Returns true if the visible state was - // changed. - bool UpdateMicSearchDecorationVisibility(); - scoped_ptr<OmniboxViewMac> omnibox_view_; AutocompleteTextField* field_; // owned by tab controller @@ -256,9 +245,6 @@ // Keyword hint decoration displayed on the right-hand side. scoped_ptr<KeywordHintDecoration> keyword_hint_decoration_; - // The voice search icon. - scoped_ptr<MicSearchDecoration> mic_search_decoration_; - // The right-hand-side button to manage passwords associated with a page. scoped_ptr<ManagePasswordsDecoration> manage_passwords_decoration_;
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 780c1a3f..dd22784 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
@@ -40,7 +40,6 @@ #import "chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h" #import "chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h" #import "chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration.h" -#import "chrome/browser/ui/cocoa/location_bar/mic_search_decoration.h" #import "chrome/browser/ui/cocoa/location_bar/page_action_decoration.h" #import "chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h" #import "chrome/browser/ui/cocoa/location_bar/star_decoration.h" @@ -102,7 +101,6 @@ translate_decoration_(new TranslateDecoration(command_updater)), zoom_decoration_(new ZoomDecoration(this)), keyword_hint_decoration_(new KeywordHintDecoration()), - mic_search_decoration_(new MicSearchDecoration(command_updater)), manage_passwords_decoration_( new ManagePasswordsDecoration(command_updater, this)), browser_(browser), @@ -122,8 +120,6 @@ base::Bind(&LocationBarViewMac::OnEditBookmarksEnabledChanged, base::Unretained(this))); - browser_->search_model()->AddObserver(this); - ui_zoom::ZoomEventManager::GetForBrowserContext(profile) ->AddZoomEventManagerObserver(this); @@ -139,7 +135,6 @@ // Disconnect from cell in case it outlives us. [[field_ cell] clearDecorations]; - browser_->search_model()->RemoveObserver(this); ui_zoom::ZoomEventManager::GetForBrowserContext(profile()) ->RemoveZoomEventManagerObserver(this); } @@ -413,7 +408,6 @@ } [cell addRightDecoration:keyword_hint_decoration_.get()]; - [cell addRightDecoration:mic_search_decoration_.get()]; // By default only the location icon is visible. location_icon_decoration_->SetVisible(true); @@ -526,7 +520,6 @@ UpdateZoomDecoration(/*default_zoom_changed=*/false); RefreshPageActionDecorations(); RefreshContentSettingsDecorations(); - UpdateMicSearchDecorationVisibility(); if (contents) omnibox_view_->OnTabChanged(contents); else @@ -587,12 +580,6 @@ return OmniboxViewMac::ImageForResource(IDR_OMNIBOX_SEARCH); } -void LocationBarViewMac::ModelChanged(const SearchModel::State& old_state, - const SearchModel::State& new_state) { - if (UpdateMicSearchDecorationVisibility()) - Layout(); -} - void LocationBarViewMac::PostNotification(NSString* notification) { [[NSNotificationCenter defaultCenter] postNotificationName:notification object:[NSValue valueWithPointer:this]]; @@ -730,12 +717,3 @@ if (UpdateZoomDecoration(/*default_zoom_changed=*/true)) OnDecorationsChanged(); } - -bool LocationBarViewMac::UpdateMicSearchDecorationVisibility() { - bool is_visible = !GetToolbarModel()->input_in_progress() && - browser_->search_model()->voice_search_supported(); - if (mic_search_decoration_->IsVisible() == is_visible) - return false; - mic_search_decoration_->SetVisible(is_visible); - return true; -}
diff --git a/chrome/browser/ui/cocoa/location_bar/mic_search_decoration.h b/chrome/browser/ui/cocoa/location_bar/mic_search_decoration.h deleted file mode 100644 index 91c05cc..0000000 --- a/chrome/browser/ui/cocoa/location_bar/mic_search_decoration.h +++ /dev/null
@@ -1,32 +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_LOCATION_BAR_MIC_SEARCH_DECORATION_H_ -#define CHROME_BROWSER_UI_COCOA_LOCATION_BAR_MIC_SEARCH_DECORATION_H_ - -#import <Cocoa/Cocoa.h> - -#include "chrome/browser/ui/cocoa/location_bar/image_decoration.h" - -class CommandUpdater; - -// Draws a microphone icon on the right side of the omnibox. This is used for -// voice search. -class MicSearchDecoration : public ImageDecoration { - public: - explicit MicSearchDecoration(CommandUpdater* command_updater); - ~MicSearchDecoration() override; - - // Implement |LocationBarDecoration|. - bool AcceptsMousePress() override; - bool OnMousePressed(NSRect frame, NSPoint location) override; - NSString* GetToolTip() override; - - private: - CommandUpdater* command_updater_; // Weak, owned by Browser. - - DISALLOW_COPY_AND_ASSIGN(MicSearchDecoration); -}; - -#endif // CHROME_BROWSER_UI_COCOA_LOCATION_BAR_MIC_SEARCH_DECORATION_H_
diff --git a/chrome/browser/ui/cocoa/location_bar/mic_search_decoration.mm b/chrome/browser/ui/cocoa/location_bar/mic_search_decoration.mm deleted file mode 100644 index f8b01849..0000000 --- a/chrome/browser/ui/cocoa/location_bar/mic_search_decoration.mm +++ /dev/null
@@ -1,33 +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/location_bar/mic_search_decoration.h" - -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/command_updater.h" -#import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" -#include "chrome/grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "ui/base/l10n/l10n_util_mac.h" - -MicSearchDecoration::MicSearchDecoration(CommandUpdater* command_updater) - : command_updater_(command_updater) { - SetImage(OmniboxViewMac::ImageForResource(IDR_OMNIBOX_MIC_SEARCH)); -} - -MicSearchDecoration::~MicSearchDecoration() { -} - -bool MicSearchDecoration::AcceptsMousePress() { - return true; -} - -bool MicSearchDecoration::OnMousePressed(NSRect frame, NSPoint location) { - command_updater_->ExecuteCommand(IDC_TOGGLE_SPEECH_INPUT); - return true; -} - -NSString* MicSearchDecoration::GetToolTip() { - return l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_MIC_SEARCH); -}
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm index b61581e..eb8de39 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm
@@ -196,7 +196,7 @@ // window. To fix, explicitly set the tab's new location so that it's // correct at tearoff time. See http://crbug.com/541674 . NSRect newTabFrame = [[draggedTab_ tabView] frame]; - newTabFrame.origin.x = sourceTabFrame_.origin.x + offset; + newTabFrame.origin.x = trunc(sourceTabFrame_.origin.x + offset); // Ensure that the tab won't extend beyond the right edge of the tab area // in the tab strip.
diff --git a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm index e7655be..5d99c136 100644 --- a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm +++ b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm
@@ -72,7 +72,6 @@ i == VIEW_ID_BROWSER_ACTION || i == VIEW_ID_FEEDBACK_BUTTON || i == VIEW_ID_SCRIPT_BUBBLE || - i == VIEW_ID_MIC_SEARCH_BUTTON || i == VIEW_ID_SAVE_CREDIT_CARD_BUTTON || i == VIEW_ID_TRANSLATE_BUTTON) { continue;
diff --git a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc index 34a519e..44167e8 100644 --- a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc +++ b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
@@ -139,9 +139,8 @@ submit_count_(0), on_esc_key_press_event_calls_(0), on_focus_changed_calls_(0), - is_focused_(false), - on_toggle_voice_search_calls_(0) { - } + is_focused_(false) {} + protected: void SetUpInProcessBrowserTestFixture() override { search::EnableQueryExtractionForTesting(); @@ -185,8 +184,6 @@ &on_focus_changed_calls_) && GetBoolFromJS(contents, "isFocused", &is_focused_) && - GetIntFromJS(contents, "onToggleVoiceSearchCalls", - &on_toggle_voice_search_calls_) && GetStringFromJS(contents, "prefetchQuery", &prefetch_query_value_); } @@ -247,7 +244,6 @@ std::string query_value_; int on_focus_changed_calls_; bool is_focused_; - int on_toggle_voice_search_calls_; std::string prefetch_query_value_; };
diff --git a/chrome/browser/ui/search/search_ipc_router.cc b/chrome/browser/ui/search/search_ipc_router.cc index 72598b2..18de364 100644 --- a/chrome/browser/ui/search/search_ipc_router.cc +++ b/chrome/browser/ui/search/search_ipc_router.cc
@@ -137,13 +137,6 @@ Send(new ChromeViewMsg_SearchBoxThemeChanged(routing_id(), theme_info)); } -void SearchIPCRouter::ToggleVoiceSearch() { - if (!policy_->ShouldSendToggleVoiceSearch()) - return; - - Send(new ChromeViewMsg_SearchBoxToggleVoiceSearch(routing_id())); -} - void SearchIPCRouter::Submit(const base::string16& text, const EmbeddedSearchRequestParams& params) { if (!policy_->ShouldSubmitQuery()) @@ -173,8 +166,6 @@ IPC_BEGIN_MESSAGE_MAP(SearchIPCRouter, message) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_InstantSupportDetermined, OnInstantSupportDetermined) - IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SetVoiceSearchSupported, - OnVoiceSearchSupportDetermined) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FocusOmnibox, OnFocusOmnibox); IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxNavigate, OnSearchBoxNavigate); @@ -208,19 +199,6 @@ delegate_->OnInstantSupportDetermined(instant_support); } -void SearchIPCRouter::OnVoiceSearchSupportDetermined( - int page_seq_no, - bool supports_voice_search) const { - if (page_seq_no != commit_counter_) - return; - - delegate_->OnInstantSupportDetermined(true); - if (!policy_->ShouldProcessSetVoiceSearchSupport()) - return; - - delegate_->OnSetVoiceSearchSupport(supports_voice_search); -} - void SearchIPCRouter::OnFocusOmnibox(int page_seq_no, OmniboxFocusState state) const { if (page_seq_no != commit_counter_)
diff --git a/chrome/browser/ui/search/search_ipc_router.h b/chrome/browser/ui/search/search_ipc_router.h index 0f62aba..e0f3749 100644 --- a/chrome/browser/ui/search/search_ipc_router.h +++ b/chrome/browser/ui/search/search_ipc_router.h
@@ -36,9 +36,6 @@ // load event. virtual void OnInstantSupportDetermined(bool supports_instant) = 0; - // Called upon determination of voice search API support. - virtual void OnSetVoiceSearchSupport(bool supports_voice_search) = 0; - // Called when the page wants the omnibox to be focused. |state| specifies // the omnibox focus state. virtual void FocusOmnibox(OmniboxFocusState state) = 0; @@ -100,7 +97,6 @@ // SearchIPCRouter calls these functions before sending/receiving messages // to/from the page. - virtual bool ShouldProcessSetVoiceSearchSupport() = 0; virtual bool ShouldProcessFocusOmnibox(bool is_active_tab) = 0; virtual bool ShouldProcessNavigateToURL(bool is_active_tab) = 0; virtual bool ShouldProcessDeleteMostVisitedItem() = 0; @@ -118,7 +114,6 @@ virtual bool ShouldSendOmniboxFocusChanged() = 0; virtual bool ShouldSendMostVisitedItems() = 0; virtual bool ShouldSendThemeBackgroundInfo() = 0; - virtual bool ShouldSendToggleVoiceSearch() = 0; virtual bool ShouldSubmitQuery() = 0; }; @@ -167,9 +162,6 @@ // Tells the renderer about the current theme background. void SendThemeBackgroundInfo(const ThemeBackgroundInfo& theme_info); - // Tells the page to toggle voice search. - void ToggleVoiceSearch(); - // Tells the page that the user pressed Enter in the omnibox. void Submit(const base::string16& text, const EmbeddedSearchRequestParams& params); @@ -199,8 +191,6 @@ bool OnMessageReceived(const IPC::Message& message) override; void OnInstantSupportDetermined(int page_seq_no, bool supports_instant) const; - void OnVoiceSearchSupportDetermined(int page_id, - bool supports_voice_search) const; void OnFocusOmnibox(int page_id, OmniboxFocusState state) const; void OnSearchBoxNavigate(int page_id, const GURL& url,
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc index 4a85e2fb..382038a0 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc +++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
@@ -22,10 +22,6 @@ SearchIPCRouterPolicyImpl::~SearchIPCRouterPolicyImpl() {} -bool SearchIPCRouterPolicyImpl::ShouldProcessSetVoiceSearchSupport() { - return true; -} - bool SearchIPCRouterPolicyImpl::ShouldProcessFocusOmnibox(bool is_active_tab) { return is_active_tab && !is_incognito_ && search::IsInstantNTP(web_contents_); } @@ -96,10 +92,6 @@ return !is_incognito_ && search::IsInstantNTP(web_contents_); } -bool SearchIPCRouterPolicyImpl::ShouldSendToggleVoiceSearch() { - return true; -} - bool SearchIPCRouterPolicyImpl::ShouldSubmitQuery() { return true; }
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.h b/chrome/browser/ui/search/search_ipc_router_policy_impl.h index b98044f..7cd10fe 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_impl.h +++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.h
@@ -21,7 +21,6 @@ friend class SearchIPCRouterPolicyTest; // Overridden from SearchIPCRouter::Policy: - bool ShouldProcessSetVoiceSearchSupport() override; bool ShouldProcessFocusOmnibox(bool is_active_tab) override; bool ShouldProcessNavigateToURL(bool is_active_tab) override; bool ShouldProcessDeleteMostVisitedItem() override; @@ -39,7 +38,6 @@ bool ShouldSendOmniboxFocusChanged() override; bool ShouldSendMostVisitedItems() override; bool ShouldSendThemeBackgroundInfo() override; - bool ShouldSendToggleVoiceSearch() override; bool ShouldSubmitQuery() override; // Used by unit tests.
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc b/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc index f358a381..ad221b5 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc +++ b/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc
@@ -41,12 +41,6 @@ } }; -TEST_F(SearchIPCRouterPolicyTest, ProcessVoiceSearchSupportMsg) { - NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); - EXPECT_TRUE(GetSearchIPCRouterPolicy()-> - ShouldProcessSetVoiceSearchSupport()); -} - TEST_F(SearchIPCRouterPolicyTest, ProcessFocusOmnibox) { NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl)); EXPECT_TRUE(GetSearchIPCRouterPolicy()->ShouldProcessFocusOmnibox(true)); @@ -205,7 +199,6 @@ SearchIPCRouter::Policy* router_policy = GetSearchIPCRouterPolicy(); EXPECT_TRUE(router_policy->ShouldSubmitQuery()); - EXPECT_TRUE(router_policy->ShouldSendToggleVoiceSearch()); EXPECT_TRUE(router_policy->ShouldSendSetOmniboxStartMargin()); } @@ -236,8 +229,3 @@ NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); EXPECT_TRUE(GetSearchIPCRouterPolicy()->ShouldSubmitQuery()); } - -TEST_F(SearchIPCRouterPolicyTest, SendToggleVoiceSearch) { - NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl)); - EXPECT_TRUE(GetSearchIPCRouterPolicy()->ShouldSendToggleVoiceSearch()); -}
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc index a9507a7..defeaa23 100644 --- a/chrome/browser/ui/search/search_ipc_router_unittest.cc +++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -46,7 +46,6 @@ virtual ~MockSearchIPCRouterDelegate() {} MOCK_METHOD1(OnInstantSupportDetermined, void(bool supports_instant)); - MOCK_METHOD1(OnSetVoiceSearchSupport, void(bool supports_voice_search)); MOCK_METHOD1(FocusOmnibox, void(OmniboxFocusState state)); MOCK_METHOD3(NavigateToURL, void(const GURL&, WindowOpenDisposition, bool)); MOCK_METHOD1(OnDeleteMostVisitedItem, void(const GURL& url)); @@ -67,7 +66,6 @@ public: virtual ~MockSearchIPCRouterPolicy() {} - MOCK_METHOD0(ShouldProcessSetVoiceSearchSupport, bool()); MOCK_METHOD1(ShouldProcessFocusOmnibox, bool(bool)); MOCK_METHOD1(ShouldProcessNavigateToURL, bool(bool)); MOCK_METHOD0(ShouldProcessDeleteMostVisitedItem, bool()); @@ -85,7 +83,6 @@ MOCK_METHOD0(ShouldSendOmniboxFocusChanged, bool()); MOCK_METHOD0(ShouldSendMostVisitedItems, bool()); MOCK_METHOD0(ShouldSendThemeBackgroundInfo, bool()); - MOCK_METHOD0(ShouldSendToggleVoiceSearch, bool()); MOCK_METHOD0(ShouldSubmitQuery, bool()); }; @@ -226,32 +223,6 @@ CURRENT_TAB, true)); } -TEST_F(SearchIPCRouterTest, ProcessVoiceSearchSupportMsg) { - NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); - SetupMockDelegateAndPolicy(); - MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); - EXPECT_CALL(*mock_delegate(), OnSetVoiceSearchSupport(true)).Times(1); - EXPECT_CALL(*(policy), ShouldProcessSetVoiceSearchSupport()).Times(1) - .WillOnce(testing::Return(true)); - - content::WebContents* contents = web_contents(); - OnMessageReceived(ChromeViewHostMsg_SetVoiceSearchSupported( - contents->GetRoutingID(), GetSearchIPCRouterSeqNo(), true)); -} - -TEST_F(SearchIPCRouterTest, IgnoreVoiceSearchSupportMsg) { - NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); - EXPECT_CALL(*mock_delegate(), OnSetVoiceSearchSupport(true)).Times(0); - SetupMockDelegateAndPolicy(); - MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); - EXPECT_CALL(*policy, ShouldProcessSetVoiceSearchSupport()).Times(1) - .WillOnce(testing::Return(false)); - - content::WebContents* contents = web_contents(); - OnMessageReceived(ChromeViewHostMsg_SetVoiceSearchSupported( - contents->GetRoutingID(), GetSearchIPCRouterSeqNo(), true)); -} - TEST_F(SearchIPCRouterTest, ProcessFocusOmniboxMsg) { NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl)); SetupMockDelegateAndPolicy(); @@ -877,30 +848,6 @@ EXPECT_FALSE(MessageWasSent(ChromeViewMsg_SearchBoxSubmit::ID)); } -TEST_F(SearchIPCRouterTest, SendToggleVoiceSearch) { - NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); - SetupMockDelegateAndPolicy(); - MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); - EXPECT_CALL(*policy, ShouldSendToggleVoiceSearch()).Times(1) - .WillOnce(testing::Return(true)); - - process()->sink().ClearMessages(); - GetSearchIPCRouter().ToggleVoiceSearch(); - EXPECT_TRUE(MessageWasSent(ChromeViewMsg_SearchBoxToggleVoiceSearch::ID)); -} - -TEST_F(SearchIPCRouterTest, DoNotSendToggleVoiceSearch) { - NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); - SetupMockDelegateAndPolicy(); - MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); - EXPECT_CALL(*policy, ShouldSendToggleVoiceSearch()).Times(1) - .WillOnce(testing::Return(false)); - - process()->sink().ClearMessages(); - GetSearchIPCRouter().ToggleVoiceSearch(); - EXPECT_FALSE(MessageWasSent(ChromeViewMsg_SearchBoxToggleVoiceSearch::ID)); -} - TEST_F(SearchIPCRouterTest, SpuriousMessageTypesIgnored) { NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); SetupMockDelegateAndPolicy();
diff --git a/chrome/browser/ui/search/search_model.cc b/chrome/browser/ui/search/search_model.cc index 17d5a96..57b83bd 100644 --- a/chrome/browser/ui/search/search_model.cc +++ b/chrome/browser/ui/search/search_model.cc
@@ -7,22 +7,14 @@ #include "chrome/browser/ui/search/search_model_observer.h" #include "components/search/search.h" -SearchModel::State::State() - : instant_support(INSTANT_SUPPORT_UNKNOWN), - voice_search_supported(false) { -} +SearchModel::State::State() : instant_support(INSTANT_SUPPORT_UNKNOWN) {} SearchModel::State::State(const SearchMode& mode, - InstantSupportState instant_support, - bool voice_search_supported) - : mode(mode), - instant_support(instant_support), - voice_search_supported(voice_search_supported) { -} + InstantSupportState instant_support) + : mode(mode), instant_support(instant_support) {} bool SearchModel::State::operator==(const State& rhs) const { - return mode == rhs.mode && instant_support == rhs.instant_support && - voice_search_supported == rhs.voice_search_supported; + return mode == rhs.mode && instant_support == rhs.instant_support; } SearchModel::SearchModel() { @@ -75,21 +67,6 @@ ModelChanged(old_state, state_)); } -void SearchModel::SetVoiceSearchSupported(bool supported) { - DCHECK(search::IsInstantExtendedAPIEnabled()) - << "Please do not try to set the SearchModel state without first " - << "checking if Search is enabled."; - - if (state_.voice_search_supported == supported) - return; - - const State old_state = state_; - state_.voice_search_supported = supported; - - FOR_EACH_OBSERVER(SearchModelObserver, observers_, - ModelChanged(old_state, state_)); -} - void SearchModel::AddObserver(SearchModelObserver* observer) { observers_.AddObserver(observer); }
diff --git a/chrome/browser/ui/search/search_model.h b/chrome/browser/ui/search/search_model.h index 3e97cf2..e7e701e 100644 --- a/chrome/browser/ui/search/search_model.h +++ b/chrome/browser/ui/search/search_model.h
@@ -24,9 +24,7 @@ public: struct State { State(); - State(const SearchMode& mode, - InstantSupportState instant_support, - bool voice_search_supported); + State(const SearchMode& mode, InstantSupportState instant_support); bool operator==(const State& rhs) const; @@ -35,9 +33,6 @@ // Does the current page support Instant? InstantSupportState instant_support; - - // Does the current page support voice search? - bool voice_search_supported; }; SearchModel(); @@ -64,13 +59,6 @@ return state_.instant_support; } - // Sets the page voice search support state. Change notifications are sent to - // observers. - void SetVoiceSearchSupported(bool supported); - - // Gets the voice search support state of the page. - bool voice_search_supported() const { return state_.voice_search_supported; } - // Add and remove observers. void AddObserver(SearchModelObserver* observer); void RemoveObserver(SearchModelObserver* observer);
diff --git a/chrome/browser/ui/search/search_model_unittest.cc b/chrome/browser/ui/search/search_model_unittest.cc index 646639e..565b1cd4 100644 --- a/chrome/browser/ui/search/search_model_unittest.cc +++ b/chrome/browser/ui/search/search_model_unittest.cc
@@ -141,17 +141,3 @@ mock_observer.VerifyNotificationCount(1); EXPECT_TRUE(model->state() == expected_new_state); } - -TEST_F(SearchModelTest, UpdateVoiceSearchSupported) { - mock_observer.VerifyNotificationCount(0); - EXPECT_FALSE(model->voice_search_supported()); - - SearchModel::State expected_old_state = model->state(); - SearchModel::State expected_new_state(model->state()); - expected_new_state.voice_search_supported = true; - - model->SetVoiceSearchSupported(true); - mock_observer.VerifySearchModelStates(expected_old_state, expected_new_state); - mock_observer.VerifyNotificationCount(1); - EXPECT_TRUE(model->voice_search_supported()); -}
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc index 6ae2211..bcfac8f 100644 --- a/chrome/browser/ui/search/search_tab_helper.cc +++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -269,10 +269,6 @@ ipc_router_.OnTabDeactivated(); } -void SearchTabHelper::ToggleVoiceSearch() { - ipc_router_.ToggleVoiceSearch(); -} - bool SearchTabHelper::IsSearchResultsPage() { return model_.mode().is_origin_search(); } @@ -371,7 +367,6 @@ } model_.SetInstantSupportState(INSTANT_SUPPORT_UNKNOWN); - model_.SetVoiceSearchSupported(false); search::SetInstantSupportStateInNavigationEntry(model_.instant_support(), entry); @@ -383,10 +378,6 @@ InstantSupportChanged(supports_instant); } -void SearchTabHelper::OnSetVoiceSearchSupport(bool supports_voice_search) { - model_.SetVoiceSearchSupported(supports_voice_search); -} - void SearchTabHelper::ThemeInfoChanged(const ThemeBackgroundInfo& theme_info) { ipc_router_.SendThemeBackgroundInfo(theme_info); }
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h index 0db8127..6c5bea9 100644 --- a/chrome/browser/ui/search/search_tab_helper.h +++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -90,9 +90,6 @@ // Called when the tab corresponding to |this| instance is deactivated. void OnTabDeactivated(); - // Tells the page to toggle voice search. - void ToggleVoiceSearch(); - // Returns true if the underlying page is a search results page. bool IsSearchResultsPage(); @@ -158,7 +155,6 @@ // Overridden from SearchIPCRouter::Delegate: void OnInstantSupportDetermined(bool supports_instant) override; - void OnSetVoiceSearchSupport(bool supports_voice_search) override; void FocusOmnibox(OmniboxFocusState state) override; void NavigateToURL(const GURL& url, WindowOpenDisposition disposition,
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc index 678c8340..ecfc8c0 100644 --- a/chrome/browser/ui/search/search_tab_helper_unittest.cc +++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -54,7 +54,6 @@ virtual ~MockSearchIPCRouterDelegate() {} MOCK_METHOD1(OnInstantSupportDetermined, void(bool supports_instant)); - MOCK_METHOD1(OnSetVoiceSearchSupport, void(bool supports_voice_search)); MOCK_METHOD1(FocusOmnibox, void(OmniboxFocusState state)); MOCK_METHOD3(NavigateToURL, void(const GURL&, WindowOpenDisposition, bool)); MOCK_METHOD1(OnDeleteMostVisitedItem, void(const GURL& url));
diff --git a/chrome/browser/ui/view_ids.h b/chrome/browser/ui/view_ids.h index 17b5093..f02d601 100644 --- a/chrome/browser/ui/view_ids.h +++ b/chrome/browser/ui/view_ids.h
@@ -88,9 +88,6 @@ // The Download shelf. VIEW_ID_DOWNLOAD_SHELF, - // The omnibox icon to do voice-based search. - VIEW_ID_MIC_SEARCH_BUTTON, - // Used in chrome/browser/ui/cocoa/view_id_util_browsertest.mm. // If you add new ids, make sure the above test passes. VIEW_ID_PREDEFINED_COUNT,
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc index 021a273..30c555f 100644 --- a/chrome/browser/ui/views/accelerator_table.cc +++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -124,8 +124,6 @@ { ui::VKEY_F, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU}, { ui::VKEY_E, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU}, { ui::VKEY_ESCAPE, ui::EF_NONE, IDC_STOP }, - { ui::VKEY_OEM_PERIOD, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, - IDC_TOGGLE_SPEECH_INPUT }, { ui::VKEY_U, ui::EF_CONTROL_DOWN, IDC_VIEW_SOURCE }, { ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS }, { ui::VKEY_SUBTRACT, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS },
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 52a9952..5f8e0d2 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -35,7 +35,6 @@ #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/autofill/save_card_icon_view.h" #include "chrome/browser/ui/views/browser_dialogs.h" #include "chrome/browser/ui/views/layout_constants.h" @@ -74,7 +73,6 @@ #include "grit/theme_resources.h" #include "ui/accessibility/ax_view_state.h" #include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/theme_provider.h" @@ -94,7 +92,6 @@ #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/button_drag_utils.h" -#include "ui/views/controls/button/image_button.h" #include "ui/views/controls/label.h" #include "ui/views/widget/widget.h" @@ -140,7 +137,6 @@ selected_keyword_view_(NULL), suggested_text_view_(NULL), keyword_hint_view_(NULL), - mic_search_view_(NULL), zoom_view_(NULL), open_pdf_in_reader_view_(NULL), manage_passwords_icon_view_(NULL), @@ -158,9 +154,6 @@ base::Bind(&LocationBarView::UpdateWithoutTabRestore, base::Unretained(this))); - if (browser_) - browser_->search_model()->AddObserver(this); - ui_zoom::ZoomEventManager::GetForBrowserContext(profile) ->AddZoomEventManagerObserver(this); @@ -174,8 +167,6 @@ LocationBarView::~LocationBarView() { if (template_url_service_) template_url_service_->RemoveObserver(this); - if (browser_) - browser_->search_model()->RemoveObserver(this); ui_zoom::ZoomEventManager::GetForBrowserContext(profile()) ->RemoveZoomEventManagerObserver(this); @@ -281,20 +272,6 @@ background_color); AddChildView(keyword_hint_view_); - mic_search_view_ = new views::ImageButton(this); - mic_search_view_->set_id(VIEW_ID_MIC_SEARCH_BUTTON); - mic_search_view_->SetAccessibilityFocusable(true); - mic_search_view_->SetTooltipText( - l10n_util::GetStringUTF16(IDS_TOOLTIP_MIC_SEARCH)); - mic_search_view_->SetImage( - views::Button::STATE_NORMAL, - ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( - IDR_OMNIBOX_MIC_SEARCH)); - mic_search_view_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, - views::ImageButton::ALIGN_MIDDLE); - mic_search_view_->SetVisible(false); - AddChildView(mic_search_view_); - const SkColor text_color = GetColor(SecurityStateModel::NONE, TEXT); ScopedVector<ContentSettingImageModel> models = ContentSettingImageModel::GenerateContentSettingImageModels(); @@ -583,12 +560,11 @@ // Compute width of omnibox-trailing content. int trailing_width = horizontal_edge_thickness; trailing_width += IncrementalMinimumWidth(star_view_) + - IncrementalMinimumWidth(translate_icon_view_) + - IncrementalMinimumWidth(open_pdf_in_reader_view_) + - IncrementalMinimumWidth(save_credit_card_icon_view_) + - IncrementalMinimumWidth(manage_passwords_icon_view_) + - IncrementalMinimumWidth(zoom_view_) + - IncrementalMinimumWidth(mic_search_view_); + IncrementalMinimumWidth(translate_icon_view_) + + IncrementalMinimumWidth(open_pdf_in_reader_view_) + + IncrementalMinimumWidth(save_credit_card_icon_view_) + + IncrementalMinimumWidth(manage_passwords_icon_view_) + + IncrementalMinimumWidth(zoom_view_); for (PageActionViews::const_iterator i(page_action_views_.begin()); i != page_action_views_.end(); ++i) trailing_width += IncrementalMinimumWidth((*i)); @@ -711,10 +687,6 @@ *i); } } - if (mic_search_view_->visible()) { - trailing_decorations.AddDecoration(vertical_padding, location_height, - mic_search_view_); - } // Because IMEs may eat the tab key, we don't show "press tab to search" while // IME composition is in progress. if (!keyword.empty() && omnibox_view_->model()->is_keyword_hint() && @@ -825,9 +797,6 @@ } void LocationBarView::Update(const WebContents* contents) { - mic_search_view_->SetVisible( - !GetToolbarModel()->input_in_progress() && browser_ && - browser_->search_model()->voice_search_supported()); RefreshContentSettingViews(); RefreshZoomView(); RefreshPageActionViews(); @@ -1340,15 +1309,6 @@ } //////////////////////////////////////////////////////////////////////////////// -// LocationBarView, private views::ButtonListener implementation: - -void LocationBarView::ButtonPressed(views::Button* sender, - const ui::Event& event) { - DCHECK_EQ(mic_search_view_, sender); - command_updater()->ExecuteCommand(IDC_TOGGLE_SPEECH_INPUT); -} - -//////////////////////////////////////////////////////////////////////////////// // LocationBarView, private views::DragController implementation: void LocationBarView::WriteDragDataForView(views::View* sender, @@ -1440,16 +1400,3 @@ if (omnibox_view_ && omnibox_view_->GetWidget()->IsActive()) ShowFirstRunBubble(); } - -//////////////////////////////////////////////////////////////////////////////// -// LocationBarView, private SearchModelObserver implementation: - -void LocationBarView::ModelChanged(const SearchModel::State& old_state, - const SearchModel::State& new_state) { - const bool visible = !GetToolbarModel()->input_in_progress() && - new_state.voice_search_supported; - if (mic_search_view_->visible() != visible) { - mic_search_view_->SetVisible(visible); - Layout(); - } -}
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h index ebd57552..0b17ae7 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -14,7 +14,6 @@ #include "chrome/browser/ssl/security_state_model.h" #include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.h" -#include "chrome/browser/ui/search/search_model_observer.h" #include "chrome/browser/ui/toolbar/chrome_toolbar_model.h" #include "chrome/browser/ui/views/dropdown_bar_host.h" #include "chrome/browser/ui/views/dropdown_bar_host_delegate.h" @@ -26,7 +25,6 @@ #include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/font.h" #include "ui/gfx/geometry/rect.h" -#include "ui/views/controls/button/button.h" #include "ui/views/drag_controller.h" class ActionBoxButtonView; @@ -56,8 +54,6 @@ namespace views { class BubbleDelegateView; -class ImageButton; -class ImageView; class Label; class Widget; } @@ -73,13 +69,11 @@ class LocationBarView : public LocationBar, public LocationBarTesting, public views::View, - public views::ButtonListener, public views::DragController, public gfx::AnimationDelegate, public ChromeOmniboxEditController, public DropdownBarHostDelegate, public TemplateURLServiceObserver, - public SearchModelObserver, public ui_zoom::ZoomEventManagerObserver { public: // The location bar view's class name. @@ -373,9 +367,6 @@ void OnPaint(gfx::Canvas* canvas) override; void PaintChildren(const ui::PaintContext& context) override; - // views::ButtonListener: - void ButtonPressed(views::Button* sender, const ui::Event& event) override; - // views::DragController: void WriteDragDataForView(View* sender, const gfx::Point& press_pt, @@ -401,10 +392,6 @@ // TemplateURLServiceObserver: void OnTemplateURLServiceChanged() override; - // SearchModelObserver: - void ModelChanged(const SearchModel::State& old_state, - const SearchModel::State& new_state) override; - // The Browser this LocationBarView is in. Note that at least // chromeos::SimpleWebViewDialog uses a LocationBarView outside any browser // window, so this may be NULL. @@ -446,9 +433,6 @@ // Shown if the selected url has a corresponding keyword. KeywordHintView* keyword_hint_view_; - // The voice search icon. - views::ImageButton* mic_search_view_; - // The content setting views. ContentSettingViews content_setting_views_;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc index 46e9ac2..0ab0325d 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -38,6 +38,7 @@ #include "ui/gfx/render_text.h" #include "ui/gfx/text_utils.h" #include "ui/gfx/vector_icons_public.h" +#include "ui/native_theme/native_theme.h" using ui::NativeTheme;
diff --git a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc index b8f18545..623879c1 100644 --- a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc +++ b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
@@ -253,8 +253,6 @@ IDS_KEYBOARD_OVERLAY_TOGGLE_CHROMEVOX_SPOKEN_FEEDBACK }, { "keyboardOverlayToggleProjectionTouchHud", IDS_KEYBOARD_OVERLAY_TOGGLE_PROJECTION_TOUCH_HUD }, - { "keyboardOverlayToggleSpeechInput", - IDS_KEYBOARD_OVERLAY_TOGGLE_SPEECH_INPUT }, { "keyboardOverlayUndo", IDS_KEYBOARD_OVERLAY_UNDO }, { "keyboardOverlayViewKeyboardOverlay", IDS_KEYBOARD_OVERLAY_VIEW_KEYBOARD_OVERLAY },
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index d19a0955..768313c 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -58,12 +58,8 @@ html_source->AddLocalizedString( "stickyKeysLabel", IDS_SETTINGS_STICKY_KEYS_LABEL); html_source->AddLocalizedString( - "stickyKeysSublabel", IDS_SETTINGS_STICKY_KEYS_SUBLABEL); - html_source->AddLocalizedString( "chromeVoxLabel", IDS_SETTINGS_CHROMEVOX_LABEL); html_source->AddLocalizedString( - "chromeVoxSublabel", IDS_SETTINGS_CHROMEVOX_SUBLABEL); - html_source->AddLocalizedString( "screenMagnifierLabel", IDS_SETTINGS_SCREEN_MAGNIFIER_LABEL); html_source->AddLocalizedString( "tapDraggingLabel", IDS_SETTINGS_TAP_DRAGGING_LABEL);
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 9606818..d08c0b22 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi
@@ -1078,8 +1078,6 @@ 'browser/ui/cocoa/location_bar/location_icon_decoration.mm', 'browser/ui/cocoa/location_bar/manage_passwords_decoration.h', 'browser/ui/cocoa/location_bar/manage_passwords_decoration.mm', - 'browser/ui/cocoa/location_bar/mic_search_decoration.h', - 'browser/ui/cocoa/location_bar/mic_search_decoration.mm', 'browser/ui/cocoa/location_bar/page_action_decoration.h', 'browser/ui/cocoa/location_bar/page_action_decoration.mm', 'browser/ui/cocoa/location_bar/selected_keyword_decoration.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index fc6b75b..bbf0c97c 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi
@@ -3152,6 +3152,7 @@ 'chrome_java', '../base/base.gyp:base_java', '../base/base.gyp:base_java_test_support', + '../components/components.gyp:policy_java_test_support', '../content/content_shell_and_tests.gyp:content_java_test_support', '../net/net.gyp:net_java', '../net/net.gyp:net_java_test_support',
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 2943ccb..c93b41d 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h
@@ -249,8 +249,6 @@ base::string16 /* identity */, bool /* identity_match */) -IPC_MESSAGE_ROUTED0(ChromeViewMsg_SearchBoxToggleVoiceSearch) - // Sent on process startup to indicate whether this process is running in // incognito mode. IPC_MESSAGE_CONTROL1(ChromeViewMsg_SetIsIncognitoProcess, @@ -539,11 +537,6 @@ int /* page_seq_no */, GURL /* url */) -// Tells InstantExtended whether the page supports voice search. -IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_SetVoiceSearchSupported, - int /* page_seq_no */, - bool /* supported */) - // Tells the renderer a list of URLs which should be bounced back to the browser // process so that they can be assigned to an Instant renderer. IPC_MESSAGE_CONTROL2(ChromeViewMsg_SetSearchURLs,
diff --git a/chrome/renderer/resources/extensions/searchbox_api.js b/chrome/renderer/resources/extensions/searchbox_api.js index f6e5b3e..d99fa26 100644 --- a/chrome/renderer/resources/extensions/searchbox_api.js +++ b/chrome/renderer/resources/extensions/searchbox_api.js
@@ -24,7 +24,6 @@ native function IsFocused(); native function IsKeyCaptureEnabled(); native function Paste(); - native function SetVoiceSearchSupported(); native function StartCapturingKeyStrokes(); native function StopCapturingKeyStrokes(); @@ -69,10 +68,6 @@ Paste(value); }; - this.setVoiceSearchSupported = function(supported) { - SetVoiceSearchSupported(supported); - }; - this.startCapturingKeyStrokes = function() { StartCapturingKeyStrokes(); }; @@ -86,7 +81,6 @@ this.onmarginchange = null; this.onsubmit = null; this.onsuggestionchange = null; - this.ontogglevoicesearch = null; //TODO(jered): Remove this empty method when google no longer requires it. this.setRestrictedValue = function() {};
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc index 8d84d8c..d231c81 100644 --- a/chrome/renderer/searchbox/searchbox.cc +++ b/chrome/renderer/searchbox/searchbox.cc
@@ -338,11 +338,6 @@ render_view()->GetRoutingID(), page_seq_no_, text)); } -void SearchBox::SetVoiceSearchSupported(bool supported) { - render_view()->Send(new ChromeViewHostMsg_SetVoiceSearchSupported( - render_view()->GetRoutingID(), page_seq_no_, supported)); -} - void SearchBox::StartCapturingKeyStrokes() { render_view()->Send(new ChromeViewHostMsg_FocusOmnibox( render_view()->GetRoutingID(), page_seq_no_, OMNIBOX_FOCUS_INVISIBLE)); @@ -392,8 +387,6 @@ IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxSubmit, OnSubmit) IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxThemeChanged, OnThemeChanged) - IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxToggleVoiceSearch, - OnToggleVoiceSearch) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -543,13 +536,6 @@ } } -void SearchBox::OnToggleVoiceSearch() { - if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { - extensions_v8::SearchBoxExtension::DispatchToggleVoiceSearch( - render_view()->GetWebView()->mainFrame()); - } -} - GURL SearchBox::GetURLForMostVisitedItem(InstantRestrictedID item_id) const { InstantMostVisitedItem item; return GetMostVisitedItemWithID(item_id, &item) ? item.url : GURL();
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h index a71cd1be..d59e287 100644 --- a/chrome/renderer/searchbox/searchbox.h +++ b/chrome/renderer/searchbox/searchbox.h
@@ -121,9 +121,6 @@ const ThemeBackgroundInfo& GetThemeBackgroundInfo(); const EmbeddedSearchRequestParams& GetEmbeddedSearchRequestParams(); - // Sends ChromeViewHostMsg_SetVoiceSearchSupported to the browser. - void SetVoiceSearchSupported(bool supported); - // Sends ChromeViewHostMsg_StartCapturingKeyStrokes to the browser. void StartCapturingKeyStrokes(); @@ -167,7 +164,6 @@ void OnSubmit(const base::string16& query, const EmbeddedSearchRequestParams& params); void OnThemeChanged(const ThemeBackgroundInfo& theme_info); - void OnToggleVoiceSearch(); // Returns the current zoom factor of the render view or 1 on failure. double GetZoom() const;
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc index 5ff9082..c687b06 100644 --- a/chrome/renderer/searchbox/searchbox_extension.cc +++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -404,17 +404,6 @@ " true;" "}"; -static const char kDispatchToggleVoiceSearchScript[] = - "if (window.chrome &&" - " window.chrome.embeddedSearch &&" - " window.chrome.embeddedSearch.searchBox &&" - " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch &&" - " typeof window.chrome.embeddedSearch.searchBox.ontogglevoicesearch ==" - " 'function') {" - " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch();" - " true;" - "}"; - // ---------------------------------------------------------------------------- class SearchBoxExtensionWrapper : public v8::Extension { @@ -515,10 +504,6 @@ // Pastes provided value or clipboard's content into the omnibox. static void Paste(const v8::FunctionCallbackInfo<v8::Value>& args); - // Indicates whether the page supports voice search. - static void SetVoiceSearchSupported( - const v8::FunctionCallbackInfo<v8::Value>& args); - // Start capturing user key strokes. static void StartCapturingKeyStrokes( const v8::FunctionCallbackInfo<v8::Value>& args); @@ -627,12 +612,6 @@ Dispatch(frame, kDispatchThemeChangeEventScript); } -// static -void SearchBoxExtension::DispatchToggleVoiceSearch( - blink::WebFrame* frame) { - Dispatch(frame, kDispatchToggleVoiceSearchScript); -} - SearchBoxExtensionWrapper::SearchBoxExtensionWrapper( const base::StringPiece& code) : v8::Extension(kSearchBoxExtensionName, code.data(), 0, 0, code.size()) { @@ -692,8 +671,6 @@ return v8::FunctionTemplate::New(isolate, NavigateContentWindow); if (name->Equals(v8::String::NewFromUtf8(isolate, "Paste"))) return v8::FunctionTemplate::New(isolate, Paste); - if (name->Equals(v8::String::NewFromUtf8(isolate, "SetVoiceSearchSupported"))) - return v8::FunctionTemplate::New(isolate, SetVoiceSearchSupported); if (name->Equals( v8::String::NewFromUtf8(isolate, "StartCapturingKeyStrokes"))) return v8::FunctionTemplate::New(isolate, StartCapturingKeyStrokes); @@ -1260,22 +1237,6 @@ } // static -void SearchBoxExtensionWrapper::SetVoiceSearchSupported( - const v8::FunctionCallbackInfo<v8::Value>& args) { - content::RenderView* render_view = GetRenderView(); - if (!render_view) { - return; - } - if (!args.Length()) { - ThrowInvalidParameters(args); - return; - } - - DVLOG(1) << render_view << " SetVoiceSearchSupported"; - SearchBox::Get(render_view)->SetVoiceSearchSupported(args[0]->BooleanValue()); -} - -// static void SearchBoxExtensionWrapper::UndoAllMostVisitedDeletions( const v8::FunctionCallbackInfo<v8::Value>& args) { content::RenderView* render_view = GetRenderView();
diff --git a/chrome/renderer/searchbox/searchbox_extension.h b/chrome/renderer/searchbox/searchbox_extension.h index fa7ea9e..162c4c3 100644 --- a/chrome/renderer/searchbox/searchbox_extension.h +++ b/chrome/renderer/searchbox/searchbox_extension.h
@@ -45,7 +45,6 @@ static void DispatchSubmit(blink::WebFrame* frame); static void DispatchSuggestionChange(blink::WebFrame* frame); static void DispatchThemeChange(blink::WebFrame* frame); - static void DispatchToggleVoiceSearch(blink::WebFrame* frame); private: DISALLOW_IMPLICIT_CONSTRUCTORS(SearchBoxExtension);
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index 6b59c31..1f65910 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -16,6 +16,7 @@ "//components/bookmarks/common/android:bookmarks_java", "//components/invalidation/impl:java", "//components/policy/android:policy_java", + "//components/policy/android:policy_java_test_support", "//components/web_contents_delegate_android:web_contents_delegate_android_java", "//content/public/android:content_java", "//content/public/test/android:content_java_test_support",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java index 16cfa52..2abc171 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java
@@ -19,6 +19,7 @@ import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.test.util.DisableInTabbedMode; import org.chromium.net.test.BaseHttpTestServer; +import org.chromium.policy.test.annotations.Policies; import org.chromium.ui.base.DeviceFormFactor; import java.io.File; @@ -214,6 +215,8 @@ super.addTestHooks(result); result.addSkipCheck(new DisableInTabbedModeSkipCheck()); result.addSkipCheck(new ChromeRestrictionSkipCheck()); + + result.addPreTestHook(Policies.getRegistrationHook()); } private class ChromeRestrictionSkipCheck extends RestrictionSkipCheck {
diff --git a/chrome/test/data/instant_extended.html b/chrome/test/data/instant_extended.html index da831f5..5dde81b 100644 --- a/chrome/test/data/instant_extended.html +++ b/chrome/test/data/instant_extended.html
@@ -18,7 +18,6 @@ var submitCount = 0; var onEscKeyPressedCalls = 0; var onFocusChangedCalls = 0; -var onToggleVoiceSearchCalls = 0; var prefetchQuery = ''; var isFocused = false; var onvisibilitycalls = 0; @@ -115,10 +114,6 @@ isFocused = apiHandle.isFocused; } -function handleToggleVoiceSearch() { - onToggleVoiceSearchCalls++; -} - function handleSuggestionChange() { prefetchQuery = getApiHandle().suggestion.text; } @@ -138,7 +133,6 @@ apiHandle.onchange = handleOnChange; apiHandle.onkeypress = handleKeyPress; apiHandle.onfocuschange = handleFocusChange; - apiHandle.ontogglevoicesearch = handleToggleVoiceSearch; apiHandle.onsuggestionchange = handleSuggestionChange; newTabPageHandle.onmostvisitedchange = handleMostVisitedChange; newTabPageHandle.onthemechange = handleThemeChange;
diff --git a/chrome/test/data/instant_extended_ntp.html b/chrome/test/data/instant_extended_ntp.html index da831f5..5dde81b 100644 --- a/chrome/test/data/instant_extended_ntp.html +++ b/chrome/test/data/instant_extended_ntp.html
@@ -18,7 +18,6 @@ var submitCount = 0; var onEscKeyPressedCalls = 0; var onFocusChangedCalls = 0; -var onToggleVoiceSearchCalls = 0; var prefetchQuery = ''; var isFocused = false; var onvisibilitycalls = 0; @@ -115,10 +114,6 @@ isFocused = apiHandle.isFocused; } -function handleToggleVoiceSearch() { - onToggleVoiceSearchCalls++; -} - function handleSuggestionChange() { prefetchQuery = getApiHandle().suggestion.text; } @@ -138,7 +133,6 @@ apiHandle.onchange = handleOnChange; apiHandle.onkeypress = handleKeyPress; apiHandle.onfocuschange = handleFocusChange; - apiHandle.ontogglevoicesearch = handleToggleVoiceSearch; apiHandle.onsuggestionchange = handleSuggestionChange; newTabPageHandle.onmostvisitedchange = handleMostVisitedChange; newTabPageHandle.onthemechange = handleThemeChange;
diff --git a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js index 708cc69..7430d6f 100644 --- a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js +++ b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
@@ -34,6 +34,7 @@ /** @override */ extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([ + 'extension_item_test.js', 'extension_service_test.js', 'extension_sidebar_test.js', '../mock_controller.js', @@ -56,6 +57,32 @@ function CrExtensionsBrowserTestWithInstalledExtension() {} +TEST_F('CrExtensionsBrowserTest', 'ExtensionItemNormalStateTest', function() { + extension_item_tests.registerTests(); + var testNames = extension_item_tests.testNames; + mocha.grep(assert(testNames.ElementVisibilityNormalState)).run(); +}); + +TEST_F('CrExtensionsBrowserTest', 'ExtensionItemDetailStateTest', function() { + extension_item_tests.registerTests(); + var testNames = extension_item_tests.testNames; + mocha.grep(assert(testNames.ElementVisibilityDetailState)).run(); +}); + +TEST_F('CrExtensionsBrowserTest', 'ExtensionItemDeveloperStateTest', + function() { + extension_item_tests.registerTests(); + var testNames = extension_item_tests.testNames; + mocha.grep(assert(testNames.ElementVisibilityDeveloperState)).run(); +}); + +TEST_F('CrExtensionsBrowserTest', 'ExtensionItemClickableItemsTest', + function() { + extension_item_tests.registerTests(); + var testNames = extension_item_tests.testNames; + mocha.grep(assert(testNames.ClickableItems)).run(); +}); + CrExtensionsBrowserTestWithInstalledExtension.prototype = { __proto__: CrExtensionsBrowserTest.prototype,
diff --git a/chrome/test/data/webui/extensions/extension_item_test.js b/chrome/test/data/webui/extensions/extension_item_test.js new file mode 100644 index 0000000..e08c08e --- /dev/null +++ b/chrome/test/data/webui/extensions/extension_item_test.js
@@ -0,0 +1,246 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** @fileoverview Suite of tests for extension-item. */ +cr.define('extension_item_tests', function() { + /** + * A mock delegate for the item, capable of testing functionality. + * @constructor + * @implements {extensions.ItemDelegate} + */ + function MockDelegate() {} + + MockDelegate.prototype = { + /** + * Tests clicking on an element and expected a delegate call from the + * item. + * @param {HTMLElement} element The element to click on. + * @param {string} callName The function expected to be called. + * @param {Array<?>=} opt_expectedArgs The arguments the function is + * expected to be called with. + */ + testClickingCalls: function(element, callName, opt_expectedArgs) { + var mock = new MockController(); + var mockMethod = mock.createFunctionMock(this, callName); + MockMethod.prototype.addExpectation.apply( + mockMethod, opt_expectedArgs); + MockInteractions.tap(element); + mock.verifyMocks(); + }, + + /** @override */ + deleteItem: function(id) {}, + + /** @override */ + setItemEnabled: function(id, enabled) {}, + + /** @override */ + showItemDetails: function(id) {}, + + /** @override */ + setItemAllowedIncognito: function(id, enabled) {}, + + /** @override */ + isInDevMode: function() { return false; } + }; + + /** @type {string} The mock extension's id. */ + var id = 'a'.repeat(32); + + /** @type {string} The mock extension's base URL. */ + var baseUrl = 'chrome-extension://' + id + '/'; + + /** + * The data used to populate the extension item. + * @type {ExtensionInfo} + */ + var extensionData = { + description: 'This is an extension', + iconUrl: 'chrome://extension-icon/' + id + '/24/0', + id: id, + incognitoAccess: {isEnabled: true, isActive: false}, + name: 'Wonderful Extension', + state: 'ENABLED', + type: 'EXTENSION', + version: '2.0', + views: [{url: baseUrl + 'foo.html'}, {url: baseUrl + 'bar.html'}], + }; + + /** + * Tests that the element's visibility matches |expectedVisible| and, + * optionally, has specific content. + * @param {HTMLElement} item The item to query for the element. + * @param {boolean} expectedVisible Whether the element should be + * visible. + * @param {string} selector The selector to find the element. + * @param {string=} opt_expected The expected textContent value. + */ + function testVisible(item, expectedVisible, selector, opt_expected) { + var element = item.$$(selector); + var elementIsVisible = !!element; + // Iterate through the parents of the element (up to the item's root) + // and check if each is visible. If one is not, then the element + // itself is not. + for (var e = element; elementIsVisible && e != item.shadowRoot; + e = e.parentNode) { + elementIsVisible = !e.hidden && e.offsetWidth > 0; + } + expectEquals(expectedVisible, elementIsVisible, selector); + if (expectedVisible && opt_expected && element) + expectEquals(opt_expected, element.textContent, selector); + } + + // The normal elements, which should always be shown. + var normalElements = [ + {selector: '#name', text: extensionData.name}, + {selector: '#description', text: extensionData.description}, + {selector: '#version', text: extensionData.version}, + {selector: '#enabled'}, + {selector: '#show-details'}, + {selector: '#delete-button'}, + ]; + // The elements in the details panel, which should only be shown if + // the isShowingDetails bit is set. + var detailElements = [ + {selector: '#allow-incognito'}, + {selector: '#details-button'}, + ]; + // The developer elements, which should only be shown if in developer + // mode *and* showing details. + var devElements = [ + {selector: '#extension-id', text: 'ID:' + extensionData.id}, + {selector: '#inspect-views'}, + ]; + + /** + * Tests that the elements' visibility matches the expected visibility. + * @param {extensions.Item} item + * @param {Array<Object<string>>} elements + * @param {boolean} visibility + */ + function testElementsVisibility(item, elements, visibility) { + elements.forEach(function(element) { + testVisible(item, visibility, element.selector, element.text); + }); + } + + /** Tests that normal elements are visible. */ + function testNormalElementsAreVisible(item) { + testElementsVisibility(item, normalElements, true); + } + + /** Tests that normal elements are hidden. */ + function testNormalElementsAreHidden(item) { + testElementsVisibility(item, normalElements, false); + } + + /** Tests that detail elements are visible. */ + function testDetailElementsAreVisible(item) { + testElementsVisibility(item, detailElements, true); + } + + /** Tests that detail elements are hidden. */ + function testDetailElementsAreHidden(item) { + testElementsVisibility(item, detailElements, false); + } + + /** Tests that dev elements are visible. */ + function testDeveloperElementsAreVisible(item) { + testElementsVisibility(item, devElements, true); + } + + /** Tests that dev elements are hidden. */ + function testDeveloperElementsAreHidden(item) { + testElementsVisibility(item, devElements, false); + } + + var testNames = { + ElementVisibilityNormalState: 'element visibility: normal state', + ElementVisibilityDetailState: + 'element visibility: after tapping show details', + ElementVisibilityDeveloperState: + 'element visibility: after enabling developer mode', + ClickableItems: 'clickable items', + }; + + function registerTests() { + suite('ExtensionItemTest', function() { + /** + * Extension item created before each test. + * @type {extensions.Item} + */ + var item; + + /** @type {MockDelegate} */ + var mockDelegate; + + suiteSetup(function() { + return PolymerTest.importHtml('chrome://extensions/item.html'); + }); + + // Initialize an extension item before each test. + setup(function() { + PolymerTest.clearBody(); + mockDelegate = new MockDelegate(); + item = new extensions.Item(extensionData, mockDelegate); + document.body.appendChild(item); + }); + + test(testNames.ElementVisibilityNormalState, function() { + testNormalElementsAreVisible(item); + testDetailElementsAreHidden(item); + testDeveloperElementsAreHidden(item); + + expectTrue(item.$.enabled.checked); + expectEquals('Enabled', item.$.enabled.textContent); + item.set('data.state', 'DISABLED'); + expectFalse(item.$.enabled.checked); + expectEquals('Disabled', item.$.enabled.textContent); + }); + + test(testNames.ElementVisibilityDetailState, function() { + MockInteractions.tap(item.$['show-details']); + testNormalElementsAreVisible(item); + testDetailElementsAreVisible(item); + testDeveloperElementsAreHidden(item); + }); + + test(testNames.ElementVisibilitydevState, function() { + MockInteractions.tap(item.$['show-details']); + item.set('inDevMode', true); + + testNormalElementsAreVisible(item); + testDetailElementsAreVisible(item); + testDeveloperElementsAreVisible(item); + + // Toggling "show details" should also hide the developer elements. + MockInteractions.tap(item.$['show-details']); + testNormalElementsAreVisible(item); + testDetailElementsAreHidden(item); + testDeveloperElementsAreHidden(item); + }); + + /** Tests that the delegate methods are correctly called. */ + test(testNames.ClickableItems, function() { + MockInteractions.tap(item.$['show-details']); + item.set('inDevMode', true); + + mockDelegate.testClickingCalls( + item.$['delete-button'], 'deleteItem', [item.data.id]); + mockDelegate.testClickingCalls( + item.$.enabled, 'setItemEnabled', [item.data.id, false]); + mockDelegate.testClickingCalls( + item.$$('#allow-incognito'), 'setItemAllowedIncognito', + [item.data.id, true]); + mockDelegate.testClickingCalls( + item.$$('#details-button'), 'showItemDetails', [item.data.id]); + }); + }); + } + + return { + registerTests: registerTests, + testNames: testNames, + }; +});
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index 3814746..845e52c 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -617,7 +617,6 @@ PasswordAutofillAgent::PasswordAutofillAgent(content::RenderFrame* render_frame) : content::RenderFrameObserver(render_frame), - legacy_(render_frame->GetRenderView(), this), logging_state_active_(false), was_username_autofilled_(false), was_password_autofilled_(false), @@ -1188,14 +1187,14 @@ } } -void PasswordAutofillAgent::LegacyDidStartProvisionalLoad( - blink::WebLocalFrame* navigated_frame) { +void PasswordAutofillAgent::DidStartProvisionalLoad() { scoped_ptr<RendererSavePasswordProgressLogger> logger; if (logging_state_active_) { logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD); } + const blink::WebLocalFrame* navigated_frame = render_frame()->GetWebFrame(); if (navigated_frame->parent()) { if (logger) logger->LogMessage(Logger::STRING_FRAME_NOT_MAIN_FRAME); @@ -1511,25 +1510,4 @@ provisionally_saved_form_->new_password_value.empty()); } -// LegacyPasswordAutofillAgent ------------------------------------------------- - -PasswordAutofillAgent::LegacyPasswordAutofillAgent::LegacyPasswordAutofillAgent( - content::RenderView* render_view, - PasswordAutofillAgent* agent) - : content::RenderViewObserver(render_view), agent_(agent) { -} - -PasswordAutofillAgent::LegacyPasswordAutofillAgent:: - ~LegacyPasswordAutofillAgent() { -} - -void PasswordAutofillAgent::LegacyPasswordAutofillAgent::OnDestruct() { - // No op. Do not delete |this|. -} - -void PasswordAutofillAgent::LegacyPasswordAutofillAgent:: - DidStartProvisionalLoad(blink::WebLocalFrame* navigated_frame) { - agent_->LegacyDidStartProvisionalLoad(navigated_frame); -} - } // namespace autofill
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h index 69f2bb5..6db7c2d7 100644 --- a/components/autofill/content/renderer/password_autofill_agent.h +++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -140,40 +140,18 @@ DISALLOW_COPY_AND_ASSIGN(PasswordValueGatekeeper); }; - // Thunk class for RenderViewObserver methods that haven't yet been migrated - // to RenderFrameObserver. Should eventually be removed. - // http://crbug.com/433486 - class LegacyPasswordAutofillAgent : public content::RenderViewObserver { - public: - LegacyPasswordAutofillAgent(content::RenderView* render_view, - PasswordAutofillAgent* agent); - ~LegacyPasswordAutofillAgent() override; - - // RenderViewObserver: - void OnDestruct() override; - void DidStartProvisionalLoad(blink::WebLocalFrame* frame) override; - - private: - PasswordAutofillAgent* agent_; - - DISALLOW_COPY_AND_ASSIGN(LegacyPasswordAutofillAgent); - }; - friend class LegacyPasswordAutofillAgent; - // RenderFrameObserver: bool OnMessageReceived(const IPC::Message& message) override; void DidFinishDocumentLoad() override; void DidFinishLoad() override; void FrameDetached() override; void FrameWillClose() override; + void DidStartProvisionalLoad() override; void DidCommitProvisionalLoad(bool is_new_navigation, bool is_same_page_navigation) override; void WillSendSubmitEvent(const blink::WebFormElement& form) override; void WillSubmitForm(const blink::WebFormElement& form) override; - // Legacy RenderViewObserver: - void LegacyDidStartProvisionalLoad(blink::WebLocalFrame* frame); - // RenderView IPC handlers: void OnFillPasswordForm(int key, const PasswordFormFillData& form_data); void OnSetLoggingState(bool active); @@ -233,9 +211,6 @@ // Helper function called when in-page navigation completed void OnSamePageNavigationCompleted(); - // Passes through |RenderViewObserver| method to |this|. - LegacyPasswordAutofillAgent legacy_; - // The logins we have filled so far with their associated info. WebInputToPasswordInfoMap web_input_to_password_info_; // And the keys under which PasswordAutofillManager can find the same info.
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 198e0765..f9975f03 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -1567,17 +1567,12 @@ 'type': 'none', 'dependencies': [ 'components.gyp:invalidation_java', + 'components.gyp:policy_java', + 'components.gyp:policy_java_test_support', '../base/base.gyp:base_java', '../base/base.gyp:base_java_test_support', '../testing/android/junit/junit_test.gyp:junit_test_support', ], - 'conditions': [ - ['configuration_policy == 1', { - 'dependencies': [ - 'components.gyp:policy_java', - ], - }], - ], 'variables': { 'main_class': 'org.chromium.testing.local.JunitTestMain', 'src_paths': [
diff --git a/components/mus/public/cpp/lib/window.cc b/components/mus/public/cpp/lib/window.cc index 3fede87..ded9b52 100644 --- a/components/mus/public/cpp/lib/window.cc +++ b/components/mus/public/cpp/lib/window.cc
@@ -175,6 +175,10 @@ return window->connection() && window->connection()->GetRoot() == window; } +bool OwnsWindowOrIsRoot(Window* window) { + return OwnsWindow(window->connection(), window) || IsConnectionRoot(window); +} + void EmptyEmbedCallback(bool result, ConnectionSpecificId connection_id) {} } // namespace @@ -183,7 +187,7 @@ // Window, public: void Window::Destroy() { - if (!OwnsWindow(connection_, this)) + if (!OwnsWindowOrIsRoot(this)) return; if (connection_) @@ -203,9 +207,7 @@ } void Window::SetBounds(const gfx::Rect& bounds) { - const bool is_root = !parent(); - const bool can_change = OwnsWindow(connection_, this) || is_root; - if (!can_change) + if (!OwnsWindowOrIsRoot(this)) return; if (bounds_ == bounds) return; @@ -216,7 +218,7 @@ } void Window::SetClientArea(const gfx::Insets& client_area) { - if (!OwnsWindow(connection_, this) && !IsConnectionRoot(this)) + if (!OwnsWindowOrIsRoot(this)) return; if (connection_) {
diff --git a/components/mus/public/cpp/window.h b/components/mus/public/cpp/window.h index 1b68e10..b7eb8b2 100644 --- a/components/mus/public/cpp/window.h +++ b/components/mus/public/cpp/window.h
@@ -49,10 +49,10 @@ using EmbedCallback = base::Callback<void(bool, ConnectionSpecificId)>; // Destroys this window and all its children. Destruction is allowed for - // windows - // that were created by this connection. For windows from other connections - // (such as the root) Destroy() does nothing. If the destruction is allowed - // observers are notified and the Window is immediately deleted. + // windows that were created by this connection, or the root window. For + // windows from other connections (except the root), Destroy() does nothing. + // If the destruction is allowed observers are notified and the Window is + // immediately deleted. void Destroy(); WindowTreeConnection* connection() { return connection_; }
diff --git a/components/mus/public/cpp/window_tree_delegate.h b/components/mus/public/cpp/window_tree_delegate.h index 6cbf9aa6..3e2f397 100644 --- a/components/mus/public/cpp/window_tree_delegate.h +++ b/components/mus/public/cpp/window_tree_delegate.h
@@ -22,8 +22,7 @@ // Window. // WindowTreeConnection is deleted by any of the following: // . If the root of the connection is destroyed. This happens if the owner -// of the root Embed()s another app in root, or the owner explicitly deletes -// root. +// of the root Embed()s another app in root, or root is explicitly deleted. // . The connection to the window manager is lost. // . Explicitly by way of calling delete. // @@ -34,16 +33,6 @@ public: // Called when the application implementing this interface is embedded at // |root|. - // - // |services| exposes the services offered by the embedder to the delegate. - // - // |exposed_services| is an object that the delegate can add services to - // expose to the embedder. - // - // Note that if a different application is subsequently embedded at |root|, - // the pipes connecting |services| and |exposed_services| to the embedder and - // any services obtained from them are not broken and will continue to be - // valid. virtual void OnEmbed(Window* root) = 0; // Sent when another app is embedded in the same Window as this connection. @@ -51,8 +40,8 @@ // notified appropriately). virtual void OnUnembed(); - // Called from the destructor of WindowTreeConnection after all the Views have - // been destroyed. |connection| is no longer valid after this call. + // Called from the destructor of WindowTreeConnection after all the Windows + // have been destroyed. |connection| is no longer valid after this call. virtual void OnConnectionLost(WindowTreeConnection* connection) = 0; protected:
diff --git a/components/mus/ws/window_manager_client_apptest.cc b/components/mus/ws/window_manager_client_apptest.cc index 6105047..67ade08 100644 --- a/components/mus/ws/window_manager_client_apptest.cc +++ b/components/mus/ws/window_manager_client_apptest.cc
@@ -381,23 +381,24 @@ EXPECT_TRUE(window->bounds() == window_in_embedded->bounds()); } -// Verifies that a window can only be destroyed by the connection that created -// it. +// Verifies that a root window can always be destroyed. TEST_F(WindowServerTest, DestroySecurity) { Window* window = window_manager()->NewWindow(); window->SetVisible(true); window_manager()->GetRoot()->AddChild(window); + WindowTreeConnection* embedded = Embed(window).connection; ASSERT_NE(nullptr, embedded); - Window* window_in_embedded = embedded->GetWindowById(window->id()); - - WindowTracker tracker2(window_in_embedded); - window_in_embedded->Destroy(); - // Window should not have been destroyed. - EXPECT_TRUE(tracker2.is_valid()); - + // The root can be destroyed, even though it was not created by the + // connection. + Window* embed_root = embedded->GetWindowById(window->id()); WindowTracker tracker1(window); + WindowTracker tracker2(embed_root); + embed_root->Destroy(); + EXPECT_FALSE(tracker2.is_valid()); + EXPECT_TRUE(tracker1.is_valid()); + window->Destroy(); EXPECT_FALSE(tracker1.is_valid()); }
diff --git a/components/mus/ws/window_tree_impl.cc b/components/mus/ws/window_tree_impl.cc index 48aaa20..56ccf6a9 100644 --- a/components/mus/ws/window_tree_impl.cc +++ b/components/mus/ws/window_tree_impl.cc
@@ -570,7 +570,9 @@ ServerWindow* window = GetWindow(WindowIdFromTransportId(transport_window_id)); bool success = false; - if (window && access_policy_->CanDeleteWindow(window)) { + bool should_close = window && (access_policy_->CanDeleteWindow(window) || + ShouldRouteToWindowManager(window)); + if (should_close) { WindowTreeImpl* connection = connection_manager_->GetConnection(window->id().connection_id); success = connection && connection->DeleteWindowImpl(this, window);
diff --git a/components/password_manager/content/browser/content_password_manager_driver_factory.cc b/components/password_manager/content/browser/content_password_manager_driver_factory.cc index 1fe3a46..b401017 100644 --- a/components/password_manager/content/browser/content_password_manager_driver_factory.cc +++ b/components/password_manager/content/browser/content_password_manager_driver_factory.cc
@@ -56,11 +56,7 @@ CreateDriverForFrame(main_frame); } -ContentPasswordManagerDriverFactory::~ContentPasswordManagerDriverFactory() { - STLDeleteContainerPairSecondPointers(frame_driver_map_.begin(), - frame_driver_map_.end()); - frame_driver_map_.clear(); -} +ContentPasswordManagerDriverFactory::~ContentPasswordManagerDriverFactory() {} // static ContentPasswordManagerDriverFactory* @@ -87,7 +83,6 @@ void ContentPasswordManagerDriverFactory::RenderFrameDeleted( content::RenderFrameHost* render_frame_host) { - delete frame_driver_map_[render_frame_host]; frame_driver_map_.erase(render_frame_host); } @@ -96,7 +91,8 @@ content::RenderFrameHost* render_frame_host) { if (!render_frame_host->IsRenderFrameLive()) return false; - return frame_driver_map_[render_frame_host]->HandleMessage(message); + return frame_driver_map_.find(render_frame_host) + ->second->HandleMessage(message); } void ContentPasswordManagerDriverFactory::DidNavigateAnyFrame( @@ -105,22 +101,23 @@ const content::FrameNavigateParams& params) { if (!render_frame_host->IsRenderFrameLive()) return; - frame_driver_map_[render_frame_host]->DidNavigateFrame(details, params); + frame_driver_map_.find(render_frame_host) + ->second->DidNavigateFrame(details, params); } void ContentPasswordManagerDriverFactory::CreateDriverForFrame( content::RenderFrameHost* render_frame_host) { - DCHECK(!frame_driver_map_[render_frame_host]); - frame_driver_map_[render_frame_host] = new ContentPasswordManagerDriver( - render_frame_host, password_client_, autofill_client_); + DCHECK(!ContainsKey(frame_driver_map_, render_frame_host)); + frame_driver_map_.set( + render_frame_host, + make_scoped_ptr(new ContentPasswordManagerDriver( + render_frame_host, password_client_, autofill_client_))); } void ContentPasswordManagerDriverFactory::TestingSetDriverForFrame( content::RenderFrameHost* render_frame_host, scoped_ptr<ContentPasswordManagerDriver> driver) { - if (frame_driver_map_[render_frame_host]) - delete frame_driver_map_[render_frame_host]; - frame_driver_map_[render_frame_host] = driver.release(); + frame_driver_map_.set(render_frame_host, driver.Pass()); } } // namespace password_manager
diff --git a/components/password_manager/content/browser/content_password_manager_driver_factory.h b/components/password_manager/content/browser/content_password_manager_driver_factory.h index 3724bd0..b2a5daa 100644 --- a/components/password_manager/content/browser/content_password_manager_driver_factory.h +++ b/components/password_manager/content/browser/content_password_manager_driver_factory.h
@@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/containers/scoped_ptr_map.h" #include "base/supports_user_data.h" #include "components/password_manager/core/browser/password_autofill_manager.h" #include "components/password_manager/core/browser/password_generation_manager.h" @@ -65,7 +66,8 @@ void CreateDriverForFrame(content::RenderFrameHost* render_frame_host); - std::map<content::RenderFrameHost*, ContentPasswordManagerDriver*> + base::ScopedPtrMap<content::RenderFrameHost*, + scoped_ptr<ContentPasswordManagerDriver>> frame_driver_map_; PasswordManagerClient* password_client_;
diff --git a/components/password_manager/core/browser/credential_manager_password_form_manager.cc b/components/password_manager/core/browser/credential_manager_password_form_manager.cc index f0ae126..1547977 100644 --- a/components/password_manager/core/browser/credential_manager_password_form_manager.cc +++ b/components/password_manager/core/browser/credential_manager_password_form_manager.cc
@@ -23,7 +23,7 @@ observed_form, true), delegate_(delegate) { - FetchMatchingLoginsFromPasswordStore(PasswordStore::DISALLOW_PROMPT); + FetchDataFromPasswordStore(PasswordStore::DISALLOW_PROMPT); } CredentialManagerPasswordFormManager::~CredentialManagerPasswordFormManager() {
diff --git a/components/password_manager/core/browser/mock_password_store.cc b/components/password_manager/core/browser/mock_password_store.cc index 5ede681..b6b65fc 100644 --- a/components/password_manager/core/browser/mock_password_store.cc +++ b/components/password_manager/core/browser/mock_password_store.cc
@@ -14,4 +14,12 @@ MockPasswordStore::~MockPasswordStore() { } +ScopedVector<InteractionsStats> MockPasswordStore::GetSiteStatsImpl( + const GURL& origin_domain) { + std::vector<InteractionsStats*> stats = GetSiteStatsMock(origin_domain); + ScopedVector<InteractionsStats> result; + result.swap(stats); + return result.Pass(); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/mock_password_store.h b/components/password_manager/core/browser/mock_password_store.h index 1127a3c..a12b8e3 100644 --- a/components/password_manager/core/browser/mock_password_store.h +++ b/components/password_manager/core/browser/mock_password_store.h
@@ -7,6 +7,7 @@ #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/password_store.h" +#include "components/password_manager/core/browser/statistics_table.h" #include "testing/gmock/include/gmock/gmock.h" namespace password_manager { @@ -47,12 +48,12 @@ MOCK_METHOD1(FillBlacklistLogins, bool(ScopedVector<autofill::PasswordForm>*)); MOCK_METHOD1(NotifyLoginsChanged, void(const PasswordStoreChangeList&)); - void AddSiteStatsImpl(const InteractionsStats& stats) override {} - void RemoveSiteStatsImpl(const GURL& origin_domain) override {} + // GMock doesn't allow to return noncopyable types. ScopedVector<InteractionsStats> GetSiteStatsImpl( - const GURL& origin_domain) override { - return ScopedVector<InteractionsStats>(); - } + const GURL& origin_domain) override; + MOCK_METHOD1(GetSiteStatsMock, std::vector<InteractionsStats*>(const GURL&)); + MOCK_METHOD1(AddSiteStatsImpl, void(const InteractionsStats&)); + MOCK_METHOD1(RemoveSiteStatsImpl, void(const GURL&)); PasswordStoreSync* GetSyncInterface() { return this; }
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc index 562bf54a..04c3bc2 100644 --- a/components/password_manager/core/browser/password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -22,6 +22,7 @@ #include "components/password_manager/core/browser/password_manager_driver.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_store.h" +#include "components/password_manager/core/browser/statistics_table.h" #include "google_apis/gaia/gaia_auth_util.h" using autofill::FormStructure; @@ -298,7 +299,7 @@ UpdateLogin(); } -void PasswordFormManager::FetchMatchingLoginsFromPasswordStore( +void PasswordFormManager::FetchDataFromPasswordStore( PasswordStore::AuthorizationPromptPolicy prompt_policy) { if (state_ == MATCHING_PHASE) { // There is currently a password store query in progress. Remember the @@ -326,6 +327,13 @@ return; } password_store->GetLogins(observed_form_, prompt_policy, this); + +// The statistics isn't needed on mobile, only on desktop. Let's save some +// processor cycles. +#if !defined(OS_IOS) && !defined(OS_ANDROID) + // The statistics is needed for the "Save password?" bubble. + password_store->GetSiteStats(observed_form_.origin.GetOrigin(), this); +#endif } bool PasswordFormManager::HasCompletedMatching() const { @@ -570,7 +578,7 @@ if (next_prompt_policy_) { // The received results are no longer up-to-date, need to re-request. state_ = PRE_MATCHING_PHASE; - FetchMatchingLoginsFromPasswordStore(*next_prompt_policy_); + FetchDataFromPasswordStore(*next_prompt_policy_); next_prompt_policy_.reset(); return; } @@ -599,6 +607,14 @@ } } +void PasswordFormManager::OnGetSiteStatistics( + ScopedVector<InteractionsStats> stats) { + // On Windows the password request may be resolved after the statistics due to + // importing from IE. + DCHECK(state_ == MATCHING_PHASE || state_ == POST_MATCHING_PHASE) << state_; + interactions_stats_.swap(stats); +} + void PasswordFormManager::SaveAsNewLogin() { DCHECK_EQ(state_, POST_MATCHING_PHASE); DCHECK(IsNewLogin());
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h index 0f36410..c07975e 100644 --- a/components/password_manager/core/browser/password_form_manager.h +++ b/components/password_manager/core/browser/password_form_manager.h
@@ -74,11 +74,12 @@ // they match. The return value is a MatchResultMask bitmask. MatchResultMask DoesManage(const autofill::PasswordForm& form) const; - // Retrieves potential matching logins from the database. + // Retrieves potential matching logins from the database. In addition the + // statistics is retrived on platforms with the password bubble. // |prompt_policy| indicates whether it's permissible to prompt the user to // authorize access to locked passwords. This argument is only used on // platforms that support prompting the user for access (such as Mac OS). - void FetchMatchingLoginsFromPasswordStore( + void FetchDataFromPasswordStore( PasswordStore::AuthorizationPromptPolicy prompt_policy); // Simple state-check to verify whether this object as received a callback @@ -119,8 +120,10 @@ // delayed until the data arrives. void ProcessFrame(const base::WeakPtr<PasswordManagerDriver>& driver); + // PasswordStoreConsumer: void OnGetPasswordStoreResults( ScopedVector<autofill::PasswordForm> results) override; + void OnGetSiteStatistics(ScopedVector<InteractionsStats> stats) override; // A user opted to 'never remember' passwords for this form. // Blacklist it so that from now on when it is seen we ignore it. @@ -205,6 +208,12 @@ // Just need to update the internal states. state_ = MATCHING_PHASE; } + + // TODO(vasilii): remove the unit test restriction when it's needed in + // production code. + const std::vector<InteractionsStats*>& interactions_stats() const { + return interactions_stats_.get(); + } #endif const autofill::PasswordForm& observed_form() const { return observed_form_; } @@ -420,6 +429,9 @@ // The PasswordForm from the page or dialog managed by |this|. const autofill::PasswordForm observed_form_; + // Statistics for the current domain. + ScopedVector<InteractionsStats> interactions_stats_; + // Stores provisionally saved form until |pending_credentials_| is created. scoped_ptr<const autofill::PasswordForm> provisionally_saved_form_; // Stores if for creating |pending_credentials_| other possible usernames
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index c9aa020..02a4339 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -6,6 +6,7 @@ #include "base/prefs/pref_registry_simple.h" #include "base/prefs/pref_service.h" #include "base/prefs/testing_pref_service.h" +#include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" #include "components/autofill/core/browser/autofill_manager.h" @@ -22,6 +23,7 @@ #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" #include "components/password_manager/core/browser/password_store.h" +#include "components/password_manager/core/browser/statistics_table.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" #include "components/password_manager/core/common/password_manager_pref_names.h" @@ -298,6 +300,8 @@ saved_match_.form_data.fields.push_back(field); mock_store_ = new NiceMock<MockPasswordStore>(); + ON_CALL(*mock_store_, GetSiteStatsMock(_)) + .WillByDefault(Return(std::vector<InteractionsStats*>())); client_.reset(new TestPasswordManagerClient(mock_store_.get())); password_manager_.reset(new PasswordManager(client_.get())); form_manager_.reset(new PasswordFormManager( @@ -317,7 +321,7 @@ const PasswordStore::AuthorizationPromptPolicy auth_policy = PasswordStore::DISALLOW_PROMPT; EXPECT_CALL(*mock_store(), GetLogins(p->observed_form(), auth_policy, p)); - p->FetchMatchingLoginsFromPasswordStore(auth_policy); + p->FetchDataFromPasswordStore(auth_policy); if (result == RESULT_NO_MATCH) { p->OnGetPasswordStoreResults(ScopedVector<PasswordForm>()); return; @@ -1240,7 +1244,7 @@ PasswordStore::DISALLOW_PROMPT; EXPECT_CALL(*mock_store(), GetLogins(encountered_form, auth_policy, &form_manager)); - form_manager.FetchMatchingLoginsFromPasswordStore(auth_policy); + form_manager.FetchDataFromPasswordStore(auth_policy); // Password store only has these incomplete credentials. scoped_ptr<PasswordForm> incomplete_form(new PasswordForm()); @@ -1665,7 +1669,7 @@ const PasswordStore::AuthorizationPromptPolicy auth_policy = PasswordStore::DISALLOW_PROMPT; EXPECT_CALL(*mock_store(), GetLogins(*form, auth_policy, &form_manager)); - form_manager.FetchMatchingLoginsFromPasswordStore(auth_policy); + form_manager.FetchDataFromPasswordStore(auth_policy); // Suddenly, the frame and its driver disappear. client()->KillDriver(); @@ -1681,7 +1685,7 @@ PasswordStore::DISALLOW_PROMPT; EXPECT_CALL(*mock_store(), GetLogins(*observed_form(), auth_policy, form_manager())); - form_manager()->FetchMatchingLoginsFromPasswordStore(auth_policy); + form_manager()->FetchDataFromPasswordStore(auth_policy); ScopedVector<PasswordForm> simulated_results; scoped_ptr<PasswordForm> form(new PasswordForm(*observed_form())); @@ -1961,8 +1965,7 @@ // Do not notify the store observer after this GetLogins call. EXPECT_CALL(*mock_store(), GetLogins(_, _, _)); - form_manager.FetchMatchingLoginsFromPasswordStore( - PasswordStore::DISALLOW_PROMPT); + form_manager.FetchDataFromPasswordStore(PasswordStore::DISALLOW_PROMPT); PasswordForm submitted_form(form); submitted_form.password_value += ASCIIToUTF16("add stuff, make it different"); @@ -1995,8 +1998,7 @@ EXPECT_CALL(*mock_store(), GetLogins(_, _, _)) .WillOnce(testing::WithArg<2>( InvokeConsumer(form, form_related, form_related2, form_unrelated))); - form_manager.FetchMatchingLoginsFromPasswordStore( - PasswordStore::DISALLOW_PROMPT); + form_manager.FetchDataFromPasswordStore(PasswordStore::DISALLOW_PROMPT); form_manager.ProvisionallySave( form, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); @@ -2026,8 +2028,7 @@ EXPECT_CALL(*mock_store(), GetLogins(_, _, _)) .WillOnce(testing::WithArg<2>( InvokeConsumer(form, form_related, form_related2, form_unrelated))); - form_manager.FetchMatchingLoginsFromPasswordStore( - PasswordStore::DISALLOW_PROMPT); + form_manager.FetchDataFromPasswordStore(PasswordStore::DISALLOW_PROMPT); PasswordForm submitted_form(form); submitted_form.password_value += ASCIIToUTF16("add stuff, make it different"); @@ -2184,7 +2185,7 @@ PasswordStore::DISALLOW_PROMPT; EXPECT_CALL(*mock_store(), GetLogins(*observed_form(), auth_policy, form_manager())); - form_manager()->FetchMatchingLoginsFromPasswordStore(auth_policy); + form_manager()->FetchDataFromPasswordStore(auth_policy); scoped_ptr<PasswordForm> generated_form(new PasswordForm(*observed_form())); generated_form->type = PasswordForm::TYPE_GENERATED; @@ -2217,7 +2218,7 @@ PasswordStore::DISALLOW_PROMPT; EXPECT_CALL(*mock_store(), GetLogins(*observed_form(), auth_policy, form_manager())); - form_manager()->FetchMatchingLoginsFromPasswordStore(auth_policy); + form_manager()->FetchDataFromPasswordStore(auth_policy); scoped_ptr<PasswordForm> generated_form(new PasswordForm(*observed_form())); generated_form->type = PasswordForm::TYPE_GENERATED; @@ -2251,8 +2252,8 @@ EXPECT_CALL(*mock_store(), GetLogins(form_manager()->observed_form(), auth_policy, form_manager())) .Times(2); - form_manager()->FetchMatchingLoginsFromPasswordStore(auth_policy); - form_manager()->FetchMatchingLoginsFromPasswordStore(auth_policy); + form_manager()->FetchDataFromPasswordStore(auth_policy); + form_manager()->FetchDataFromPasswordStore(auth_policy); // First response from the store, should be ignored. scoped_ptr<PasswordForm> saved_form(new PasswordForm(*saved_match())); @@ -2301,8 +2302,7 @@ // Ask store for logins, but store should not respond yet. EXPECT_CALL(*mock_store(), GetLogins(form_manager()->observed_form(), _, form_manager())); - form_manager()->FetchMatchingLoginsFromPasswordStore( - PasswordStore::DISALLOW_PROMPT); + form_manager()->FetchDataFromPasswordStore(PasswordStore::DISALLOW_PROMPT); // Now add the extra driver. form_manager()->ProcessFrame(extra_driver.AsWeakPtr()); @@ -2509,4 +2509,36 @@ EXPECT_EQ(credentials.origin, new_credentials.origin); } +#if !defined(OS_IOS) && !defined(OS_ANDROID) +TEST_F(PasswordFormManagerTest, FetchStatistics) { + const PasswordStore::AuthorizationPromptPolicy auth_policy = + PasswordStore::DISALLOW_PROMPT; + InteractionsStats stats; + stats.origin_domain = observed_form()->origin.GetOrigin(); + stats.username_value = saved_match()->username_value; + stats.dismissal_count = 5; + EXPECT_CALL(*mock_store(), + GetLogins(*observed_form(), auth_policy, form_manager())); + std::vector<InteractionsStats*> db_stats; + db_stats.push_back(new InteractionsStats(stats)); + EXPECT_CALL(*mock_store(), GetSiteStatsMock(stats.origin_domain)) + .WillOnce(Return(db_stats)); + form_manager()->FetchDataFromPasswordStore(auth_policy); + base::RunLoop().RunUntilIdle(); + + EXPECT_THAT(form_manager()->interactions_stats(), + ElementsAre(Pointee(stats))); +} +#else +TEST_F(PasswordFormManagerTest, DontFetchStatistics) { + const PasswordStore::AuthorizationPromptPolicy auth_policy = + PasswordStore::DISALLOW_PROMPT; + EXPECT_CALL(*mock_store(), + GetLogins(*observed_form(), auth_policy, form_manager())); + EXPECT_CALL(*mock_store(), GetSiteStatsMock(_)).Times(0); + form_manager()->FetchDataFromPasswordStore(auth_policy); + base::RunLoop().RunUntilIdle(); +} +#endif + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index b609e6f..99be508 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -340,7 +340,7 @@ void PasswordManager::UpdateFormManagers() { for (PasswordFormManager* form_manager : pending_login_managers_) { - form_manager->FetchMatchingLoginsFromPasswordStore( + form_manager->FetchDataFromPasswordStore( client_->GetAuthorizationPromptPolicy(form_manager->observed_form())); } } @@ -514,7 +514,7 @@ PasswordStore::AuthorizationPromptPolicy prompt_policy = client_->GetAuthorizationPromptPolicy(*iter); - manager->FetchMatchingLoginsFromPasswordStore(prompt_policy); + manager->FetchDataFromPasswordStore(prompt_policy); } if (logger) {
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index c1a3e6f08..6fb28b50 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -15,6 +15,7 @@ #include "components/password_manager/core/browser/password_autofill_manager.h" #include "components/password_manager/core/browser/password_manager_driver.h" #include "components/password_manager/core/browser/password_store.h" +#include "components/password_manager/core/browser/statistics_table.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" #include "components/password_manager/core/common/password_manager_pref_names.h" @@ -101,7 +102,7 @@ arg0->OnGetPasswordStoreResults(result.Pass()); } -ACTION(InvokeEmptyConsumer) { +ACTION(InvokeEmptyConsumerWithForms) { arg0->OnGetPasswordStoreResults(ScopedVector<PasswordForm>()); } @@ -118,6 +119,7 @@ EXPECT_CALL(client_, GetPasswordStore()) .WillRepeatedly(Return(store_.get())); + EXPECT_CALL(*store_, GetSiteStatsMock(_)).Times(AnyNumber()); EXPECT_CALL(client_, GetDriver()).WillRepeatedly(Return(&driver_)); manager_.reset(new PasswordManager(&client_)); @@ -235,7 +237,7 @@ PasswordForm form(MakeFormWithOnlyNewPasswordField()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -273,7 +275,7 @@ PasswordForm form(MakeFormWithOnlyNewPasswordField()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -345,7 +347,7 @@ PasswordForm form(MakeSimpleForm()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -363,7 +365,7 @@ PasswordForm form(MakeSimpleForm()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -402,7 +404,7 @@ std::vector<PasswordForm> observed; observed.push_back(first_form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); observed.clear(); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -445,7 +447,7 @@ PasswordForm form(MakeSimpleForm()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -518,7 +520,7 @@ PasswordForm login_form(MakeTwitterLoginForm()); observed.push_back(login_form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -545,7 +547,7 @@ PasswordForm form(MakeSimpleForm()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -668,7 +670,7 @@ std::vector<PasswordForm> observed; observed.push_back(first_form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -701,7 +703,7 @@ form.new_password_value.clear(); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillOnce(WithArg<2>(InvokeEmptyConsumer())); + .WillOnce(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -736,7 +738,7 @@ PasswordForm form(MakeSimpleFormWithOnlyPasswordField()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillOnce(WithArg<2>(InvokeEmptyConsumer())); + .WillOnce(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -789,7 +791,7 @@ PasswordForm form(MakeSimpleForm()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillOnce(WithArg<2>(InvokeEmptyConsumer())); + .WillOnce(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -851,7 +853,7 @@ observed.push_back(wrong_action_form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -911,7 +913,7 @@ observed.push_back(wrong_submit_form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -959,7 +961,7 @@ PasswordForm form(MakeSimpleForm()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1042,7 +1044,7 @@ PasswordForm form(MakeFormWithOnlyNewPasswordField()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1077,7 +1079,7 @@ PasswordForm form(MakeFormWithOnlyNewPasswordField()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1118,7 +1120,7 @@ PasswordForm form(MakeFormWithOnlyNewPasswordField()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1150,7 +1152,7 @@ PasswordForm form(MakeFormWithOnlyNewPasswordField()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1183,7 +1185,7 @@ PasswordForm form(MakeFormWithOnlyNewPasswordField()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1219,7 +1221,7 @@ std::vector<PasswordForm> observed; observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1246,7 +1248,7 @@ std::vector<PasswordForm> observed; observed.push_back(empty_password_form); EXPECT_CALL(*store_, GetLogins(_, _, _)) - .WillRepeatedly(WithArg<2>(InvokeEmptyConsumer())); + .WillRepeatedly(WithArg<2>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true);
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 6a2c1877..b6c291c 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -15,6 +15,7 @@ #include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/password_store_consumer.h" #include "components/password_manager/core/browser/password_syncable_service.h" +#include "components/password_manager/core/browser/statistics_table.h" #include "url/origin.h" using autofill::PasswordForm;
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index ec22f90..785efc1 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -15,7 +15,6 @@ #include "base/time/time.h" #include "components/password_manager/core/browser/password_store_change.h" #include "components/password_manager/core/browser/password_store_sync.h" -#include "components/password_manager/core/browser/statistics_table.h" #include "sync/api/syncable_service.h" namespace url { @@ -37,6 +36,7 @@ class AffiliatedMatchHelper; class PasswordStoreConsumer; class PasswordSyncableService; +struct InteractionsStats; // Interface for storing form passwords in a platform-specific secure way. // The login request/manipulation API is not threadsafe and must be used @@ -282,9 +282,8 @@ // Synchronous implementation for manipulating with statistics. virtual void AddSiteStatsImpl(const InteractionsStats& stats) = 0; virtual void RemoveSiteStatsImpl(const GURL& origin_domain) = 0; - // Returns a raw pointer so that InteractionsStats can be forward declared. virtual ScopedVector<InteractionsStats> GetSiteStatsImpl( - const GURL& origin_domain) WARN_UNUSED_RESULT = 0; + const GURL& origin_domain) = 0; // Log UMA stats for number of bulk deletions. void LogStatsForBulkDeletion(int num_deletions);
diff --git a/components/password_manager/core/browser/statistics_table.cc b/components/password_manager/core/browser/statistics_table.cc index 6cc4027..e679663 100644 --- a/components/password_manager/core/browser/statistics_table.cc +++ b/components/password_manager/core/browser/statistics_table.cc
@@ -22,6 +22,13 @@ InteractionsStats::InteractionsStats() = default; +bool operator==(const InteractionsStats& lhs, const InteractionsStats& rhs) { + return lhs.origin_domain == rhs.origin_domain && + lhs.username_value == rhs.username_value && + lhs.dismissal_count == rhs.dismissal_count && + lhs.update_time == rhs.update_time; +} + StatisticsTable::StatisticsTable() : db_(nullptr) { } @@ -58,6 +65,8 @@ } bool StatisticsTable::AddRow(const InteractionsStats& stats) { + if (!stats.origin_domain.is_valid()) + return false; sql::Statement s(db_->GetCachedStatement( SQL_FROM_HERE, "INSERT OR REPLACE INTO stats " @@ -71,6 +80,8 @@ } bool StatisticsTable::RemoveRow(const GURL& domain) { + if (!domain.is_valid()) + return false; sql::Statement s(db_->GetCachedStatement(SQL_FROM_HERE, "DELETE FROM stats WHERE " "origin_domain = ? ")); @@ -79,6 +90,8 @@ } ScopedVector<InteractionsStats> StatisticsTable::GetRows(const GURL& domain) { + if (!domain.is_valid()) + return ScopedVector<InteractionsStats>(); const char query[] = "SELECT origin_domain, username_value, " "dismissal_count, update_time FROM stats WHERE origin_domain == ?";
diff --git a/components/password_manager/core/browser/statistics_table.h b/components/password_manager/core/browser/statistics_table.h index 9a48f1e..a4900f9 100644 --- a/components/password_manager/core/browser/statistics_table.h +++ b/components/password_manager/core/browser/statistics_table.h
@@ -34,6 +34,8 @@ base::Time update_time; }; +bool operator==(const InteractionsStats& lhs, const InteractionsStats& rhs); + // Represents the 'stats' table in the Login Database. class StatisticsTable { public:
diff --git a/components/password_manager/core/browser/statistics_table_unittest.cc b/components/password_manager/core/browser/statistics_table_unittest.cc index f592e0a..4736cea 100644 --- a/components/password_manager/core/browser/statistics_table_unittest.cc +++ b/components/password_manager/core/browser/statistics_table_unittest.cc
@@ -23,13 +23,6 @@ using ::testing::Pointee; using ::testing::UnorderedElementsAre; -MATCHER_P(StatsIs, stats, "") { - return arg.origin_domain == stats.origin_domain && - arg.username_value == stats.username_value && - arg.dismissal_count == stats.dismissal_count && - arg.update_time == stats.update_time; -} - class StatisticsTableTest : public testing::Test { protected: void SetUp() override { @@ -65,7 +58,7 @@ TEST_F(StatisticsTableTest, Sanity) { EXPECT_TRUE(db()->AddRow(test_data())); EXPECT_THAT(db()->GetRows(test_data().origin_domain), - ElementsAre(Pointee(StatsIs(test_data())))); + ElementsAre(Pointee(test_data()))); EXPECT_TRUE(db()->RemoveRow(test_data().origin_domain)); EXPECT_THAT(db()->GetRows(test_data().origin_domain), IsEmpty()); } @@ -76,7 +69,7 @@ ReloadDatabase(); EXPECT_THAT(db()->GetRows(test_data().origin_domain), - ElementsAre(Pointee(StatsIs(test_data())))); + ElementsAre(Pointee(test_data()))); } TEST_F(StatisticsTableTest, DoubleOperation) { @@ -85,7 +78,7 @@ EXPECT_TRUE(db()->AddRow(test_data())); EXPECT_THAT(db()->GetRows(test_data().origin_domain), - ElementsAre(Pointee(StatsIs(test_data())))); + ElementsAre(Pointee(test_data()))); EXPECT_TRUE(db()->RemoveRow(test_data().origin_domain)); EXPECT_THAT(db()->GetRows(test_data().origin_domain), IsEmpty()); @@ -99,9 +92,8 @@ EXPECT_TRUE(db()->AddRow(stats1)); EXPECT_TRUE(db()->AddRow(stats2)); - EXPECT_THAT( - db()->GetRows(test_data().origin_domain), - UnorderedElementsAre(Pointee(StatsIs(stats1)), Pointee(StatsIs(stats2)))); + EXPECT_THAT(db()->GetRows(test_data().origin_domain), + UnorderedElementsAre(Pointee(stats1), Pointee(stats2))); EXPECT_TRUE(db()->RemoveRow(test_data().origin_domain)); EXPECT_THAT(db()->GetRows(test_data().origin_domain), IsEmpty()); } @@ -116,15 +108,15 @@ EXPECT_TRUE(db()->AddRow(stats1)); EXPECT_TRUE(db()->AddRow(stats2)); EXPECT_THAT(db()->GetRows(stats1.origin_domain), - ElementsAre(Pointee(StatsIs(stats1)))); + ElementsAre(Pointee(stats1))); EXPECT_THAT(db()->GetRows(stats2.origin_domain), - ElementsAre(Pointee(StatsIs(stats2)))); + ElementsAre(Pointee(stats2))); // Remove the first one only. EXPECT_TRUE(db()->RemoveStatsBetween(base::Time(), base::Time::FromTimeT(2))); EXPECT_THAT(db()->GetRows(stats1.origin_domain), IsEmpty()); EXPECT_THAT(db()->GetRows(stats2.origin_domain), - ElementsAre(Pointee(StatsIs(stats2)))); + ElementsAre(Pointee(stats2))); // Remove the second one only. EXPECT_TRUE(db()->RemoveStatsBetween(base::Time::FromTimeT(2), base::Time())); @@ -132,5 +124,19 @@ EXPECT_THAT(db()->GetRows(stats2.origin_domain), IsEmpty()); } +TEST_F(StatisticsTableTest, BadURL) { + test_data().origin_domain = GURL("trash"); + EXPECT_FALSE(db()->AddRow(test_data())); + EXPECT_THAT(db()->GetRows(test_data().origin_domain), IsEmpty()); + EXPECT_FALSE(db()->RemoveRow(test_data().origin_domain)); +} + +TEST_F(StatisticsTableTest, EmptyURL) { + test_data().origin_domain = GURL(); + EXPECT_FALSE(db()->AddRow(test_data())); + EXPECT_THAT(db()->GetRows(test_data().origin_domain), IsEmpty()); + EXPECT_FALSE(db()->RemoveRow(test_data().origin_domain)); +} + } // namespace } // namespace password_manager
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc index 776a869..bb81d46c 100644 --- a/components/password_manager/core/browser/test_password_store.cc +++ b/components/password_manager/core/browser/test_password_store.cc
@@ -6,6 +6,7 @@ #include "base/thread_task_runner_handle.h" #include "components/autofill/core/common/password_form.h" +#include "components/password_manager/core/browser/statistics_table.h" namespace password_manager {
diff --git a/components/policy.gypi b/components/policy.gypi index 7788538..63808772 100644 --- a/components/policy.gypi +++ b/components/policy.gypi
@@ -427,6 +427,20 @@ }, 'includes': [ '../build/java.gypi' ], }, + { + # GN: //components/policy/android:policy_java_test_support + 'target_name': 'policy_java_test_support', + 'type': 'none', + 'dependencies': [ + '../base/base.gyp:base_java', + '../base/base.gyp:base_java_test_support', + 'policy_java' + ], + 'variables': { + 'java_in_dir': 'policy/android/javatests', + }, + 'includes': [ '../build/java.gypi' ], + }, ], }], ['OS=="win" and target_arch=="ia32" and configuration_policy==1', {
diff --git a/components/policy/android/BUILD.gn b/components/policy/android/BUILD.gn index 53bc165..ab1003b 100644 --- a/components/policy/android/BUILD.gn +++ b/components/policy/android/BUILD.gn
@@ -22,6 +22,20 @@ ] } +# GYP: //components/components.gyp:policy_test_support_java +android_library("policy_java_test_support") { + testonly = true + deps = [ + "//base:base_java", + "//base:base_java_test_support", + ":policy_java", + ] + java_files = [ + "javatests/src/org/chromium/policy/test/annotations/Policies.java", + "javatests/src/org/chromium/policy/test/PolicyData.java", + ] +} + # GYP: //components/components.gyp:policy_jni_headers generate_jni("jni_headers") { visibility = [ "//components/policy/*" ] @@ -29,13 +43,17 @@ jni_package = "policy" } +# GYP: //components/components_test.gyp:components_junit_tests junit_binary("components_policy_junit_tests") { java_files = [ "junit/src/org/chromium/policy/AbstractAppRestrictionsProviderTest.java", "junit/src/org/chromium/policy/CombinedPolicyProviderTest.java", + "junit/src/org/chromium/policy/test/annotations/PoliciesTest.java", ] deps = [ - "//base:base_java", + ":policy_java_test_support", ":policy_java", + "//base:base_java", + "//third_party/junit:hamcrest", ] }
diff --git a/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java b/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java index 60b40bd..82b19399 100644 --- a/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java +++ b/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java
@@ -15,6 +15,7 @@ import android.preference.PreferenceManager; import android.util.Base64; +import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; @@ -30,6 +31,11 @@ public abstract class AbstractAppRestrictionsProvider extends PolicyProvider { private static final String PREFERENCE_KEY = "App Restrictions"; + private static final String TAG = "policy"; + + /** {@link Bundle} holding the restrictions to be used during tests. */ + private static Bundle sTestRestrictions = null; + private final Context mContext; private final SharedPreferences mSharedPreferences; private final BroadcastReceiver mAppRestrictionsChangedReceiver = new BroadcastReceiver() { @@ -79,6 +85,11 @@ */ @Override public void refresh() { + if (sTestRestrictions != null) { + notifySettingsAvailable(sTestRestrictions); + return; + } + final Bundle cachedResult = getCachedPolicies(); if (cachedResult != null) { notifySettingsAvailable(cachedResult); @@ -169,4 +180,18 @@ void setTaskExecutor(Executor testExecutor) { mExecutor = testExecutor; } + + /** + * Restrictions to be used during tests. Subsequent attempts to retrieve the restrictions will + * return the provided bundle instead. + * + * Chrome and WebView tests are set up to use annotations for policy testing and reset the + * restrictions to an empty bundle if nothing is specified. To stop using a test bundle, + * provide {@code null} as value instead. + */ + @VisibleForTesting + public static void setTestRestrictions(Bundle policies) { + Log.d(TAG, "Test Restrictions: %s", policies.keySet().toArray()); + sTestRestrictions = policies; + } }
diff --git a/components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java b/components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java new file mode 100644 index 0000000..6b230d86 --- /dev/null +++ b/components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java
@@ -0,0 +1,119 @@ +// Copyright 2015 The Chromium 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.policy.test; + +import android.os.Bundle; + +import junit.framework.Assert; + +import org.chromium.base.Log; +import org.json.JSONArray; + +/** + * Helper class to transform Java types to {@link Bundle}s usable by the Policy system. + * + * Use the subclasses to define the data and then transform it using {@link #asBundle(Iterable)} + */ +public abstract class PolicyData { + private static final String TAG = "policy_test"; + private final String mKey; + + public PolicyData(String key) { + mKey = key; + } + + public String getKey() { + return mKey; + } + + public abstract void putInBundle(Bundle bundle); + + public static Bundle asBundle(Iterable<PolicyData> policies) { + Bundle bundle = new Bundle(); + for (PolicyData data : policies) { + Log.d(TAG, "Adding to policy bundle: %s", data); + data.putInBundle(bundle); + } + return bundle; + } + + /** {@link PolicyData} for the {@link String} type. */ + public static class Str extends PolicyData { + private final String mValue; + + public Str(String key, String value) { + super(key); + mValue = value; + } + + public String getValue() { + return mValue; + } + + @Override + public void putInBundle(Bundle bundle) { + bundle.putString(getKey(), mValue); + } + + @Override + public String toString() { + return String.format("PolicyData.Str{%s=%s}", getKey(), mValue); + } + } + + /** {@link PolicyData} with no value, for error states. Doesn't put anything in a bundle.*/ + public static class Undefined extends PolicyData { + public Undefined(String key) { + super(key); + } + + @Override + public void putInBundle(Bundle bundle) { + Assert.fail(String.format( + "Attempted to push the '%s' policy without value to a bundle.", getKey())); + } + + @Override + public String toString() { + return String.format("PolicyData.Undefined{%s}", getKey()); + } + } + + /** + * {@link PolicyData} for the {@link String} array type. + * Outputs a string encoded as a JSON array. + */ + public static class StrArray extends PolicyData { + private final String[] mValue; + + public StrArray(String key, String[] value) { + super(key); + mValue = value.clone(); + } + + public String[] getValue() { + return mValue.clone(); + } + + private String valueToString() { + // JSONArray(Object[]) requires API 19 + JSONArray array = new JSONArray(); + for (String s : mValue) { + array.put(s); + } + return array.toString(); + } + + @Override + public void putInBundle(Bundle bundle) { + bundle.putString(getKey(), valueToString()); + } + + @Override + public String toString() { + return String.format("PolicyData.StrArray{%s=%s}", getKey(), valueToString()); + } + } +} \ No newline at end of file
diff --git a/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java b/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java new file mode 100644 index 0000000..11b7be2d --- /dev/null +++ b/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java
@@ -0,0 +1,141 @@ +// Copyright 2015 The Chromium 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.policy.test.annotations; + +import android.content.Context; +import android.os.Bundle; + +import junit.framework.Assert; + +import org.chromium.base.VisibleForTesting; +import org.chromium.base.test.BaseTestResult.PreTestHook; +import org.chromium.policy.AbstractAppRestrictionsProvider; +import org.chromium.policy.test.PolicyData; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * Annotations and utilities for testing code dependent on policies. + * + * Usage example: + * <pre> + * @Policies.Add({ + * @Policies.Item(key="Foo", string="Bar"), + * @Policies.Item(key="Baz", stringArray={"Baz"}) + * }) + * public class MyTestClass extends BaseActivityInstrumentationTestCase<ContentActivity> { + * + * public void MyTest1() { + * // Will run the Foo and Bar policies set + * } + * + * @Policies.Remove(@Policies.Item(key="Baz")) + * public void MyTest2() { + * // Will run with only the Foo policy set + * } + * } + * </pre> + */ +public final class Policies { + /** Items declared here will be added to the list of used policies. */ + @Inherited + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.TYPE}) + public @interface Add { + Item[] value(); + } + + /** Items declared here will be removed from the list of used policies. */ + @Inherited + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.TYPE}) + public @interface Remove { + Item[] value(); + } + + /** + * Individual policy item. Identified by a {@link #key}, and optional data values. + * At most one value argument (e.g. {@link #string()}, {@link #stringArray()}) can be used. A + * test failure will be caused otherwise. + */ + @Inherited + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.TYPE}) + public @interface Item { + String key(); + + String string() default ""; + + String[] stringArray() default {}; + } + + /** Parses the annotations to extract usable information as {@link PolicyData} objects. */ + private static Map<String, PolicyData> fromItems(Item[] items) { + Map<String, PolicyData> result = new HashMap<>(); + for (Item item : items) { + PolicyData data = null; + + if (!item.string().isEmpty()) { + Assert.assertNull("There can be at most one type of value for the policy", data); + data = new PolicyData.Str(item.key(), item.string()); + } + + if (item.stringArray().length != 0) { + Assert.assertNull("There can be at most one type of value for the policy", data); + data = new PolicyData.StrArray(item.key(), item.stringArray()); + } + + if (data == null) data = new PolicyData.Undefined(item.key()); + result.put(data.getKey(), data); + } + return result; + } + + /** @see PreTestHook */ + public static PreTestHook getRegistrationHook() { + return new RegistrationHook(); + } + + @VisibleForTesting + static Map<String, PolicyData> getPolicies(AnnotatedElement element) { + AnnotatedElement parent = (element instanceof Method) + ? ((Method) element).getDeclaringClass() + : ((Class<?>) element).getSuperclass(); + Map<String, PolicyData> flags = (parent == null) + ? new HashMap<String, PolicyData>() + : getPolicies(parent); + + if (element.isAnnotationPresent(Policies.Add.class)) { + flags.putAll(fromItems(element.getAnnotation(Policies.Add.class).value())); + } + + if (element.isAnnotationPresent(Policies.Remove.class)) { + flags.keySet().removeAll( + fromItems(element.getAnnotation(Policies.Remove.class).value()).keySet()); + } + + return flags; + } + + /** + * Registration hook for the {@link Policies} annotation family. Before a test, will parse + * the declared policies and use them as cached policies. + */ + public static class RegistrationHook implements PreTestHook { + @Override + public void run(Context targetContext, Method testMethod) { + final Bundle policyBundle = PolicyData.asBundle(getPolicies(testMethod).values()); + AbstractAppRestrictionsProvider.setTestRestrictions(policyBundle); + } + } +}
diff --git a/components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java b/components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java new file mode 100644 index 0000000..7bc08e44 --- /dev/null +++ b/components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java
@@ -0,0 +1,94 @@ +// Copyright 2015 The Chromium 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.policy.test.annotations; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import org.chromium.policy.test.PolicyData; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Unit tests for the {@link Policies} annotations + */ +@RunWith(BlockJUnit4ClassRunner.class) +public class PoliciesTest { + @Test + public void testGetPolicies() throws NoSuchMethodException { + Method method; + + // Simple element, one annotation, no parent + assertThat(Policies.getPolicies(SomeClass.class).keySet(), is(makeSet("Ni"))); + + // Simple element, removing an annotation just has no effect + assertThat(Policies.getPolicies(SomeClassThatRemoves.class).isEmpty(), is(true)); + + // Simple element, adds and removes the same element: We process additions, then removals. + assertThat(Policies.getPolicies(SomeConfusedClass.class).isEmpty(), is(true)); + + // Annotations are inherited + method = SomeClass.class.getDeclaredMethod("someMethodWithoutWord"); + assertThat(Policies.getPolicies(method).keySet(), is(makeSet("Ni"))); + + // Annotations add up + method = SomeClass.class.getDeclaredMethod("someMethod"); + assertThat(Policies.getPolicies(method).keySet(), is(makeSet("Ni", "Neee-wom"))); + + // Annotations from methods are not inherited + method = SomeDerivedClass.class.getDeclaredMethod("someMethod"); + assertThat(Policies.getPolicies(method).keySet(), is(makeSet("Ni"))); + + // Annotations are properly deduped, we get the one closest to the examined element + method = SomeClass.class.getDeclaredMethod("someMethodThatDuplicates"); + Map<String, PolicyData> policies = Policies.getPolicies(method); + assertThat(policies.size(), is(1)); + assertThat(policies.get("Ni"), is(PolicyData.Str.class)); + + // Annotations can be removed + method = SomeClass.class.getDeclaredMethod("someMethodThatTilRecentlyHadNi"); + assertThat(Policies.getPolicies(method).keySet(), + is(makeSet("Ekke Ekke Ekke Ekke Ptangya Zoooooooom Boing Ni"))); + } + + private Set<String> makeSet(String... keys) { + return new HashSet<String>(Arrays.asList(keys)); + } + + @Policies.Add(@Policies.Item(key = "Ni")) + private static class SomeClass { + @SuppressWarnings("unused") + void someMethodWithoutWord() {} + + @Policies.Add(@Policies.Item(key = "Neee-wom")) + void someMethod() {} + + @Policies.Add(@Policies.Item(key = "Ni", string = "Makes it string, not undefined.")) + void someMethodThatDuplicates() {} + + @Policies.Remove(@Policies.Item(key = "Ni")) + @Policies.Add(@Policies.Item(key = "Ekke Ekke Ekke Ekke Ptangya Zoooooooom Boing Ni")) + void someMethodThatTilRecentlyHadNi() {} + } + + private static class SomeDerivedClass extends SomeClass { + @Override + void someMethod() {} + } + + @Policies.Remove(@Policies.Item(key = "Ni")) + private static class SomeClassThatRemoves {} + + @Policies.Add(@Policies.Item(key = "Ni")) + @Policies.Remove(@Policies.Item(key = "Ni")) + private static class SomeConfusedClass {} +}
diff --git a/components/proximity_auth/cryptauth/proto/cryptauth_api.proto b/components/proximity_auth/cryptauth/proto/cryptauth_api.proto index 120b8f3..301355f 100644 --- a/components/proximity_auth/cryptauth/proto/cryptauth_api.proto +++ b/components/proximity_auth/cryptauth/proto/cryptauth_api.proto
@@ -30,7 +30,7 @@ enum DeviceType { UNKNOWN = 0; - ANDROID = 1; + ANDROIDOS = 1; CHROME = 2; IOS = 3; BROWSER = 4; @@ -228,7 +228,7 @@ optional string device_manufacturer = 31; // Used to indicate which type of device this is. - optional DeviceType device_type = 32 [default = ANDROID]; + optional DeviceType device_type = 32 [default = ANDROIDOS]; // Fields corresponding to screenlock type/features and hardware features // should be numbered in the 400 range.
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc index 9cf0a527..4b2d4a0b 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -57,6 +57,10 @@ const int kMaxFetcherRetries = 8; +// Name of the GAIA cookie that is being observed to detect when available +// accounts have changed in the content-area. +const char* kGaiaCookieName = "APISID"; + enum GaiaCookieRequestType { ADD_ACCOUNT, LOG_OUT_ALL_ACCOUNTS, @@ -292,8 +296,7 @@ void GaiaCookieManagerService::Init() { cookie_changed_subscription_ = signin_client_->AddCookieChangedCallback( - GaiaUrls::GetInstance()->google_url(), - "APISID", + GaiaUrls::GetInstance()->google_url(), kGaiaCookieName, base::Bind(&GaiaCookieManagerService::OnCookieChanged, base::Unretained(this))); } @@ -366,6 +369,15 @@ } } +void GaiaCookieManagerService::ForceOnCookieChangedProcessing() { + GURL google_url = GaiaUrls::GetInstance()->google_url(); + net::CanonicalCookie cookie(google_url, kGaiaCookieName, "", + google_url.host(), "", base::Time(), base::Time(), + base::Time(), false, false, false, + net::COOKIE_PRIORITY_DEFAULT); + OnCookieChanged(cookie, true); +} + void GaiaCookieManagerService::LogOutAllAccounts() { VLOG(1) << "GaiaCookieManagerService::LogOutAllAccounts"; @@ -434,7 +446,7 @@ void GaiaCookieManagerService::OnCookieChanged( const net::CanonicalCookie& cookie, bool removed) { - DCHECK_EQ("APISID", cookie.Name()); + DCHECK_EQ(kGaiaCookieName, cookie.Name()); DCHECK_EQ(GaiaUrls::GetInstance()->google_url().host(), cookie.Domain()); // Ignore changes to the cookie while requests are pending. These changes // are caused by the service itself as it adds accounts. A side effects is
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.h b/components/signin/core/browser/gaia_cookie_manager_service.h index 5dcd109..d3cf34e 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.h +++ b/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -173,6 +173,11 @@ // that a check which GAIA should be done can force it. void TriggerListAccounts(); + // Forces the processing of OnCookieChanged. This is public so that callers + // that know the GAIA APISID cookie might have changed can inform the + // service. Virtual for testing. + virtual void ForceOnCookieChangedProcessing(); + // Add or remove observers of this helper. void AddObserver(Observer* observer); void RemoveObserver(Observer* observer);
diff --git a/components/signin/ios/browser/account_consistency_service.h b/components/signin/ios/browser/account_consistency_service.h index 653cb11..af2436d 100644 --- a/components/signin/ios/browser/account_consistency_service.h +++ b/components/signin/ios/browser/account_consistency_service.h
@@ -74,6 +74,9 @@ // Does nothing if the cookie is not set on |domain|. void RemoveXChromeConnectedCookieFromDomain(const std::string& domain); + // Notifies the AccountConsistencyService that browsing data has been removed. + void OnBrowsingDataRemoved(); + private: friend class AccountConsistencyServiceTest;
diff --git a/components/signin/ios/browser/account_consistency_service.mm b/components/signin/ios/browser/account_consistency_service.mm index 4dd1af4..7e6e1a1 100644 --- a/components/signin/ios/browser/account_consistency_service.mm +++ b/components/signin/ios/browser/account_consistency_service.mm
@@ -390,6 +390,19 @@ } } +void AccountConsistencyService::OnBrowsingDataRemoved() { + // X-CHROME-CONNECTED cookies have been removed, update internal state + // accordingly. + ResetWKWebView(); + cookie_requests_.clear(); + domains_with_cookies_.clear(); + base::DictionaryValue dict; + signin_client_->GetPrefs()->Set(kDomainsWithCookiePref, dict); + + // APISID cookie has been removed, notify the GCMS. + gaia_cookie_manager_service_->ForceOnCookieChangedProcessing(); +} + void AccountConsistencyService::OnAddAccountToCookieCompleted( const std::string& account_id, const GoogleServiceAuthError& error) {
diff --git a/components/signin/ios/browser/account_consistency_service_unittest.mm b/components/signin/ios/browser/account_consistency_service_unittest.mm index 7134713..3458982 100644 --- a/components/signin/ios/browser/account_consistency_service_unittest.mm +++ b/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -73,6 +73,16 @@ MOCK_METHOD1(OnReceivedManageAccountsResponse, void(signin::GAIAServiceType)); }; +// Mock GaiaCookieManagerService to catch call to ForceOnCookieChangedProcessing +class MockGaiaCookieManagerService : public GaiaCookieManagerService { + public: + MockGaiaCookieManagerService() + : GaiaCookieManagerService(nullptr, + GaiaConstants::kChromeSource, + nullptr) {} + MOCK_METHOD0(ForceOnCookieChangedProcessing, void()); +}; + // TestWebState that allows control over its policy decider. class TestWebState : public web::TestWebState { public: @@ -111,8 +121,7 @@ HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry()); SigninManagerBase::RegisterProfilePrefs(prefs_.registry()); - gaia_cookie_manager_service_.reset(new GaiaCookieManagerService( - nullptr, GaiaConstants::kChromeSource, nullptr)); + gaia_cookie_manager_service_.reset(new MockGaiaCookieManagerService()); signin_client_.reset(new TestSigninClient(&prefs_)); signin_manager_.reset(new FakeSigninManager( signin_client_.get(), nullptr, &account_tracker_service_, nullptr)); @@ -181,7 +190,7 @@ scoped_ptr<AccountConsistencyService> account_consistency_service_; scoped_ptr<TestSigninClient> signin_client_; scoped_ptr<FakeSigninManager> signin_manager_; - scoped_ptr<GaiaCookieManagerService> gaia_cookie_manager_service_; + scoped_ptr<MockGaiaCookieManagerService> gaia_cookie_manager_service_; scoped_refptr<HostContentSettingsMap> settings_map_; scoped_refptr<content_settings::CookieSettings> cookie_settings_; }; @@ -362,3 +371,23 @@ SignOut(); EXPECT_OCMOCK_VERIFY(GetMockWKWebView()); } + +// Tests that domains with cookie are cleared when browsing data is removed. +TEST_F(AccountConsistencyServiceTest, DomainsClearedOnBrowsingDataRemoved) { + CR_TEST_REQUIRES_WK_WEB_VIEW(); + + AddPageLoadedExpectation(kGoogleUrl, true /* continue_navigation */); + AddPageLoadedExpectation(kYoutubeUrl, true /* continue_navigation */); + SignIn(); + EXPECT_OCMOCK_VERIFY(GetMockWKWebView()); + const base::DictionaryValue* dict = + prefs_.GetDictionary(AccountConsistencyService::kDomainsWithCookiePref); + EXPECT_EQ(2u, dict->size()); + + EXPECT_CALL(*gaia_cookie_manager_service_, ForceOnCookieChangedProcessing()) + .Times(1); + account_consistency_service_->OnBrowsingDataRemoved(); + dict = + prefs_.GetDictionary(AccountConsistencyService::kDomainsWithCookiePref); + EXPECT_EQ(0u, dict->size()); +}
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index df10f33..97b637fe 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -474,6 +474,11 @@ BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE, BACKGROUND_SYNC_STATUS_OK); + if (existing_registration->IsFiring()) { + existing_registration->set_sync_state( + BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING); + } + base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind( @@ -1255,9 +1260,12 @@ } if (registration->options()->periodicity == SYNC_ONE_SHOT) { - if (status_code != SERVICE_WORKER_OK) { + if (registration->sync_state() == + BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING) { + registration->set_sync_state(BACKGROUND_SYNC_STATE_PENDING); + registration->set_num_attempts(0); + } else if (status_code != SERVICE_WORKER_OK) { // Sync failed bool can_retry = registration->num_attempts() < max_sync_attempts_; - if (registration->sync_state() == BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING) { registration->set_sync_state(can_retry @@ -1270,11 +1278,11 @@ clock_->Now() + base::TimeDelta::FromMinutes(kInitialRetryDelayInMins) * pow(kRetryDelayFactor, registration->num_attempts() - 1)); - } else { // can't retry + } else { registration->set_sync_state(BACKGROUND_SYNC_STATE_FAILED); registration->RunFinishedCallbacks(); } - } else { // sync succeeded + } else { // Sync succeeded registration->set_sync_state(BACKGROUND_SYNC_STATE_SUCCESS); registration->RunFinishedCallbacks(); }
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc index 387b2e9..1e3d416 100644 --- a/content/browser/background_sync/background_sync_manager_unittest.cc +++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -275,13 +275,7 @@ public: BackgroundSyncManagerTest() : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), - network_change_notifier_(net::NetworkChangeNotifier::CreateMock()), - test_background_sync_manager_(nullptr), - counting_controller_(nullptr), - test_clock_(nullptr), - callback_status_(BACKGROUND_SYNC_STATUS_OK), - callback_sw_status_code_(SERVICE_WORKER_OK), - sync_events_called_(0) { + network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) { sync_options_1_.tag = "foo"; sync_options_1_.periodicity = SYNC_ONE_SHOT; sync_options_1_.network_state = NETWORK_STATE_ONLINE; @@ -532,6 +526,29 @@ return callback_status_ == BACKGROUND_SYNC_STATUS_OK; } + bool NotifyWhenFinished( + BackgroundSyncRegistrationHandle* registration_handle) { + callback_finished_called_ = false; + callback_finished_status_ = BACKGROUND_SYNC_STATUS_NOT_FOUND; + callback_finished_state_ = BACKGROUND_SYNC_STATE_FAILED; + + registration_handle->NotifyWhenFinished( + base::Bind(&NotifyWhenFinishedCallback, &callback_finished_called_, + &callback_finished_status_, &callback_finished_state_)); + base::RunLoop().RunUntilIdle(); + + if (callback_finished_called_) + EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, callback_finished_status_); + + return callback_finished_called_; + } + + BackgroundSyncState FinishedState() { + EXPECT_TRUE(callback_finished_called_); + EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, callback_finished_status_); + return callback_finished_state_; + } + bool GetRegistration( const BackgroundSyncRegistrationOptions& registration_options) { return GetRegistrationWithServiceWorkerId(sw_registration_id_1_, @@ -637,14 +654,14 @@ TestBrowserThreadBundle browser_thread_bundle_; scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; - TestPowerSource* power_monitor_source_; // owned by power_monitor_ + TestPowerSource* power_monitor_source_ = nullptr; // owned by power_monitor_ scoped_ptr<base::PowerMonitor> power_monitor_; scoped_ptr<EmbeddedWorkerTestHelper> helper_; scoped_ptr<BackgroundSyncManager> background_sync_manager_; scoped_ptr<StoragePartitionImpl> storage_partition_impl_; - TestBackgroundSyncManager* test_background_sync_manager_; + TestBackgroundSyncManager* test_background_sync_manager_ = nullptr; CountingBackgroundSyncController* counting_controller_; - base::SimpleTestClock* test_clock_; + base::SimpleTestClock* test_clock_ = nullptr; int64 sw_registration_id_1_; int64 sw_registration_id_2_; @@ -655,12 +672,16 @@ BackgroundSyncRegistrationOptions sync_options_2_; // Callback values. - BackgroundSyncStatus callback_status_; + BackgroundSyncStatus callback_status_ = BACKGROUND_SYNC_STATUS_OK; scoped_ptr<BackgroundSyncRegistrationHandle> callback_registration_handle_; scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>> callback_registration_handles_; - ServiceWorkerStatusCode callback_sw_status_code_; - int sync_events_called_; + ServiceWorkerStatusCode callback_sw_status_code_ = SERVICE_WORKER_OK; + bool callback_finished_called_ = false; + BackgroundSyncStatus callback_finished_status_ = + BACKGROUND_SYNC_STATUS_NOT_FOUND; + BackgroundSyncState callback_finished_state_ = BACKGROUND_SYNC_STATE_FAILED; + int sync_events_called_ = 0; ServiceWorkerVersion::StatusCallback sync_fired_callback_; }; @@ -1157,16 +1178,8 @@ EXPECT_TRUE(Register(sync_options_1_)); EXPECT_EQ(1, sync_events_called_); - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, sync_state); + EXPECT_TRUE(NotifyWhenFinished(callback_registration_handle_.get())); + EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState()); } TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedBeforeEventSuccess) { @@ -1174,22 +1187,13 @@ RegisterAndVerifySyncEventDelayed(sync_options_1_); - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); // Finish firing the event. sync_fired_callback_.Run(SERVICE_WORKER_OK); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, sync_events_called_); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState()); } TEST_F(BackgroundSyncManagerTest, @@ -1197,15 +1201,7 @@ InitDelayedSyncEventTest(); RegisterAndVerifySyncEventDelayed(sync_options_1_); - - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); // Unregistering should set the state to UNREGISTERED but finished shouldn't // be called until the event finishes firing, at which point its state should @@ -1216,10 +1212,7 @@ // Finish firing the event. sync_fired_callback_.Run(SERVICE_WORKER_OK); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, sync_events_called_); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState()); } TEST_F(BackgroundSyncManagerTest, @@ -1227,15 +1220,7 @@ InitDelayedSyncEventTest(); RegisterAndVerifySyncEventDelayed(sync_options_1_); - - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); // Unregistering should set the state to UNREGISTERED but finished shouldn't // be called until the event finishes firing, at which point its state should @@ -1247,9 +1232,7 @@ sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, sync_events_called_); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState()); } TEST_F(BackgroundSyncManagerTest, @@ -1259,17 +1242,8 @@ SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE); EXPECT_TRUE(Register(sync_options_1_)); EXPECT_TRUE(Unregister(callback_registration_handle_.get())); - - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, sync_state); + EXPECT_TRUE(NotifyWhenFinished(callback_registration_handle_.get())); + EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState()); } TEST_F(BackgroundSyncManagerTest, @@ -1277,16 +1251,7 @@ InitDelayedSyncEventTest(); RegisterAndVerifySyncEventDelayed(sync_options_1_); - - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); // Drop the client's handle to the registration before the event fires, ensure // that the finished callback is still run. @@ -1296,9 +1261,7 @@ sync_fired_callback_.Run(SERVICE_WORKER_OK); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, sync_events_called_); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState()); } TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedAfterEventFailure) { @@ -1307,71 +1270,77 @@ EXPECT_TRUE(Register(sync_options_1_)); EXPECT_EQ(1, sync_events_called_); - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, sync_state); + EXPECT_TRUE(NotifyWhenFinished(callback_registration_handle_.get())); + EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState()); } TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedBeforeEventFailure) { InitDelayedSyncEventTest(); RegisterAndVerifySyncEventDelayed(sync_options_1_); - - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); // Finish firing the event. sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState()); } TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedAfterUnregistered) { EXPECT_TRUE(Register(sync_options_1_)); EXPECT_TRUE(Unregister(callback_registration_handle_.get())); - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, sync_state); + EXPECT_TRUE(NotifyWhenFinished(callback_registration_handle_.get())); + EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState()); } TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedBeforeUnregistered) { Register(sync_options_1_); - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); - + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); EXPECT_TRUE(Unregister(callback_registration_handle_.get())); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState()); +} + +TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptFails) { + InitDelayedSyncEventTest(); + test_background_sync_manager_->set_max_sync_attempts(1); + RegisterAndVerifySyncEventDelayed(sync_options_1_); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); + + // Reregister the event mid-sync + EXPECT_TRUE(Register(sync_options_1_)); + + // The first sync attempt fails. + sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(callback_finished_called_); + + // It should fire again since it was reregistered mid-sync. + EXPECT_TRUE(GetRegistration(sync_options_1_)); + sync_fired_callback_.Run(SERVICE_WORKER_OK); + EXPECT_FALSE(GetRegistration(sync_options_1_)); + EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState()); +} + +TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptSucceeds) { + InitDelayedSyncEventTest(); + test_background_sync_manager_->set_max_sync_attempts(1); + RegisterAndVerifySyncEventDelayed(sync_options_1_); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); + + // Reregister the event mid-sync + EXPECT_TRUE(Register(sync_options_1_)); + + // The first sync event succeeds. + sync_fired_callback_.Run(SERVICE_WORKER_OK); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(callback_finished_called_); + + // It should fire again since it was reregistered mid-sync. + EXPECT_TRUE(GetRegistration(sync_options_1_)); + sync_fired_callback_.Run(SERVICE_WORKER_OK); + EXPECT_FALSE(GetRegistration(sync_options_1_)); + EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState()); } TEST_F(BackgroundSyncManagerTest, @@ -1379,16 +1348,7 @@ InitDelayedSyncEventTest(); RegisterAndVerifySyncEventDelayed(sync_options_1_); - - // Register for notification when the sync is finished. - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_NOT_ALLOWED; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); // Unregister the event mid-sync. EXPECT_TRUE(Unregister(callback_registration_handle_.get())); @@ -1396,10 +1356,9 @@ // Finish firing the event. sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); + // Since there were no retry attempts left, the sync ultimately failed. - EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState()); } TEST_F(BackgroundSyncManagerTest, @@ -1408,16 +1367,7 @@ test_background_sync_manager_->set_max_sync_attempts(2); RegisterAndVerifySyncEventDelayed(sync_options_1_); - - // Register for notification when the sync is finished. - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_NOT_ALLOWED; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); // Unregister the event mid-sync. EXPECT_TRUE(Unregister(callback_registration_handle_.get())); @@ -1425,11 +1375,9 @@ // Finish firing the event. sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); // Since there was one retry attempt left, the sync didn't completely fail // before it was unregistered. - EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState()); } TEST_F(BackgroundSyncManagerTest, OverwritePendingRegistration) { @@ -1450,16 +1398,8 @@ EXPECT_EQ(POWER_STATE_AUTO, callback_registration_handle_->options()->power_state); - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - original_handle->NotifyWhenFinished(base::Bind(&NotifyWhenFinishedCallback, - ¬ify_finished_called, - &status, &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, sync_state); + EXPECT_TRUE(NotifyWhenFinished(original_handle.get())); + EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState()); EXPECT_EQ(0, sync_events_called_); } @@ -1479,23 +1419,12 @@ // Overwrite the firing registration. sync_options_1_.power_state = POWER_STATE_AUTO; EXPECT_TRUE(Register(sync_options_1_)); - - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - original_handle->NotifyWhenFinished(base::Bind(&NotifyWhenFinishedCallback, - ¬ify_finished_called, - &status, &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(original_handle.get())); // Successfully finish the first event. sync_fired_callback_.Run(SERVICE_WORKER_OK); base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState()); } TEST_F(BackgroundSyncManagerTest, OverwriteFiringRegistrationWhichFails) { @@ -1514,23 +1443,12 @@ // Overwrite the firing registration. sync_options_1_.power_state = POWER_STATE_AUTO; EXPECT_TRUE(Register(sync_options_1_)); - - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - original_handle->NotifyWhenFinished(base::Bind(&NotifyWhenFinishedCallback, - ¬ify_finished_called, - &status, &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(original_handle.get())); // Fail the first event. sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED); base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, status); - EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState()); } TEST_F(BackgroundSyncManagerTest, DisableWhilePendingNotifiesFinished) { @@ -1540,24 +1458,14 @@ // can fire. SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE); EXPECT_TRUE(Register(sync_options_1_)); - - // Listen for notification of completion. - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); // Corrupting the backend should result in the manager disabling itself on the // next operation. While disabling, it should finalize any pending // registrations. test_background_sync_manager_->set_corrupt_backend(true); EXPECT_FALSE(Register(sync_options_2_)); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState()); } TEST_F(BackgroundSyncManagerTest, DisableWhileFiringNotifiesFinished) { @@ -1565,30 +1473,20 @@ // Register a one-shot that pauses mid-fire. RegisterAndVerifySyncEventDelayed(sync_options_1_); - - // Listen for notification of completion. - bool notify_finished_called = false; - BackgroundSyncStatus status = BACKGROUND_SYNC_STATUS_OK; - BackgroundSyncState sync_state = BACKGROUND_SYNC_STATE_SUCCESS; - callback_registration_handle_->NotifyWhenFinished( - base::Bind(&NotifyWhenFinishedCallback, ¬ify_finished_called, &status, - &sync_state)); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get())); // Corrupting the backend should result in the manager disabling itself on the // next operation. Even though the manager is disabled, the firing sync event // should still be able to complete successfully and notify as much. test_background_sync_manager_->set_corrupt_backend(true); EXPECT_FALSE(Register(sync_options_2_)); - EXPECT_FALSE(notify_finished_called); + EXPECT_FALSE(callback_finished_called_); test_background_sync_manager_->set_corrupt_backend(false); // Successfully complete the firing event. sync_fired_callback_.Run(SERVICE_WORKER_OK); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(notify_finished_called); - EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, sync_state); + EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState()); } // TODO(jkarlin): Change this to a periodic test as one-shots can't be power @@ -1749,26 +1647,6 @@ EXPECT_FALSE(GetRegistration(sync_options_1_)); } -TEST_F(BackgroundSyncManagerTest, ReregisterOneShotMidSync) { - InitDelayedSyncEventTest(); - - RegisterAndVerifySyncEventDelayed(sync_options_1_); - - // Register the same sync, but don't delay it. It shouldn't run as it's - // already firing. - test_background_sync_manager_->set_one_shot_callback( - base::Bind(OneShotSuccessfulCallback, &sync_events_called_)); - EXPECT_TRUE(Register(sync_options_1_)); - EXPECT_EQ(1, sync_events_called_); - EXPECT_TRUE(GetRegistration(sync_options_1_)); - - // Finish the original event, note that the second never runs. - sync_fired_callback_.Run(SERVICE_WORKER_OK); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, sync_events_called_); - EXPECT_FALSE(GetRegistration(sync_options_1_)); -} - TEST_F(BackgroundSyncManagerTest, UnregisterOneShotMidSync) { InitDelayedSyncEventTest();
diff --git a/content/browser/background_sync/background_sync_registration.cc b/content/browser/background_sync/background_sync_registration.cc index 14bdc46a..b20e2ef7 100644 --- a/content/browser/background_sync/background_sync_registration.cc +++ b/content/browser/background_sync/background_sync_registration.cc
@@ -51,6 +51,7 @@ switch (sync_state_) { case BACKGROUND_SYNC_STATE_PENDING: case BACKGROUND_SYNC_STATE_FIRING: + case BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING: case BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING: return false; case BACKGROUND_SYNC_STATE_FAILED: @@ -62,15 +63,31 @@ return false; } +bool BackgroundSyncRegistration::IsFiring() const { + switch (sync_state_) { + case BACKGROUND_SYNC_STATE_FIRING: + case BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING: + case BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING: + return true; + case BACKGROUND_SYNC_STATE_PENDING: + case BACKGROUND_SYNC_STATE_FAILED: + case BACKGROUND_SYNC_STATE_SUCCESS: + case BACKGROUND_SYNC_STATE_UNREGISTERED: + return false; + } + NOTREACHED(); + return false; +} + void BackgroundSyncRegistration::SetUnregisteredState() { DCHECK(!HasCompleted()); - bool firing = sync_state_ == BACKGROUND_SYNC_STATE_FIRING || - sync_state_ == BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING; - sync_state_ = firing ? BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING - : BACKGROUND_SYNC_STATE_UNREGISTERED; + bool is_firing = IsFiring(); - if (!firing) { + sync_state_ = is_firing ? BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING + : BACKGROUND_SYNC_STATE_UNREGISTERED; + + if (!is_firing) { // If the registration is currently firing then wait to run // RunFinishedCallbacks until after it has finished as it might // change state to SUCCESS first.
diff --git a/content/browser/background_sync/background_sync_registration.h b/content/browser/background_sync/background_sync_registration.h index 7fe6dd9d..df558ce3 100644 --- a/content/browser/background_sync/background_sync_registration.h +++ b/content/browser/background_sync/background_sync_registration.h
@@ -34,6 +34,7 @@ void AddFinishedCallback(const StateCallback& callback); void RunFinishedCallbacks(); bool HasCompleted() const; + bool IsFiring() const; // If the registration is currently firing, sets its state to // BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING. If it is firing, it sets
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index a9bdefbb..9e0d43a 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1584,6 +1584,7 @@ if (snapshot.has_tree_data) { AXContentTreeDataToAXTreeData(snapshot.tree_data, &dst_snapshot.tree_data); + dst_snapshot.has_tree_data = true; } it->second.Run(dst_snapshot); ax_tree_snapshot_callbacks_.erase(it);
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index dcd93c5..d0db9ce2 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -124,6 +124,10 @@ if (delegate) delegate->GenerateMetadataDict(metadata_dict.get()); + // Highres ticks. + metadata_dict->SetBoolean("highres-ticks", + base::TimeTicks::IsHighResolution()); + return metadata_dict.Pass(); }
diff --git a/content/child/background_sync/background_sync_provider.cc b/content/child/background_sync/background_sync_provider.cc index 5dab9e4..a5d6039 100644 --- a/content/child/background_sync/background_sync_provider.cc +++ b/content/child/background_sync/background_sync_provider.cc
@@ -393,6 +393,7 @@ switch (state) { case BACKGROUND_SYNC_STATE_PENDING: case BACKGROUND_SYNC_STATE_FIRING: + case BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING: case BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING: NOTREACHED(); break;
diff --git a/content/common/background_sync_service.mojom b/content/common/background_sync_service.mojom index 159f828..d1b0cd1 100644 --- a/content/common/background_sync_service.mojom +++ b/content/common/background_sync_service.mojom
@@ -21,6 +21,7 @@ PENDING, FIRING, UNREGISTERED_WHILE_FIRING, + REREGISTERED_WHILE_FIRING, FAILED, SUCCESS, UNREGISTERED
diff --git a/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc b/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc index 69fdd308..19106cb 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc +++ b/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc
@@ -129,7 +129,7 @@ scoped_refptr<gfx::GLImageOzoneNativePixmap> image( new gfx::GLImageOzoneNativePixmap(size, internalformat)); - if (!image->Initialize(pixmap.get(), format)) { + if (!image->Initialize(pixmap.get())) { LOG(ERROR) << "Failed to create GLImage"; return nullptr; }
diff --git a/content/common/gpu/media/va_surface.h b/content/common/gpu/media/va_surface.h index c76c11f..8901fa6 100644 --- a/content/common/gpu/media/va_surface.h +++ b/content/common/gpu/media/va_surface.h
@@ -90,6 +90,7 @@ VASurface(VASurfaceID va_surface_id, const gfx::Size& size, + unsigned int format, const ReleaseCB& release_cb); VASurfaceID id() { @@ -97,6 +98,7 @@ } const gfx::Size& size() const { return size_; } + unsigned int format() const { return format_; } private: friend class base::RefCountedThreadSafe<VASurface>; @@ -104,6 +106,7 @@ const VASurfaceID va_surface_id_; gfx::Size size_; + unsigned int format_; ReleaseCB release_cb_; DISALLOW_COPY_AND_ASSIGN(VASurface);
diff --git a/content/common/gpu/media/vaapi_drm_picture.cc b/content/common/gpu/media/vaapi_drm_picture.cc index d344a1b5..dfa4124 100644 --- a/content/common/gpu/media/vaapi_drm_picture.cc +++ b/content/common/gpu/media/vaapi_drm_picture.cc
@@ -17,6 +17,37 @@ #include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/surface_factory_ozone.h" +namespace { +// We decode video into YUV420, but for usage with GLImages we have to convert +// to BGRX_8888. +const gfx::BufferFormat kPictureForGLImageFormat = gfx::BufferFormat::BGRX_8888; + +uint32_t BufferFormatToVAFourCC(gfx::BufferFormat fmt) { + switch (fmt) { + case gfx::BufferFormat::BGRX_8888: + return VA_FOURCC_BGRX; + case gfx::BufferFormat::UYVY_422: + return VA_FOURCC_UYVY; + default: + NOTREACHED(); + return 0; + } +} + +uint32_t BufferFormatToVARTFormat(gfx::BufferFormat fmt) { + switch (fmt) { + case gfx::BufferFormat::UYVY_422: + return VA_RT_FORMAT_YUV422; + case gfx::BufferFormat::BGRX_8888: + return VA_RT_FORMAT_RGB32; + default: + NOTREACHED(); + return 0; + } +} + +} // namespace + namespace content { VaapiDrmPicture::VaapiDrmPicture( @@ -54,7 +85,8 @@ // Create a VASurface out of the created buffer using the dmabuf. VASurfaceAttribExternalBuffers va_attrib_extbuf; memset(&va_attrib_extbuf, 0, sizeof(va_attrib_extbuf)); - va_attrib_extbuf.pixel_format = VA_FOURCC_BGRX; + va_attrib_extbuf.pixel_format = + BufferFormatToVAFourCC(pixmap->GetBufferFormat()); va_attrib_extbuf.width = pixmap_size.width(); va_attrib_extbuf.height = pixmap_size.height(); va_attrib_extbuf.data_size = pixmap_size.height() * dmabuf_pitch; @@ -80,7 +112,8 @@ va_attribs[1].value.value.p = &va_attrib_extbuf; scoped_refptr<VASurface> va_surface = vaapi_wrapper_->CreateUnownedSurface( - VA_RT_FORMAT_RGB32, pixmap_size, va_attribs); + BufferFormatToVARTFormat(pixmap->GetBufferFormat()), pixmap_size, + va_attribs); if (!va_surface) { LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap"; return nullptr; @@ -90,13 +123,13 @@ } scoped_refptr<ui::NativePixmap> VaapiDrmPicture::CreateNativePixmap( - gfx::Size size) { + gfx::Size size, + gfx::BufferFormat format) { ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); // Create a buffer from Ozone. - return factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, - gfx::BufferFormat::BGRX_8888, + return factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, format, gfx::BufferUsage::SCANOUT); } @@ -104,7 +137,7 @@ // We want to create a VASurface and an EGLImage out of the same // memory buffer, so we can output decoded pictures to it using // VAAPI and also use it to paint with GL. - pixmap_ = CreateNativePixmap(size()); + pixmap_ = CreateNativePixmap(size(), kPictureForGLImageFormat); if (!pixmap_) { LOG(ERROR) << "Failed creating an Ozone NativePixmap"; return false; @@ -117,10 +150,10 @@ } // Weak pointers can only bind to methods without return values, - // hence we cannot bind ScalePixmap here. Instead we use a + // hence we cannot bind ProcessPixmap here. Instead we use a // static function to solve this problem. - pixmap_->SetScalingCallback(base::Bind(&VaapiDrmPicture::CallScalePixmap, - weak_this_factory_.GetWeakPtr())); + pixmap_->SetProcessingCallback(base::Bind(&VaapiDrmPicture::CallProcessPixmap, + weak_this_factory_.GetWeakPtr())); if (!make_context_current_.Run()) return false; @@ -129,7 +162,7 @@ texture_id()); scoped_refptr<gfx::GLImageOzoneNativePixmap> image( new gfx::GLImageOzoneNativePixmap(size(), GL_BGRA_EXT)); - if (!image->Initialize(pixmap_.get(), gfx::BufferFormat::BGRX_8888)) { + if (!image->Initialize(pixmap_.get())) { LOG(ERROR) << "Failed to create GLImage"; return false; } @@ -148,45 +181,51 @@ } // static -scoped_refptr<ui::NativePixmap> VaapiDrmPicture::CallScalePixmap( +scoped_refptr<ui::NativePixmap> VaapiDrmPicture::CallProcessPixmap( base::WeakPtr<VaapiDrmPicture> weak_ptr, - gfx::Size new_size) { + gfx::Size target_size, + gfx::BufferFormat target_format) { if (!weak_ptr.get()) { - LOG(ERROR) << "Failed scaling NativePixmap as scaling " + LOG(ERROR) << "Failed processing NativePixmap as processing " "unit(VaapiDrmPicture) is deleted"; return nullptr; } - return weak_ptr->ScalePixmap(new_size); + return weak_ptr->ProcessPixmap(target_size, target_format); } -scoped_refptr<ui::NativePixmap> VaapiDrmPicture::ScalePixmap( - gfx::Size new_size) { - if (!scaled_va_surface_.get() || scaled_va_surface_->size() != new_size) { - scaled_pixmap_ = CreateNativePixmap(new_size); - if (!scaled_pixmap_) { - LOG(ERROR) << "Failed creating an Ozone NativePixmap for scaling"; - scaled_va_surface_ = nullptr; +scoped_refptr<ui::NativePixmap> VaapiDrmPicture::ProcessPixmap( + gfx::Size target_size, + gfx::BufferFormat target_format) { + if (!processed_va_surface_.get() || + processed_va_surface_->size() != target_size || + processed_va_surface_->format() != + BufferFormatToVARTFormat(target_format)) { + processed_pixmap_ = CreateNativePixmap(target_size, target_format); + if (!processed_pixmap_) { + LOG(ERROR) << "Failed creating an Ozone NativePixmap for processing"; + processed_va_surface_ = nullptr; return nullptr; } - scaled_va_surface_ = CreateVASurfaceForPixmap(scaled_pixmap_, new_size); - if (!scaled_va_surface_) { + processed_va_surface_ = + CreateVASurfaceForPixmap(processed_pixmap_, target_size); + if (!processed_va_surface_) { LOG(ERROR) << "Failed creating VA Surface for pixmap"; - scaled_pixmap_ = nullptr; + processed_pixmap_ = nullptr; return nullptr; } } - DCHECK(scaled_pixmap_); + DCHECK(processed_pixmap_); bool vpp_result = - vaapi_wrapper_->BlitSurface(va_surface_, scaled_va_surface_); + vaapi_wrapper_->BlitSurface(va_surface_, processed_va_surface_); if (!vpp_result) { LOG(ERROR) << "Failed scaling NativePixmap"; - scaled_pixmap_ = nullptr; - scaled_va_surface_ = nullptr; + processed_pixmap_ = nullptr; + processed_va_surface_ = nullptr; return nullptr; } - return scaled_pixmap_; + return processed_pixmap_; } scoped_refptr<gl::GLImage> VaapiDrmPicture::GetImageToBind() {
diff --git a/content/common/gpu/media/vaapi_drm_picture.h b/content/common/gpu/media/vaapi_drm_picture.h index 4ea787fb..e480c8c9 100644 --- a/content/common/gpu/media/vaapi_drm_picture.h +++ b/content/common/gpu/media/vaapi_drm_picture.h
@@ -13,6 +13,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/common/gpu/media/vaapi_picture.h" +#include "ui/gfx/buffer_types.h" #include "ui/gfx/geometry/size.h" namespace gl { @@ -47,17 +48,21 @@ bool AllowOverlay() const override; private: - // Calls ScalePixmap() if weak_ptr is not NULL. - static scoped_refptr<ui::NativePixmap> CallScalePixmap( + // Calls ProcessPixmap() if weak_ptr is not NULL. + static scoped_refptr<ui::NativePixmap> CallProcessPixmap( base::WeakPtr<VaapiDrmPicture> weak_ptr, - gfx::Size new_size); - // Use VPP to scale underlying pixmap_ to |new_size| and return the - // scaling result with a new pixmap. - scoped_refptr<ui::NativePixmap> ScalePixmap(gfx::Size new_size); + gfx::Size target_size, + gfx::BufferFormat target_format); + // Use VPP to process underlying pixmap_, scaling to |target_size| and + // converting to |target_format|. + scoped_refptr<ui::NativePixmap> ProcessPixmap( + gfx::Size target_size, + gfx::BufferFormat target_format); scoped_refptr<VASurface> CreateVASurfaceForPixmap( scoped_refptr<ui::NativePixmap> pixmap, gfx::Size pixmap_size); - scoped_refptr<ui::NativePixmap> CreateNativePixmap(gfx::Size size); + scoped_refptr<ui::NativePixmap> CreateNativePixmap(gfx::Size size, + gfx::BufferFormat format); VaapiWrapper* vaapi_wrapper_; // Not owned. base::Callback<bool(void)> make_context_current_; @@ -65,8 +70,8 @@ // Ozone buffer, the storage of the EGLImage and the VASurface. scoped_refptr<ui::NativePixmap> pixmap_; - // Ozone buffer, the storage of the scaled buffer for overlay. - scoped_refptr<ui::NativePixmap> scaled_pixmap_; + // Ozone buffer, the storage of the processed buffer for overlay. + scoped_refptr<ui::NativePixmap> processed_pixmap_; // EGLImage bound to the GL textures used by the VDA client. scoped_refptr<gl::GLImage> gl_image_; @@ -74,8 +79,8 @@ // VASurface used to transfer from the decoder's pixel format. scoped_refptr<VASurface> va_surface_; - // VaSurface used to apply scaling. - scoped_refptr<VASurface> scaled_va_surface_; + // VaSurface used to apply processing. + scoped_refptr<VASurface> processed_va_surface_; // The WeakPtrFactory for VaapiDrmPicture. base::WeakPtrFactory<VaapiDrmPicture> weak_this_factory_;
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc index 704f7f2..97823a7 100644 --- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc +++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -999,9 +999,9 @@ return nullptr; DCHECK(!awaiting_va_surfaces_recycle_); - scoped_refptr<VASurface> va_surface( - new VASurface(available_va_surfaces_.front(), requested_pic_size_, - va_surface_release_cb_)); + scoped_refptr<VASurface> va_surface(new VASurface( + available_va_surfaces_.front(), requested_pic_size_, + vaapi_wrapper_->va_surface_format(), va_surface_release_cb_)); available_va_surfaces_.pop_front(); scoped_refptr<VaapiDecodeSurface> dec_surface =
diff --git a/content/common/gpu/media/vaapi_video_encode_accelerator.cc b/content/common/gpu/media/vaapi_video_encode_accelerator.cc index 9c078b2..495f2f1 100644 --- a/content/common/gpu/media/vaapi_video_encode_accelerator.cc +++ b/content/common/gpu/media/vaapi_video_encode_accelerator.cc
@@ -584,11 +584,13 @@ } current_encode_job_->input_surface = new VASurface( - available_va_surface_ids_.back(), coded_size_, va_surface_release_cb_); + available_va_surface_ids_.back(), coded_size_, + vaapi_wrapper_->va_surface_format(), va_surface_release_cb_); available_va_surface_ids_.pop_back(); current_encode_job_->recon_surface = new VASurface( - available_va_surface_ids_.back(), coded_size_, va_surface_release_cb_); + available_va_surface_ids_.back(), coded_size_, + vaapi_wrapper_->va_surface_format(), va_surface_release_cb_); available_va_surface_ids_.pop_back(); // Reference surfaces are needed until the job is done, but they get
diff --git a/content/common/gpu/media/vaapi_wrapper.cc b/content/common/gpu/media/vaapi_wrapper.cc index 4f073d3a..4240f94 100644 --- a/content/common/gpu/media/vaapi_wrapper.cc +++ b/content/common/gpu/media/vaapi_wrapper.cc
@@ -114,8 +114,12 @@ VASurface::VASurface(VASurfaceID va_surface_id, const gfx::Size& size, + unsigned int format, const ReleaseCB& release_cb) - : va_surface_id_(va_surface_id), size_(size), release_cb_(release_cb) { + : va_surface_id_(va_surface_id), + size_(size), + format_(format), + release_cb_(release_cb) { DCHECK(!release_cb_.is_null()); } @@ -124,7 +128,8 @@ } VaapiWrapper::VaapiWrapper() - : va_display_(NULL), + : va_surface_format_(0), + va_display_(NULL), va_config_id_(VA_INVALID_ID), va_context_id_(VA_INVALID_ID), va_vpp_config_id_(VA_INVALID_ID), @@ -511,6 +516,7 @@ DCHECK(va_surfaces->empty()); DCHECK(va_surface_ids_.empty()); + DCHECK_EQ(va_surface_format_, 0u); va_surface_ids_.resize(num_surfaces); // Allocate surfaces in driver. @@ -537,6 +543,7 @@ } *va_surfaces = va_surface_ids_; + va_surface_format_ = va_format; return true; } @@ -557,6 +564,7 @@ va_surface_ids_.clear(); va_context_id_ = VA_INVALID_ID; + va_surface_format_ = 0; } scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface( @@ -579,7 +587,7 @@ // of the destruction order. All the surfaces will be destroyed // before VaapiWrapper. va_surface = new VASurface( - va_surface_id, size, + va_surface_id, size, va_format, base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this))); return va_surface;
diff --git a/content/common/gpu/media/vaapi_wrapper.h b/content/common/gpu/media/vaapi_wrapper.h index 49e9f04..036bee4 100644 --- a/content/common/gpu/media/vaapi_wrapper.h +++ b/content/common/gpu/media/vaapi_wrapper.h
@@ -195,6 +195,9 @@ // Initialize static data before sandbox is enabled. static void PreSandboxInitialization(); + // Get the created surfaces format. + unsigned int va_surface_format() const { return va_surface_format_; } + private: struct ProfileInfo { VAProfile va_profile; @@ -325,6 +328,9 @@ // Allocated ids for VASurfaces. std::vector<VASurfaceID> va_surface_ids_; + // VA format of surfaces with va_surface_ids_. + unsigned int va_surface_format_; + // Singleton instance of VADisplayState. static base::LazyInstance<VADisplayState> va_display_state_;
diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc index 7140cc8c..7d107a0 100644 --- a/content/zygote/zygote_linux.cc +++ b/content/zygote/zygote_linux.cc
@@ -5,6 +5,8 @@ #include "content/zygote/zygote_linux.h" #include <fcntl.h> +#include <poll.h> +#include <signal.h> #include <stdint.h> #include <string.h> #include <sys/socket.h> @@ -25,6 +27,7 @@ #include "base/process/launch.h" #include "base/process/process.h" #include "base/process/process_handle.h" +#include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "content/common/child_process_sandbox_support_impl_linux.h" #include "content/common/sandbox_linux/sandbox_linux.h" @@ -84,14 +87,16 @@ } // namespace -Zygote::Zygote(int sandbox_flags, ScopedVector<ZygoteForkDelegate> helpers, +Zygote::Zygote(int sandbox_flags, + ScopedVector<ZygoteForkDelegate> helpers, const std::vector<base::ProcessHandle>& extra_children, const std::vector<int>& extra_fds) : sandbox_flags_(sandbox_flags), helpers_(helpers.Pass()), initial_uma_index_(0), extra_children_(extra_children), - extra_fds_(extra_fds) {} + extra_fds_(extra_fds), + to_reap_() {} Zygote::~Zygote() { } @@ -109,6 +114,13 @@ action.sa_handler = &SIGCHLDHandler; PCHECK(sigaction(SIGCHLD, &action, NULL) == 0); + // Block SIGCHLD until a child might be ready to reap. + sigset_t sigset; + sigset_t orig_sigmask; + PCHECK(sigemptyset(&sigset) == 0); + PCHECK(sigaddset(&sigset, SIGCHLD) == 0); + PCHECK(sigprocmask(SIG_BLOCK, &sigset, &orig_sigmask) == 0); + if (UsingSUIDSandbox() || UsingNSSandbox()) { // Let the ZygoteHost know we are ready to go. // The receiving code is in content/browser/zygote_host_linux.cc. @@ -128,10 +140,70 @@ #endif } + sigset_t ppoll_sigmask = orig_sigmask; + PCHECK(sigdelset(&ppoll_sigmask, SIGCHLD) == 0); + struct pollfd pfd; + pfd.fd = kZygoteSocketPairFd; + pfd.events = POLLIN; + + struct timespec timeout; + timeout.tv_sec = 2; + timeout.tv_nsec = 0; + for (;;) { - // This function call can return multiple times, once per fork(). - if (HandleRequestFromBrowser(kZygoteSocketPairFd)) - return true; + struct timespec* timeout_ptr = nullptr; + if (!to_reap_.empty()) + timeout_ptr = &timeout; + int rc = ppoll(&pfd, 1, timeout_ptr, &ppoll_sigmask); + PCHECK(rc >= 0 || errno == EINTR); + ReapChildren(); + + if (pfd.revents & POLLIN) { + // This function call can return multiple times, once per fork(). + if (HandleRequestFromBrowser(kZygoteSocketPairFd)) { + PCHECK(sigprocmask(SIG_SETMASK, &orig_sigmask, NULL) == 0); + return true; + } + } + } + // The loop should not be exited unless a request was successfully processed. + NOTREACHED(); + return false; +} + +bool Zygote::ReapChild(const base::TimeTicks& now, ZygoteProcessInfo* child) { + pid_t pid = child->internal_pid; + pid_t r = HANDLE_EINTR(waitpid(pid, NULL, WNOHANG)); + if (r > 0) { + if (r != pid) { + DLOG(ERROR) << "While waiting for " << pid << " to terminate, " + "waitpid returned " + << r; + } + return r == pid; + } + if ((now - child->time_of_reap_request).InSeconds() < 2) { + return false; + } + // If the process has been requested reaped >= 2 seconds ago, kill it. + if (!child->sent_sigkill) { + if (kill(pid, SIGKILL) != 0) + DPLOG(ERROR) << "Sending SIGKILL to process " << pid << " failed"; + + child->sent_sigkill = true; + } + return false; +} + +void Zygote::ReapChildren() { + base::TimeTicks now = base::TimeTicks::Now(); + std::vector<ZygoteProcessInfo>::iterator it = to_reap_.begin(); + while (it != to_reap_.end()) { + if (ReapChild(now, &(*it))) { + it = to_reap_.erase(it); + } else { + it++; + } } } @@ -243,23 +315,10 @@ NOTREACHED(); return; } + child_info.time_of_reap_request = base::TimeTicks::Now(); if (!child_info.started_from_helper) { - // Do not call base::EnsureProcessTerminated() under ThreadSanitizer, as it - // spawns a separate thread which may live until the call to fork() in the - // zygote. As a result, ThreadSanitizer will report an error and almost - // disable race detection in the child process. - // Not calling EnsureProcessTerminated() may result in zombie processes - // sticking around. This will only happen during testing, so we can live - // with this for now. -#if !defined(THREAD_SANITIZER) - // TODO(jln): this old code is completely broken. See crbug.com/274855. - base::EnsureProcessTerminated(base::Process(child_info.internal_pid)); -#else - LOG(WARNING) << "Zygote process omitting a call to " - << "base::EnsureProcessTerminated() for child pid " << child - << " under ThreadSanitizer. See http://crbug.com/274855."; -#endif + to_reap_.push_back(child_info); } else { // For processes from the helper, send a GetTerminationStatus request // with known_dead set to true.
diff --git a/content/zygote/zygote_linux.h b/content/zygote/zygote_linux.h index d371e12..f96b906d 100644 --- a/content/zygote/zygote_linux.h +++ b/content/zygote/zygote_linux.h
@@ -15,6 +15,8 @@ #include "base/posix/global_descriptors.h" #include "base/process/kill.h" #include "base/process/process.h" +#include "base/process/process_handle.h" +#include "base/time/time.h" namespace base { class Pickle; @@ -43,6 +45,10 @@ base::ProcessHandle internal_pid; // Keeps track of which fork delegate helper the process was started from. ZygoteForkDelegate* started_from_helper; + // Records when the browser requested the zygote to reap this process. + base::TimeTicks time_of_reap_request; + // Notes whether the zygote has sent SIGKILL to this process. + bool sent_sigkill; }; typedef base::SmallMap< std::map<base::ProcessHandle, ZygoteProcessInfo> > ZygoteProcessMap; @@ -114,6 +120,14 @@ bool HandleGetSandboxStatus(int fd, base::PickleIterator iter); + // Attempt to reap the child process by calling waitpid, and return + // whether successful. If the process has not terminated within + // 2 seconds of its reap request, send it SIGKILL. + bool ReapChild(const base::TimeTicks& now, ZygoteProcessInfo* child); + + // Attempt to reap all outstanding children in |to_reap_|. + void ReapChildren(); + // The Zygote needs to keep some information about each process. Most // notably what the PID of the process is inside the PID namespace of // the Zygote and whether or not a process was started by the @@ -136,6 +150,9 @@ // This vector contains the FDs that must be closed before reaping the extra // children. std::vector<int> extra_fds_; + + // The vector contains the child processes that need to be reaped. + std::vector<ZygoteProcessInfo> to_reap_; }; } // namespace content
diff --git a/extensions/renderer/resources/media_router_bindings.js b/extensions/renderer/resources/media_router_bindings.js index c877fd4..13bf88b 100644 --- a/extensions/renderer/resources/media_router_bindings.js +++ b/extensions/renderer/resources/media_router_bindings.js
@@ -98,6 +98,28 @@ } /** + * Converts presentation connection state to Mojo enum value. + * @param {!string} state + * @return {!mediaRouterMojom.MediaRouter.PresentationConnectionState} + */ + function presentationConnectionStateToMojo_(state) { + switch (state) { + case 'connected': + return + mediaRouterMojom.MediaRouter.PresentationConnectionState.CONNECTED; + case 'closed': + return mediaRouterMojom.MediaRouter.PresentationConnectionState.CLOSED; + case 'terminated': + return + mediaRouterMojom.MediaRouter.PresentationConnectionState.TERMINATED; + default: + console.error('Unknown presentation connection state: ' + state); + return + mediaRouterMojom.MediaRouter.PresentationConnectionState.TERMINATED; + } + } + + /** * Creates a new MediaRouter. * Converts a route struct to its Mojo form. * @param {!MediaRouterService} service @@ -265,13 +287,26 @@ /** * Called by the provider manager when sink availability has been updated. - * @param {!MediaRouter.SinkAvailability} The new sink availability. + * @param {!mediaRouterMojom.MediaRouter.SinkAvailability} availability + * The new sink availability. */ MediaRouter.prototype.onSinkAvailabilityUpdated = function(availability) { this.service_.onSinkAvailabilityUpdated(availability); }; /** + * Called by the provider manager when the state of a presentation connected + * to a route has changed. + * @param {!string} routeId + * @param {!string} state + */ + MediaRouter.prototype.onPresentationConnectionStateChanged = + function(routeId, state) { + this.service_.onPresentationConnectionStateChanged( + routeId, presentationConnectionStateToMojo_(state)); + }; + + /** * Object containing callbacks set by the provider manager. * * @constructor
diff --git a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm index d28fa43..ee1f6e7 100644 --- a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm +++ b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
@@ -23,6 +23,7 @@ #include "ios/chrome/browser/history/history_service_factory.h" #include "ios/chrome/browser/history/top_sites_factory.h" #include "ios/chrome/browser/history/web_history_service_factory.h" +#include "ios/chrome/browser/invalidation/ios_chrome_profile_invalidation_provider_factory.h" #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" #include "ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.h" @@ -84,6 +85,7 @@ IOSChromeLargeIconServiceFactory::GetInstance(); IOSChromeFaviconLoaderFactory::GetInstance(); IOSChromePasswordStoreFactory::GetInstance(); + IOSChromeProfileInvalidationProviderFactory::GetInstance(); OAuth2TokenServiceFactory::GetInstance(); PersonalDataManagerFactory::GetInstance(); SigninClientFactory::GetInstance();
diff --git a/ios/chrome/browser/invalidation/OWNERS b/ios/chrome/browser/invalidation/OWNERS new file mode 100644 index 0000000..9b396653 --- /dev/null +++ b/ios/chrome/browser/invalidation/OWNERS
@@ -0,0 +1,3 @@ +dcheng@chromium.org +nyquist@chromium.org +pavely@chromium.org
diff --git a/ios/chrome/browser/invalidation/ios_chrome_profile_invalidation_provider_factory.cc b/ios/chrome/browser/invalidation/ios_chrome_profile_invalidation_provider_factory.cc new file mode 100644 index 0000000..70b7a8f --- /dev/null +++ b/ios/chrome/browser/invalidation/ios_chrome_profile_invalidation_provider_factory.cc
@@ -0,0 +1,87 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/invalidation/ios_chrome_profile_invalidation_provider_factory.h" + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" +#include "base/prefs/pref_registry.h" +#include "components/gcm_driver/gcm_profile_service.h" +#include "components/invalidation/impl/invalidator_storage.h" +#include "components/invalidation/impl/profile_invalidation_provider.h" +#include "components/invalidation/impl/ticl_invalidation_service.h" +#include "components/invalidation/impl/ticl_profile_settings_provider.h" +#include "components/keyed_service/ios/browser_state_dependency_manager.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "components/signin/core/browser/profile_identity_provider.h" +#include "components/signin/core/browser/signin_manager.h" +#include "ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.h" +#include "ios/chrome/browser/signin/oauth2_token_service_factory.h" +#include "ios/chrome/browser/signin/signin_manager_factory.h" +#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/web/public/web_client.h" +#include "net/url_request/url_request_context_getter.h" + +using invalidation::InvalidatorStorage; +using invalidation::ProfileInvalidationProvider; +using invalidation::TiclInvalidationService; + +// static +invalidation::ProfileInvalidationProvider* +IOSChromeProfileInvalidationProviderFactory::GetForBrowserState( + ios::ChromeBrowserState* browser_state) { + return static_cast<ProfileInvalidationProvider*>( + GetInstance()->GetServiceForBrowserState(browser_state, true)); +} + +// static +IOSChromeProfileInvalidationProviderFactory* +IOSChromeProfileInvalidationProviderFactory::GetInstance() { + return base::Singleton<IOSChromeProfileInvalidationProviderFactory>::get(); +} + +IOSChromeProfileInvalidationProviderFactory:: + IOSChromeProfileInvalidationProviderFactory() + : BrowserStateKeyedServiceFactory( + "InvalidationService", + BrowserStateDependencyManager::GetInstance()) { + DependsOn(ios::SigninManagerFactory::GetInstance()); + DependsOn(IOSChromeGCMProfileServiceFactory::GetInstance()); + DependsOn(OAuth2TokenServiceFactory::GetInstance()); +} + +IOSChromeProfileInvalidationProviderFactory:: + ~IOSChromeProfileInvalidationProviderFactory() {} + +scoped_ptr<KeyedService> +IOSChromeProfileInvalidationProviderFactory::BuildServiceInstanceFor( + web::BrowserState* context) const { + ios::ChromeBrowserState* browser_state = + ios::ChromeBrowserState::FromBrowserState(context); + + scoped_ptr<IdentityProvider> identity_provider(new ProfileIdentityProvider( + ios::SigninManagerFactory::GetForBrowserState(browser_state), + OAuth2TokenServiceFactory::GetForBrowserState(browser_state), + // LoginUIServiceFactory is not built on iOS. + base::Closure())); + + scoped_ptr<TiclInvalidationService> service(new TiclInvalidationService( + web::GetWebClient()->GetUserAgent(false), identity_provider.Pass(), + make_scoped_ptr(new invalidation::TiclProfileSettingsProvider( + browser_state->GetPrefs())), + IOSChromeGCMProfileServiceFactory::GetForBrowserState(browser_state) + ->driver(), + browser_state->GetRequestContext())); + service->Init( + make_scoped_ptr(new InvalidatorStorage(browser_state->GetPrefs()))); + + return make_scoped_ptr(new ProfileInvalidationProvider(service.Pass())); +} + +void IOSChromeProfileInvalidationProviderFactory::RegisterBrowserStatePrefs( + user_prefs::PrefRegistrySyncable* registry) { + ProfileInvalidationProvider::RegisterProfilePrefs(registry); + InvalidatorStorage::RegisterProfilePrefs(registry); +}
diff --git a/ios/chrome/browser/invalidation/ios_chrome_profile_invalidation_provider_factory.h b/ios/chrome/browser/invalidation/ios_chrome_profile_invalidation_provider_factory.h new file mode 100644 index 0000000..5fc2bf3 --- /dev/null +++ b/ios/chrome/browser/invalidation/ios_chrome_profile_invalidation_provider_factory.h
@@ -0,0 +1,56 @@ +// Copyright 2015 The Chromium 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 IOS_CHROME_BROWSER_INVALIDATION_IOS_CHROME_PROFILE_INVALIDATION_PROVIDER_FACTORY_H_ +#define IOS_CHROME_BROWSER_INVALIDATION_IOS_CHROME_PROFILE_INVALIDATION_PROVIDER_FACTORY_H_ + +#include "base/macros.h" +#include "components/keyed_service/ios/browser_state_keyed_service_factory.h" + +namespace base { +template <typename T> +struct DefaultSingletonTraits; +} + +namespace invalidation { +class ProfileInvalidationProvider; +} + +namespace ios { +class ChromeBrowserState; +} + +namespace user_prefs { +class PrefRegistrySyncable; +} + +// A BrowserContextKeyedServiceFactory to construct InvalidationServices wrapped +// in ProfileInvalidationProviders. +class IOSChromeProfileInvalidationProviderFactory + : public BrowserStateKeyedServiceFactory { + public: + // Returns the ProfileInvalidationProvider for the given |browser_state|, + // lazily creating one first if required. + static invalidation::ProfileInvalidationProvider* GetForBrowserState( + ios::ChromeBrowserState* browser_state); + + static IOSChromeProfileInvalidationProviderFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits< + IOSChromeProfileInvalidationProviderFactory>; + + IOSChromeProfileInvalidationProviderFactory(); + ~IOSChromeProfileInvalidationProviderFactory() override; + + // BrowserStateKeyedServiceFactory: + scoped_ptr<KeyedService> BuildServiceInstanceFor( + web::BrowserState* context) const override; + void RegisterBrowserStatePrefs( + user_prefs::PrefRegistrySyncable* registry) override; + + DISALLOW_COPY_AND_ASSIGN(IOSChromeProfileInvalidationProviderFactory); +}; + +#endif // IOS_CHROME_BROWSER_INVALIDATION_IOS_CHROME_PROFILE_INVALIDATION_PROVIDER_FACTORY_H_
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp index 74e7156d..4d430bbfe 100644 --- a/ios/chrome/ios_chrome.gyp +++ b/ios/chrome/ios_chrome.gyp
@@ -298,6 +298,8 @@ 'browser/install_time_util.mm', 'browser/installation_notifier.h', 'browser/installation_notifier.mm', + 'browser/invalidation/ios_chrome_profile_invalidation_provider_factory.cc', + 'browser/invalidation/ios_chrome_profile_invalidation_provider_factory.h', 'browser/ios_chrome_field_trials.cc', 'browser/ios_chrome_field_trials.h', 'browser/memory/memory_debugger.h',
diff --git a/mandoline/ui/desktop_ui/browser_window.cc b/mandoline/ui/desktop_ui/browser_window.cc index 5a9dcaf..2b4ad48 100644 --- a/mandoline/ui/desktop_ui/browser_window.cc +++ b/mandoline/ui/desktop_ui/browser_window.cc
@@ -27,7 +27,7 @@ #include "ui/views/controls/button/label_button.h" #include "ui/views/mus/aura_init.h" #include "ui/views/mus/display_converter.h" -#include "ui/views/mus/native_widget_view_manager.h" +#include "ui/views/mus/native_widget_mus.h" #include "ui/views/widget/widget_delegate.h" namespace mandoline { @@ -415,8 +415,8 @@ views::Widget* widget = new views::Widget; views::Widget::InitParams params( views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.native_widget = - new views::NativeWidgetViewManager(widget, app_->shell(), root_); + params.native_widget = new views::NativeWidgetMus( + widget, app_->shell(), root, mus::mojom::SURFACE_TYPE_DEFAULT); params.delegate = widget_delegate; params.bounds = root_->bounds(); widget->Init(params);
diff --git a/mandoline/ui/omnibox/omnibox_application.cc b/mandoline/ui/omnibox/omnibox_application.cc index 3a17170..631a3863 100644 --- a/mandoline/ui/omnibox/omnibox_application.cc +++ b/mandoline/ui/omnibox/omnibox_application.cc
@@ -20,7 +20,7 @@ #include "ui/views/layout/layout_manager.h" #include "ui/views/mus/aura_init.h" #include "ui/views/mus/display_converter.h" -#include "ui/views/mus/native_widget_view_manager.h" +#include "ui/views/mus/native_widget_mus.h" #include "ui/views/widget/widget_delegate.h" namespace mandoline { @@ -139,8 +139,8 @@ views::Widget* widget = new views::Widget; views::Widget::InitParams params( views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.native_widget = - new views::NativeWidgetViewManager(widget, app_->shell(), root); + params.native_widget = new views::NativeWidgetMus( + widget, app_->shell(), root, mus::mojom::SURFACE_TYPE_DEFAULT); params.delegate = widget_delegate; params.bounds = root->bounds(); params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
diff --git a/media/audio/win/audio_device_listener_win.cc b/media/audio/win/audio_device_listener_win.cc index 056ab7c..505007ba 100644 --- a/media/audio/win/audio_device_listener_win.cc +++ b/media/audio/win/audio_device_listener_win.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" +#include "base/system_monitor/system_monitor.h" #include "base/time/default_tick_clock.h" #include "base/win/scoped_co_mem.h" #include "base/win/windows_version.h" @@ -30,7 +31,7 @@ } } -AudioDeviceListenerWin::AudioDeviceListenerWin(const ListenerCB& listener_cb) +AudioDeviceListenerWin::AudioDeviceListenerWin(const base::Closure& listener_cb) : listener_cb_(listener_cb), tick_clock_(new base::DefaultTickClock()) { CHECK(CoreAudioUtil::IsSupported()); @@ -97,7 +98,10 @@ STDMETHODIMP AudioDeviceListenerWin::OnDeviceStateChanged(LPCWSTR device_id, DWORD new_state) { - listener_cb_.Run(kInputDeviceChange); + base::SystemMonitor* monitor = base::SystemMonitor::Get(); + if (monitor) + monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); + return S_OK; } @@ -127,7 +131,7 @@ now - last_device_change_time_ > base::TimeDelta::FromMilliseconds(kDeviceChangeLimitMs)) { last_device_change_time_ = now; - listener_cb_.Run(kOutputDeviceChange); + listener_cb_.Run(); did_run_listener_cb = true; }
diff --git a/media/audio/win/audio_device_listener_win.h b/media/audio/win/audio_device_listener_win.h index 8875269..053afa6 100644 --- a/media/audio/win/audio_device_listener_win.h +++ b/media/audio/win/audio_device_listener_win.h
@@ -31,14 +31,10 @@ // TODO(dalecurtis, henrika): Support input device changes. class MEDIA_EXPORT AudioDeviceListenerWin : public IMMNotificationClient { public: - // Callback returns whether input or output devices have changed. - enum DeviceNotificationType { kInputDeviceChange, kOutputDeviceChange }; - using ListenerCB = base::Callback<void(DeviceNotificationType)>; - // The listener callback will be called from a system level multimedia thread, // thus the callee must be thread safe. |listener| is a permanent callback // and must outlive AudioDeviceListenerWin. - explicit AudioDeviceListenerWin(const ListenerCB& listener_cb); + explicit AudioDeviceListenerWin(const base::Closure& listener_cb); virtual ~AudioDeviceListenerWin(); private: @@ -60,7 +56,7 @@ ERole role, LPCWSTR new_default_device_id) override; - ListenerCB listener_cb_; + base::Closure listener_cb_; ScopedComPtr<IMMDeviceEnumerator> device_enumerator_; // Used to rate limit device change events.
diff --git a/media/audio/win/audio_device_listener_win_unittest.cc b/media/audio/win/audio_device_listener_win_unittest.cc index 855c590a..4b78d93 100644 --- a/media/audio/win/audio_device_listener_win_unittest.cc +++ b/media/audio/win/audio_device_listener_win_unittest.cc
@@ -60,8 +60,8 @@ base::ASCIIToUTF16(new_device_id).c_str()) == S_OK; } - MOCK_METHOD1(OnDeviceChange, - void(AudioDeviceListenerWin::DeviceNotificationType)); + + MOCK_METHOD0(OnDeviceChange, void()); private: ScopedCOMInitializer com_init_; @@ -75,16 +75,12 @@ TEST_F(AudioDeviceListenerWinTest, OutputDeviceChange) { ABORT_AUDIO_TEST_IF_NOT(CoreAudioUtil::IsSupported()); - EXPECT_CALL(*this, - OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange)) - .Times(1); + EXPECT_CALL(*this, OnDeviceChange()).Times(1); ASSERT_TRUE(SimulateDefaultOutputDeviceChange(kFirstTestDevice)); testing::Mock::VerifyAndClear(this); AdvanceLastDeviceChangeTime(); - EXPECT_CALL(*this, - OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange)) - .Times(1); + EXPECT_CALL(*this, OnDeviceChange()).Times(1); ASSERT_TRUE(SimulateDefaultOutputDeviceChange(kSecondTestDevice)); // The second device event should be ignored since it occurs too soon. @@ -96,23 +92,17 @@ TEST_F(AudioDeviceListenerWinTest, NullOutputDeviceChange) { ABORT_AUDIO_TEST_IF_NOT(CoreAudioUtil::IsSupported()); - EXPECT_CALL(*this, - OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange)) - .Times(1); + EXPECT_CALL(*this, OnDeviceChange()).Times(1); ASSERT_TRUE(SimulateNullDefaultOutputDeviceChange()); testing::Mock::VerifyAndClear(this); AdvanceLastDeviceChangeTime(); - EXPECT_CALL(*this, - OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange)) - .Times(1); + EXPECT_CALL(*this, OnDeviceChange()).Times(1); ASSERT_TRUE(SimulateDefaultOutputDeviceChange(kFirstTestDevice)); testing::Mock::VerifyAndClear(this); AdvanceLastDeviceChangeTime(); - EXPECT_CALL(*this, - OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange)) - .Times(1); + EXPECT_CALL(*this, OnDeviceChange()).Times(1); ASSERT_TRUE(SimulateNullDefaultOutputDeviceChange()); }
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc index 0b97afbc..70e6c1b 100644 --- a/media/audio/win/audio_manager_win.cc +++ b/media/audio/win/audio_manager_win.cc
@@ -21,9 +21,9 @@ #include "base/process/launch.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "base/system_monitor/system_monitor.h" #include "base/win/windows_version.h" #include "media/audio/audio_parameters.h" +#include "media/audio/win/audio_device_listener_win.h" #include "media/audio/win/audio_low_latency_input_win.h" #include "media/audio/win/audio_low_latency_output_win.h" #include "media/audio/win/audio_manager_win.h" @@ -171,7 +171,7 @@ // AudioDeviceListenerWin must be initialized on a COM thread and should // only be used if WASAPI / Core Audio is supported. output_device_listener_.reset(new AudioDeviceListenerWin(BindToCurrentLoop( - base::Bind(&AudioManagerWin::StallAudioThreadAfterDeviceChange, + base::Bind(&AudioManagerWin::NotifyAllOutputDeviceChangeListeners, base::Unretained(this))))); } } @@ -538,23 +538,6 @@ xp_device_id); } -void AudioManagerWin::StallAudioThreadAfterDeviceChange( - AudioDeviceListenerWin::DeviceNotificationType notification_type) { - base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); - - if (notification_type == AudioDeviceListenerWin::kInputDeviceChange) { - base::SystemMonitor* monitor = base::SystemMonitor::Get(); - if (monitor) { - monitor->ProcessDevicesChanged( - base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); - } - return; - } - - DCHECK_EQ(notification_type, AudioDeviceListenerWin::kOutputDeviceChange); - NotifyAllOutputDeviceChangeListeners(); -} - /// static AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { return new AudioManagerWin(audio_log_factory);
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h index 3d33b55..9826566 100644 --- a/media/audio/win/audio_manager_win.h +++ b/media/audio/win/audio_manager_win.h
@@ -8,10 +8,11 @@ #include <string> #include "media/audio/audio_manager_base.h" -#include "media/audio/win/audio_device_listener_win.h" namespace media { +class AudioDeviceListenerWin; + // Windows implementation of the AudioManager singleton. This class is internal // to the audio output and only internal users can call methods not exposed by // the AudioManager class. @@ -87,12 +88,6 @@ void GetAudioDeviceNamesImpl(bool input, AudioDeviceNames* device_names); - // We frequently see deadlock in third party Windows audio drivers, so after - // a device change is detected, stall for a second before allowing calls into - // the Windows audio subsystem. See http://crbug.com/422522 - void StallAudioThreadAfterDeviceChange( - AudioDeviceListenerWin::DeviceNotificationType notification_type); - // Listen for output device changes. scoped_ptr<AudioDeviceListenerWin> output_device_listener_;
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc index 4fa0d55..3bd2a69 100644 --- a/net/socket/tcp_socket_win.cc +++ b/net/socket/tcp_socket_win.cc
@@ -5,6 +5,7 @@ #include "net/socket/tcp_socket.h" #include "net/socket/tcp_socket_win.h" +#include <errno.h> #include <mstcpip.h> #include "base/callback_helpers.h"
diff --git a/net/tools/flip_server/acceptor_thread.cc b/net/tools/flip_server/acceptor_thread.cc index 2b65e5d..4e78663 100644 --- a/net/tools/flip_server/acceptor_thread.cc +++ b/net/tools/flip_server/acceptor_thread.cc
@@ -7,6 +7,7 @@ #include <errno.h> #include <netinet/in.h> #include <netinet/tcp.h> // For TCP_NODELAY +#include <string.h> // For strerror #include <sys/socket.h> #include <sys/types.h>
diff --git a/net/tools/flip_server/create_listener.cc b/net/tools/flip_server/create_listener.cc index 1fc5a7e..3e97603 100644 --- a/net/tools/flip_server/create_listener.cc +++ b/net/tools/flip_server/create_listener.cc
@@ -11,6 +11,7 @@ #include <netinet/in.h> #include <netinet/tcp.h> #include <stdlib.h> +#include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h>
diff --git a/net/tools/flip_server/flip_in_mem_edsm_server.cc b/net/tools/flip_server/flip_in_mem_edsm_server.cc index 1e6a8cef..ed449f8 100644 --- a/net/tools/flip_server/flip_in_mem_edsm_server.cc +++ b/net/tools/flip_server/flip_in_mem_edsm_server.cc
@@ -5,6 +5,7 @@ #include <errno.h> #include <signal.h> #include <stdio.h> +#include <string.h> #include <sys/file.h> #include <sys/stat.h>
diff --git a/net/tools/quic/quic_socket_utils.cc b/net/tools/quic/quic_socket_utils.cc index 3bc0db0..c2d65409 100644 --- a/net/tools/quic/quic_socket_utils.cc +++ b/net/tools/quic/quic_socket_utils.cc
@@ -6,6 +6,7 @@ #include <errno.h> #include <netinet/in.h> +#include <string.h> #include <sys/socket.h> #include <sys/uio.h> #include <string>
diff --git a/remoting/webapp/crd/js/it2me_activity.js b/remoting/webapp/crd/js/it2me_activity.js index c05d2192..1e69c63 100644 --- a/remoting/webapp/crd/js/it2me_activity.js +++ b/remoting/webapp/crd/js/it2me_activity.js
@@ -46,28 +46,41 @@ remoting.It2MeActivity.prototype.start = function() { var that = this; + var SessionState = remoting.ChromotingEvent.SessionState; this.logger_ = this.createLogger_(); - this.logger_.logSessionStateChange( - remoting.ChromotingEvent.SessionState.STARTED); + this.logger_.logSessionStateChange(SessionState.STARTED); + console.assert( + !this.desktopActivity_, 'Zombie DesktopActivity from previous session'); + base.dispose(this.desktopActivity_); this.desktopActivity_ = new remoting.DesktopRemotingActivity(this, this.logger_); + function onError(/** remoting.Error */ error) { + if (error.isCancel()) { + that.logger_.logSessionStateChange(SessionState.CONNECTION_CANCELED); + remoting.setMode(remoting.AppMode.HOME); + } else { + that.logger_.logSessionStateChange(SessionState.CONNECTION_FAILED, error); + that.showErrorMessage_(error); + } + + base.dispose(that.desktopActivity_); + that.desktopActivity_ = null; + } + + var sessionStart = Date.now(); + this.accessCodeDialog_.show().then(function(/** string */ accessCode) { + that.logger_.setAuthTotalTime(Date.now() - sessionStart); that.desktopActivity_.getConnectingDialog().show(); return that.verifyAccessCode_(accessCode); }).then(function() { return remoting.HostListApi.getInstance().getSupportHost(that.hostId_); }).then(function(/** remoting.Host */ host) { that.connect_(host); - }).catch(remoting.Error.handler(function(/** remoting.Error */ error) { - if (error.hasTag(remoting.Error.Tag.CANCELLED)) { - remoting.setMode(remoting.AppMode.HOME); - } else { - that.showErrorMessage_(error); - } - })); + }).catch(remoting.Error.handler(onError)); };
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/CustomShadowAsyncTask.java b/testing/android/junit/java/src/org/chromium/testing/local/CustomShadowAsyncTask.java new file mode 100644 index 0000000..6c81130 --- /dev/null +++ b/testing/android/junit/java/src/org/chromium/testing/local/CustomShadowAsyncTask.java
@@ -0,0 +1,27 @@ +// Copyright 2015 The Chromium 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.testing.local; + +import android.os.AsyncTask; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.shadows.ShadowAsyncTask; + +import java.util.concurrent.Executor; + +/** + * Forces async tasks to execute with the default executor. + * This works around Robolectric not working out of the box with custom executors. + */ +@Implements(AsyncTask.class) +public class CustomShadowAsyncTask<Params, Progress, Result> + extends ShadowAsyncTask<Params, Progress, Result> { + @Implementation + public AsyncTask<Params, Progress, Result> executeOnExecutor( + Executor executor, Params... params) { + return super.execute(params); + } +}
diff --git a/testing/buildbot/chromium.json b/testing/buildbot/chromium.json index e9127b2..fb9c356 100644 --- a/testing/buildbot/chromium.json +++ b/testing/buildbot/chromium.json
@@ -1,8 +1,5 @@ { "Linux x64": { - "additional_compile_targets": [ - "all" - ], "scripts": [ { "name": "sizes",
diff --git a/testing/buildbot/trybot_analyze_config.json b/testing/buildbot/trybot_analyze_config.json index da3533e..16112d1 100644 --- a/testing/buildbot/trybot_analyze_config.json +++ b/testing/buildbot/trybot_analyze_config.json
@@ -9,6 +9,8 @@ ".*isolate", "build/.*gyp[i]?", "build/android/.*py", + "build/android/devil/.*", + "build/android/play_services/.*", "build/android/pylib/.*", "build/compiler_version.py", "build/get_landmines.py",
diff --git a/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-getSources-expected.txt b/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-getSources-expected.txt index 2e6d9c2..76f45bb 100644 --- a/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-getSources-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-getSources-expected.txt
@@ -1,3 +1,4 @@ +CONSOLE WARNING: MediaStreamTrack.getSources is deprecated. See https://www.chromestatus.com/feature/4765305641369600 for more details. Tests MediaStreamTrack::getSources. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/WebKit/LayoutTests/inspector/animation/animation-timeline-expected.txt b/third_party/WebKit/LayoutTests/inspector/animation/animation-timeline-expected.txt index 179bf6a..4a51f22 100644 --- a/third_party/WebKit/LayoutTests/inspector/animation/animation-timeline-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/animation/animation-timeline-expected.txt
@@ -3,21 +3,21 @@ >>>> Animation with start delay only WebAnimation <div class="animation-name" style="transform: translateX(229.22px); width: 444px;"></div> -<svg class="animation-ui" height="50" width="680.67" style="margin-left: -7px; transform: translateX(0px);"><g style="transform: translateX(222.22px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="451.44" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.94 10.85 L 3.51 10.85 L 7.66 10.85 L 13.28 10.85 L 20.28 10.85 L 28.59 10.85 L 38.10 10.85 L 48.73 10.85 L 60.39 10.85 L 72.99 10.85 L 86.44 10.85 L 100.65 10.85 L 115.54 10.85 L 131.00 10.85 L 146.95 10.85 L 163.31 10.85 L 179.98 10.85 L 196.87 10.85 L 213.90 10.85 L 230.96 10.85 L 247.99 10.85 L 264.88 10.85 L 281.54 10.85 L 297.89 10.85 L 313.83 10.85 L 329.28 10.85 L 344.15 10.85 L 358.34 10.85 L 371.77 10.85 L 384.35 10.85 L 395.99 10.85 L 406.60 10.85 L 416.08 10.85 L 424.36 10.85 L 431.33 10.85 L 436.92 10.85 L 441.03 10.85 L 443.56 10.85 L 444.44 10.85 L 444.44 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="451.44" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="229.22" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line></svg> +<svg class="animation-ui" height="50" style="margin-left: -7px; transform: translateX(0px);" width="680.67"><g style="transform: translateX(222.22px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="451.44" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.94 10.85 L 3.51 10.85 L 7.66 10.85 L 13.28 10.85 L 20.28 10.85 L 28.59 10.85 L 38.10 10.85 L 48.73 10.85 L 60.39 10.85 L 72.99 10.85 L 86.44 10.85 L 100.65 10.85 L 115.54 10.85 L 131.00 10.85 L 146.95 10.85 L 163.31 10.85 L 179.98 10.85 L 196.87 10.85 L 213.90 10.85 L 230.96 10.85 L 247.99 10.85 L 264.88 10.85 L 281.54 10.85 L 297.89 10.85 L 313.83 10.85 L 329.28 10.85 L 344.15 10.85 L 358.34 10.85 L 371.77 10.85 L 384.35 10.85 L 395.99 10.85 L 406.60 10.85 L 416.08 10.85 L 424.36 10.85 L 431.33 10.85 L 436.92 10.85 L 441.03 10.85 L 443.56 10.85 L 444.44 10.85 L 444.44 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="451.44" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="229.22" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line></svg> >>>> Animation with start and end delay WebAnimation <div class="animation-name" style="transform: translateX(10.28px); width: 600px;"></div> -<svg class="animation-ui" height="50" width="680.67" style="margin-left: -7px; transform: translateX(0px);"><g style="transform: translateX(3.28px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="663.81" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.03 10.85 L 1.39 10.85 L 5.19 10.85 L 11.32 10.85 L 19.62 10.85 L 29.97 10.85 L 42.25 10.85 L 56.31 10.85 L 72.02 10.85 L 89.25 10.85 L 107.87 10.85 L 127.75 10.85 L 148.75 10.85 L 170.74 10.85 L 193.59 10.85 L 217.17 10.85 L 241.34 10.85 L 265.98 10.85 L 290.94 10.85 L 316.10 10.85 L 341.33 10.85 L 366.49 10.85 L 391.44 10.85 L 416.07 10.85 L 440.23 10.85 L 463.79 10.85 L 486.62 10.85 L 508.59 10.85 L 529.57 10.85 L 549.42 10.85 L 568.01 10.85 L 585.21 10.85 L 600.88 10.85 L 614.90 10.85 L 627.13 10.85 L 637.44 10.85 L 645.70 10.85 L 651.76 10.85 L 655.51 10.85 L 656.81 10.85 L 656.81 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="663.81" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="10.28" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="13.57" style="stroke: black; transform: translateX(660.1px);"></line></svg> +<svg class="animation-ui" height="50" style="margin-left: -7px; transform: translateX(0px);" width="680.67"><g style="transform: translateX(3.28px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="663.81" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.03 10.85 L 1.39 10.85 L 5.19 10.85 L 11.32 10.85 L 19.62 10.85 L 29.97 10.85 L 42.25 10.85 L 56.31 10.85 L 72.02 10.85 L 89.25 10.85 L 107.87 10.85 L 127.75 10.85 L 148.75 10.85 L 170.74 10.85 L 193.59 10.85 L 217.17 10.85 L 241.34 10.85 L 265.98 10.85 L 290.94 10.85 L 316.10 10.85 L 341.33 10.85 L 366.49 10.85 L 391.44 10.85 L 416.07 10.85 L 440.23 10.85 L 463.79 10.85 L 486.62 10.85 L 508.59 10.85 L 529.57 10.85 L 549.42 10.85 L 568.01 10.85 L 585.21 10.85 L 600.88 10.85 L 614.90 10.85 L 627.13 10.85 L 637.44 10.85 L 645.70 10.85 L 651.76 10.85 L 655.51 10.85 L 656.81 10.85 L 656.81 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="663.81" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="10.28" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="13.57" style="stroke: black; transform: translateX(660.1px);"></line></svg> >>>> Animation with step timing function WebAnimation <div class="animation-name" style="transform: translateX(7px); width: 666px;"></div> -<svg class="animation-ui" height="50" width="680.67" style="margin-left: -7px; transform: translateX(0px);"><g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="673.67" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.03 10.85 L 1.41 10.85 L 5.27 10.85 L 11.49 10.85 L 19.91 10.85 L 30.42 10.85 L 42.88 10.85 L 57.15 10.85 L 73.10 10.85 L 90.59 10.85 L 109.49 10.85 L 129.66 10.85 L 150.98 10.85 L 173.30 10.85 L 196.50 10.85 L 220.43 10.85 L 244.96 10.85 L 269.97 10.85 L 295.31 10.85 L 320.84 10.85 L 346.45 10.85 L 371.98 10.85 L 397.31 10.85 L 422.31 10.85 L 446.83 10.85 L 470.75 10.85 L 493.92 10.85 L 516.22 10.85 L 537.51 10.85 L 557.66 10.85 L 576.53 10.85 L 593.99 10.85 L 609.90 10.85 L 624.13 10.85 L 636.54 10.85 L 647.00 10.85 L 655.38 10.85 L 661.54 10.85 L 665.35 10.85 L 666.67 10.85 L 666.67 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="673.67" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line></svg> +<svg class="animation-ui" height="50" style="margin-left: -7px; transform: translateX(0px);" width="680.67"><g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="673.67" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.03 10.85 L 1.41 10.85 L 5.27 10.85 L 11.49 10.85 L 19.91 10.85 L 30.42 10.85 L 42.88 10.85 L 57.15 10.85 L 73.10 10.85 L 90.59 10.85 L 109.49 10.85 L 129.66 10.85 L 150.98 10.85 L 173.30 10.85 L 196.50 10.85 L 220.43 10.85 L 244.96 10.85 L 269.97 10.85 L 295.31 10.85 L 320.84 10.85 L 346.45 10.85 L 371.98 10.85 L 397.31 10.85 L 422.31 10.85 L 446.83 10.85 L 470.75 10.85 L 493.92 10.85 L 516.22 10.85 L 537.51 10.85 L 557.66 10.85 L 576.53 10.85 L 593.99 10.85 L 609.90 10.85 L 624.13 10.85 L 636.54 10.85 L 647.00 10.85 L 655.38 10.85 L 661.54 10.85 L 665.35 10.85 L 666.67 10.85 L 666.67 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="673.67" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line></svg> >>>> CSS animation started CSSAnimation <div class="animation-name" style="transform: translateX(7px); width: 666px;">anim</div> -<svg class="animation-ui" height="50" width="680.67" style="margin-left: -7px; transform: translateX(0px);"><g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="673.67" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.52 24.97 L 21.68 22.90 L 42.20 20.86 L 62.11 18.88 L 81.45 16.99 L 100.24 15.22 L 118.53 13.59 L 136.34 12.11 L 153.72 10.79 L 170.70 9.63 L 187.31 8.62 L 203.59 7.75 L 219.57 7.02 L 235.29 6.41 L 250.79 5.91 L 266.09 5.51 L 281.23 5.20 L 296.26 4.97 L 311.20 4.83 L 326.08 4.76 L 340.95 4.76 L 355.83 4.83 L 370.77 4.97 L 385.80 5.20 L 400.95 5.51 L 416.26 5.91 L 431.76 6.41 L 447.48 7.02 L 463.47 7.75 L 479.76 8.62 L 496.38 9.63 L 513.36 10.79 L 530.75 12.11 L 548.58 13.59 L 566.87 15.22 L 585.68 16.99 L 605.03 18.88 L 624.95 20.86 L 645.48 22.90 L 666.67 24.97 L 666.67 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="673.67" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line></svg> +<svg class="animation-ui" height="50" style="margin-left: -7px; transform: translateX(0px);" width="680.67"><g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="673.67" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.52 24.97 L 21.68 22.90 L 42.20 20.86 L 62.11 18.88 L 81.45 16.99 L 100.24 15.22 L 118.53 13.59 L 136.34 12.11 L 153.72 10.79 L 170.70 9.63 L 187.31 8.62 L 203.59 7.75 L 219.57 7.02 L 235.29 6.41 L 250.79 5.91 L 266.09 5.51 L 281.23 5.20 L 296.26 4.97 L 311.20 4.83 L 326.08 4.76 L 340.95 4.76 L 355.83 4.83 L 370.77 4.97 L 385.80 5.20 L 400.95 5.51 L 416.26 5.91 L 431.76 6.41 L 447.48 7.02 L 463.47 7.75 L 479.76 8.62 L 496.38 9.63 L 513.36 10.79 L 530.75 12.11 L 548.58 13.59 L 566.87 15.22 L 585.68 16.99 L 605.03 18.88 L 624.95 20.86 L 645.48 22.90 L 666.67 24.97 L 666.67 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="673.67" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line></svg> >>>> CSS transition started CSSTransition <div class="animation-name" style="transform: translateX(7px); width: 666px;">background-color</div> -<svg class="animation-ui" height="50" width="680.67" style="margin-left: -7px; transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="673.67" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 0.00 L 0.71 0.00 L 2.69 0.00 L 5.90 0.02 L 10.33 0.11 L 15.93 0.31 L 22.68 0.66 L 30.54 1.15 L 39.47 1.76 L 49.44 2.45 L 60.43 3.21 L 72.38 4.00 L 85.28 4.82 L 99.09 5.64 L 113.77 6.47 L 129.29 7.29 L 145.62 8.10 L 162.73 8.90 L 180.57 9.69 L 199.12 10.46 L 218.34 11.23 L 238.20 11.98 L 258.66 12.72 L 279.70 13.46 L 301.28 14.19 L 323.36 14.91 L 345.91 15.63 L 368.90 16.35 L 392.29 17.08 L 416.06 17.80 L 440.16 18.53 L 464.56 19.26 L 489.23 20.01 L 514.14 20.76 L 539.25 21.52 L 564.53 22.30 L 589.95 23.09 L 615.46 23.90 L 641.05 24.72 L 666.67 25.57 L 666.67 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="673.67" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line></svg> +<svg class="animation-ui" height="50" style="margin-left: -7px; transform: translateX(0px);" width="680.67"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="673.67" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 0.00 L 0.71 0.00 L 2.69 0.00 L 5.90 0.02 L 10.33 0.11 L 15.93 0.31 L 22.68 0.66 L 30.54 1.15 L 39.47 1.76 L 49.44 2.45 L 60.43 3.21 L 72.38 4.00 L 85.28 4.82 L 99.09 5.64 L 113.77 6.47 L 129.29 7.29 L 145.62 8.10 L 162.73 8.90 L 180.57 9.69 L 199.12 10.46 L 218.34 11.23 L 238.20 11.98 L 258.66 12.72 L 279.70 13.46 L 301.28 14.19 L 323.36 14.91 L 345.91 15.63 L 368.90 16.35 L 392.29 17.08 L 416.06 17.80 L 440.16 18.53 L 464.56 19.26 L 489.23 20.01 L 514.14 20.76 L 539.25 21.52 L 564.53 22.30 L 589.95 23.09 L 615.46 23.90 L 641.05 24.72 L 666.67 25.57 L 666.67 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="673.67" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line></svg>
diff --git a/third_party/WebKit/ManualTests/animation/animateMotion-to.svg b/third_party/WebKit/ManualTests/animation/animateMotion-to.svg deleted file mode 100644 index 17e2cdce..0000000 --- a/third_party/WebKit/ManualTests/animation/animateMotion-to.svg +++ /dev/null
@@ -1,8 +0,0 @@ -<svg xmlns='http://www.w3.org/2000/svg'> - <rect width='100' height='100'> - <animateMotion to='100,0' dur='3s' /> - </rect> - <text x='10' y='120'> - The rect should from 0,0 to 100,0 over 3 seconds. - </text> -</svg>
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index e5f1af4..fb40bcc7 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -404,8 +404,8 @@ , m_parsingState(FinishedParsing) , m_gotoAnchorNeededAfterStylesheetsLoad(false) , m_containsValidityStyleRules(false) - , m_updateFocusAppearanceRestoresSelection(false) , m_containsPlugins(false) + , m_updateFocusAppearanceSelectionBahavior(SelectionBehaviorOnFocus::Reset) , m_ignoreDestructiveWriteCount(0) , m_markers(adoptPtrWillBeNoop(new DocumentMarkerController)) , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired) @@ -4902,9 +4902,9 @@ return isMainThread(); } -void Document::updateFocusAppearanceSoon(bool restorePreviousSelection) +void Document::updateFocusAppearanceSoon(SelectionBehaviorOnFocus selectionbehavioronfocus) { - m_updateFocusAppearanceRestoresSelection = restorePreviousSelection; + m_updateFocusAppearanceSelectionBahavior = selectionbehavioronfocus; if (!m_updateFocusAppearanceTimer.isActive()) m_updateFocusAppearanceTimer.startOneShot(0, BLINK_FROM_HERE); } @@ -4921,7 +4921,7 @@ return; updateLayout(); if (element->isFocusable()) - element->updateFocusAppearance(m_updateFocusAppearanceRestoresSelection); + element->updateFocusAppearance(m_updateFocusAppearanceSelectionBahavior); } void Document::attachRange(Range* range)
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index a37c362e..b1a529e 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -168,7 +168,7 @@ class TreeWalker; class VisitedLinkState; class WebGLRenderingContext; - +enum class SelectionBehaviorOnFocus; struct AnnotatedRegionValue; struct IconURL; @@ -803,7 +803,7 @@ void setUseSecureKeyboardEntryWhenActive(bool); bool useSecureKeyboardEntryWhenActive() const; - void updateFocusAppearanceSoon(bool restorePreviousSelection); + void updateFocusAppearanceSoon(SelectionBehaviorOnFocus); void cancelFocusAppearanceUpdate(); bool isDNSPrefetchEnabled() const { return m_isDNSPrefetchEnabled; } @@ -1246,8 +1246,8 @@ bool m_isDNSPrefetchEnabled; bool m_haveExplicitlyDisabledDNSPrefetch; bool m_containsValidityStyleRules; - bool m_updateFocusAppearanceRestoresSelection; bool m_containsPlugins; + SelectionBehaviorOnFocus m_updateFocusAppearanceSelectionBahavior; // http://www.whatwg.org/specs/web-apps/current-work/#ignore-destructive-writes-counter unsigned m_ignoreDestructiveWriteCount;
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index 6caa421..ff7212a 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -2348,7 +2348,7 @@ return elementData()->attributes().find(qName); } -void Element::focus(bool restorePreviousSelection, WebFocusType type, InputDeviceCapabilities* sourceCapabilities) +void Element::focus(const FocusParams& params) { if (!inDocument()) return; @@ -2370,13 +2370,13 @@ // Slide the focus to its inner node. Element* next = document().page()->focusController().findFocusableElement(WebFocusTypeForward, *this); if (next && containsIncludingShadowDOM(next)) { - next->focus(false, WebFocusTypeForward); + next->focus(FocusParams(SelectionBehaviorOnFocus::Reset, WebFocusTypeForward, nullptr)); return; } } RefPtrWillBeRawPtr<Node> protect(this); - if (!document().page()->focusController().setFocusedElement(this, document().frame(), type, sourceCapabilities)) + if (!document().page()->focusController().setFocusedElement(this, document().frame(), params.type, params.sourceCapabilities)) return; // Setting the focused node above might have invalidated the layout due to scripts. @@ -2385,7 +2385,7 @@ return; cancelFocusAppearanceUpdate(); - updateFocusAppearance(restorePreviousSelection); + updateFocusAppearance(params.selectionBehavior); if (UserGestureIndicator::processedUserGestureSinceLoad()) { // Bring up the keyboard in the context of anything triggered by a user @@ -2396,7 +2396,7 @@ } } -void Element::updateFocusAppearance(bool /*restorePreviousSelection*/) +void Element::updateFocusAppearance(SelectionBehaviorOnFocus) { if (isRootEditableElement()) { // Taking the ownership since setSelection() may release the last reference to |frame|.
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h index c39e834..12520790 100644 --- a/third_party/WebKit/Source/core/dom/Element.h +++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -87,6 +87,25 @@ enum class ShadowRootType; +enum class SelectionBehaviorOnFocus { + Reset, + Restore, +}; + +struct FocusParams { + STACK_ALLOCATED(); + + FocusParams() {} + FocusParams(SelectionBehaviorOnFocus selection, WebFocusType focusType, InputDeviceCapabilities* capabilities) + : selectionBehavior(selection) + , type(focusType) + , sourceCapabilities(capabilities) {} + + SelectionBehaviorOnFocus selectionBehavior = SelectionBehaviorOnFocus::Restore; + WebFocusType type = WebFocusTypeNone; + Member<InputDeviceCapabilities> sourceCapabilities = nullptr; +}; + typedef WillBeHeapVector<RefPtrWillBeMember<Attr>> AttrNodeList; class CORE_EXPORT Element : public ContainerNode { @@ -371,8 +390,8 @@ virtual const AtomicString imageSourceURL() const; virtual Image* imageContents() { return nullptr; } - virtual void focus(bool restorePreviousSelection = true, WebFocusType = WebFocusTypeNone, InputDeviceCapabilities* sourceCapabilities = nullptr); - virtual void updateFocusAppearance(bool restorePreviousSelection); + virtual void focus(const FocusParams& = FocusParams()); + virtual void updateFocusAppearance(SelectionBehaviorOnFocus); virtual void blur(); void setDistributeScroll(ScrollStateCallback*, String nativeScrollBehavior);
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp index 2e11e86..6bd3f6a 100644 --- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp +++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
@@ -563,11 +563,11 @@ // FirstLetter seem to have different ideas of where things can split. // FirstLetter takes the punctuation + first letter, and BIDI will // split out the punctuation and possibly reorder it. - if (nextTextBox && nextTextBox->layoutObject() != layoutObject) { + if (nextTextBox && !(nextTextBox->lineLayoutItem().isEqual(layoutObject))) { m_textBox = 0; return; } - ASSERT(!nextTextBox || nextTextBox->layoutObject() == layoutObject); + ASSERT(!nextTextBox || nextTextBox->lineLayoutItem().isEqual(layoutObject)); if (runStart < runEnd) { // Handle either a single newline character (which becomes a space),
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp index 11b0dc8d..c7c7867 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.cpp +++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -955,6 +955,9 @@ case V8SVGElement_OffsetHeight_AttributeGetter: return "'SVGElement.offsetHeight' is deprecated and will be removed in M50, around April 2016. See https://www.chromestatus.com/features/5724912467574784 for more details."; + case MediaStreamTrackGetSources: + return "MediaStreamTrack.getSources is deprecated. See https://www.chromestatus.com/feature/4765305641369600 for more details."; + // Features that aren't deprecated don't have a deprecation message. default: return String();
diff --git a/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp b/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp index 82d63475d..19d45c8 100644 --- a/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp
@@ -222,16 +222,13 @@ toLayoutImage(layoutObject)->areaElementFocusChanged(this); } -void HTMLAreaElement::updateFocusAppearance(bool restorePreviousSelection) +void HTMLAreaElement::updateFocusAppearance(SelectionBehaviorOnFocus selectionBehavior) { if (!isFocusable()) return; - HTMLImageElement* imageElement = this->imageElement(); - if (!imageElement) - return; - - imageElement->updateFocusAppearance(restorePreviousSelection); + if (HTMLImageElement* imageElement = this->imageElement()) + imageElement->updateFocusAppearance(selectionBehavior); } }
diff --git a/third_party/WebKit/Source/core/html/HTMLAreaElement.h b/third_party/WebKit/Source/core/html/HTMLAreaElement.h index 1513f8f..0659add 100644 --- a/third_party/WebKit/Source/core/html/HTMLAreaElement.h +++ b/third_party/WebKit/Source/core/html/HTMLAreaElement.h
@@ -56,7 +56,7 @@ bool isKeyboardFocusable() const override; bool isMouseFocusable() const override; bool layoutObjectIsFocusable() const override; - void updateFocusAppearance(bool /*restorePreviousSelection*/) override; + void updateFocusAppearance(SelectionBehaviorOnFocus) override; void setFocus(bool) override; enum Shape { Default, Poly, Rect, Circle, Unknown };
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp index ba6302a..a16d3980 100644 --- a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
@@ -340,17 +340,21 @@ return m_inputType->shouldShowFocusRingOnMouseFocus(); } -void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection) +void HTMLInputElement::updateFocusAppearance(SelectionBehaviorOnFocus selectionBehavior) { if (isTextField()) { - if (!restorePreviousSelection) + switch (selectionBehavior) { + case SelectionBehaviorOnFocus::Reset: select(NotDispatchSelectEvent); - else + break; + case SelectionBehaviorOnFocus::Restore: restoreCachedSelection(); + break; + } if (document().frame()) document().frame()->selection().revealSelection(); } else { - HTMLTextFormControlElement::updateFocusAppearance(restorePreviousSelection); + HTMLTextFormControlElement::updateFocusAppearance(selectionBehavior); } } @@ -504,7 +508,7 @@ } if (document().focusedElement() == this) - document().updateFocusAppearanceSoon(true /* restore selection */); + document().updateFocusAppearanceSoon(SelectionBehaviorOnFocus::Restore); setTextAsOfLastFormControlChangeEvent(value()); setChangedSinceLastFormControlChangeEvent(false); @@ -831,7 +835,7 @@ m_inputType->countUsage(); if (document().focusedElement() == this) - document().updateFocusAppearanceSoon(true /* restore selection */); + document().updateFocusAppearanceSoon(SelectionBehaviorOnFocus::Restore); } void HTMLInputElement::detach(const AttachContext& context)
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.h b/third_party/WebKit/Source/core/html/HTMLInputElement.h index b79b6eb..fec9689 100644 --- a/third_party/WebKit/Source/core/html/HTMLInputElement.h +++ b/third_party/WebKit/Source/core/html/HTMLInputElement.h
@@ -150,7 +150,7 @@ bool layoutObjectIsNeeded(const ComputedStyle&) final; LayoutObject* createLayoutObject(const ComputedStyle&) override; void detach(const AttachContext& = AttachContext()) final; - void updateFocusAppearance(bool restorePreviousSelection) final; + void updateFocusAppearance(SelectionBehaviorOnFocus) final; // FIXME: For isActivatedSubmit and setActivatedSubmit, we should use the NVI-idiom here by making // it private virtual in all classes and expose a public method in HTMLFormControlElement to call
diff --git a/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp b/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp index 0268776b..c32e3b8 100644 --- a/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp
@@ -186,7 +186,7 @@ // In case of double click or triple click, selection will be there, // so do not focus the control element. if (!isLabelTextSelected) - element->focus(true, WebFocusTypeMouse); + element->focus(FocusParams(SelectionBehaviorOnFocus::Restore, WebFocusTypeMouse, nullptr)); } // Click the corresponding control. @@ -208,13 +208,13 @@ return HTMLElement::willRespondToMouseClickEvents(); } -void HTMLLabelElement::focus(bool, WebFocusType type, InputDeviceCapabilities* sourceCapabilities) +void HTMLLabelElement::focus(const FocusParams& params) { // to match other browsers, always restore previous selection if (HTMLElement* element = control()) - element->focus(true, type, sourceCapabilities); + element->focus(FocusParams(SelectionBehaviorOnFocus::Restore, params.type, params.sourceCapabilities)); if (isFocusable()) - HTMLElement::focus(true, type, sourceCapabilities); + HTMLElement::focus(params); } void HTMLLabelElement::accessKeyAction(bool sendMouseEvents)
diff --git a/third_party/WebKit/Source/core/html/HTMLLabelElement.h b/third_party/WebKit/Source/core/html/HTMLLabelElement.h index fca7c915..9c9fd06 100644 --- a/third_party/WebKit/Source/core/html/HTMLLabelElement.h +++ b/third_party/WebKit/Source/core/html/HTMLLabelElement.h
@@ -69,7 +69,7 @@ // Overridden to either click() or focus() the corresponding control. void defaultEventHandler(Event*) override; - void focus(bool restorePreviousSelection, WebFocusType, InputDeviceCapabilities* sourceCapabilities) override; + void focus(const FocusParams&) override; // FormAssociatedElement methods bool isFormControlElement() const override { return false; }
diff --git a/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp b/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp index b548d3bf..19e95de 100644 --- a/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp
@@ -54,16 +54,16 @@ return Traversal<HTMLFormControlElement>::next(*fieldset, fieldset); } -void HTMLLegendElement::focus(bool, WebFocusType type, InputDeviceCapabilities* sourceCapabilities) +void HTMLLegendElement::focus(const FocusParams& params) { if (isFocusable()) { - Element::focus(true, type, sourceCapabilities); + Element::focus(params); return; } // To match other browsers' behavior, never restore previous selection. if (HTMLFormControlElement* control = associatedControl()) - control->focus(false, type, sourceCapabilities); + control->focus(FocusParams(SelectionBehaviorOnFocus::Reset, params.type, params.sourceCapabilities)); } void HTMLLegendElement::accessKeyAction(bool sendMouseEvents)
diff --git a/third_party/WebKit/Source/core/html/HTMLLegendElement.h b/third_party/WebKit/Source/core/html/HTMLLegendElement.h index dedea4d3..dc8763815 100644 --- a/third_party/WebKit/Source/core/html/HTMLLegendElement.h +++ b/third_party/WebKit/Source/core/html/HTMLLegendElement.h
@@ -44,7 +44,7 @@ HTMLFormControlElement* associatedControl(); void accessKeyAction(bool sendMouseEvents) override; - void focus(bool restorePreviousSelection, WebFocusType, InputDeviceCapabilities* sourceCapabilities) override; + void focus(const FocusParams&) override; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp index 55cec81..358e5f49 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -1335,7 +1335,7 @@ if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { InputDeviceCapabilities* sourceCapabilities = toMouseEvent(event)->fromTouch() ? InputDeviceCapabilities::firesTouchEventsSourceCapabilities() : InputDeviceCapabilities::doesntFireTouchEventsSourceCapabilities(); - focus(true, WebFocusTypeNone, sourceCapabilities); + focus(FocusParams(SelectionBehaviorOnFocus::Restore, WebFocusTypeNone, sourceCapabilities)); if (layoutObject() && layoutObject()->isMenuList() && !isDisabledFormControl()) { if (popupIsVisible()) { hidePopup();
diff --git a/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp b/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp index 635a6a48..6c1aa8c 100644 --- a/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp
@@ -241,13 +241,16 @@ return true; } -void HTMLTextAreaElement::updateFocusAppearance(bool restorePreviousSelection) +void HTMLTextAreaElement::updateFocusAppearance(SelectionBehaviorOnFocus selectionBehavior) { - if (!restorePreviousSelection) + switch (selectionBehavior) { + case SelectionBehaviorOnFocus::Reset: setSelectionRange(0, 0, SelectionHasNoDirection, NotDispatchSelectEvent); - else + break; + case SelectionBehaviorOnFocus::Restore: restoreCachedSelection(); - + break; + } if (document().frame()) document().frame()->selection().revealSelection(); }
diff --git a/third_party/WebKit/Source/core/html/HTMLTextAreaElement.h b/third_party/WebKit/Source/core/html/HTMLTextAreaElement.h index 80f8dcb..62c2186 100644 --- a/third_party/WebKit/Source/core/html/HTMLTextAreaElement.h +++ b/third_party/WebKit/Source/core/html/HTMLTextAreaElement.h
@@ -125,7 +125,7 @@ bool hasCustomFocusLogic() const override; bool shouldShowFocusRingOnMouseFocus() const override; bool isKeyboardFocusable() const override; - void updateFocusAppearance(bool restorePreviousSelection) override; + void updateFocusAppearance(SelectionBehaviorOnFocus) override; void accessKeyAction(bool sendMouseEvents) override;
diff --git a/third_party/WebKit/Source/core/html/forms/InputType.cpp b/third_party/WebKit/Source/core/html/forms/InputType.cpp index c986cda..5feee4b7 100644 --- a/third_party/WebKit/Source/core/html/forms/InputType.cpp +++ b/third_party/WebKit/Source/core/html/forms/InputType.cpp
@@ -489,7 +489,7 @@ void InputType::accessKeyAction(bool) { - element().focus(false); + element().focus(FocusParams(SelectionBehaviorOnFocus::Reset, WebFocusTypeNone, nullptr)); } void InputType::countUsage()
diff --git a/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp b/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp index 1cf07fb..849905f 100644 --- a/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp +++ b/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp
@@ -352,7 +352,7 @@ rpContainer->appendChild(editingViewPort.release()); rpContainer->appendChild(DataListIndicatorElement::create(document)); if (element().document().focusedElement() == element()) - element().updateFocusAppearance(true /* restore selection */); + element().updateFocusAppearance(SelectionBehaviorOnFocus::Restore); } } else { picker->remove(ASSERT_NO_EXCEPTION);
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp index 0f681c7..1f84d71d 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.cpp +++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -1837,7 +1837,7 @@ Element* next = page->focusController().findFocusableElement(WebFocusTypeForward, *element.authorShadowRoot()); if (next && element.containsIncludingShadowDOM(next)) { // Use WebFocusTypeForward instead of WebFocusTypeMouse here to mean the focus has slided. - next->focus(false, WebFocusTypeForward); + next->focus(FocusParams(SelectionBehaviorOnFocus::Reset, WebFocusTypeForward, nullptr)); return true; } } @@ -3710,6 +3710,29 @@ } } +namespace { + +// Defining this class type local to dispatchTouchEvents() and annotating +// it with STACK_ALLOCATED(), runs into MSVC(VS 2013)'s C4822 warning +// that the local class doesn't provide a local definition for 'operator new'. +// Which it intentionally doesn't and shouldn't. +// +// Work around such toolchain bugginess by lifting out the type, thereby +// taking it out of C4822's reach. +class ChangedTouches final { + STACK_ALLOCATED(); +public: + // The touches corresponding to the particular change state this struct + // instance represents. + RefPtrWillBeMember<TouchList> m_touches; + + using EventTargetSet = WillBeHeapHashSet<RefPtrWillBeMember<EventTarget>>; + // Set of targets involved in m_touches. + EventTargetSet m_targets; +}; + +} // namespace + bool EventHandler::dispatchTouchEvents(const PlatformTouchEvent& event, WillBeHeapVector<TouchInfo>& touchInfos, bool freshTouchEvents, bool allTouchReleased) { @@ -3727,14 +3750,7 @@ TargetTouchesHeapMap touchesByTarget; // Array of touches per state, used to assemble the 'changedTouches' list. - using EventTargetSet = WillBeHeapHashSet<RefPtrWillBeMember<EventTarget>>; - struct { - // The touches corresponding to the particular change state this struct - // instance represents. - RefPtrWillBeMember<TouchList> m_touches; - // Set of targets involved in m_touches. - EventTargetSet m_targets; - } changedTouches[PlatformTouchPoint::TouchStateEnd]; + ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd]; for (unsigned i = 0; i < touchInfos.size(); ++i) { const TouchInfo& touchInfo = touchInfos[i]; @@ -3798,8 +3814,7 @@ continue; const AtomicString& eventName(touchEventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state))); - const EventTargetSet& targetsForState = changedTouches[state].m_targets; - for (const RefPtrWillBeMember<EventTarget>& eventTarget : targetsForState) { + for (const auto& eventTarget : changedTouches[state].m_targets) { EventTarget* touchEventTarget = eventTarget.get(); RefPtrWillBeRawPtr<TouchEvent> touchEvent = TouchEvent::create( touches.get(), touchesByTarget.get(touchEventTarget), changedTouches[state].m_touches.get(),
diff --git a/third_party/WebKit/Source/core/page/FocusController.cpp b/third_party/WebKit/Source/core/page/FocusController.cpp index 4c0a57a..2679a2bc 100644 --- a/third_party/WebKit/Source/core/page/FocusController.cpp +++ b/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -773,7 +773,7 @@ frame->selection().setSelection(newSelection); } - element->focus(false, type, sourceCapabilities); + element->focus(FocusParams(SelectionBehaviorOnFocus::Reset, type, sourceCapabilities)); return true; } @@ -1026,7 +1026,7 @@ Element* element = toElement(focusCandidate.focusableNode); ASSERT(element); - element->focus(false, type); + element->focus(FocusParams(SelectionBehaviorOnFocus::Reset, type, nullptr)); return true; }
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js index 3e7bab7..0df465b2 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
@@ -261,6 +261,7 @@ return; this._selectedGroup.seekTo(0); this._animateTime(0); + this._updateControlButton(); }, /** @@ -393,8 +394,10 @@ ui.element.classList.toggle("selected", this._selectedGroup === group); } - if (this._selectedGroup === group) + if (this._selectedGroup === group) { + this._replay(); return; + } this._selectedGroup = group; this._previewMap.forEach(applySelectionClass, this); this._reset(); @@ -402,7 +405,7 @@ this._addAnimation(anim); this.scheduleRedraw(); this._timelineScrubber.classList.remove("hidden"); - this._syncScrubber(); + this._replay(); }, /**
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp index 9c8f7c946..8ab9ea34 100644 --- a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp +++ b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
@@ -31,6 +31,7 @@ #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" #include "core/events/Event.h" +#include "core/frame/UseCounter.h" #include "modules/mediastream/MediaStream.h" #include "modules/mediastream/MediaStreamTrackSourcesCallback.h" #include "modules/mediastream/MediaStreamTrackSourcesRequestImpl.h" @@ -145,6 +146,7 @@ exceptionState.throwDOMException(NotSupportedError, "No sources controller available; is this a detached window?"); return; } + UseCounter::countDeprecation(context, UseCounter::MediaStreamTrackGetSources); MediaStreamTrackSourcesRequest* request = MediaStreamTrackSourcesRequestImpl::create(*context, callback); userMedia->requestSources(request); }
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.idl b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.idl index 5c1f2e59..f9ac2563 100644 --- a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.idl +++ b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.idl
@@ -34,7 +34,7 @@ readonly attribute boolean remote; readonly attribute DOMString readyState; - [CallWith=ExecutionContext, RaisesException, MeasureAs=MediaStreamTrackGetSources] static void getSources(MediaStreamTrackSourcesCallback callback); + [CallWith=ExecutionContext, RaisesException, DeprecateAs=MediaStreamTrackGetSources] static void getSources(MediaStreamTrackSourcesCallback callback); [ImplementedAs=stopTrack, RaisesException] void stop(); [CallWith=ExecutionContext] MediaStreamTrack clone();
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp index 22c4148e..8230ce1 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
@@ -371,4 +371,9 @@ handleMessageQueue(); } +bool PresentationConnection::isDisconnected() const +{ + return m_state == WebPresentationConnectionState::Closed || m_state == WebPresentationConnectionState::Terminated; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnection.h b/third_party/WebKit/Source/modules/presentation/PresentationConnection.h index 25c1096..7644a6e 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnection.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnection.h
@@ -116,6 +116,9 @@ void didFinishLoadingBlob(PassRefPtr<DOMArrayBuffer>); void didFailLoadingBlob(FileError::ErrorCode); + // Returns true iff current state is closed or terminated. + bool isDisconnected() const; + String m_id; String m_url; WebPresentationConnectionState m_state;
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index de86ef8..a710e85d 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -421,7 +421,7 @@ // focused, then the focus element shows with a focus ring but // no caret and does respond to keyboard inputs. if (element->isTextFormControl()) { - element->updateFocusAppearance(true); + element->updateFocusAppearance(SelectionBehaviorOnFocus::Restore); } else if (element->isContentEditable()) { // updateFocusAppearance() selects all the text of // contentseditable DIVs. So we set the selection explicitly
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp index 7e83339..bc80f45 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -2193,7 +2193,7 @@ // focused, then the focus element shows with a focus ring but // no caret and does respond to keyboard inputs. if (element->isTextFormControl()) { - element->updateFocusAppearance(true); + element->updateFocusAppearance(SelectionBehaviorOnFocus::Restore); } else if (element->isContentEditable()) { // updateFocusAppearance() selects all the text of // contentseditable DIVs. So we set the selection explicitly
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 134179d..259a0161 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -60,8 +60,8 @@ # This is just for completeness; any bot that uses this config should never actually run MB. 'none': ['none'], - 'noswarming_gn_release_bot_linux_dump_symbols': ['noswarming', 'gn', 'release_bot', 'linux_dump_symbols'], 'noswarming_gyp_release_bot': ['noswarming', 'gyp', 'release_bot'], + 'noswarming_gyp_release_bot_linux_dump_symbols': ['noswarming', 'gyp', 'release_bot', 'linux_dump_symbols'], 'noswarming_gyp_release_bot_mac_strip': ['noswarming', 'gyp', 'release_bot', 'mac_strip'], 'noswarming_gyp_release_bot_x86_linux_dump_symbols': ['noswarming', 'gyp', 'release_bot', 'x86', 'linux_dump_symbols'], @@ -244,7 +244,7 @@ 'libfuzzer': { 'gn_args': 'use_libfuzzer=true' }, 'linux_dump_symbols': { - 'gn_args': '', # TODO(GYP): Port linux_dump_symbols? + 'gn_args': 'error', # TODO(GYP): Port linux_dump_symbols? 'gyp_defines': 'linux_dump_symbols=1', }, @@ -353,7 +353,7 @@ 'chromium': { 'Win': 'noswarming_gyp_release_bot', 'Mac': 'noswarming_gyp_release_bot_mac_strip', - 'Linux x64': 'noswarming_gn_release_bot_linux_dump_symbols', + 'Linux x64': 'noswarming_gyp_release_bot_linux_dump_symbols', 'Linux': 'noswarming_gyp_release_bot_x86_linux_dump_symbols', 'Android': 'android_gyp_release_bot_minimal_symbols', }, @@ -492,7 +492,6 @@ 'linux_arm_tester': 'none', 'linux_chromium_compile_dbg_32_ng': 'swarming_gyp_debug_trybot_x86', 'linux_chromium_dbg_32_ng': 'swarming_gyp_debug_trybot_x86', - 'linux_chromium_archive_rel_ng': 'noswarming_gn_release_bot_linux_dump_symbols', 'linux_chromium_clobber_rel_ng': 'gyp_release_trybot', 'linux_chromium_gn_upload': 'gn_linux_upload', 'cast_shell_linux': 'cast_gyp_release_trybot',
diff --git a/tools/telemetry/telemetry/core/platform.py b/tools/telemetry/telemetry/core/platform.py index ebd4223b..a163b252 100644 --- a/tools/telemetry/telemetry/core/platform.py +++ b/tools/telemetry/telemetry/core/platform.py
@@ -3,6 +3,7 @@ # found in the LICENSE file. import logging as real_logging import os +import sys from telemetry.core import discover from telemetry.core import local_server @@ -63,8 +64,9 @@ return _remote_platforms[device.guid] return None except Exception: + current_exception = sys.exc_info() logging.error('Fail to create platform instance for %s.', device.name) - raise + raise current_exception[0], current_exception[1], current_exception[2] class Platform(object):
diff --git a/tools/telemetry/telemetry/timeline/thread.py b/tools/telemetry/telemetry/timeline/thread.py index f04f9da..e58e6b8 100644 --- a/tools/telemetry/telemetry/timeline/thread.py +++ b/tools/telemetry/telemetry/timeline/thread.py
@@ -158,6 +158,14 @@ self.PushSlice(new_slice) return new_slice + def PushMarkSlice(self, category, name, timestamp, thread_timestamp, + args=None): + new_slice = slice_module.Slice(self, category, name, timestamp, + thread_timestamp=thread_timestamp, + args=args) + self.PushSlice(new_slice) + return new_slice + def PushSlice(self, new_slice): self._newly_added_slices.append(new_slice) return new_slice
diff --git a/tools/telemetry/telemetry/timeline/trace_event_importer.py b/tools/telemetry/telemetry/timeline/trace_event_importer.py index 6d79d410..111e241 100644 --- a/tools/telemetry/telemetry/timeline/trace_event_importer.py +++ b/tools/telemetry/telemetry/timeline/trace_event_importer.py
@@ -140,6 +140,16 @@ event['tdur'] / 1000.0 if 'tdur' in event else None, event['args']) + def _ProcessMarkEvent(self, event): + thread = (self._GetOrCreateProcess(event['pid']) + .GetOrCreateThread(event['tid'])) + thread.PushMarkSlice( + event['cat'], + event['name'], + event['ts'] / 1000.0, + event['tts'] / 1000.0 if 'tts' in event else None, + event['args'] if 'args' in event else None) + def _ProcessMetadataEvent(self, event): if event['name'] == 'thread_name': thread = (self._GetOrCreateProcess(event['pid']) @@ -222,6 +232,8 @@ self._ProcessFlowEvent(event) elif phase == 'v': self._ProcessMemoryDumpEvent(event) + elif phase == 'R': + self._ProcessMarkEvent(event) else: self._model.import_errors.append('Unrecognized event phase: ' + phase + '(' + event['name'] + ')')
diff --git a/tools/telemetry/telemetry/timeline/trace_event_importer_unittest.py b/tools/telemetry/telemetry/timeline/trace_event_importer_unittest.py index 10fd01f..ae4410d 100644 --- a/tools/telemetry/telemetry/timeline/trace_event_importer_unittest.py +++ b/tools/telemetry/telemetry/timeline/trace_event_importer_unittest.py
@@ -940,6 +940,39 @@ self.assertTrue(slice_event.did_not_finish) self.assertEqual(0, len(slice_event.sub_slices)) + def testImportMarkEvent(self): + events = [ + {'name': 'a', 'pid': 52, 'ts': 629, 'cat': 'baz', 'tid': 53, 'ph': 'R'}, + {'name': 'b', 'pid': 52, 'ts': 730, 'cat': 'foo', 'tid': 53, 'ph': 'R'}, + {'name': 'c', 'pid': 52, 'ts': 740, 'cat': 'baz', 'tid': 53, 'ph': 'R'}, + ] + trace_data = trace_data_module.TraceData(events) + m = timeline_model.TimelineModel(trace_data) + p = m.GetAllProcesses()[0] + t = p.threads[53] + self.assertEqual(3, len(t.all_slices)) + + slice_event = t.all_slices[0] + self.assertEqual('a', slice_event.name) + self.assertEqual('baz', slice_event.category) + self.assertAlmostEqual(0.0, slice_event.start) + self.assertFalse(slice_event.did_not_finish) + self.assertEqual(0, len(slice_event.sub_slices)) + + slice_event = t.all_slices[1] + self.assertEqual('b', slice_event.name) + self.assertEqual('foo', slice_event.category) + self.assertAlmostEqual((730 - 629) / 1000.0, slice_event.start) + self.assertFalse(slice_event.did_not_finish) + self.assertEqual(0, len(slice_event.sub_slices)) + + slice_event = t.all_slices[2] + self.assertEqual('c', slice_event.name) + self.assertEqual('baz', slice_event.category) + self.assertAlmostEqual((740 - 629) / 1000.0, slice_event.start) + self.assertFalse(slice_event.did_not_finish) + self.assertEqual(0, len(slice_event.sub_slices)) + def testImportFlowEvent(self): events = [ {'name': 'a', 'cat': 'foo', 'id': 72, 'pid': 52, 'tid': 53, 'ts': 548,
diff --git a/tools/win/new_analyze_warnings/OWNERS b/tools/win/OWNERS similarity index 100% rename from tools/win/new_analyze_warnings/OWNERS rename to tools/win/OWNERS
diff --git a/ui/aura/window_tree_host_platform.h b/ui/aura/window_tree_host_platform.h index 41870b9..18b8e4d 100644 --- a/ui/aura/window_tree_host_platform.h +++ b/ui/aura/window_tree_host_platform.h
@@ -43,7 +43,6 @@ void SetPlatformWindow(scoped_ptr<ui::PlatformWindow> window); ui::PlatformWindow* platform_window() { return window_.get(); } - private: // ui::PlatformWindowDelegate: void OnBoundsChanged(const gfx::Rect& new_bounds) override; void OnDamageRect(const gfx::Rect& damaged_region) override; @@ -57,6 +56,7 @@ void OnAcceleratedWidgetDestroyed() override; void OnActivationChanged(bool active) override; + private: gfx::AcceleratedWidget widget_; scoped_ptr<ui::PlatformWindow> window_; gfx::NativeCursor current_cursor_;
diff --git a/ui/events/cocoa/events_mac.mm b/ui/events/cocoa/events_mac.mm index bf0dd31..804ffbd5 100644 --- a/ui/events/cocoa/events_mac.mm +++ b/ui/events/cocoa/events_mac.mm
@@ -134,6 +134,11 @@ return 0; } +PointerDetails GetMousePointerDetailsFromNative( + const base::NativeEvent& native_event) { + return PointerDetails(EventPointerType::POINTER_TYPE_MOUSE); +} + gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& event) { if ([event respondsToSelector:@selector(hasPreciseScrollingDeltas)] && [event hasPreciseScrollingDeltas]) {
diff --git a/ui/events/event.cc b/ui/events/event.cc index 71f5e27..0e7d0f19 100644 --- a/ui/events/event.cc +++ b/ui/events/event.cc
@@ -320,7 +320,7 @@ MouseEvent::MouseEvent(const base::NativeEvent& native_event) : LocatedEvent(native_event), changed_button_flags_(GetChangedMouseButtonFlagsFromNative(native_event)), - pointer_details_(PointerDetails(EventPointerType::POINTER_TYPE_MOUSE)) { + pointer_details_(GetMousePointerDetailsFromNative(native_event)) { if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED) SetClickCount(GetRepeatCount(*this)); }
diff --git a/ui/events/event_utils.cc b/ui/events/event_utils.cc index 1b3d7a9..c2d2adb 100644 --- a/ui/events/event_utils.cc +++ b/ui/events/event_utils.cc
@@ -6,7 +6,6 @@ #include <vector> -#include "ui/events/event.h" #include "ui/gfx/display.h" #include "ui/gfx/screen.h"
diff --git a/ui/events/event_utils.h b/ui/events/event_utils.h index 7488439..ab4779a 100644 --- a/ui/events/event_utils.h +++ b/ui/events/event_utils.h
@@ -9,6 +9,7 @@ #include "base/event_types.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" +#include "ui/events/event.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/display.h" @@ -93,6 +94,10 @@ EVENTS_EXPORT int GetChangedMouseButtonFlagsFromNative( const base::NativeEvent& native_event); +// Returns the detailed pointer information for mouse events. +EVENTS_EXPORT PointerDetails GetMousePointerDetailsFromNative( + const base::NativeEvent& native_event); + // Gets the mouse wheel offsets from a native event. EVENTS_EXPORT gfx::Vector2d GetMouseWheelOffset( const base::NativeEvent& native_event);
diff --git a/ui/events/events_default.cc b/ui/events/events_default.cc index 4fb85a34..7d55e8e 100644 --- a/ui/events/events_default.cc +++ b/ui/events/events_default.cc
@@ -46,6 +46,14 @@ return event->changed_button_flags(); } +PointerDetails GetMousePointerDetailsFromNative( + const base::NativeEvent& native_event) { + const ui::MouseEvent* event = + static_cast<const ui::MouseEvent*>(native_event); + DCHECK(event->IsMouseEvent() || event->IsScrollEvent()); + return event->pointer_details(); +} + KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) { const ui::KeyEvent* event = static_cast<const ui::KeyEvent*>(native_event); DCHECK(event->IsKeyEvent());
diff --git a/ui/events/events_stub.cc b/ui/events/events_stub.cc index d4ba557..87c71a5 100644 --- a/ui/events/events_stub.cc +++ b/ui/events/events_stub.cc
@@ -56,6 +56,11 @@ return 0; } +PointerDetails GetMousePointerDetailsFromNative( + const base::NativeEvent& native_event) { + return PointerDetails(EventPointerType::POINTER_TYPE_MOUSE); +} + gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) { NOTIMPLEMENTED(); return gfx::Vector2d();
diff --git a/ui/events/win/events_win.cc b/ui/events/win/events_win.cc index c2f35f43..18ddfa98 100644 --- a/ui/events/win/events_win.cc +++ b/ui/events/win/events_win.cc
@@ -283,6 +283,11 @@ return 0; } +PointerDetails GetMousePointerDetailsFromNative( + const base::NativeEvent& native_event) { + return PointerDetails(EventPointerType::POINTER_TYPE_MOUSE); +} + gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) { DCHECK(native_event.message == WM_MOUSEWHEEL || native_event.message == WM_MOUSEHWHEEL);
diff --git a/ui/events/x/events_x.cc b/ui/events/x/events_x.cc index 6afb53c..cbc14b66 100644 --- a/ui/events/x/events_x.cc +++ b/ui/events/x/events_x.cc
@@ -675,6 +675,11 @@ return 0; } +PointerDetails GetMousePointerDetailsFromNative( + const base::NativeEvent& native_event) { + return PointerDetails(EventPointerType::POINTER_TYPE_MOUSE); +} + gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) { float x_offset, y_offset; if (GetScrollOffsets(
diff --git a/ui/gl/gl_image_ozone_native_pixmap.cc b/ui/gl/gl_image_ozone_native_pixmap.cc index 818426178..9bcefcb 100644 --- a/ui/gl/gl_image_ozone_native_pixmap.cc +++ b/ui/gl/gl_image_ozone_native_pixmap.cc
@@ -86,9 +86,9 @@ GLImageOzoneNativePixmap::~GLImageOzoneNativePixmap() { } -bool GLImageOzoneNativePixmap::Initialize(ui::NativePixmap* pixmap, - BufferFormat format) { +bool GLImageOzoneNativePixmap::Initialize(ui::NativePixmap* pixmap) { DCHECK(!pixmap_); + BufferFormat format = pixmap->GetBufferFormat(); if (pixmap->GetEGLClientBuffer()) { EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; if (!gl::GLImageEGL::Initialize(EGL_NATIVE_PIXMAP_KHR,
diff --git a/ui/gl/gl_image_ozone_native_pixmap.h b/ui/gl/gl_image_ozone_native_pixmap.h index f76e98b..d0e1cde 100644 --- a/ui/gl/gl_image_ozone_native_pixmap.h +++ b/ui/gl/gl_image_ozone_native_pixmap.h
@@ -15,7 +15,7 @@ public: GLImageOzoneNativePixmap(const Size& size, unsigned internalformat); - bool Initialize(ui::NativePixmap* pixmap, BufferFormat format); + bool Initialize(ui::NativePixmap* pixmap); // Overridden from GLImage: unsigned GetInternalFormat() override;
diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc index c4b7642fa..978c98231 100644 --- a/ui/gl/gl_surface_ozone.cc +++ b/ui/gl/gl_surface_ozone.cc
@@ -575,7 +575,7 @@ return false; scoped_refptr<GLImageOzoneNativePixmap> image = new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT); - if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRA_8888)) + if (!image->Initialize(pixmap.get())) return false; images_[i] = image; // Bind image to texture.
diff --git a/ui/ozone/demo/surfaceless_gl_renderer.cc b/ui/ozone/demo/surfaceless_gl_renderer.cc index 60575d6..81aaf06 100644 --- a/ui/ozone/demo/surfaceless_gl_renderer.cc +++ b/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -43,7 +43,7 @@ gfx::BufferUsage::SCANOUT); scoped_refptr<gfx::GLImageOzoneNativePixmap> image( new gfx::GLImageOzoneNativePixmap(size, GL_RGB)); - if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRX_8888)) { + if (!image->Initialize(pixmap.get())) { LOG(ERROR) << "Failed to create GLImage"; return false; }
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc index f374f0de..174dd78 100644 --- a/ui/ozone/platform/cast/surface_factory_cast.cc +++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -190,6 +190,9 @@ } int GetDmaBufFd() override { return 0; } int GetDmaBufPitch() override { return 0; } + gfx::BufferFormat GetBufferFormat() override { + return gfx::BufferFormat::LAST; + } bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int plane_z_order, gfx::OverlayTransform plane_transform, @@ -197,8 +200,11 @@ const gfx::RectF& crop_rect) override { return true; } - void SetScalingCallback(const ScalingCallback& scaling_callback) override {} - scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) override { + void SetProcessingCallback( + const ProcessingCallback& processing_callback) override {} + scoped_refptr<NativePixmap> GetProcessedPixmap( + gfx::Size target_size, + gfx::BufferFormat target_format) override { return nullptr; } gfx::NativePixmapHandle ExportHandle() override {
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc index eb98ea0..00d4333 100644 --- a/ui/ozone/platform/drm/common/drm_util.cc +++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -277,10 +277,25 @@ return DRM_FORMAT_ARGB8888; case gfx::BufferFormat::BGRX_8888: return DRM_FORMAT_XRGB8888; + case gfx::BufferFormat::UYVY_422: + return DRM_FORMAT_UYVY; default: NOTREACHED(); return 0; } } +gfx::BufferFormat GetBufferFormatFromFourCCFormat(int format) { + switch (format) { + case DRM_FORMAT_ARGB8888: + return gfx::BufferFormat::BGRA_8888; + case DRM_FORMAT_XRGB8888: + return gfx::BufferFormat::BGRX_8888; + case DRM_FORMAT_UYVY: + return gfx::BufferFormat::UYVY_422; + default: + NOTREACHED(); + return gfx::BufferFormat::LAST; + } +} } // namespace ui
diff --git a/ui/ozone/platform/drm/common/drm_util.h b/ui/ozone/platform/drm/common/drm_util.h index ca13fa4e..4630957 100644 --- a/ui/ozone/platform/drm/common/drm_util.h +++ b/ui/ozone/platform/drm/common/drm_util.h
@@ -59,6 +59,7 @@ const gfx::Point& origin); int GetFourCCFormatFromBufferFormat(gfx::BufferFormat format); +gfx::BufferFormat GetBufferFormatFromFourCCFormat(int format); } // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/drm_buffer.cc b/ui/ozone/platform/drm/gpu/drm_buffer.cc index 4a2db96b7..bd2e9a9 100644 --- a/ui/ozone/platform/drm/gpu/drm_buffer.cc +++ b/ui/ozone/platform/drm/gpu/drm_buffer.cc
@@ -13,25 +13,6 @@ namespace { -uint8_t GetColorDepth(SkColorType type) { - switch (type) { - case kUnknown_SkColorType: - case kAlpha_8_SkColorType: - return 0; - case kIndex_8_SkColorType: - return 8; - case kRGB_565_SkColorType: - return 16; - case kARGB_4444_SkColorType: - return 16; - case kN32_SkColorType: - return 32; - default: - NOTREACHED(); - return 0; - } -} - uint32_t GetFourCCCodeForSkColorType(SkColorType type) { switch (type) { case kUnknown_SkColorType: @@ -84,14 +65,17 @@ } if (should_register_framebuffer) { - if (!drm_->AddFramebuffer( - info.width(), info.height(), GetColorDepth(info.colorType()), - info.bytesPerPixel() << 3, stride_, handle_, &framebuffer_)) { - PLOG(ERROR) << "DrmBuffer: AddFramebuffer: handle " << handle_; + uint32_t handles[4] = {0}; + handles[0] = handle_; + uint32_t strides[4] = {0}; + strides[0] = stride_; + uint32_t offsets[4] = {0}; + fb_pixel_format_ = GetFourCCCodeForSkColorType(info.colorType()); + if (!drm_->AddFramebuffer2(info.width(), info.height(), fb_pixel_format_, + handles, strides, offsets, &framebuffer_, 0)) { + PLOG(ERROR) << "DrmBuffer: AddFramebuffer2: handle " << handle_; return false; } - - fb_pixel_format_ = GetFourCCCodeForSkColorType(info.colorType()); } surface_ =
diff --git a/ui/ozone/platform/drm/gpu/drm_device.cc b/ui/ozone/platform/drm/gpu/drm_device.cc index ad4979c4..62d606e8 100644 --- a/ui/ozone/platform/drm/gpu/drm_device.cc +++ b/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -299,17 +299,18 @@ drmModeGetConnector(file_.GetPlatformFile(), connector_id)); } -bool DrmDevice::AddFramebuffer(uint32_t width, - uint32_t height, - uint8_t depth, - uint8_t bpp, - uint32_t stride, - uint32_t handle, - uint32_t* framebuffer) { +bool DrmDevice::AddFramebuffer2(uint32_t width, + uint32_t height, + uint32_t format, + uint32_t handles[4], + uint32_t strides[4], + uint32_t offsets[4], + uint32_t* framebuffer, + uint32_t flags) { DCHECK(file_.IsValid()); - TRACE_EVENT1("drm", "DrmDevice::AddFramebuffer", "handle", handle); - return !drmModeAddFB(file_.GetPlatformFile(), width, height, depth, bpp, - stride, handle, framebuffer); + TRACE_EVENT1("drm", "DrmDevice::AddFramebuffer", "handle", handles[0]); + return !drmModeAddFB2(file_.GetPlatformFile(), width, height, format, handles, + strides, offsets, framebuffer, flags); } bool DrmDevice::RemoveFramebuffer(uint32_t framebuffer) {
diff --git a/ui/ozone/platform/drm/gpu/drm_device.h b/ui/ozone/platform/drm/gpu/drm_device.h index cadc429..ec3054a 100644 --- a/ui/ozone/platform/drm/gpu/drm_device.h +++ b/ui/ozone/platform/drm/gpu/drm_device.h
@@ -77,15 +77,16 @@ // Returns the connector properties for |connector_id|. virtual ScopedDrmConnectorPtr GetConnector(uint32_t connector_id); - // Register a buffer with the CRTC. On successful registration, the CRTC will - // assign a framebuffer ID to |framebuffer|. - virtual bool AddFramebuffer(uint32_t width, - uint32_t height, - uint8_t depth, - uint8_t bpp, - uint32_t stride, - uint32_t handle, - uint32_t* framebuffer); + // Register any format buffer with the CRTC. On successful registration, the + // CRTC will assign a framebuffer ID to |framebuffer|. + virtual bool AddFramebuffer2(uint32_t width, + uint32_t height, + uint32_t format, + uint32_t handles[4], + uint32_t strides[4], + uint32_t offsets[4], + uint32_t* framebuffer, + uint32_t flags); // Deregister the given |framebuffer|. virtual bool RemoveFramebuffer(uint32_t framebuffer);
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc index 8c3c396..2e269bf 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -20,6 +20,11 @@ #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h" #include "ui/ozone/platform/drm/gpu/gbm_surfaceless.h" +namespace { +// Optimal format for rendering on overlay. +const gfx::BufferFormat kOverlayRenderFormat = gfx::BufferFormat::UYVY_422; +} // namespace + namespace ui { GbmBuffer::GbmBuffer(const scoped_refptr<GbmDevice>& gbm, @@ -80,12 +85,15 @@ return true; } -void GbmPixmap::SetScalingCallback(const ScalingCallback& scaling_callback) { - scaling_callback_ = scaling_callback; +void GbmPixmap::SetProcessingCallback( + const ProcessingCallback& processing_callback) { + processing_callback_ = processing_callback; } -scoped_refptr<NativePixmap> GbmPixmap::GetScaledPixmap(gfx::Size new_size) { - return scaling_callback_.Run(new_size); +scoped_refptr<NativePixmap> GbmPixmap::GetProcessedPixmap( + gfx::Size target_size, + gfx::BufferFormat target_format) { + return processing_callback_.Run(target_size, target_format); } gfx::NativePixmapHandle GbmPixmap::ExportHandle() { @@ -117,17 +125,23 @@ return dma_buf_pitch_; } +gfx::BufferFormat GbmPixmap::GetBufferFormat() { + return GetBufferFormatFromFourCCFormat(buffer_->GetFramebufferPixelFormat()); +} + bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int plane_z_order, gfx::OverlayTransform plane_transform, const gfx::Rect& display_bounds, const gfx::RectF& crop_rect) { - gfx::Size required_size; - if (plane_z_order && - ShouldApplyScaling(display_bounds, crop_rect, &required_size)) { - scoped_refptr<NativePixmap> scaled_pixmap = GetScaledPixmap(required_size); - if (scaled_pixmap) { - return scaled_pixmap->ScheduleOverlayPlane( + gfx::Size target_size; + gfx::BufferFormat target_format; + if (plane_z_order && ShouldApplyProcessing(display_bounds, crop_rect, + &target_size, &target_format)) { + scoped_refptr<NativePixmap> processed_pixmap = + GetProcessedPixmap(target_size, target_format); + if (processed_pixmap) { + return processed_pixmap->ScheduleOverlayPlane( widget, plane_z_order, plane_transform, display_bounds, crop_rect); } else { return false; @@ -146,25 +160,30 @@ return true; } -bool GbmPixmap::ShouldApplyScaling(const gfx::Rect& display_bounds, - const gfx::RectF& crop_rect, - gfx::Size* required_size) { +bool GbmPixmap::ShouldApplyProcessing(const gfx::Rect& display_bounds, + const gfx::RectF& crop_rect, + gfx::Size* target_size, + gfx::BufferFormat* target_format) { if (crop_rect.width() == 0 || crop_rect.height() == 0) { - PLOG(ERROR) << "ShouldApplyScaling passed zero scaling target."; + PLOG(ERROR) << "ShouldApplyProcessing passed zero processing target."; return false; } if (!buffer_) { - PLOG(ERROR) << "ShouldApplyScaling requires a buffer."; + PLOG(ERROR) << "ShouldApplyProcessing requires a buffer."; return false; } + // TODO(william.xie): Figure out the optimal render format for overlay. + // See http://crbug.com/553264. + *target_format = kOverlayRenderFormat; gfx::Size pixmap_size = buffer_->GetSize(); // If the required size is not integer-sized, round it to the next integer. - *required_size = gfx::ToCeiledSize( + *target_size = gfx::ToCeiledSize( gfx::SizeF(display_bounds.width() / crop_rect.width(), display_bounds.height() / crop_rect.height())); - return pixmap_size != *required_size; + + return pixmap_size != *target_size || GetBufferFormat() != *target_format; } } // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.h b/ui/ozone/platform/drm/gpu/gbm_buffer.h index a8edaad0..d63963d8 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.h +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -44,13 +44,17 @@ explicit GbmPixmap(GbmSurfaceFactory* surface_manager); void Initialize(base::ScopedFD dma_buf, int dma_buf_pitch); bool InitializeFromBuffer(const scoped_refptr<GbmBuffer>& buffer); - void SetScalingCallback(const ScalingCallback& scaling_callback) override; - scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) override; + void SetProcessingCallback( + const ProcessingCallback& processing_callback) override; + scoped_refptr<NativePixmap> GetProcessedPixmap( + gfx::Size target_size, + gfx::BufferFormat target_format) override; // NativePixmap: void* GetEGLClientBuffer() override; int GetDmaBufFd() override; int GetDmaBufPitch() override; + gfx::BufferFormat GetBufferFormat() override; bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int plane_z_order, gfx::OverlayTransform plane_transform, @@ -62,9 +66,10 @@ private: ~GbmPixmap() override; - bool ShouldApplyScaling(const gfx::Rect& display_bounds, - const gfx::RectF& crop_rect, - gfx::Size* required_size); + bool ShouldApplyProcessing(const gfx::Rect& display_bounds, + const gfx::RectF& crop_rect, + gfx::Size* target_size, + gfx::BufferFormat* target_format); scoped_refptr<GbmBuffer> buffer_; base::ScopedFD dma_buf_; @@ -72,7 +77,7 @@ GbmSurfaceFactory* surface_manager_; - ScalingCallback scaling_callback_; + ProcessingCallback processing_callback_; DISALLOW_COPY_AND_ASSIGN(GbmPixmap); };
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc b/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc index 355b0af..5f27c51 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc +++ b/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc
@@ -11,35 +11,31 @@ namespace ui { -namespace { - -// Pixel configuration for the current buffer format. -// TODO(dnicoara) These will need to change once we query the hardware for -// supported configurations. -const uint8_t kColorDepth = 24; -const uint8_t kPixelDepth = 32; - -} // namespace - GbmBufferBase::GbmBufferBase(const scoped_refptr<DrmDevice>& drm, gbm_bo* bo, bool scanout) : drm_(drm), bo_(bo) { if (scanout) { - if (!drm_->AddFramebuffer(gbm_bo_get_width(bo), gbm_bo_get_height(bo), - kColorDepth, kPixelDepth, gbm_bo_get_stride(bo), - gbm_bo_get_handle(bo).u32, &framebuffer_)) { - PLOG(ERROR) << "Failed to register buffer"; - return; - } - fb_pixel_format_ = gbm_bo_get_format(bo); if (fb_pixel_format_ == GBM_FORMAT_ARGB8888) fb_pixel_format_ = GBM_FORMAT_XRGB8888; - // For now, we always create a frame buffer of 24 bit color depth and - // support only XRGB format. - DCHECK(fb_pixel_format_ == GBM_FORMAT_XRGB8888); + // For now, we only support XRGB and UYVY format. + DCHECK(fb_pixel_format_ == GBM_FORMAT_XRGB8888 || + fb_pixel_format_ == GBM_FORMAT_UYVY); + + uint32_t handles[4] = {0}; + handles[0] = gbm_bo_get_handle(bo).u32; + uint32_t strides[4] = {0}; + strides[0] = gbm_bo_get_stride(bo); + uint32_t offsets[4] = {0}; + + if (!drm_->AddFramebuffer2(gbm_bo_get_width(bo), gbm_bo_get_height(bo), + fb_pixel_format_, handles, strides, offsets, + &framebuffer_, 0)) { + PLOG(ERROR) << "Failed to register buffer"; + return; + } } }
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/ui/ozone/platform/drm/gpu/mock_drm_device.cc index 53f5773..8f3e751 100644 --- a/ui/ozone/platform/drm/gpu/mock_drm_device.cc +++ b/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -119,13 +119,14 @@ return ScopedDrmConnectorPtr(DrmAllocator<drmModeConnector>()); } -bool MockDrmDevice::AddFramebuffer(uint32_t width, - uint32_t height, - uint8_t depth, - uint8_t bpp, - uint32_t stride, - uint32_t handle, - uint32_t* framebuffer) { +bool MockDrmDevice::AddFramebuffer2(uint32_t width, + uint32_t height, + uint32_t format, + uint32_t handles[4], + uint32_t strides[4], + uint32_t offsets[4], + uint32_t* framebuffer, + uint32_t flags) { add_framebuffer_call_count_++; *framebuffer = add_framebuffer_call_count_; return add_framebuffer_expectation_;
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.h b/ui/ozone/platform/drm/gpu/mock_drm_device.h index e14c7fc..c492606 100644 --- a/ui/ozone/platform/drm/gpu/mock_drm_device.h +++ b/ui/ozone/platform/drm/gpu/mock_drm_device.h
@@ -70,13 +70,14 @@ bool SetCrtc(drmModeCrtc* crtc, std::vector<uint32_t> connectors) override; bool DisableCrtc(uint32_t crtc_id) override; ScopedDrmConnectorPtr GetConnector(uint32_t connector_id) override; - bool AddFramebuffer(uint32_t width, - uint32_t height, - uint8_t depth, - uint8_t bpp, - uint32_t stride, - uint32_t handle, - uint32_t* framebuffer) override; + bool AddFramebuffer2(uint32_t width, + uint32_t height, + uint32_t format, + uint32_t handles[4], + uint32_t strides[4], + uint32_t offsets[4], + uint32_t* framebuffer, + uint32_t flags) override; bool RemoveFramebuffer(uint32_t framebuffer) override; ScopedDrmFramebufferPtr GetFramebuffer(uint32_t framebuffer) override; bool PageFlip(uint32_t crtc_id,
diff --git a/ui/ozone/public/native_pixmap.h b/ui/ozone/public/native_pixmap.h index 5bb007a..a472fb5 100644 --- a/ui/ozone/public/native_pixmap.h +++ b/ui/ozone/public/native_pixmap.h
@@ -27,6 +27,7 @@ virtual void* /* EGLClientBuffer */ GetEGLClientBuffer() = 0; virtual int GetDmaBufFd() = 0; virtual int GetDmaBufPitch() = 0; + virtual gfx::BufferFormat GetBufferFormat() = 0; // Sets the overlay plane to switch to at the next page flip. // |w| specifies the screen to display this overlay plane on. @@ -45,14 +46,19 @@ const gfx::Rect& display_bounds, const gfx::RectF& crop_rect) = 0; - // This represents a callback function pointing to scaling unit like VPP - // to do scaling operations on native pixmap with required size. - typedef base::Callback<scoped_refptr<NativePixmap>(gfx::Size)> - ScalingCallback; + // This represents a callback function pointing to processing unit like VPP to + // do post-processing operations on native pixmap with required size and + // format. + typedef base::Callback<scoped_refptr<NativePixmap>(gfx::Size, + gfx::BufferFormat)> + ProcessingCallback; - // Set callback function for the pixmap used for scaling. - virtual void SetScalingCallback(const ScalingCallback& scaling_callback) = 0; - virtual scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) = 0; + // Set callback function for the pixmap used for post processing. + virtual void SetProcessingCallback( + const ProcessingCallback& processing_callback) = 0; + virtual scoped_refptr<NativePixmap> GetProcessedPixmap( + gfx::Size target_size, + gfx::BufferFormat target_format) = 0; // Export the buffer for sharing across processes. // Any file descriptors in the exported handle are owned by the caller.
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn index 9c92efb..e65c390 100644 --- a/ui/views/mus/BUILD.gn +++ b/ui/views/mus/BUILD.gn
@@ -14,8 +14,6 @@ "input_method_mus.h", "native_widget_mus.cc", "native_widget_mus.h", - "native_widget_view_manager.cc", - "native_widget_view_manager.h", "surface_binding.cc", "surface_binding.h", "surface_context_factory.cc",
diff --git a/ui/views/mus/native_widget_mus.cc b/ui/views/mus/native_widget_mus.cc index efed7c2..5fc56f3 100644 --- a/ui/views/mus/native_widget_mus.cc +++ b/ui/views/mus/native_widget_mus.cc
@@ -4,6 +4,7 @@ #include "ui/views/mus/native_widget_mus.h" +#include "base/thread_task_runner_handle.h" #include "components/mus/public/cpp/property_type_converters.h" #include "components/mus/public/cpp/window.h" #include "mojo/converters/geometry/geometry_type_converters.h" @@ -173,8 +174,16 @@ native_widget_delegate_(delegate), surface_type_(surface_type), show_state_before_fullscreen_(ui::PLATFORM_WINDOW_STATE_UNKNOWN), - content_(new aura::Window(this)) {} -NativeWidgetMus::~NativeWidgetMus() {} + ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), + content_(new aura::Window(this)), + close_widget_factory_(this) {} + +NativeWidgetMus::~NativeWidgetMus() { + if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) + delete native_widget_delegate_; + else + CloseNow(); +} // static void NativeWidgetMus::SetWindowManagerClientAreaInsets( @@ -185,6 +194,25 @@ window_manager_client_area_insets = new WindowManagerClientAreaInsets(insets); } +void NativeWidgetMus::OnPlatformWindowClosed() { + GetWidget()->Close(); +} + +void NativeWidgetMus::OnActivationChanged(bool active) { + if (!native_widget_delegate_) + return; + if (active) { + native_widget_delegate_->OnNativeFocus(); + GetWidget()->GetFocusManager()->RestoreFocusedView(); + } else { + native_widget_delegate_->OnNativeBlur(); + GetWidget()->GetFocusManager()->StoreFocusedView(true); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// NativeWidgetMus, private: + // static void NativeWidgetMus::ConfigurePropertiesForNewWindow( const Widget::InitParams& init_params, @@ -205,8 +233,9 @@ } void NativeWidgetMus::InitNativeWidget(const Widget::InitParams& params) { + ownership_ = params.ownership; window_tree_host_.reset( - new WindowTreeHostMus(shell_, window_, surface_type_)); + new WindowTreeHostMus(shell_, this, window_, surface_type_)); window_tree_host_->InitHost(); focus_client_.reset(new wm::FocusController(new FocusRulesImpl)); @@ -231,6 +260,8 @@ window_tree_host_->window()->AddChild(content_); // TODO(beng): much else, see [Desktop]NativeWidgetAura. + + native_widget_delegate_->OnNativeWidgetCreated(false); } bool NativeWidgetMus::ShouldUseNativeFrame() const { @@ -383,11 +414,18 @@ } void NativeWidgetMus::Close() { - // NOTIMPLEMENTED(); + Hide(); + if (!close_widget_factory_.HasWeakPtrs()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&NativeWidgetMus::CloseNow, + close_widget_factory_.GetWeakPtr())); + } } void NativeWidgetMus::CloseNow() { - // NOTIMPLEMENTED(); + // Note: Deleting |content_| triggers the |OnWindowDestroyed()| callback, + // which can delete |this|. + delete content_; } void NativeWidgetMus::Show() { @@ -411,7 +449,7 @@ bool NativeWidgetMus::IsVisible() const { // TODO(beng): this should probably be wired thru PlatformWindow. - return window_tree_host_->mus_window()->visible(); + return window_->visible(); } void NativeWidgetMus::Activate() { @@ -638,13 +676,12 @@ } void NativeWidgetMus::OnWindowDestroying(aura::Window* window) { - // Cleanup happens in OnHostClosed(). } void NativeWidgetMus::OnWindowDestroyed(aura::Window* window) { - // Cleanup happens in OnHostClosed(). We own |content_window_| (indirectly by - // way of |dispatcher_|) so there should be no need to do any processing - // here. + native_widget_delegate_->OnNativeWidgetDestroyed(); + if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) + delete this; } void NativeWidgetMus::OnWindowTargetVisibilityChanged(bool visible) {
diff --git a/ui/views/mus/native_widget_mus.h b/ui/views/mus/native_widget_mus.h index 504d4c5..81e9624 100644 --- a/ui/views/mus/native_widget_mus.h +++ b/ui/views/mus/native_widget_mus.h
@@ -9,6 +9,7 @@ #include <string> #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "components/mus/public/interfaces/window_manager.mojom.h" #include "ui/aura/window_delegate.h" #include "ui/platform_window/platform_window_delegate.h" @@ -70,6 +71,9 @@ mus::Window* window() { return window_; } + void OnPlatformWindowClosed(); + void OnActivationChanged(bool active); + protected: // internal::NativeWidgetPrivate: NonClientFrameView* CreateNonClientFrameView() override; @@ -195,12 +199,16 @@ const mus::mojom::SurfaceType surface_type_; ui::PlatformWindowState show_state_before_fullscreen_; + // See class documentation for Widget in widget.h for a note about ownership. + Widget::InitParams::Ownership ownership_; + // Aura configuration. scoped_ptr<WindowTreeHostMus> window_tree_host_; aura::Window* content_; scoped_ptr<wm::FocusController> focus_client_; scoped_ptr<aura::client::DefaultCaptureClient> capture_client_; scoped_ptr<aura::client::WindowTreeClient> window_tree_client_; + base::WeakPtrFactory<NativeWidgetMus> close_widget_factory_; DISALLOW_COPY_AND_ASSIGN(NativeWidgetMus); };
diff --git a/ui/views/mus/native_widget_view_manager.cc b/ui/views/mus/native_widget_view_manager.cc deleted file mode 100644 index 826abad..0000000 --- a/ui/views/mus/native_widget_view_manager.cc +++ /dev/null
@@ -1,136 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/views/mus/native_widget_view_manager.h" - -#include "components/mus/public/cpp/window.h" -#include "components/mus/public/cpp/window_observer.h" -#include "components/mus/public/interfaces/window_manager.mojom.h" -#include "mojo/converters/geometry/geometry_type_converters.h" -#include "ui/aura/client/default_capture_client.h" -#include "ui/aura/layout_manager.h" -#include "ui/aura/window.h" -#include "ui/aura/window_event_dispatcher.h" -#include "ui/base/ime/input_method_delegate.h" -#include "ui/views/mus/input_method_mus.h" -#include "ui/views/mus/window_tree_host_mus.h" -#include "ui/wm/core/base_focus_rules.h" -#include "ui/wm/core/capture_controller.h" -#include "ui/wm/core/focus_controller.h" - -namespace views { -namespace { - -// TODO: figure out what this should be. -class FocusRulesImpl : public wm::BaseFocusRules { - public: - FocusRulesImpl() {} - ~FocusRulesImpl() override {} - - bool SupportsChildActivation(aura::Window* window) const override { - return true; - } - - private: - DISALLOW_COPY_AND_ASSIGN(FocusRulesImpl); -}; - -class NativeWidgetWindowObserver : public mus::WindowObserver { - public: - NativeWidgetWindowObserver(NativeWidgetViewManager* view_manager) - : view_manager_(view_manager) { - view_manager_->window_->AddObserver(this); - } - - ~NativeWidgetWindowObserver() override { - if (view_manager_->window_) - view_manager_->window_->RemoveObserver(this); - } - - private: - // WindowObserver: - void OnWindowDestroyed(mus::Window* view) override { - DCHECK_EQ(view, view_manager_->window_); - view->RemoveObserver(this); - view_manager_->window_ = nullptr; - // TODO(sky): WindowTreeHostMus assumes the View outlives it. - // NativeWidgetWindowObserver needs to deal, likely by deleting this. - } - - NativeWidgetViewManager* const view_manager_; - - DISALLOW_COPY_AND_ASSIGN(NativeWidgetWindowObserver); -}; - -class WindowTreeHostWindowLayoutManager : public aura::LayoutManager { - public: - WindowTreeHostWindowLayoutManager(aura::Window* outer, aura::Window* inner) - : outer_(outer), inner_(inner) {} - ~WindowTreeHostWindowLayoutManager() override {} - - private: - // aura::LayoutManager: - void OnWindowResized() override { inner_->SetBounds(outer_->bounds()); } - void OnWindowAddedToLayout(aura::Window* child) override {} - void OnWillRemoveWindowFromLayout(aura::Window* child) override {} - void OnWindowRemovedFromLayout(aura::Window* child) override {} - void OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) override {} - void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) override { - SetChildBoundsDirect(child, requested_bounds); - } - - aura::Window* outer_; - aura::Window* inner_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeHostWindowLayoutManager); -}; - -} // namespace - -NativeWidgetViewManager::NativeWidgetViewManager( - views::internal::NativeWidgetDelegate* delegate, - mojo::Shell* shell, - mus::Window* window) - : NativeWidgetAura(delegate), window_(window) { - window_tree_host_.reset( - new WindowTreeHostMus(shell, window_, mus::mojom::SURFACE_TYPE_DEFAULT)); - window_tree_host_->InitHost(); - - focus_client_.reset(new wm::FocusController(new FocusRulesImpl)); - - aura::client::SetFocusClient(window_tree_host_->window(), - focus_client_.get()); - aura::client::SetActivationClient(window_tree_host_->window(), - focus_client_.get()); - window_tree_host_->window()->AddPreTargetHandler(focus_client_.get()); - window_tree_host_->window()->SetLayoutManager( - new WindowTreeHostWindowLayoutManager(window_tree_host_->window(), - GetNativeWindow())); - - capture_client_.reset( - new aura::client::DefaultCaptureClient(window_tree_host_->window())); - - window_observer_.reset(new NativeWidgetWindowObserver(this)); -} - -NativeWidgetViewManager::~NativeWidgetViewManager() {} - -void NativeWidgetViewManager::InitNativeWidget( - const views::Widget::InitParams& in_params) { - views::Widget::InitParams params(in_params); - params.parent = window_tree_host_->window(); - NativeWidgetAura::InitNativeWidget(params); -} - -void NativeWidgetViewManager::OnWindowVisibilityChanged(aura::Window* window, - bool visible) { - window_->SetVisible(visible); - // NOTE: We could also update aura::Window's visibility when the View's - // visibility changes, but this code isn't going to be around for very long so - // I'm not bothering. -} - -} // namespace views
diff --git a/ui/views/mus/native_widget_view_manager.h b/ui/views/mus/native_widget_view_manager.h deleted file mode 100644 index c52cf1b..0000000 --- a/ui/views/mus/native_widget_view_manager.h +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_VIEWS_MUS_NATIVE_WIDGET_VIEW_MANAGER_H_ -#define UI_VIEWS_MUS_NATIVE_WIDGET_VIEW_MANAGER_H_ - -#include "ui/views/widget/native_widget_aura.h" - -namespace aura { -namespace client { -class DefaultCaptureClient; -} -} - -namespace mojo { -class Shell; -} - -namespace mus { -class Window; -namespace mojom { -class WindowManager; -} -} - -namespace ui { -namespace internal { -class InputMethodDelegate; -} -} - -namespace wm { -class FocusController; -} - -namespace views { - -namespace { -class NativeWidgetWindowObserver; -} - -class WindowTreeHostMus; - -class NativeWidgetViewManager : public views::NativeWidgetAura { - public: - NativeWidgetViewManager(views::internal::NativeWidgetDelegate* delegate, - mojo::Shell* shell, - mus::Window* window); - ~NativeWidgetViewManager() override; - - private: - friend class NativeWidgetWindowObserver; - - // Overridden from internal::NativeWidgetAura: - void InitNativeWidget(const views::Widget::InitParams& in_params) override; - void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; - - scoped_ptr<WindowTreeHostMus> window_tree_host_; - scoped_ptr<NativeWidgetWindowObserver> window_observer_; - - scoped_ptr<wm::FocusController> focus_client_; - - mus::Window* window_; - - scoped_ptr<aura::client::DefaultCaptureClient> capture_client_; - - DISALLOW_COPY_AND_ASSIGN(NativeWidgetViewManager); -}; - -} // namespace views - -#endif // UI_VIEWS_MUS_NATIVE_WIDGET_VIEW_MANAGER_H_
diff --git a/ui/views/mus/window_tree_host_mus.cc b/ui/views/mus/window_tree_host_mus.cc index a2efd52..61c6f46 100644 --- a/ui/views/mus/window_tree_host_mus.cc +++ b/ui/views/mus/window_tree_host_mus.cc
@@ -20,6 +20,7 @@ #include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window_delegate.h" #include "ui/views/mus/input_method_mus.h" +#include "ui/views/mus/native_widget_mus.h" #include "ui/views/mus/surface_context_factory.h" #include "ui/views/mus/window_manager_connection.h" @@ -45,8 +46,10 @@ } ~PlatformWindowMus() override { - if (mus_window_) - mus_window_->RemoveObserver(this); + if (!mus_window_) + return; + mus_window_->RemoveObserver(this); + mus_window_->Destroy(); } private: @@ -89,8 +92,8 @@ // mus::WindowObserver: void OnWindowDestroyed(mus::Window* window) override { DCHECK_EQ(mus_window_, window); - mus_window_ = nullptr; delegate_->OnClosed(); + mus_window_ = nullptr; } void OnWindowBoundsChanged(mus::Window* window, @@ -159,24 +162,25 @@ // WindowTreeHostMus, public: WindowTreeHostMus::WindowTreeHostMus(mojo::Shell* shell, + NativeWidgetMus* native_widget, mus::Window* window, mus::mojom::SurfaceType surface_type) - : mus_window_(window), + : native_widget_(native_widget), show_state_(ui::PLATFORM_WINDOW_STATE_UNKNOWN) { context_factory_.reset( - new SurfaceContextFactory(shell, mus_window_, surface_type)); + new SurfaceContextFactory(shell, window, surface_type)); // WindowTreeHost creates the compositor using the ContextFactory from // aura::Env. Install |context_factory_| there so that |context_factory_| is // picked up. ui::ContextFactory* default_context_factory = aura::Env::GetInstance()->context_factory(); aura::Env::GetInstance()->set_context_factory(context_factory_.get()); - SetPlatformWindow(make_scoped_ptr(new PlatformWindowMus(this, mus_window_))); + SetPlatformWindow(make_scoped_ptr(new PlatformWindowMus(this, window))); compositor()->SetHostHasTransparentBackground(true); aura::Env::GetInstance()->set_context_factory(default_context_factory); DCHECK_EQ(context_factory_.get(), compositor()->context_factory()); - input_method_.reset(new InputMethodMUS(this, mus_window_)); + input_method_.reset(new InputMethodMUS(this, window)); SetSharedInputMethod(input_method_.get()); } @@ -185,10 +189,18 @@ DestroyDispatcher(); } +void WindowTreeHostMus::DispatchEvent(ui::Event* event) { + if (event->IsKeyEvent() && GetInputMethod()) { + GetInputMethod()->DispatchKeyEvent(static_cast<ui::KeyEvent*>(event)); + event->StopPropagation(); + return; + } + WindowTreeHostPlatform::DispatchEvent(event); +} + void WindowTreeHostMus::OnClosed() { - // TODO(sad): NativeWidgetMus needs to know about this, and tear down the - // associated Widget (and this WindowTreeHostMus too). - NOTIMPLEMENTED(); + if (native_widget_) + native_widget_->OnPlatformWindowClosed(); } void WindowTreeHostMus::OnWindowStateChanged(ui::PlatformWindowState state) { @@ -200,6 +212,9 @@ GetInputMethod()->OnFocus(); else GetInputMethod()->OnBlur(); + if (native_widget_) + native_widget_->OnActivationChanged(active); + WindowTreeHostPlatform::OnActivationChanged(active); } } // namespace views
diff --git a/ui/views/mus/window_tree_host_mus.h b/ui/views/mus/window_tree_host_mus.h index ecbce97a..758e97b 100644 --- a/ui/views/mus/window_tree_host_mus.h +++ b/ui/views/mus/window_tree_host_mus.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "components/mus/public/interfaces/window_tree.mojom.h" #include "ui/aura/window_tree_host_platform.h" +#include "ui/views/widget/native_widget_private.h" class SkBitmap; @@ -26,27 +27,28 @@ namespace views { class InputMethodMUS; +class NativeWidgetMus; class SurfaceContextFactory; class WindowTreeHostMus : public aura::WindowTreeHostPlatform { public: WindowTreeHostMus(mojo::Shell* shell, + NativeWidgetMus* native_widget_, mus::Window* window, mus::mojom::SurfaceType surface_type); ~WindowTreeHostMus() override; - mus::Window* mus_window() { return mus_window_; } - using WindowTreeHostPlatform::platform_window; ui::PlatformWindowState show_state() const { return show_state_; } private: // aura::WindowTreeHostPlatform: + void DispatchEvent(ui::Event* event) override; void OnClosed() override; void OnWindowStateChanged(ui::PlatformWindowState new_state) override; void OnActivationChanged(bool active) override; - mus::Window* mus_window_; + NativeWidgetMus* native_widget_; scoped_ptr<InputMethodMUS> input_method_; scoped_ptr<SurfaceContextFactory> context_factory_; ui::PlatformWindowState show_state_;