diff --git a/DEPS b/DEPS index 54249c5..1f7e9024 100644 --- a/DEPS +++ b/DEPS
@@ -36,7 +36,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': 'c90bc40fdd7f0e8908df81766891e5c62fe77932', + 'skia_revision': 'f119796f95f336d5b29f06f369b15b48a6a0df45', # 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/android_webview/tools/cts_config/expected_failure_on_bot.json b/android_webview/tools/cts_config/expected_failure_on_bot.json index 45a8625..1969d47 100644 --- a/android_webview/tools/cts_config/expected_failure_on_bot.json +++ b/android_webview/tools/cts_config/expected_failure_on_bot.json
@@ -3,10 +3,6 @@ { "name": "testPageScroll", "_bug_id": "crbug.com/534643" - }, - { - "name": "testFindNext", - "_bug_id": "crbug.com/618089" } ] }
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py index f283c5b..0a01525 100644 --- a/build/android/pylib/gtest/gtest_test_instance.py +++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -90,8 +90,6 @@ _RE_TEST_STATUS = re.compile( r'\[ +((?:RUN)|(?:FAILED)|(?:OK)|(?:CRASHED)) +\]' r' ?([^ ]+)?(?: \((\d+) ms\))?$') -_RE_TEST_RUN_STATUS = re.compile( - r'\[ +(PASSED|RUNNER_FAILED|CRASHED) \] ?[^ ]+') # Crash detection constants. _RE_TEST_ERROR = re.compile(r'FAILURES!!! Tests run: \d+,' r' Failures: \d+, Errors: 1') @@ -139,6 +137,8 @@ Returns: A list of base_test_result.BaseTestResults. """ + duration = 0 + fallback_result_type = None log = [] result_type = None results = [] @@ -147,8 +147,9 @@ def handle_possibly_unknown_test(): if test_name is not None: results.append(base_test_result.BaseTestResult( - test_name, base_test_result.ResultType.UNKNOWN, 0, - log=('\n'.join(log) if log else ''))) + test_name, + fallback_result_type or base_test_result.ResultType.UNKNOWN, + duration, log=('\n'.join(log) if log else ''))) for l in output: logging.info(l) @@ -156,13 +157,16 @@ if matcher: if matcher.group(1) == 'RUN': handle_possibly_unknown_test() + duration = 0 + fallback_result_type = None log = [] + result_type = None elif matcher.group(1) == 'OK': result_type = base_test_result.ResultType.PASS elif matcher.group(1) == 'FAILED': result_type = base_test_result.ResultType.FAIL elif matcher.group(1) == 'CRASHED': - result_type = base_test_result.ResultType.CRASH + fallback_result_type = base_test_result.ResultType.CRASH # Be aware that test name and status might not appear on same line. test_name = matcher.group(2) if matcher.group(2) else test_name duration = int(matcher.group(3)) if matcher.group(3) else 0 @@ -182,8 +186,6 @@ results.append(base_test_result.BaseTestResult( test_name, result_type, duration, log=('\n'.join(log) if log else ''))) - log = None - result_type = None test_name = None handle_possibly_unknown_test()
diff --git a/build/android/pylib/gtest/gtest_test_instance_test.py b/build/android/pylib/gtest/gtest_test_instance_test.py index 910ac40..02e29bb 100755 --- a/build/android/pylib/gtest/gtest_test_instance_test.py +++ b/build/android/pylib/gtest/gtest_test_instance_test.py
@@ -152,6 +152,19 @@ self.assertEquals(1, actual[1].GetDuration()) self.assertEquals(base_test_result.ResultType.PASS, actual[1].GetType()) + def testParseGTestOutput_deathTestCrashOk(self): + raw_output = [ + '[ RUN ] FooTest.Bar', + '[ CRASHED ]', + '[ OK ] FooTest.Bar (1 ms)', + ] + actual = gtest_test_instance.ParseGTestOutput(raw_output) + self.assertEquals(1, len(actual)) + + self.assertEquals('FooTest.Bar', actual[0].GetName()) + self.assertEquals(1, actual[0].GetDuration()) + self.assertEquals(base_test_result.ResultType.PASS, actual[0].GetType()) + if __name__ == '__main__': unittest.main(verbosity=2)
diff --git a/build/config/mac/gen_plist.py b/build/config/mac/gen_plist.py index e3d4f4af..00041795 100644 --- a/build/config/mac/gen_plist.py +++ b/build/config/mac/gen_plist.py
@@ -18,7 +18,7 @@ # while IDENT_RE matches all characters that are not valid in an "identifier" # value (used when applying the modifier). SUBST_RE = re.compile(r'\$\{(?P<id>[^}]*?)(?P<modifier>:[^}]*)?\}') -IDENT_RE = re.compile(r'[/\s]') +IDENT_RE = re.compile(r'[_/\s]') class ArgumentParser(argparse.ArgumentParser): @@ -73,13 +73,13 @@ return None # Some values need to be identifier and thus the variables references may # contains :modifier attributes to indicate how they should be converted - # to identifiers ("identifier" replaces all invalid characters by '-' and - # "rfc1034identifier" replaces them by "_" to make valid URI too). + # to identifiers ("identifier" replaces all invalid characters by '_' and + # "rfc1034identifier" replaces them by "-" to make valid URI too). modifier = match.group('modifier') - if modifier == 'identifier': - interpolated = IDENT_RE.sub('-', substitutions[variable]) - elif modifier == 'rfc1034identifier': + if modifier == ':identifier': interpolated = IDENT_RE.sub('_', substitutions[variable]) + elif modifier == ':rfc1034identifier': + interpolated = IDENT_RE.sub('-', substitutions[variable]) else: interpolated = substitutions[variable] result = result[:match.start()] + interpolated + result[match.end():]
diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py index d1aa1aac..35b913b 100755 --- a/build/linux/sysroot_scripts/install-sysroot.py +++ b/build/linux/sysroot_scripts/install-sysroot.py
@@ -3,18 +3,19 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Install Debian Wheezy sysroots for building chromium. +"""Install Debian sysroots for building chromium. """ # The sysroot is needed to ensure that binaries will run on Debian Wheezy, -# the oldest supported linux distribution. This script can be run manually but -# is more often run as part of gclient hooks. When run from hooks this script -# in a no-op on non-linux platforms. +# the oldest supported linux distribution. For ARM64 linux, we have Debian +# Jessie sysroot as Jessie is the first version with ARM64 support. This script +# can be run manually but is more often run as part of gclient hooks. When run +# from hooks this script is a no-op on non-linux platforms. # The sysroot image could be constructed from scratch based on the current -# state or Debian Wheezy but for consistency we currently use a pre-built root -# image. The image will normally need to be rebuilt every time chrome's build -# dependencies are changed. +# state or Debian Wheezy/Jessie but for consistency we currently use a +# pre-built root image. The image will normally need to be rebuilt every time +# chrome's build dependencies are changed. import hashlib import platform @@ -164,6 +165,7 @@ # TODO(thestig) Consider putting this else where to avoid having to recreate # it on every build. linux_dir = os.path.dirname(SCRIPT_DIR) + debian_release = 'Wheezy' if target_arch == 'amd64': sysroot = os.path.join(linux_dir, SYSROOT_DIR_AMD64) tarball_filename = TARBALL_AMD64 @@ -175,6 +177,7 @@ tarball_sha1sum = TARBALL_ARM_SHA1SUM revision = REVISION_ARM elif target_arch == 'arm64': + debian_release = 'Jessie' sysroot = os.path.join(linux_dir, SYSROOT_DIR_ARM64) tarball_filename = TARBALL_ARM64 tarball_sha1sum = TARBALL_ARM64_SHA1SUM @@ -198,11 +201,12 @@ if os.path.exists(stamp): with open(stamp) as s: if s.read() == url: - print 'Debian Wheezy %s root image already up to date: %s' % \ - (target_arch, sysroot) + print 'Debian %s %s root image already up to date: %s' % \ + (debian_release, target_arch, sysroot) return - print 'Installing Debian Wheezy %s root image: %s' % (target_arch, sysroot) + print 'Installing Debian %s %s root image: %s' % \ + (debian_release, target_arch, sysroot) if os.path.isdir(sysroot): shutil.rmtree(sysroot) os.mkdir(sysroot)
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc index d175058..92abb20a 100644 --- a/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -436,8 +436,8 @@ filters.Append(FilterOperation::CreateBlurFilter(5.0f)); filter->SetBackgroundFilters(filters); -#if defined(OS_WIN) - // Windows has 3.065% pixels off by at most 2: crbug.com/225027 + // Allow some fuzziness so that this doesn't fail when Skia makes minor + // changes to blur or rectangle rendering. float percentage_pixels_large_error = 3.1f; float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 2.f; @@ -448,7 +448,6 @@ percentage_pixels_large_error, percentage_pixels_small_error, average_error_allowed_in_bad_pixels, large_error_allowed, small_error_allowed)); -#endif RunPixelTest(test_type, background, image_name); }
diff --git a/chrome/android/java/res/layout/autofill_editor_base_buttons.xml b/chrome/android/java/res/layout/autofill_editor_base_buttons.xml index fe127a8..32670cb 100644 --- a/chrome/android/java/res/layout/autofill_editor_base_buttons.xml +++ b/chrome/android/java/res/layout/autofill_editor_base_buttons.xml
@@ -9,19 +9,18 @@ <Space style="@style/ButtonBarTopSpacerLight" /> - <!-- CANCEL and SAVE buttons. - paddingEnd is already handled by the ScrollView parent. - --> + <!-- CANCEL and DONE buttons. --> <org.chromium.chrome.browser.widget.DualControlLayout android:id="@+id/button_bar" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="@dimen/payments_section_large_spacing" + android:paddingStart="@dimen/pref_autofill_field_horizontal_padding" + android:paddingEnd="@dimen/pref_autofill_field_horizontal_padding" android:paddingTop="@dimen/payments_section_large_spacing" android:paddingBottom="@dimen/payments_section_large_spacing" android:background="@android:color/white" app:stackedMargin="@dimen/infobar_margin_between_stacked_buttons" - app:primaryButtonText="@string/save" + app:primaryButtonText="@string/done" app:secondaryButtonText="@string/cancel" /> </merge> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/new_tab_page_layout.xml b/chrome/android/java/res/layout/new_tab_page_layout.xml index b8dfd5ae..89d1f21 100644 --- a/chrome/android/java/res/layout/new_tab_page_layout.xml +++ b/chrome/android/java/res/layout/new_tab_page_layout.xml
@@ -14,9 +14,9 @@ android:paddingTop="@dimen/toolbar_height_no_shadow" android:visibility="gone" > - <!-- Spacer. Note: this must have layout_weight="1" and the other spacers must have - layout_weight="0". The NewTabPageLayout will redistribute the extra space between - them. --> + <!-- Top spacer. Note: the top spacer must have layout_weight="1" and the middle and bottom + spacers must have layout_weight="0". The NewTabPageLayout will redistribute the extra space + between them. --> <View android:id="@+id/ntp_top_spacer" android:layout_width="0dp" @@ -70,7 +70,7 @@ android:src="@drawable/btn_mic" /> </LinearLayout> - <!-- Spacer --> + <!-- Middle spacer --> <View android:id="@+id/ntp_middle_spacer" android:layout_width="0dp" @@ -99,7 +99,7 @@ android:inflatedId="@+id/most_visited_placeholder" android:layout="@layout/most_visited_placeholder" /> - <!-- Spacer --> + <!-- Bottom spacer --> <View android:id="@+id/ntp_bottom_spacer" android:layout_width="0dp" @@ -107,6 +107,7 @@ android:layout_weight="0" android:visibility="invisible" /> + <!-- Logo spacer --> <View android:id="@+id/no_search_logo_spacer" android:layout_width="match_parent" @@ -114,6 +115,7 @@ android:layout_weight="1" android:visibility="gone" /> + <!-- Scroll spacer --> <View android:id="@+id/ntp_scroll_spacer" android:layout_width="match_parent"
diff --git a/chrome/android/java/res/layout/payment_request_editor.xml b/chrome/android/java/res/layout/payment_request_editor.xml index 419a37b..2c1ae15 100644 --- a/chrome/android/java/res/layout/payment_request_editor.xml +++ b/chrome/android/java/res/layout/payment_request_editor.xml
@@ -4,48 +4,48 @@ found in the LICENSE file. --> <!-- PaymentRequestUI editor dialog. --> -<LinearLayout +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:chrome="http://schemas.android.com/apk/res-auto" - android:orientation="vertical" > + xmlns:chrome="http://schemas.android.com/apk/res-auto" > - <!-- Toolbar and shadow. --> + <!-- Toolbar --> <org.chromium.chrome.browser.payments.ui.EditorDialogToolbar android:id="@+id/action_bar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" + android:layout_alignParentTop="true" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" android:background="@color/dark_action_bar_color" /> - <org.chromium.chrome.browser.widget.FadingShadowView - android:id="@+id/shadow" - android:layout_width="match_parent" - android:layout_height="10dp" /> <!-- All the page content in scrollable form. --> <org.chromium.chrome.browser.payments.ui.FadingEdgeScrollView android:id="@+id/scroll_view" android:layout_height="0dp" android:layout_width="match_parent" - android:layout_weight="1" > + android:layout_below="@id/action_bar" + android:layout_alignParentBottom="true" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" > <LinearLayout android:id="@+id/contents" android:layout_width="match_parent" android:layout_height="wrap_content" + android:paddingTop="@dimen/payments_section_large_spacing" android:paddingStart="@dimen/pref_autofill_content_spacing" android:paddingEnd="@dimen/pref_autofill_content_spacing" android:orientation="vertical" /> </org.chromium.chrome.browser.payments.ui.FadingEdgeScrollView> - <!-- CANCEL and DONE buttons. --> - <org.chromium.chrome.browser.widget.DualControlLayout - android:id="@+id/button_bar" + <!-- Shadow overlaps the FadingEdgeScrollView. --> + <org.chromium.chrome.browser.widget.FadingShadowView + android:id="@+id/shadow" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:padding="@dimen/payments_section_large_spacing" - android:background="@android:color/white" - chrome:stackedMargin="@dimen/infobar_margin_between_stacked_buttons" - chrome:primaryButtonText="@string/done" - chrome:secondaryButtonText="@string/cancel" /> + android:layout_height="10dp" + android:layout_below="@id/action_bar" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" /> -</LinearLayout> +</RelativeLayout>
diff --git a/chrome/android/java/res/layout/payment_request_editor_footer.xml b/chrome/android/java/res/layout/payment_request_editor_footer.xml index 84741e60..24ad020 100644 --- a/chrome/android/java/res/layout/payment_request_editor_footer.xml +++ b/chrome/android/java/res/layout/payment_request_editor_footer.xml
@@ -3,12 +3,19 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<TextView +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:layout_marginBottom="16dp" - android:textColor="@color/descriptive_text_color" - android:textSize="12sp" - android:text="@string/payments_required_field_message" /> \ No newline at end of file + android:orientation="vertical" > + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginBottom="16dp" + android:textColor="@color/descriptive_text_color" + android:textSize="12sp" + android:text="@string/payments_required_field_message" /> + + <include layout="@layout/autofill_editor_base_buttons" /> + +</LinearLayout> \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index f4d35a24..00fbc885 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -659,6 +659,7 @@ } return true; } else if (id == R.id.info_menu_id) { + if (getTabModelSelector().getCurrentTab() == null) return false; WebsiteSettingsPopup.show( this, getTabModelSelector().getCurrentTab(), getToolbarManager().getContentPublisher(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java index f74873f..a4e1f4f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -61,10 +61,9 @@ mBottomSpacerIdealHeight = Math.round(density * BOTTOM_SPACER_HEIGHT_DP); mTotalSpacerIdealHeight = Math.round(density * TOTAL_SPACER_HEIGHT_DP); mMostVisitedLayoutBleed = res.getDimensionPixelSize(R.dimen.most_visited_layout_bleed); - - mPeekingCardHeight = getResources() - .getDimensionPixelSize(R.dimen.snippets_padding_and_peeking_card_height); - mTabStripHeight = getResources().getDimensionPixelSize(R.dimen.tab_strip_height); + mPeekingCardHeight = + res.getDimensionPixelSize(R.dimen.snippets_padding_and_peeking_card_height); + mTabStripHeight = res.getDimensionPixelSize(R.dimen.tab_strip_height); } @Override @@ -102,6 +101,8 @@ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Remove the scroll spacer from the layout so the weighted children can be measured + // correctly. mScrollCompensationSpacer.setVisibility(View.GONE); super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -110,8 +111,11 @@ // to see all of it. Extra spacing should be added at the bottom so the user can scroll // until Most Visited is at the top. - // All the spacers have height 0 since they use weights to set height. + // The top, middle, and bottom spacers should have a measured height of 0 at this point + // since they use weights to set height, and there was no extra space. assert mTopSpacer.getMeasuredHeight() == 0; + assert mMiddleSpacer.getMeasuredHeight() == 0; + assert mBottomSpacer.getMeasuredHeight() == 0; final int topOfMostVisited = calculateTopOfMostVisited(); final int belowTheFoldHeight = getMeasuredHeight() - mParentViewportHeight; @@ -124,15 +128,20 @@ mScrollCompensationSpacer.getLayoutParams().height -= mPeekingCardHeight; } + // Include the scroll spacer in the layout and call super.onMeasure again so it is + // measured. mScrollCompensationSpacer.setVisibility(View.INVISIBLE); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } else { - // This layout is smaller than it's parent viewport, redistribute the extra space. + // This layout is smaller than or equal to its parent viewport. Redistribute any + // weighted space. if (mCardsUiEnabled) { - getLayoutParams().height = Math.max(getMeasuredHeight(), + // Call super.onMeasure with mode EXACTLY and the target height to allow the top + // spacer (which has a weight of 1) to grow and take up the remaining space. + int targetHeight = Math.max(getMeasuredHeight(), mParentViewportHeight - mPeekingCardHeight - mTabStripHeight); - // Call onMeasure to update mTopScaper's height. + heightMeasureSpec = MeasureSpec.makeMeasureSpec(targetHeight, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } distributeExtraSpace(mTopSpacer.getMeasuredHeight()); @@ -141,9 +150,10 @@ // Make the search box and logo as wide as the most visited items. if (mMostVisitedLayout.getVisibility() != GONE) { final int width = mMostVisitedLayout.getMeasuredWidth() - mMostVisitedLayoutBleed; - setMeasure(mSearchBoxView, width + mSearchboxViewShadowWidth, + measureExactly(mSearchBoxView, width + mSearchboxViewShadowWidth, mSearchBoxView.getMeasuredHeight()); - setMeasure(mSearchProviderLogoView, width, mSearchProviderLogoView.getMeasuredHeight()); + measureExactly( + mSearchProviderLogoView, width, mSearchProviderLogoView.getMeasuredHeight()); } } @@ -197,7 +207,8 @@ } /** - * Distribute extra vertical space between the three spacer views. + * Distribute extra vertical space between the three spacer views. Doing this here allows for + * more sophisticated constraints than in xml. * @param extraHeight The amount of extra space, in pixels. */ private void distributeExtraSpace(int extraHeight) { @@ -220,17 +231,16 @@ bottomSpacerHeight = mBottomSpacerIdealHeight + extraHeight / 2; } - setMeasure(mTopSpacer, 0, topSpacerHeight); - setMeasure(mMiddleSpacer, 0, middleSpacerHeight); - setMeasure(mBottomSpacer, 0, bottomSpacerHeight); + measureExactly(mTopSpacer, 0, topSpacerHeight); + measureExactly(mMiddleSpacer, 0, middleSpacerHeight); + measureExactly(mBottomSpacer, 0, bottomSpacerHeight); } - /** - * Convenience method to call |measure| on the given View with MeasureSpecs converted from the + * Convenience method to call measure() on the given View with MeasureSpecs converted from the * given dimensions (in pixels) with MeasureSpec.EXACTLY. */ - private void setMeasure(View view, int widthPx, int heightPx) { + private static void measureExactly(View view, int widthPx, int heightPx) { view.measure(MeasureSpec.makeMeasureSpec(widthPx, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightPx, MeasureSpec.EXACTLY)); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorView.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorView.java index 9b21004..710f836 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorView.java
@@ -62,7 +62,7 @@ private final int mHalfRowMargin; private final List<EditorTextField> mEditorTextFields; - private ViewGroup mLayout; + private View mLayout; private EditorModel mEditorModel; private Button mDoneButton; private ViewGroup mDataView; @@ -152,8 +152,6 @@ R.color.toolbar_shadow_color), FadingShadow.POSITION_TOP); // The top shadow is handled by the toolbar, so hide the one used in the field editor. - // TODO(dfalcantara): Make the toolbar's shadow cover the field editor instead of pushing - // it down. Maybe use a RelativeLayout with overlapping views? FadingEdgeScrollView scrollView = (FadingEdgeScrollView) mLayout.findViewById(R.id.scroll_view); scrollView.setShadowVisibility(false, true); @@ -312,16 +310,15 @@ setOnDismissListener(this); mEditorModel = editorModel; - mLayout = (LinearLayout) LayoutInflater.from(mContext).inflate( - R.layout.payment_request_editor, null); + mLayout = LayoutInflater.from(mContext).inflate(R.layout.payment_request_editor, null); setContentView(mLayout); mFooter = LayoutInflater.from(mContext).inflate( R.layout.payment_request_editor_footer, null, false); prepareToolbar(); - prepareButtons(); prepareEditor(); + prepareButtons(); show(); // Immediately focus the first invalid field to make it faster to edit.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java index c16c2cf..35bf3cd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -506,6 +506,8 @@ // in JavaScript. dismissRunnable.run(); } else { + mIsProcessingPayClicked = false; + // Animate the bottom sheet going away. new DisappearingAnimator(false); @@ -712,7 +714,8 @@ /** @return Whether or not the dialog can be closed via the X close button. */ private boolean isAcceptingCloseButton() { - return mSheetAnimator == null && mSectionAnimator == null && mIsInitialLayoutComplete; + return mSheetAnimator == null && mSectionAnimator == null && mIsInitialLayoutComplete + && !mIsProcessingPayClicked; } /** @return Whether or not the dialog is accepting user input. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheController.java b/chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheController.java index 4ee943e..d7cfa9c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheController.java
@@ -105,17 +105,23 @@ /** Receiver that will be notified when conditions become wrong for precaching. */ private final BroadcastReceiver mDeviceStateReceiver = new BroadcastReceiver() { @Override - public void onReceive(Context context, Intent intent) { - Log.v(TAG, "conditions changed: precaching(%s), powered(%s), unmetered(%s)", - isPrecaching(), mDeviceState.isPowerConnected(context), - mDeviceState.isUnmeteredNetworkAvailable(context)); - if (isPrecaching() && (!mDeviceState.isPowerConnected(context) - || !mDeviceState.isUnmeteredNetworkAvailable(context))) { - recordFailureReasons(context); - cancelPrecaching(!mDeviceState.isPowerConnected(context) - ? PrecacheUMA.Event.PRECACHE_CANCEL_NO_POWER - : PrecacheUMA.Event.PRECACHE_CANCEL_NO_UNMETERED_NETWORK); - } + public void onReceive(final Context context, Intent intent) { + runOnInstanceThread(new Runnable() { + @Override + public void run() { + Log.v(TAG, "conditions changed: precaching(%s), powered(%s), unmetered(%s)", + isPrecaching(), mDeviceState.isPowerConnected(context), + mDeviceState.isUnmeteredNetworkAvailable(context)); + if (isPrecaching() + && (!mDeviceState.isPowerConnected(context) + || !mDeviceState.isUnmeteredNetworkAvailable(context))) { + recordFailureReasons(context); + cancelPrecaching(!mDeviceState.isPowerConnected(context) + ? PrecacheUMA.Event.PRECACHE_CANCEL_NO_POWER + : PrecacheUMA.Event.PRECACHE_CANCEL_NO_UNMETERED_NETWORK); + } + } + }); } }; @@ -276,12 +282,7 @@ cancelPrecacheCompletionTask(appContext); } if (cancelRequired) { - sInstance.runOnInstanceThread(new Runnable() { - @Override - public void run() { - sInstance.cancelPrecaching(PrecacheUMA.Event.PRECACHE_CANCEL_DISABLED_PREF); - } - }); + sInstance.cancelPrecaching(PrecacheUMA.Event.PRECACHE_CANCEL_DISABLED_PREF); } } @@ -413,13 +414,20 @@ * Cancels the current precache session. * @param event the failure reason. */ - private void cancelPrecaching(int event) { - Log.v(TAG, "canceling precache session"); - if (setIsPrecaching(false)) { - mPrecacheLauncher.cancel(); - shutdownPrecaching(true); - } - PrecacheUMA.record(event); + private void cancelPrecaching(final int event) { + // cancelPrecaching() could be called from PrecacheManager::Shutdown(), precache GCM task, + // etc., where it could be a different thread. + runOnInstanceThread(new Runnable() { + @Override + public void run() { + Log.v(TAG, "canceling precache session"); + if (setIsPrecaching(false)) { + mPrecacheLauncher.cancel(); + shutdownPrecaching(true); + } + PrecacheUMA.record(event); + } + }); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java index 174da7e4..535de6534 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -1813,7 +1813,16 @@ mTabSwitcherButtonDrawableLight.updateForTabCount(numberOfTabs, isIncognito()); mTabSwitcherButtonDrawable.updateForTabCount(numberOfTabs, isIncognito()); - boolean useTabStackDrawableLight = isIncognito(); + int themeColor; + if (getToolbarDataProvider() != null) { + themeColor = getToolbarDataProvider().getPrimaryColor(); + } else { + themeColor = getToolbarColorForVisualState( + isIncognito() ? VisualState.INCOGNITO : VisualState.NORMAL); + } + + boolean useTabStackDrawableLight = isIncognito() + || ColorUtils.shouldUseLightForegroundOnBackground(themeColor); if (mTabSwitcherAnimationTabStackDrawable == null || mIsOverlayTabStackDrawableLight != useTabStackDrawableLight) { mTabSwitcherAnimationTabStackDrawable =
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index f8af92a0..e1ac0da 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -159,7 +159,6 @@ #include "content/public/common/content_descriptors.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" -#include "content/public/common/mojo_shell_connection.h" #include "content/public/common/sandbox_type.h" #include "content/public/common/url_utils.h" #include "content/public/common/web_preferences.h" @@ -2850,8 +2849,8 @@ #if defined(OS_CHROMEOS) #if defined(MOJO_SHELL_CLIENT) if (chrome::IsRunningInMash()) { - content::MojoShellConnection::GetForProcess()->AddConnectionFilter( - base::MakeUnique<chromeos::ChromeInterfaceFactory>()); + content::MojoShellConnection::GetForProcess()->MergeService( + base::WrapUnique(new chromeos::ChromeInterfaceFactory)); } #endif // MOJO_SHELL_CLIENT #endif // OS_CHROMEOS
diff --git a/chrome/browser/chromeos/arc/arc_auth_service_unittest.cc b/chrome/browser/chromeos/arc/arc_auth_service_unittest.cc index 7aa97f3..352899f 100644 --- a/chrome/browser/chromeos/arc/arc_auth_service_unittest.cc +++ b/chrome/browser/chromeos/arc/arc_auth_service_unittest.cc
@@ -74,8 +74,7 @@ // Check initial conditions. EXPECT_EQ(bridge_service_.get(), ArcBridgeService::Get()); EXPECT_FALSE(ArcBridgeService::Get()->available()); - EXPECT_EQ(ArcBridgeService::State::STOPPED, - ArcBridgeService::Get()->state()); + EXPECT_TRUE(ArcBridgeService::Get()->stopped()); const AccountId account_id( AccountId::FromUserEmailGaiaId("user@gmail.com", "1234567890")); @@ -178,7 +177,7 @@ } TEST_F(ArcAuthServiceTest, BaseWorkflow) { - ASSERT_EQ(ArcBridgeService::State::STOPPED, bridge_service()->state()); + ASSERT_FALSE(bridge_service()->ready()); ASSERT_EQ(ArcAuthService::State::NOT_INITIALIZED, auth_service()->state()); ASSERT_EQ(std::string(), auth_service()->GetAndResetAuthCode()); @@ -195,14 +194,14 @@ auth_service()->SetAuthCodeAndStartArc(kTestAuthCode); ASSERT_EQ(ArcAuthService::State::ACTIVE, auth_service()->state()); - ASSERT_EQ(ArcBridgeService::State::READY, bridge_service()->state()); + ASSERT_TRUE(bridge_service()->ready()); // Auth code valid only for one call. ASSERT_EQ(kTestAuthCode, auth_service()->GetAndResetAuthCode()); ASSERT_EQ(std::string(), auth_service()->GetAndResetAuthCode()); auth_service()->Shutdown(); ASSERT_EQ(ArcAuthService::State::NOT_INITIALIZED, auth_service()->state()); - ASSERT_EQ(ArcBridgeService::State::STOPPED, bridge_service()->state()); + ASSERT_FALSE(bridge_service()->ready()); ASSERT_EQ(std::string(), auth_service()->GetAndResetAuthCode()); // Send profile and don't provide a code. @@ -278,27 +277,27 @@ EXPECT_EQ(ArcAuthService::State::FETCHING_CODE, auth_service()->state()); auth_service()->SetAuthCodeAndStartArc(kTestAuthCode); EXPECT_EQ(ArcAuthService::State::ACTIVE, auth_service()->state()); - EXPECT_EQ(ArcBridgeService::State::READY, bridge_service()->state()); + EXPECT_TRUE(bridge_service()->ready()); EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn)); auth_service()->OnSignInComplete(); EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn)); EXPECT_EQ(ArcAuthService::State::ACTIVE, auth_service()->state()); - EXPECT_EQ(ArcBridgeService::State::READY, bridge_service()->state()); + EXPECT_TRUE(bridge_service()->ready()); // Second start, no fetching code is expected. auth_service()->Shutdown(); EXPECT_EQ(ArcAuthService::State::NOT_INITIALIZED, auth_service()->state()); - EXPECT_EQ(ArcBridgeService::State::STOPPED, bridge_service()->state()); + EXPECT_FALSE(bridge_service()->ready()); auth_service()->OnPrimaryUserProfilePrepared(profile()); EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn)); EXPECT_EQ(ArcAuthService::State::ACTIVE, auth_service()->state()); - EXPECT_EQ(ArcBridgeService::State::READY, bridge_service()->state()); + EXPECT_TRUE(bridge_service()->ready()); // Report failure. auth_service()->OnSignInFailed(mojom::ArcSignInFailureReason::NETWORK_ERROR); EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn)); EXPECT_EQ(ArcAuthService::State::STOPPED, auth_service()->state()); - EXPECT_EQ(ArcBridgeService::State::STOPPED, bridge_service()->state()); + EXPECT_FALSE(bridge_service()->ready()); // Correctly stop service. auth_service()->Shutdown();
diff --git a/chrome/browser/chromeos/chrome_interface_factory.cc b/chrome/browser/chromeos/chrome_interface_factory.cc index 3e29eec..a4b334d 100644 --- a/chrome/browser/chromeos/chrome_interface_factory.cc +++ b/chrome/browser/chromeos/chrome_interface_factory.cc
@@ -4,13 +4,6 @@ #include "chrome/browser/chromeos/chrome_interface_factory.h" -#include <memory> - -#include "ash/sysui/public/interfaces/wallpaper.mojom.h" -#include "base/lazy_instance.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" -#include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/app_list/app_list_presenter_service.h" @@ -18,16 +11,7 @@ #include "chrome/browser/ui/ash/keyboard_ui_service.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" -#include "content/public/common/mojo_shell_connection.h" -#include "mash/public/interfaces/launchable.mojom.h" -#include "mojo/public/cpp/bindings/binding_set.h" #include "services/shell/public/cpp/connection.h" -#include "ui/app_list/presenter/app_list_presenter.mojom.h" -#include "ui/keyboard/keyboard.mojom.h" - -namespace chromeos { - -namespace { class ChromeLaunchable : public mash::mojom::Launchable { public: @@ -73,92 +57,49 @@ DISALLOW_COPY_AND_ASSIGN(ChromeLaunchable); }; -class FactoryImpl { - public: - FactoryImpl() {} - ~FactoryImpl() {} +namespace chromeos { - template <typename Interface> - static void AddFactory( - shell::Connection* connection, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - connection->AddInterface<Interface>( - base::Bind(&FactoryImpl::CallMainThreadFactory<Interface>), - task_runner); - } - - private: - static FactoryImpl* Get() { - if (!factory_.Get()) - factory_.Get().reset(new FactoryImpl); - return factory_.Get().get(); - } - - template <typename Interface> - static void CallMainThreadFactory(mojo::InterfaceRequest<Interface> request) { - Get()->BindRequest(std::move(request)); - } - - void BindRequest(keyboard::mojom::KeyboardRequest request) { - if (!keyboard_ui_service_) - keyboard_ui_service_.reset(new KeyboardUIService); - keyboard_bindings_.AddBinding(keyboard_ui_service_.get(), - std::move(request)); - } - - void BindRequest(mash::mojom::LaunchableRequest request) { - if (!launchable_) - launchable_.reset(new ChromeLaunchable); - launchable_->ProcessRequest(std::move(request)); - } - - void BindRequest(ash::sysui::mojom::WallpaperManagerRequest request) { - if (!wallpaper_manager_) - wallpaper_manager_.reset(new ChromeWallpaperManager); - wallpaper_manager_->ProcessRequest(std::move(request)); - } - - void BindRequest(app_list::mojom::AppListPresenterRequest request) { - if (!app_list_presenter_service_) - app_list_presenter_service_.reset(new AppListPresenterService); - app_list_presenter_bindings_.AddBinding(app_list_presenter_service_.get(), - std::move(request)); - } - - static base::LazyInstance<std::unique_ptr<FactoryImpl>>::Leaky factory_; - - std::unique_ptr<KeyboardUIService> keyboard_ui_service_; - mojo::BindingSet<keyboard::mojom::Keyboard> keyboard_bindings_; - std::unique_ptr<ChromeLaunchable> launchable_; - std::unique_ptr<ChromeWallpaperManager> wallpaper_manager_; - std::unique_ptr<AppListPresenterService> app_list_presenter_service_; - mojo::BindingSet<app_list::mojom::AppListPresenter> - app_list_presenter_bindings_; - - DISALLOW_COPY_AND_ASSIGN(FactoryImpl); -}; - -base::LazyInstance<std::unique_ptr<FactoryImpl>>::Leaky FactoryImpl::factory_ = - LAZY_INSTANCE_INITIALIZER; - -} // namespace - -ChromeInterfaceFactory::ChromeInterfaceFactory() - : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {} - +ChromeInterfaceFactory::ChromeInterfaceFactory() {} ChromeInterfaceFactory::~ChromeInterfaceFactory() {} -bool ChromeInterfaceFactory::OnConnect(shell::Connection* connection, - shell::Connector* connector) { - FactoryImpl::AddFactory<keyboard::mojom::Keyboard>( - connection, main_thread_task_runner_); - FactoryImpl::AddFactory<mash::mojom::Launchable>( - connection, main_thread_task_runner_); - FactoryImpl::AddFactory<ash::sysui::mojom::WallpaperManager>( - connection, main_thread_task_runner_); - FactoryImpl::AddFactory<app_list::mojom::AppListPresenter>( - connection, main_thread_task_runner_); +bool ChromeInterfaceFactory::OnConnect(shell::Connection* connection) { + connection->AddInterface<keyboard::mojom::Keyboard>(this); + connection->AddInterface<mash::mojom::Launchable>(this); + connection->AddInterface<ash::sysui::mojom::WallpaperManager>(this); + connection->AddInterface<app_list::mojom::AppListPresenter>(this); return true; } +void ChromeInterfaceFactory::Create( + shell::Connection* connection, + mojo::InterfaceRequest<keyboard::mojom::Keyboard> request) { + if (!keyboard_ui_service_) + keyboard_ui_service_.reset(new KeyboardUIService); + keyboard_bindings_.AddBinding(keyboard_ui_service_.get(), std::move(request)); +} + +void ChromeInterfaceFactory::Create(shell::Connection* connection, + mash::mojom::LaunchableRequest request) { + if (!launchable_) + launchable_.reset(new ChromeLaunchable); + launchable_->ProcessRequest(std::move(request)); +} + +void ChromeInterfaceFactory::Create( + shell::Connection* connection, + ash::sysui::mojom::WallpaperManagerRequest request) { + if (!wallpaper_manager_) + wallpaper_manager_.reset(new ChromeWallpaperManager); + wallpaper_manager_->ProcessRequest(std::move(request)); +} + +void ChromeInterfaceFactory::Create( + shell::Connection* connection, + mojo::InterfaceRequest<app_list::mojom::AppListPresenter> request) { + if (!app_list_presenter_service_) + app_list_presenter_service_.reset(new AppListPresenterService); + app_list_presenter_bindings_.AddBinding(app_list_presenter_service_.get(), + std::move(request)); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/chrome_interface_factory.h b/chrome/browser/chromeos/chrome_interface_factory.h index 3538bbc0..d8afb09f 100644 --- a/chrome/browser/chromeos/chrome_interface_factory.h +++ b/chrome/browser/chromeos/chrome_interface_factory.h
@@ -5,25 +5,62 @@ #ifndef CHROME_BROWSER_CHROMEOS_CHROME_INTERFACE_FACTORY_H_ #define CHROME_BROWSER_CHROMEOS_CHROME_INTERFACE_FACTORY_H_ -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "content/public/common/connection_filter.h" +#include "ash/sysui/public/interfaces/wallpaper.mojom.h" +#include "content/public/common/mojo_shell_connection.h" +#include "mash/public/interfaces/launchable.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "services/shell/public/cpp/interface_factory.h" +#include "services/shell/public/cpp/service.h" +#include "ui/app_list/presenter/app_list_presenter.mojom.h" +#include "ui/keyboard/keyboard.mojom.h" + +class AppListPresenterService; +class ChromeLaunchable; +class ChromeWallpaperManager; +class KeyboardUIService; namespace chromeos { // InterfaceFactory for creating all services provided by chrome. -class ChromeInterfaceFactory : public content::ConnectionFilter { +class ChromeInterfaceFactory + : public shell::Service, + public shell::InterfaceFactory<keyboard::mojom::Keyboard>, + public shell::InterfaceFactory<mash::mojom::Launchable>, + public shell::InterfaceFactory<ash::sysui::mojom::WallpaperManager>, + public shell::InterfaceFactory<app_list::mojom::AppListPresenter> { public: ChromeInterfaceFactory(); ~ChromeInterfaceFactory() override; private: - // content::ConnectionFilter: - bool OnConnect(shell::Connection* connection, - shell::Connector* connector) override; + // shell::Service: + bool OnConnect(shell::Connection* connection) override; - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; + // shell::InterfaceFactory<keyboard::Keyboard>: + void Create( + shell::Connection* connection, + mojo::InterfaceRequest<keyboard::mojom::Keyboard> request) override; + + // mojo::InterfaceFactory<mash::mojom::Launchable> + void Create(shell::Connection* connection, + mash::mojom::LaunchableRequest request) override; + + // mojo::InterfaceFactory<ash::sysui::mojom::WallpaperManager> + void Create(shell::Connection* connection, + ash::sysui::mojom::WallpaperManagerRequest request) override; + + // mojo::InterfaceFactory<app_list::AppListPresenter>: + void Create(shell::Connection* connection, + mojo::InterfaceRequest<app_list::mojom::AppListPresenter> request) + override; + + std::unique_ptr<KeyboardUIService> keyboard_ui_service_; + mojo::BindingSet<keyboard::mojom::Keyboard> keyboard_bindings_; + std::unique_ptr<ChromeLaunchable> launchable_; + std::unique_ptr<ChromeWallpaperManager> wallpaper_manager_; + std::unique_ptr<AppListPresenterService> app_list_presenter_service_; + mojo::BindingSet<app_list::mojom::AppListPresenter> + app_list_presenter_bindings_; DISALLOW_COPY_AND_ASSIGN(ChromeInterfaceFactory); };
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 1725076..f4d108818 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -3950,7 +3950,7 @@ = arc::ArcBridgeService::Get(); // ARC is switched off by default. - EXPECT_EQ(arc::ArcBridgeService::State::STOPPED, arc_bridge_service->state()); + EXPECT_TRUE(arc_bridge_service->stopped()); EXPECT_FALSE(pref->GetBoolean(prefs::kArcEnabled)); // Enable ARC. @@ -3960,7 +3960,7 @@ base::WrapUnique(new base::FundamentalValue(true)), nullptr); UpdateProviderPolicy(policies); EXPECT_TRUE(pref->GetBoolean(prefs::kArcEnabled)); - EXPECT_EQ(arc::ArcBridgeService::State::READY, arc_bridge_service->state()); + EXPECT_TRUE(arc_bridge_service->ready()); // Disable ARC. policies.Set(key::kArcEnabled, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, @@ -3968,7 +3968,7 @@ base::WrapUnique(new base::FundamentalValue(false)), nullptr); UpdateProviderPolicy(policies); EXPECT_FALSE(pref->GetBoolean(prefs::kArcEnabled)); - EXPECT_EQ(arc::ArcBridgeService::State::STOPPED, arc_bridge_service->state()); + EXPECT_TRUE(arc_bridge_service->stopped()); TearDownTest(); }
diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc index 47eca0f..f9923d4a 100644 --- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc +++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
@@ -5,12 +5,14 @@ #include <vector> #include "base/command_line.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test_utils.h" @@ -18,6 +20,7 @@ #include "content/public/test/text_input_test_utils.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "ui/base/ime/composition_underline.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" @@ -206,6 +209,32 @@ DISALLOW_COPY_AND_ASSIGN(ViewSelectionBoundsChangedObserver); }; +// This class observes the |expected_view| for the first change in its +// composition range information. +class ViewCompositionRangeChangedObserver + : public TextInputManagerObserverBase { + public: + ViewCompositionRangeChangedObserver( + content::WebContents* web_contents, + content::RenderWidgetHostView* expected_view) + : TextInputManagerObserverBase(web_contents), + expected_view_(expected_view) { + tester()->SetOnImeCompositionRangeChangedCallback( + base::Bind(&ViewCompositionRangeChangedObserver::VerifyChange, + base::Unretained(this))); + } + + private: + void VerifyChange() { + if (expected_view_ == tester()->GetUpdatedView()) + OnSuccess(); + } + + const content::RenderWidgetHostView* const expected_view_; + + DISALLOW_COPY_AND_ASSIGN(ViewCompositionRangeChangedObserver); +}; + } // namespace // Main class for all TextInputState and IME related tests. @@ -484,7 +513,7 @@ // receives the corresponding update on the change in selection bounds on the // browser side. IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest, - TrackSelectionBoundsForChildFrames) { + TrackSelectionBoundsForAllFrames) { CreateIframePage("a(b,c(a,b),d)"); std::vector<content::RenderFrameHost*> frames{ GetFrame(IndexVector{}), GetFrame(IndexVector{0}), @@ -515,6 +544,44 @@ send_tab_insert_text_wait_for_bounds_change(view); } +// This test creates a page with multiple child frames and adds an <input> to +// each frame. Then, sequentially, each <input> is focused by sending a tab key. +// Then, after |TextInputState.type| for a view is changed to text, the test +// sends a set composition IPC to the active widget and waits until the widget +// updates its composition range. +IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest, + TrackCompositionRangeForAllFrames) { + // TODO(ekaramd): After IME methods are implemented for WebFrameWidgetImpl, + // change the page so that it contains child frames as well + // (crbug.com/626746). + CreateIframePage("a()"); + std::vector<content::RenderFrameHost*> frames{GetFrame(IndexVector{})}; + std::vector<content::RenderWidgetHostView*> views; + for (auto frame : frames) + views.push_back(frame->GetView()); + for (size_t i = 0; i < frames.size(); ++i) + AddInputFieldToFrame(frames[i], "text", "", true); + + content::WebContents* web_contents = active_contents(); + + auto send_tab_set_composition_wait_for_bounds_change = + [&web_contents](content::RenderWidgetHostView* view) { + ViewTextInputTypeObserver type_observer(web_contents, view, + ui::TEXT_INPUT_TYPE_TEXT); + SimulateKeyPress(web_contents, ui::DomKey::TAB, ui::DomCode::TAB, + ui::VKEY_TAB, false, false, false, false); + type_observer.Wait(); + ViewCompositionRangeChangedObserver range_observer(web_contents, view); + content::SetCompositionForRenderWidgetHost( + view->GetRenderWidgetHost(), base::ASCIIToUTF16("text"), + {ui::CompositionUnderline()}, gfx::Range::InvalidRange(), 0, 0); + range_observer.Wait(); + }; + + for (auto view : views) + send_tab_set_composition_wait_for_bounds_change(view); +} + // TODO(ekaramad): The following tests are specifically written for Aura and are // based on InputMethodObserver. Write similar tests for Mac/Android/Mus // (crbug.com/602723).
diff --git a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html index ee16710f..8da11aa 100644 --- a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html +++ b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html
@@ -102,13 +102,13 @@ #pin-input { -webkit-text-security: disc; + background-color: white; border: 0; font-size: 18px; height: 64px; left: 20px; padding: 28px 3px 12px 3px; position: relative; - text-align: center; width: 180px; } @@ -170,6 +170,7 @@ <inner-text>$i18n{pinKeyboard7}</inner-text> </paper-button> <paper-button class="digit-button center-button" on-tap="onNumberTap_" + value="8"> <inner-text>$i18n{pinKeyboard8}</inner-text> </paper-button> <paper-button class="digit-button" on-tap="onNumberTap_" value="9">
diff --git a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js index de93c08d..f9f5873 100644 --- a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js +++ b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
@@ -48,6 +48,22 @@ } }, + /** + * Gets the container holding the password field. + * @type {!HTMLInputElement} + */ + get inputElement() { + return this.$$('#pin-input'); + }, + + /** + * Gets the submit button. + * @type {!HTMLElement} + */ + get submitButton() { + return this.$$('.submit-button'); + }, + /** Transfers focus to the input element. */ focus: function() { this.$$('#pin-input').focus();
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html index 607fde2..04cdcb15 100644 --- a/chrome/browser/resources/settings/device_page/display.html +++ b/chrome/browser/resources/settings/device_page/display.html
@@ -39,6 +39,7 @@ .info-text { color: var(--paper-grey-500); + margin-top: 5px; } .settings-box > paper-button:first-child { @@ -82,16 +83,17 @@ </div> <div class="settings-box embedded"> <div class="start textarea">$i18n{displayOrientation}</div> - <paper-dropdown-menu> + <paper-dropdown-menu no-label-float> <paper-listbox class="dropdown-content" selected="[[selectedDisplay.rotation]]" attr-for-selected="value" on-iron-activate="onSetOrientation_"> - <paper-item value="0">$i18n{displayOrientationStandard} - </paper-item> - <paper-item value="90">90</paper-item> - <paper-item value="180">180</paper-item> - <paper-item value="270">270</paper-item> + <div class="dropdown-item" value="0"> + $i18n{displayOrientationStandard} + </div> + <div class="dropdown-item" value="90">90</div> + <div class="dropdown-item" value="180">180</div> + <div class="dropdown-item" value="270">270</div> </paper-listbox> </paper-dropdown-menu> </div>
diff --git a/chrome/browser/resources/settings/device_page/display_layout.html b/chrome/browser/resources/settings/device_page/display_layout.html index acbe3dc0..fda6b74 100644 --- a/chrome/browser/resources/settings/device_page/display_layout.html +++ b/chrome/browser/resources/settings/device_page/display_layout.html
@@ -16,6 +16,8 @@ position: relative; width: 100%; } + /* Note: the size of the border / box shadow affects the style generated + in getDivStyle_ and getMirrorDivStyle_ */ .display { align-items: center; background: var(--paper-grey-200); @@ -30,6 +32,10 @@ border: var(--google-blue-500) solid 2px; box-shadow: none; } + .display.mirror { + border: var(--google-blue-500) solid 1px; + box-shadow: none; + } .highlight-left { border-left: var(--google-blue-700) solid 1px; } @@ -45,7 +51,13 @@ </style> <div id="displayArea" on-iron-resize="calculateVisualScale_"> <template is="dom-repeat" items="[[displays]]"> - <div id="_[[item.id]]" class="display" draggable="true" + <div id="_mirror_[[item.id]]" class="display mirror" + hidden$="[[!mirroring]]" + style$="[[getMirrorDivStyle_(item.id, item.bounds, visualScale)]]" + </div> + </template> + <template is="dom-repeat" items="[[displays]]"> + <div id="_[[item.id]]" class="display" draggable="[[dragEnabled]]" style$="[[getDivStyle_(item.id, item.bounds, visualScale)]]" selected$="[[isSelected_(item, selectedDisplay)]]" on-tap="onSelectDisplayTap_">
diff --git a/chrome/browser/resources/settings/device_page/display_layout.js b/chrome/browser/resources/settings/device_page/display_layout.js index c37f9cb..eb1931f 100644 --- a/chrome/browser/resources/settings/device_page/display_layout.js +++ b/chrome/browser/resources/settings/device_page/display_layout.js
@@ -28,12 +28,6 @@ */ displays: Array, - /** - * Whether or not mirroring is enabled. - * @type {boolean} - */ - mirroring: false, - /** @type {!chrome.system.display.DisplayUnitInfo|undefined} */ selectedDisplay: Object, @@ -48,19 +42,6 @@ visualOffset_: {left: 0, top: 0}, /** @override */ - attached: function() { - // TODO(stevenjb): Remove retry once fixed: - // https://github.com/Polymer/polymer/issues/3629 - var self = this; - var retry = 100; // ms - function tryCalcVisualScale() { - if (!self.calculateVisualScale_()) - setTimeout(tryCalcVisualScale, retry); - } - tryCalcVisualScale(); - }, - - /** @override */ detached: function() { this.initializeDrag(false); }, /** @@ -73,11 +54,15 @@ this.displays = displays; this.layouts = layouts; - this.mirroring = displays.length > 0 && !!displays[0].mirroringSourceId; - this.initializeDisplayLayout(displays, layouts); - this.calculateVisualScale_(); + var self = this; + var retry = 100; // ms + function tryCalcVisualScale() { + if (!self.calculateVisualScale_()) + setTimeout(tryCalcVisualScale, retry); + } + tryCalcVisualScale(); this.initializeDrag( !this.mirroring, this.$.displayArea, this.onDrag_.bind(this)); @@ -150,24 +135,39 @@ * @param {string} id * @param {!chrome.system.display.Bounds} displayBounds * @param {number} visualScale + * @param {boolean=} opt_mirrored * @return {string} The style string for the div. * @private */ - getDivStyle_: function(id, displayBounds, visualScale) { + getDivStyle_: function(id, displayBounds, visualScale, opt_mirrored) { // This matches the size of the box-shadow or border in CSS. - /** @const {number} */ var BORDER = 2; - var bounds = this.getCalculatedDisplayBounds(id); + /** @const {number} */ var BORDER = opt_mirrored ? 1 : 2; + /** @const {number} */ var OFFSET = opt_mirrored ? -4 : 0; + var bounds = this.getCalculatedDisplayBounds(id, true /* notest */); + if (!bounds) + return ''; var height = Math.round(bounds.height * this.visualScale) - BORDER * 2; var width = Math.round(bounds.width * this.visualScale) - BORDER * 2; - var left = + var left = OFFSET + Math.round(this.visualOffset_.left + (bounds.left * this.visualScale)); - var top = + var top = OFFSET + Math.round(this.visualOffset_.top + (bounds.top * this.visualScale)); return `height: ${height}px; width: ${width}px;` + ` left: ${left}px; top: ${top}px`; }, /** + * @param {string} id + * @param {!chrome.system.display.Bounds} displayBounds + * @param {number} visualScale + * @return {string} The style string for the mirror div. + * @private + */ + getMirrorDivStyle_: function(id, displayBounds, visualScale) { + return this.getDivStyle_(id, displayBounds, visualScale, true); + }, + + /** * @param {!chrome.system.display.DisplayUnitInfo} display * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay * @return {boolean}
diff --git a/chrome/browser/resources/settings/device_page/drag_behavior.js b/chrome/browser/resources/settings/device_page/drag_behavior.js index 91d9c50..0d92c6d 100644 --- a/chrome/browser/resources/settings/device_page/drag_behavior.js +++ b/chrome/browser/resources/settings/device_page/drag_behavior.js
@@ -17,15 +17,17 @@ /** @polymerBehavior */ var DragBehavior = { + properties: { + /** Whether or not drag is enabled (e.g. not mirrored). */ + dragEnabled: Boolean, + }, + /** * The id of the element being dragged, or empty if not dragging. * @private {string} */ dragId_: '', - /** @private {boolean} */ - enabled_: false, - /** @private {!HTMLDivElement|undefined} */ container_: undefined, @@ -62,62 +64,69 @@ * @param {!function(string, ?DragPosition):void=} opt_callback */ initializeDrag: function(enabled, opt_container, opt_callback) { - this.enabled_ = enabled; + this.dragEnabled = enabled; if (!enabled) { - if (this.container) { - this.container.removeEventListener('mousdown', this.mouseDownListener_); - this.mouseDownListener_ = null; - this.container.removeEventListener( - 'mousemove', this.mouseMoveListener_); - this.mouseMoveListener_ = null; - this.container.removeEventListener( - 'touchstart', this.touchStartListener_); - this.touchStartListener_ = null; - this.container.removeEventListener( - 'touchmove', this.touchMoveListener_); - this.touchMoveListener_ = null; - this.container.removeEventListener('touchend', this.endDragListener_); - } - if (this.mouseUpListener_) - window.removeEventListener('mouseup', this.endDragListener_); - this.endDragListener_ = null; + this.removeListeners_(); return; } if (opt_container !== undefined) this.container_ = opt_container; - var container = this.container_; - assert(container); - this.mouseDownListener_ = this.onMouseDown_.bind(this); - container.addEventListener('mousedown', this.mouseDownListener_, true); - - this.mouseMoveListener_ = this.onMouseMove_.bind(this); - container.addEventListener('mousemove', this.mouseMoveListener_, true); - - this.touchStartListener_ = this.onTouchStart_.bind(this); - container.addEventListener('touchstart', this.touchStartListener_, true); - - this.touchMoveListener_ = this.onTouchMove_.bind(this); - container.addEventListener('touchmove', this.touchMoveListener_, true); - - this.endDragListener_ = this.endDrag_.bind(this); - window.addEventListener('mouseup', this.endDragListener_, true); - container.addEventListener('touchend', this.endDragListener_, true); + this.addListeners_(); if (opt_callback !== undefined) this.callback_ = opt_callback; }, + /** @private */ + addListeners_() { + let container = this.container_; + if (!container || this.mouseDownListener_) + return; + this.mouseDownListener_ = this.onMouseDown_.bind(this); + container.addEventListener('mousedown', this.mouseDownListener_); + + this.mouseMoveListener_ = this.onMouseMove_.bind(this); + container.addEventListener('mousemove', this.mouseMoveListener_); + + this.touchStartListener_ = this.onTouchStart_.bind(this); + container.addEventListener('touchstart', this.touchStartListener_); + + this.touchMoveListener_ = this.onTouchMove_.bind(this); + container.addEventListener('touchmove', this.touchMoveListener_); + + this.endDragListener_ = this.endDrag_.bind(this); + window.addEventListener('mouseup', this.endDragListener_); + container.addEventListener('touchend', this.endDragListener_); + }, + + /** @private */ + removeListeners_() { + let container = this.container_; + if (!container || !this.mouseDownListener_) + return; + container.removeEventListener('mousedown', this.mouseDownListener_); + this.mouseDownListener_ = null; + container.removeEventListener('mousemove', this.mouseMoveListener_); + this.mouseMoveListener_ = null; + container.removeEventListener('touchstart', this.touchStartListener_); + this.touchStartListener_ = null; + container.removeEventListener('touchmove', this.touchMoveListener_); + this.touchMoveListener_ = null; + container.removeEventListener('touchend', this.endDragListener_); + if (this.endDragListener_) + window.removeEventListener('mouseup', this.endDragListener_); + this.endDragListener_ = null; + }, + /** * @param {Event} e The mouse down event. * @return {boolean} * @private */ onMouseDown_: function(e) { - if (e.button != 0) - return true; - if (!e.target.getAttribute('draggable')) + if (e.button != 0 || !e.target.getAttribute('draggable')) return true; e.preventDefault(); var target = assertInstanceof(e.target, HTMLElement); @@ -181,6 +190,7 @@ * @private */ startDrag_: function(target, eventLocation) { + assert(this.dragEnabled); this.dragId_ = target.id; this.dragStartLocation_ = eventLocation; return false; @@ -192,6 +202,7 @@ * @private */ endDrag_: function(e) { + assert(this.dragEnabled); if (this.dragId_ && this.callback_) this.callback_(this.dragId_, null); this.dragId_ = ''; @@ -206,6 +217,7 @@ * @private */ processDrag_: function(e, eventLocation) { + assert(this.dragEnabled); if (!this.dragId_) return true; if (this.callback_) {
diff --git a/chrome/browser/resources/settings/device_page/layout_behavior.js b/chrome/browser/resources/settings/device_page/layout_behavior.js index 51ba51bd..33e2162 100644 --- a/chrome/browser/resources/settings/device_page/layout_behavior.js +++ b/chrome/browser/resources/settings/device_page/layout_behavior.js
@@ -15,6 +15,12 @@ * @type {!Array<!chrome.system.display.DisplayLayout>} */ layouts: Array, + + /** + * Whether or not mirroring is enabled. + * @type {boolean} + */ + mirroring: false, }, /** @private {!Map<string, chrome.system.display.Bounds>} */ @@ -49,6 +55,8 @@ this.dragLayoutId = ''; this.dragParentId_ = ''; + this.mirroring = displays.length > 0 && !!displays[0].mirroringSourceId; + this.displayBoundsMap_.clear(); for (let display of displays) this.displayBoundsMap_.set(display.id, display.bounds); @@ -182,11 +190,12 @@ /** * @param {string} displayId + * @param {boolean=} opt_notest Set to true if bounds may not be set. * @return {!chrome.system.display.Bounds} bounds */ - getCalculatedDisplayBounds: function(displayId) { + getCalculatedDisplayBounds: function(displayId, opt_notest) { var bounds = this.calculatedBoundsMap_.get(displayId); - assert(bounds); + assert(opt_notest || bounds); return bounds; }, @@ -308,7 +317,7 @@ calculateBounds_: function(id, width, height) { var left, top; var layout = this.displayLayoutMap_.get(id); - if (!layout || !layout.parentId) { + if (this.mirroring || !layout || !layout.parentId) { left = -width / 2; top = -height / 2; } else {
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js b/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js index 5456283..b70692a6 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js +++ b/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js
@@ -131,7 +131,7 @@ /** @override */ manageExtension: function(extensionId) { - window.location = 'chrome://extensions?id=' + extensionId; + window.open('chrome://extensions?id=' + extensionId); }, };
diff --git a/chrome/browser/resources/settings/settings.js b/chrome/browser/resources/settings/settings.js index 8de0323..17ef39b 100644 --- a/chrome/browser/resources/settings/settings.js +++ b/chrome/browser/resources/settings/settings.js
@@ -2,6 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +cr.exportPath('settings'); +assert(!settings.defaultResourceLoaded, + 'settings.js run twice. You probably have an invalid import.'); +/** Global defined when the main Settings script runs. */ +settings.defaultResourceLoaded = true; + /** * @fileoverview * 'cr-settings' is the main MD-Settings element, combining the UI and models.
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc index bcbc88c..fa58150 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -235,7 +235,8 @@ DCHECK(bridge_service); bridge_service->AddObserver(this); - OnStateChanged(bridge_service->state()); + if (!bridge_service->ready()) + OnBridgeStopped(); } ArcAppListPrefs::~ArcAppListPrefs() { @@ -562,9 +563,8 @@ RemoveAllApps(); } -void ArcAppListPrefs::OnStateChanged(arc::ArcBridgeService::State state) { - if (state != arc::ArcBridgeService::State::READY) - DisableAllApps(); +void ArcAppListPrefs::OnBridgeStopped() { + DisableAllApps(); } void ArcAppListPrefs::OnAppInstanceReady() {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h index 0357525..173843c5 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -206,7 +206,7 @@ ArcAppListPrefs(const base::FilePath& base_path, PrefService* prefs); // arc::ArcBridgeService::Observer: - void OnStateChanged(arc::ArcBridgeService::State state) override; + void OnBridgeStopped() override; void OnAppInstanceReady() override; void OnAppInstanceClosed() override;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_test.cc b/chrome/browser/ui/app_list/arc/arc_app_test.cc index 7ef0ed9..a32626c6 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_test.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_test.cc
@@ -118,8 +118,7 @@ // Check initial conditions. EXPECT_EQ(bridge_service_.get(), arc::ArcBridgeService::Get()); EXPECT_TRUE(!arc::ArcBridgeService::Get()->available()); - EXPECT_EQ(arc::ArcBridgeService::State::STOPPED, - arc::ArcBridgeService::Get()->state()); + EXPECT_FALSE(arc::ArcBridgeService::Get()->ready()); // At this point we should have ArcAppListPrefs as observer of service. EXPECT_TRUE(bridge_service_->HasObserver(arc_app_list_pref_));
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc index ecdc856..cf5a14a7 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
@@ -6,6 +6,7 @@ #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm/window_state.h" #include "ash/common/wm_shell.h" +#include "ash/display/display_manager.h" #include "ash/display/screen_orientation_controller_chromeos.h" #include "ash/shelf/shelf_delegate.h" #include "ash/shelf/shelf_util.h" @@ -28,6 +29,7 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/env.h" #include "ui/base/base_window.h" +#include "ui/display/display.h" #include "ui/views/widget/widget.h" namespace { @@ -38,8 +40,29 @@ NON_ACTIVE, // Fullscreen was not activated for an app. }; +arc::mojom::OrientationLock GetCurrentOrientation() { + if (!display::Display::HasInternalDisplay()) + return arc::mojom::OrientationLock::NONE; + display::Display internal_display = + ash::Shell::GetInstance()->display_manager()->GetDisplayForId( + display::Display::InternalDisplayId()); + + // ChromeOS currently assumes that the internal panel is always + // landscape (ROTATE_0 == landscape). + switch (internal_display.rotation()) { + case display::Display::ROTATE_0: + case display::Display::ROTATE_180: + return arc::mojom::OrientationLock::LANDSCAPE; + case display::Display::ROTATE_90: + case display::Display::ROTATE_270: + return arc::mojom::OrientationLock::PORTRAIT; + } + return arc::mojom::OrientationLock::NONE; +} + blink::WebScreenOrientationLockType BlinkOrientationLockFromMojom( arc::mojom::OrientationLock orientation_lock) { + DCHECK_NE(arc::mojom::OrientationLock::CURRENT, orientation_lock); if (orientation_lock == arc::mojom::OrientationLock::PORTRAIT) { return blink::WebScreenOrientationLockPortrait; } else if (orientation_lock == arc::mojom::OrientationLock::LANDSCAPE) { @@ -572,6 +595,13 @@ return; orientation_lock = app_info->orientation_lock; } + + if (orientation_lock == arc::mojom::OrientationLock::CURRENT) { + // Resolve the orientation when it first resolved. + orientation_lock = GetCurrentOrientation(); + app_window->set_requested_orientation_lock(orientation_lock); + } + shell->screen_orientation_controller()->LockOrientationForWindow( window, BlinkOrientationLockFromMojom(orientation_lock)); }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc index c39afdf9..458e78b 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
@@ -3466,8 +3466,86 @@ "AppList, Chrome"); } -TEST_F(ChromeLauncherControllerImplTest, ArcOrientationLock) { - DCHECK(display::Display::HasInternalDisplay()); +namespace { + +class ChromeLauncherControllerOrientationTest + : public ChromeLauncherControllerImplTest { + public: + ChromeLauncherControllerOrientationTest() {} + ~ChromeLauncherControllerOrientationTest() override {} + + protected: + void InitApps() { + appinfo_none_ = + CreateAppInfo("None", "None", "com.example.app", OrientationLock::NONE); + appinfo_landscape_ = + CreateAppInfo("Landscape", "Landscape", "com.example.app", + OrientationLock::LANDSCAPE); + appinfo_portrait_ = CreateAppInfo("Portrait", "Portrait", "com.example.app", + OrientationLock::PORTRAIT); + appinfo_current_ = CreateAppInfo( + "LockCurrent", "current", "com.example.app", OrientationLock::CURRENT); + + AddArcAppAndShortcut(appinfo_none_); + AddArcAppAndShortcut(appinfo_landscape_); + AddArcAppAndShortcut(appinfo_portrait_); + AddArcAppAndShortcut(appinfo_current_); + + ash::ScreenOrientationController* controller = + ash::Shell::GetInstance()->screen_orientation_controller(); + + // Creating a window with NONE orientation will not lock the screen. + window_none_ = CreateArcWindow(window_app_id_none_); + NotifyOnTaskCreated(appinfo_none_, task_id_none_); + EXPECT_FALSE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Create a arc window with PORTRAIT orientation locks the screen to 90. + window_portrait_ = CreateArcWindow(window_app_id_portrait_); + NotifyOnTaskCreated(appinfo_portrait_, task_id_portrait_); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Create a arc window with LANDSCAPE orientation locks the screen to 0. + window_landscape_ = CreateArcWindow(window_app_id_landscape_); + NotifyOnTaskCreated(appinfo_landscape_, task_id_landscape_); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + } + + int32_t task_id_none_ = 1; + int32_t task_id_landscape_ = 2; + int32_t task_id_portrait_ = 3; + int32_t task_id_current_ = 4; + + // This needs to be kept on the instance because window's property has + // refeference to this. + std::string window_app_id_none_ = {"org.chromium.arc.1"}; + std::string window_app_id_landscape_ = {"org.chromium.arc.2"}; + std::string window_app_id_portrait_ = {"org.chromium.arc.3"}; + std::string window_app_id_current_ = {"org.chromium.arc.4"}; + + arc::mojom::AppInfo appinfo_none_; + arc::mojom::AppInfo appinfo_landscape_; + arc::mojom::AppInfo appinfo_portrait_; + arc::mojom::AppInfo appinfo_current_; + + views::Widget* window_none_ = nullptr; + views::Widget* window_landscape_ = nullptr; + views::Widget* window_portrait_ = nullptr; + views::Widget* window_current_ = nullptr; + + private: + DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerOrientationTest); +}; + +} // namespace + +TEST_F(ChromeLauncherControllerOrientationTest, ArcOrientationLock) { + ASSERT_TRUE(display::Display::HasInternalDisplay()); extension_service_->AddExtension(arc_support_host_.get()); arc_test_.SetUp(profile()); @@ -3476,59 +3554,19 @@ InitLauncherController(); arc::ArcAuthService::SetShelfDelegateForTesting(launcher_controller_.get()); - arc::mojom::AppInfo appinfo_none = - CreateAppInfo("None", "None", "com.example.app", OrientationLock::NONE); - arc::mojom::AppInfo appinfo_landscape = CreateAppInfo( - "Landscape", "Landscape", "com.example.app", OrientationLock::LANDSCAPE); - arc::mojom::AppInfo appinfo_portrait = CreateAppInfo( - "Portrait", "Portrait", "com.example.app", OrientationLock::PORTRAIT); - const std::string app_id_none = AddArcAppAndShortcut(appinfo_none); - const std::string app_id_landscape = AddArcAppAndShortcut(appinfo_landscape); - const std::string app_id_portrait = AddArcAppAndShortcut(appinfo_portrait); - - int32_t task_id_none = 1; - int32_t task_id_landscape = 2; - int32_t task_id_portrait = 3; - - // This needs to be kept on stack because window's property has - // refeference to this. - std::string window_app_id_none("org.chromium.arc.1"); - std::string window_app_id_landscape("org.chromium.arc.2"); - std::string window_app_id_portrait("org.chromium.arc.3"); - + InitApps(); ash::ScreenOrientationController* controller = ash::Shell::GetInstance()->screen_orientation_controller(); - // Creating a window with NONE orientation will not lock the screen. - views::Widget* window_none = CreateArcWindow(window_app_id_none); - NotifyOnTaskCreated(appinfo_none, task_id_none); - EXPECT_FALSE(controller->rotation_locked()); - EXPECT_EQ(display::Display::ROTATE_0, - display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); - - // Create a arc window with PORTRAIT orientation locks the screen to 90. - views::Widget* window_portrait = CreateArcWindow(window_app_id_portrait); - NotifyOnTaskCreated(appinfo_portrait, task_id_portrait); - EXPECT_TRUE(controller->rotation_locked()); - EXPECT_EQ(display::Display::ROTATE_90, - display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); - - // Create a arc window with LANDSCAPE orientation locks the screen to 0. - views::Widget* window_landscape = CreateArcWindow(window_app_id_landscape); - NotifyOnTaskCreated(appinfo_landscape, task_id_landscape); - EXPECT_TRUE(controller->rotation_locked()); - EXPECT_EQ(display::Display::ROTATE_0, - display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); - // Activating a window with NON orientation unlocks the screen. - window_none->Activate(); + window_none_->Activate(); EXPECT_FALSE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_0, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); // Activating a window with PORTRAIT orientation locks the screen to 90. - window_portrait->Activate(); + window_portrait_->Activate(); EXPECT_TRUE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_90, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); @@ -3545,38 +3583,38 @@ EXPECT_EQ(display::Display::ROTATE_90, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); - window_portrait->Activate(); + window_portrait_->Activate(); EXPECT_TRUE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_90, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); - window_landscape->Activate(); + window_landscape_->Activate(); EXPECT_TRUE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_0, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); // OnTaskOrientationLockRequested can overwrite the current lock. - NotifyOnTaskOrientationLockRequested(task_id_landscape, + NotifyOnTaskOrientationLockRequested(task_id_landscape_, OrientationLock::NONE); EXPECT_FALSE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_0, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); - NotifyOnTaskOrientationLockRequested(task_id_landscape, + NotifyOnTaskOrientationLockRequested(task_id_landscape_, OrientationLock::PORTRAIT); EXPECT_TRUE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_90, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); // Non active window won't change the lock. - NotifyOnTaskOrientationLockRequested(task_id_none, + NotifyOnTaskOrientationLockRequested(task_id_none_, OrientationLock::LANDSCAPE); EXPECT_TRUE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_90, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); // But activating it will change the locked orinetation. - window_none->Activate(); + window_none_->Activate(); EXPECT_TRUE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_0, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); @@ -3587,7 +3625,8 @@ EXPECT_EQ(display::Display::ROTATE_0, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); - NotifyOnTaskOrientationLockRequested(task_id_none, OrientationLock::PORTRAIT); + NotifyOnTaskOrientationLockRequested(task_id_none_, + OrientationLock::PORTRAIT); EXPECT_FALSE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_0, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); @@ -3598,4 +3637,71 @@ EXPECT_TRUE(controller->rotation_locked()); EXPECT_EQ(display::Display::ROTATE_90, display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Manually unlock first. + NotifyOnTaskOrientationLockRequested(task_id_none_, OrientationLock::NONE); + EXPECT_FALSE(controller->rotation_locked()); +} + +TEST_F(ChromeLauncherControllerOrientationTest, CurrentWithLandscapeDisplay) { + ASSERT_TRUE(display::Display::HasInternalDisplay()); + + extension_service_->AddExtension(arc_support_host_.get()); + arc_test_.SetUp(profile()); + EnableArc(true); + EnableTabletMode(true); + + InitLauncherController(); + arc::ArcAuthService::SetShelfDelegateForTesting(launcher_controller_.get()); + + InitApps(); + ash::ScreenOrientationController* controller = + ash::Shell::GetInstance()->screen_orientation_controller(); + + // Start with portrait. + window_portrait_->Activate(); + + // Create a arc window to lock the CURRENT orientation. + views::Widget* window_current = CreateArcWindow(window_app_id_current_); + NotifyOnTaskCreated(appinfo_current_, task_id_current_); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Re-activating changes the orientation to previously locked orientation. + window_landscape_->Activate(); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + window_current->Activate(); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Exitting and re-entering tablet mode re-locks the orientation. + EnableTabletMode(false); + EXPECT_FALSE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + EnableTabletMode(true); + EXPECT_TRUE(window_current->IsActive()); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Manually unlock, and lock again at landscape. + NotifyOnTaskOrientationLockRequested(task_id_current_, OrientationLock::NONE); + window_landscape_->Activate(); + EXPECT_TRUE(controller->rotation_locked()); + window_current->Activate(); + EXPECT_FALSE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + NotifyOnTaskOrientationLockRequested(task_id_current_, + OrientationLock::CURRENT); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); }
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index cbae94c..7ea8a87 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -1565,7 +1565,7 @@ current_profile_name->SetHorizontalAlignment(gfx::ALIGN_LEFT); NonInteractiveContainer* profile_name_container = new NonInteractiveContainer(); - int name_container_v_spacing = views::kRelatedControlSmallVerticalSpacing; + int name_container_v_spacing = views::kRelatedControlVerticalSpacing; if (!avatar_item.signed_in || switches::IsEnableAccountConsistency()) name_container_v_spacing += views::kRelatedControlVerticalSpacing; profile_name_container->SetLayoutManager(new views::BoxLayout( @@ -1801,15 +1801,17 @@ views::View* ProfileChooserView::CreateSupervisedUserDisclaimerView() { views::View* view = new views::View(); + int horizontal_margin = switches::IsMaterialDesignUserMenu() ? + kMaterialMenuEdgeMargin : views::kButtonHEdgeMarginNew; views::GridLayout* layout = CreateSingleColumnLayout( - view, GetFixedMenuWidth() - 2 * views::kButtonHEdgeMarginNew); + view, GetFixedMenuWidth() - 2 * horizontal_margin); if (switches::IsMaterialDesignUserMenu()) { - layout->SetInsets(0, kMaterialMenuEdgeMargin, kMaterialMenuEdgeMargin, - kMaterialMenuEdgeMargin); + layout->SetInsets(0, horizontal_margin, + kMaterialMenuEdgeMargin, horizontal_margin); } else { layout->SetInsets( - views::kRelatedControlVerticalSpacing, views::kButtonHEdgeMarginNew, - views::kRelatedControlVerticalSpacing, views::kButtonHEdgeMarginNew); + views::kRelatedControlVerticalSpacing, horizontal_margin, + views::kRelatedControlVerticalSpacing, horizontal_margin); } views::Label* disclaimer = new views::Label(
diff --git a/chrome/installer/gcapi_mac/gcapi.mm b/chrome/installer/gcapi_mac/gcapi.mm index c95c2ab..798a539 100644 --- a/chrome/installer/gcapi_mac/gcapi.mm +++ b/chrome/installer/gcapi_mac/gcapi.mm
@@ -58,8 +58,8 @@ // 10.2. int mac_os_x_minor_version = darwin_major_version - 4; - // Chrome is known to work on 10.9 - 10.11. - return mac_os_x_minor_version >= 9 && mac_os_x_minor_version <= 11; + // Chrome is known to work on 10.9 - 10.12. + return mac_os_x_minor_version >= 9 && mac_os_x_minor_version <= 12; } // Returns the pid/gid of the logged-in user, even if getuid() claims that the
diff --git a/chrome/test/base/mash_browser_tests_main.cc b/chrome/test/base/mash_browser_tests_main.cc index 47d736f..e23e754 100644 --- a/chrome/test/base/mash_browser_tests_main.cc +++ b/chrome/test/base/mash_browser_tests_main.cc
@@ -10,7 +10,6 @@ #include "base/memory/ptr_util.h" #include "base/process/launch.h" #include "base/sys_info.h" -#include "base/threading/thread_task_runner_handle.h" #include "chrome/test/base/chrome_test_launcher.h" #include "chrome/test/base/chrome_test_suite.h" #include "chrome/test/base/mojo_test_connector.h" @@ -109,9 +108,7 @@ MashTestLauncherDelegate* delegate) { std::unique_ptr<content::MojoShellConnection> connection( content::MojoShellConnection::Create( - delegate->GetMojoTestConnectorForSingleProcess()->Init(), - base::ThreadTaskRunnerHandle::Get())); - connection->Start(); + delegate->GetMojoTestConnectorForSingleProcess()->Init())); ConnectToDefaultApps(connection->GetConnector()); return connection; }
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index dfaf07e..ba961b80 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -67,6 +67,9 @@ _VERSION_SPECIFIC_FILTER['HEAD'] = [ # https://code.google.com/p/chromedriver/issues/detail?id=992 'ChromeDownloadDirTest.testDownloadDirectoryOverridesExistingPreferences', + # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1431 + 'ChromeDriverTest.testAutoReporting', + 'ChromeDriverTest.testConsoleLogSources', ] _OS_SPECIFIC_FILTER = {}
diff --git a/chrome/utility/safe_browsing/mac/hfs.cc b/chrome/utility/safe_browsing/mac/hfs.cc index f984636..9a27223 100644 --- a/chrome/utility/safe_browsing/mac/hfs.cc +++ b/chrome/utility/safe_browsing/mac/hfs.cc
@@ -369,7 +369,10 @@ // Read the entire extent now, to avoid excessive seeking and re-reading. if (!read_current_extent_) { - hfs_->SeekToBlock(extent->startBlock); + if (!hfs_->SeekToBlock(extent->startBlock)) { + DLOG(ERROR) << "Failed to seek to block " << extent->startBlock; + return false; + } current_extent_data_.resize(extent_size.ValueOrDie()); if (!hfs_->stream()->ReadExact(¤t_extent_data_[0], extent_size.ValueOrDie())) {
diff --git a/chrome/utility/safe_browsing/mac/udif.cc b/chrome/utility/safe_browsing/mac/udif.cc index 90fde88..d3cadf8 100644 --- a/chrome/utility/safe_browsing/mac/udif.cc +++ b/chrome/utility/safe_browsing/mac/udif.cc
@@ -181,29 +181,62 @@ // endian, the data for both the block and the chunk. class UDIFBlock { public: - explicit UDIFBlock(const UDIFBlockData* block_data) : block(*block_data) { - ConvertBigEndian(&block); - for (uint32_t i = 0; i < block.chunk_count; ++i) { - chunks.push_back(block_data->chunks[i]); - ConvertBigEndian(&chunks[i]); + UDIFBlock() : block_() {} + + bool ParseBlockData(const UDIFBlockData* block_data, uint16_t sector_size) { + block_ = *block_data; + ConvertBigEndian(&block_); + + // Make sure the number of sectors doesn't overflow. + auto block_size = base::CheckedNumeric<size_t>(sector_count()) * + sector_size; + if (!block_size.IsValid()) { + DLOG(ERROR) << "UDIF block size overflows"; + return false; } + + // Make sure that the chunk data isn't larger than the block reports. + base::CheckedNumeric<size_t> chunk_sectors(0); + for (uint32_t i = 0; i < block_.chunk_count; ++i) { + chunks_.push_back(block_data->chunks[i]); + UDIFBlockChunk* chunk = &chunks_[i]; + ConvertBigEndian(chunk); + + chunk_sectors += chunk->sector_count; + if (!chunk_sectors.IsValid() || + chunk_sectors.ValueOrDie() > sector_count()) { + DLOG(ERROR) << "Total chunk sectors larger than reported block sectors"; + return false; + } + + auto chunk_end_offset = + base::CheckedNumeric<size_t>(chunk->compressed_offset) + + chunk->compressed_length; + if (!chunk_end_offset.IsValid() || + chunk->compressed_length > block_size.ValueOrDie()) { + DLOG(ERROR) << "UDIF chunk data length " << i << " overflows"; + return false; + } + } + + return true; } - uint32_t signature() const { return block.signature; } - uint32_t version() const { return block.version; } - uint64_t start_sector() const { return block.start_sector; } - uint64_t sector_count() const { return block.sector_count; } - uint64_t chunk_count() const { return chunks.size(); } + uint32_t signature() const { return block_.signature; } + uint32_t version() const { return block_.version; } + uint64_t start_sector() const { return block_.start_sector; } + uint64_t sector_count() const { return block_.sector_count; } + uint64_t chunk_count() const { return chunks_.size(); } const UDIFBlockChunk* chunk(uint32_t i) const { if (i >= chunk_count()) return nullptr; - return &chunks[i]; + return &chunks_[i]; } private: - UDIFBlockData block; - std::vector<UDIFBlockChunk> chunks; + UDIFBlockData block_; + std::vector<UDIFBlockChunk> chunks_; DISALLOW_COPY_AND_ASSIGN(UDIFBlock); }; @@ -348,7 +381,8 @@ bool UDIFParser::ParseBlkx() { UDIFResourceFile trailer; - if (stream_->Seek(-sizeof(trailer), SEEK_END) == -1) + off_t trailer_start = stream_->Seek(-sizeof(trailer), SEEK_END); + if (trailer_start == -1) return false; if (!stream_->ReadType(&trailer)) { @@ -367,6 +401,14 @@ return false; } + auto plist_end = base::CheckedNumeric<size_t>(trailer.plist_offset) + + trailer.plist_length; + if (!plist_end.IsValid() || + plist_end.ValueOrDie() > base::checked_cast<size_t>(trailer_start)) { + DLOG(ERROR) << "blkx plist extends past UDIF trailer"; + return false; + } + std::vector<uint8_t> plist_bytes(trailer.plist_length, 0); if (stream_->Seek(trailer.plist_offset, SEEK_SET) == -1) @@ -434,9 +476,13 @@ } // Copy the block table out of the plist. - auto block_data = - reinterpret_cast<const UDIFBlockData*>(CFDataGetBytePtr(data)); - std::unique_ptr<UDIFBlock> block(new UDIFBlock(block_data)); + std::unique_ptr<UDIFBlock> block(new UDIFBlock()); + if (!block->ParseBlockData( + reinterpret_cast<const UDIFBlockData*>(CFDataGetBytePtr(data)), + block_size_)) { + DLOG(ERROR) << "Failed to parse UDIF block data"; + return false; + } if (block->signature() != UDIFBlockData::kSignature) { DLOG(ERROR) << "Skipping block " << i << " because its signature does not" @@ -480,14 +526,6 @@ return true; } -bool UDIFParser::ReadBlockChunk(const UDIFBlockChunk* chunk, - std::vector<uint8_t>* decompressed_data) { - UDIFBlockChunkReadStream chunk_read_stream(stream_, block_size_, chunk); - decompressed_data->resize(chunk_read_stream.length_in_bytes()); - return chunk_read_stream.ReadExact(&(*decompressed_data)[0], - decompressed_data->size()); -} - namespace { UDIFPartitionReadStream::UDIFPartitionReadStream(
diff --git a/chrome/utility/safe_browsing/mac/udif.h b/chrome/utility/safe_browsing/mac/udif.h index 3b1a29d..023a8729 100644 --- a/chrome/utility/safe_browsing/mac/udif.h +++ b/chrome/utility/safe_browsing/mac/udif.h
@@ -76,11 +76,6 @@ // Parses the blkx plist trailer structure. bool ParseBlkx(); - // Reads the data pointed to by the block |chunk|, decompressing it as - // necessary, into the out-buffer |decompressed_data|. - bool ReadBlockChunk(const UDIFBlockChunk* chunk, - std::vector<uint8_t>* decompressed_data); - ReadStream* const stream_; // The stream backing the UDIF image. Weak. std::vector<std::string> partition_names_; // The names of all partitions. ScopedVector<const UDIFBlock> blocks_; // All blocks in the UDIF image.
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc index 1544f84..ed543fa6 100644 --- a/chromecast/renderer/cast_content_renderer_client.cc +++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -96,18 +96,9 @@ blink::WebFrameWidget* web_frame_widget = render_view->GetWebFrameWidget(); web_frame_widget->setBaseBackgroundColor(kColorBlack); - // The following settings express consistent behaviors across Cast - // embedders, though Android has enabled by default for mobile browsers. - webview->settings()->setShrinksViewportContentToFit(false); + // Settings for ATV (Android defaults are not what we want): webview->settings()->setMediaControlsOverlayPlayButtonEnabled(false); - // Scale 1 ensures window.innerHeight/Width match application resolution. - // PageScaleOverride is the 'user agent' value which overrides page - // settings (from meta viewport tag) - thus preventing inconsistency - // between Android and non-Android cast_shell. - webview->setDefaultPageScaleLimits(1.f, 1.f); - webview->setInitialPageScaleOverride(1.f); - // Disable application cache as Chromecast doesn't support off-line // application running. webview->settings()->setOfflineWebApplicationCacheEnabled(false);
diff --git a/components/arc/arc_bridge_service.cc b/components/arc/arc_bridge_service.cc index 179cde9..bc864faf 100644 --- a/components/arc/arc_bridge_service.cc +++ b/components/arc/arc_bridge_service.cc
@@ -576,11 +576,9 @@ void ArcBridgeService::SetState(State state) { DCHECK(CalledOnValidThread()); - // DCHECK on enum classes not supported. - DCHECK(state_ != state); + DCHECK_NE(state_, state); state_ = state; VLOG(2) << "State: " << static_cast<uint32_t>(state_); - FOR_EACH_OBSERVER(Observer, observer_list(), OnStateChanged(state_)); if (state_ == State::READY) FOR_EACH_OBSERVER(Observer, observer_list(), OnBridgeReady()); else if (state == State::STOPPED) @@ -589,7 +587,7 @@ void ArcBridgeService::SetAvailable(bool available) { DCHECK(CalledOnValidThread()); - DCHECK(available_ != available); + DCHECK_NE(available_, available); available_ = available; FOR_EACH_OBSERVER(Observer, observer_list(), OnAvailableChanged(available_)); }
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h index 3d719694..bcd5b09 100644 --- a/components/arc/arc_bridge_service.h +++ b/components/arc/arc_bridge_service.h
@@ -22,53 +22,17 @@ namespace arc { class ArcBridgeBootstrap; +class ArcBridgeTest; // The Chrome-side service that handles ARC instances and ARC bridge creation. // This service handles the lifetime of ARC instances and sets up the // communication channel (the ARC bridge) used to send and receive messages. class ArcBridgeService : public mojom::ArcBridgeHost { public: - // The possible states of the bridge. In the normal flow, the state changes - // in the following sequence: - // - // STOPPED - // PrerequisitesChanged() -> - // CONNECTING - // OnConnectionEstablished() -> - // READY - // - // The ArcBridgeBootstrap state machine can be thought of being substates of - // ArcBridgeService's CONNECTING state. - // - // * - // StopInstance() -> - // STOPPING - // OnStopped() -> - // STOPPED - enum class State { - // ARC is not currently running. - STOPPED, - - // The request to connect has been sent. - CONNECTING, - - // The instance has started, and the bridge is fully established. - CONNECTED, - - // The ARC instance has finished initializing and is now ready for user - // interaction. - READY, - - // The ARC instance has started shutting down. - STOPPING, - }; - // Notifies life cycle events of ArcBridgeService. class Observer { public: // Called whenever the state of the bridge has changed. - // TODO(lchavez): Rename to OnStateChangedForTest - virtual void OnStateChanged(State state) {} virtual void OnBridgeReady() {} virtual void OnBridgeStopped() {} @@ -283,15 +247,57 @@ void OnWindowManagerInstanceReady( mojom::WindowManagerInstancePtr window_manager_ptr) override; - // Gets the current state of the bridge service. - State state() const { return state_; } - // Gets if ARC is available in this system. bool available() const { return available_; } + // Gets if ARC is currently running. + bool ready() const { return state() == State::READY; } + + // Gets if ARC is currently stopped. This is not exactly !ready() since there + // are transient states between ready() and stopped(). + bool stopped() const { return state() == State::STOPPED; } + protected: + // The possible states of the bridge. In the normal flow, the state changes + // in the following sequence: + // + // STOPPED + // PrerequisitesChanged() -> + // CONNECTING + // OnConnectionEstablished() -> + // READY + // + // The ArcBridgeBootstrap state machine can be thought of being substates of + // ArcBridgeService's CONNECTING state. + // + // * + // StopInstance() -> + // STOPPING + // OnStopped() -> + // STOPPED + enum class State { + // ARC is not currently running. + STOPPED, + + // The request to connect has been sent. + CONNECTING, + + // The instance has started, and the bridge is fully established. + CONNECTED, + + // The ARC instance has finished initializing and is now ready for user + // interaction. + READY, + + // The ARC instance has started shutting down. + STOPPING, + }; + ArcBridgeService(); + // Gets the current state of the bridge service. + State state() const { return state_; } + // Changes the current state and notifies all observers. void SetState(State state);
diff --git a/components/arc/arc_bridge_service_unittest.cc b/components/arc/arc_bridge_service_unittest.cc index 598e54b..52ad15fc 100644 --- a/components/arc/arc_bridge_service_unittest.cc +++ b/components/arc/arc_bridge_service_unittest.cc
@@ -20,25 +20,23 @@ namespace { +class DummyObserver : public ArcBridgeService::Observer {}; + +} // namespace + class ArcBridgeTest : public testing::Test, public ArcBridgeService::Observer { public: ArcBridgeTest() : ready_(false) {} ~ArcBridgeTest() override {} - void OnStateChanged(ArcBridgeService::State state) override { - state_ = state; - switch (state) { - case ArcBridgeService::State::READY: - ready_ = true; - break; + void OnBridgeReady() override { + state_ = ArcBridgeService::State::READY; + ready_ = true; + } - case ArcBridgeService::State::STOPPED: - message_loop_.PostTask(FROM_HERE, message_loop_.QuitWhenIdleClosure()); - break; - - default: - break; - } + void OnBridgeStopped() override { + state_ = ArcBridgeService::State::STOPPED; + message_loop_.PostTask(FROM_HERE, message_loop_.QuitWhenIdleClosure()); } bool ready() const { return ready_; } @@ -77,10 +75,6 @@ DISALLOW_COPY_AND_ASSIGN(ArcBridgeTest); }; -class DummyObserver : public ArcBridgeService::Observer {}; - -} // namespace - // Exercises the basic functionality of the ARC Bridge Service. A message from // within the instance should cause the observer to be notified. TEST_F(ArcBridgeTest, Basic) {
diff --git a/components/arc/common/app.mojom b/components/arc/common/app.mojom index d3d3039..1110e41b 100644 --- a/components/arc/common/app.mojom +++ b/components/arc/common/app.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Next MinVersion: 12 +// Next MinVersion: 13 module arc.mojom; @@ -15,6 +15,7 @@ NONE = 0, PORTRAIT = 1, LANDSCAPE = 2, + CURRENT = 3, }; // Describes ARC app. @@ -24,7 +25,7 @@ string activity; [MinVersion=2] bool sticky; // true if the app cannot be uninstalled [MinVersion=7] bool notifications_enabled; - [MinVersion=11] OrientationLock orientation_lock; + [MinVersion=12] OrientationLock orientation_lock; }; // Describes ARC package. @@ -107,7 +108,7 @@ [MinVersion=9] OnInstallShortcut@11(ShortcutInfo shortcut); // Notifies that task requested orientation lock. - [MinVersion=11] OnTaskOrientationLockRequested@12(int32 task_id, + [MinVersion=12] OnTaskOrientationLockRequested@12(int32 task_id, OrientationLock lock); };
diff --git a/components/arc/user_data/arc_user_data_service.cc b/components/arc/user_data/arc_user_data_service.cc index f946de5..e37f8782 100644 --- a/components/arc/user_data/arc_user_data_service.cc +++ b/components/arc/user_data/arc_user_data_service.cc
@@ -47,7 +47,7 @@ void ArcUserDataService::ClearIfDisabled() { DCHECK(thread_checker_.CalledOnValidThread()); - if (arc_bridge_service()->state() != ArcBridgeService::State::STOPPED) { + if (!arc_bridge_service()->stopped()) { LOG(ERROR) << "ARC instance not stopped, user data can't be cleared"; return; }
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index c90af58..5ead8eb 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -21,7 +21,7 @@ Automatic credit card filling is disabled because this form does not use a secure connection. </message> <message name="IDS_AUTOFILL_CREDIT_CARD_SIGNIN_PROMO" desc="Promo text shown alongside credit card suggestions to get people to sign in."> - Sign in to Chrome to use cards you saved to your Google Account. + To use cards you saved to your Google Account, sign in to Chrome. </message> <if expr="_google_chrome"> <message name="IDS_AUTOFILL_DELETE_AUTOCOMPLETE_SUGGESTION_CONFIRMATION_BODY" desc="Text in a dialog to confirm that the user wants to delete an autocomplete form history suggestion.">
diff --git a/components/devtools_discovery/devtools_discovery_manager.cc b/components/devtools_discovery/devtools_discovery_manager.cc index 3233085a..7953b6c 100644 --- a/components/devtools_discovery/devtools_discovery_manager.cc +++ b/components/devtools_discovery/devtools_discovery_manager.cc
@@ -67,15 +67,15 @@ base::DictionaryValue* command_dict) { int id; std::string method; - std::string initial_url; + std::string url; const base::DictionaryValue* params_dict = nullptr; if (command_dict->GetInteger("id", &id) && command_dict->GetString("method", &method) && - method == "Browser.newPage" && + method == "Browser.createTarget" && command_dict->GetDictionary("params", ¶ms_dict) && - params_dict->GetString("initialUrl", &initial_url)) { + params_dict->GetString("url", &url)) { std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor> descriptor = - CreateNew(GURL(initial_url)); + CreateNew(GURL(url)); if (!descriptor) return nullptr; std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
diff --git a/components/precache/content/precache_manager.cc b/components/precache/content/precache_manager.cc index 9a81fbb..2f896f3e 100644 --- a/components/precache/content/precache_manager.cc +++ b/components/precache/content/precache_manager.cc
@@ -197,12 +197,12 @@ if (precache_fetcher_) { std::unique_ptr<PrecacheUnfinishedWork> unfinished_work = precache_fetcher_->CancelPrecaching(); - BrowserThread::PostTask( - BrowserThread::DB, - FROM_HERE, - base::Bind(&PrecacheDatabase::SaveUnfinishedWork, - precache_database_->GetWeakPtr(), - base::Passed(&unfinished_work))); + if (unfinished_work) { + BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, + base::Bind(&PrecacheDatabase::SaveUnfinishedWork, + precache_database_->GetWeakPtr(), + base::Passed(&unfinished_work))); + } // Destroying the |precache_fetcher_| will cancel any fetch in progress. precache_fetcher_.reset(); }
diff --git a/components/precache/core/precache_fetcher.cc b/components/precache/core/precache_fetcher.cc index dc0d3a2..a5cf650 100644 --- a/components/precache/core/precache_fetcher.cc +++ b/components/precache/core/precache_fetcher.cc
@@ -359,6 +359,10 @@ } std::unique_ptr<PrecacheUnfinishedWork> PrecacheFetcher::CancelPrecaching() { + // This could get called multiple times, and it should be handled gracefully. + if (!unfinished_work_) + return nullptr; + unfinished_work_->clear_manifest(); unfinished_work_->clear_resource(); for (const auto& manifest : manifest_urls_to_fetch_)
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc index 729df89..3a8d0a4b 100644 --- a/content/browser/browser_context.cc +++ b/content/browser/browser_context.cc
@@ -152,9 +152,7 @@ std::unique_ptr<shell::Connection> connection, shell::mojom::ServiceRequest request) : root_connection_(std::move(connection)), - shell_connection_(MojoShellConnection::Create( - std::move(request), - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))) {} + shell_connection_(MojoShellConnection::Create(std::move(request))) {} ~BrowserContextShellConnectionHolder() override {} MojoShellConnection* shell_connection() { return shell_connection_.get(); } @@ -435,7 +433,6 @@ browser_context->SetUserData(kMojoShellConnection, connection_holder); MojoShellConnection* connection = connection_holder->shell_connection(); - connection->Start(); // New embedded service factories should be added to |connection| here.
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 910422da..80c84a73 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -278,8 +278,8 @@ void WaitForMojoShellInitialize() { // TODO(rockot): Remove this. http://crbug.com/594852. base::RunLoop wait_loop; - MojoShellConnection::GetForProcess()->SetInitializeHandler( - wait_loop.QuitClosure()); + MojoShellConnection::GetForProcess()->GetShellConnection()-> + set_initialize_handler(wait_loop.QuitClosure()); wait_loop.Run(); } #endif // defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
diff --git a/content/browser/devtools/protocol/browser_handler.cc b/content/browser/devtools/protocol/browser_handler.cc index 83fd95f..be31b84c 100644 --- a/content/browser/devtools/protocol/browser_handler.cc +++ b/content/browser/devtools/protocol/browser_handler.cc
@@ -56,7 +56,7 @@ return Response::ServerError("Not supported"); } -Response BrowserHandler::CreateTarget(const std::string& initial_url, +Response BrowserHandler::CreateTarget(const std::string& url, const int* width, const int* height, const std::string* context_id,
diff --git a/content/browser/devtools/protocol/browser_handler.h b/content/browser/devtools/protocol/browser_handler.h index 3cf34de7..ee14bfd 100644 --- a/content/browser/devtools/protocol/browser_handler.h +++ b/content/browser/devtools/protocol/browser_handler.h
@@ -37,7 +37,7 @@ Response CreateBrowserContext(std::string* out_context_id); Response DisposeBrowserContext(const std::string& context_id, bool* out_success); - Response CreateTarget(const std::string& initial_url, + Response CreateTarget(const std::string& url, const int* width, const int* height, const std::string* context_id,
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index e6e8357..858070b 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -587,13 +587,13 @@ dialog_manager.Handle(); } -IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserNewPage) { +IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateTarget) { NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1); Attach(); EXPECT_EQ(1u, shell()->windows().size()); std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue()); - params->SetString("initialUrl", "about:blank"); - SendCommand("Browser.newPage", std::move(params), true); + params->SetString("url", "about:blank"); + SendCommand("Browser.createTarget", std::move(params), true); EXPECT_EQ(2u, shell()->windows().size()); }
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index bc4ba82c..f776f54 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -4685,6 +4685,94 @@ EXPECT_EQ(0U, root->child_count()); } +// Ensure that we do not corrupt a NavigationEntry's PageState if two forward +// navigations compete in different frames, and the main frame entry contains an +// iframe of its own. See https://crbug.com/623319. +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, + PageStateWithIframeAfterForwardInCompetingFrames) { + // Navigate to a page with an iframe. + GURL url_a(embedded_test_server()->GetURL( + "/navigation_controller/page_with_data_iframe.html")); + GURL data_url("data:text/html,Subframe"); + EXPECT_TRUE(NavigateToURL(shell(), url_a)); + + NavigationController& controller = shell()->web_contents()->GetController(); + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + EXPECT_EQ(url_a, root->current_url()); + EXPECT_EQ(data_url, root->child_at(0)->current_url()); + + // Navigate the iframe to a first real page. + GURL frame_url_a1 = embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html"); + NavigateFrameToURL(root->child_at(0), frame_url_a1); + + // Navigate the iframe to a second real page. + GURL frame_url_a2 = embedded_test_server()->GetURL( + "/navigation_controller/simple_page_2.html"); + NavigateFrameToURL(root->child_at(0), frame_url_a2); + EXPECT_EQ(3, controller.GetEntryCount()); + EXPECT_EQ(2, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(url_a, root->current_url()); + EXPECT_EQ(frame_url_a2, root->child_at(0)->current_url()); + + // Go back to the middle entry. + controller.GoBack(); + EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); + EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); + + // Replace the entry with a cross-site top-level page with an iframe. By + // doing a replacement, the main frame pages before and after have the same + // item sequence number, and thus going between them only requires loads in + // the subframe. + GURL url_b(embedded_test_server()->GetURL( + "b.com", "/navigation_controller/page_with_data_iframe.html")); + std::string replace_script = "location.replace('" + url_b.spec() + "')"; + TestNavigationObserver replace_observer(shell()->web_contents()); + EXPECT_TRUE(ExecuteScript(shell()->web_contents(), replace_script)); + replace_observer.Wait(); + EXPECT_EQ(3, controller.GetEntryCount()); + EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(url_b, root->current_url()); + EXPECT_EQ(data_url, root->child_at(0)->current_url()); + + // Go back to the original page. + controller.GoBack(); + EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); + + // Navigate forward twice using script. This will race, but in either outcome + // we want to ensure that the subframes target entry index 1 and not 2. In + // https://crbug.com/623319, the subframes targeted the wrong entry, leading + // to a URL spoof and renderer kill. + EXPECT_TRUE(ExecuteScript(shell()->web_contents(), + "history.forward(); history.forward();")); + EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); + EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); + EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive()); + EXPECT_EQ(url_b, root->current_url()); + EXPECT_EQ(data_url, root->child_at(0)->current_url()); + NavigationEntry* entry = controller.GetLastCommittedEntry(); + EXPECT_EQ(url_b, entry->GetURL()); + ExplodedPageState exploded_state; + EXPECT_TRUE( + DecodePageState(entry->GetPageState().ToEncodedData(), &exploded_state)); + EXPECT_EQ(url_b, GURL(exploded_state.top.url_string.string())); + + // Go back and then forward to see if the PageState loads correctly. + controller.GoBack(); + EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); + controller.GoForward(); + EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); + + // We should be on url_b, and the renderer process shouldn't be killed. + ASSERT_TRUE(root->current_frame_host()->IsRenderFrameLive()); + EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(url_b, shell()->web_contents()->GetVisibleURL()); + EXPECT_EQ(url_b, root->current_url()); + EXPECT_EQ(data_url, root->child_at(0)->current_url()); +} + // Ensure that forward navigations in cloned tabs can commit if they redirect to // a different site than before. This causes the navigation's item sequence // number to change, meaning that we can't use it for determining whether the
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc index 9be164e..67dfe7d 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.cc +++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -233,12 +233,6 @@ NOTREACHED(); } -void RenderWidgetHostViewChildFrame::ImeCompositionRangeChanged( - const gfx::Range& range, - const std::vector<gfx::Rect>& character_bounds) { - // TODO(kenrb): Fix OOPIF Ime. -} - void RenderWidgetHostViewChildFrame::UpdateCursor(const WebCursor& cursor) { if (frame_connector_) frame_connector_->UpdateCursor(cursor);
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h index eef16d0..dc9bd12 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.h +++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -96,9 +96,6 @@ void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override; void UpdateCursor(const WebCursor& cursor) override; void SetIsLoading(bool is_loading) override; - void ImeCompositionRangeChanged( - const gfx::Range& range, - const std::vector<gfx::Rect>& character_bounds) override; void RenderProcessGone(base::TerminationStatus status, int error_code) override; void Destroy() override;
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index ff47de9..8c3a201 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -565,9 +565,10 @@ DCHECK(!mojo_child_connection_); mojo_child_connection_.reset(new MojoChildConnection( - kGpuMojoApplicationName, "", child_token_, - MojoShellContext::GetConnectorForIOThread(), - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))); + kGpuMojoApplicationName, + "", + child_token_, + MojoShellContext::GetConnectorForIOThread())); gpu::GpuPreferences gpu_preferences = GetGpuPreferencesFromCommandLine(); if (in_process_) { @@ -938,11 +939,11 @@ } shell::InterfaceRegistry* GpuProcessHost::GetInterfaceRegistry() { - return mojo_child_connection_->GetInterfaceRegistry(); + return mojo_child_connection_->connection()->GetInterfaceRegistry(); } shell::InterfaceProvider* GpuProcessHost::GetRemoteInterfaces() { - return mojo_child_connection_->GetRemoteInterfaces(); + return mojo_child_connection_->connection()->GetRemoteInterfaces(); } GpuProcessHost::GpuProcessKind GpuProcessHost::kind() {
diff --git a/content/browser/mojo/mojo_child_connection.cc b/content/browser/mojo/mojo_child_connection.cc index 1fe0c2e..cb7ea985 100644 --- a/content/browser/mojo/mojo_child_connection.cc +++ b/content/browser/mojo/mojo_child_connection.cc
@@ -7,7 +7,6 @@ #include <stdint.h> #include <utility> -#include "base/macros.h" #include "content/public/common/mojo_shell_connection.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/public/cpp/system/message_pipe.h" @@ -17,163 +16,43 @@ namespace content { -namespace { - -void CallBinderOnTaskRunner( - const shell::InterfaceRegistry::Binder& binder, - scoped_refptr<base::SequencedTaskRunner> task_runner, - const mojo::String& interface_name, - mojo::ScopedMessagePipeHandle request_handle) { - task_runner->PostTask( - FROM_HERE, - base::Bind(binder, interface_name, base::Passed(&request_handle))); -} - -} // namespace - -class MojoChildConnection::IOThreadContext - : public base::RefCountedThreadSafe<IOThreadContext> { - public: - IOThreadContext() {} - - void Initialize(const std::string& application_name, - const std::string& instance_id, - shell::Connector* connector, - mojo::ScopedMessagePipeHandle service_pipe, - scoped_refptr<base::SequencedTaskRunner> io_task_runner, - const shell::InterfaceRegistry::Binder& default_binder) { - DCHECK(!io_task_runner_); - io_task_runner_ = io_task_runner; - std::unique_ptr<shell::Connector> io_thread_connector; - if (connector) - io_thread_connector = connector->Clone(); - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&IOThreadContext::InitializeOnIOThread, this, - application_name, instance_id, - base::Passed(&io_thread_connector), - base::Passed(&service_pipe), - base::Bind(&CallBinderOnTaskRunner, default_binder, - base::ThreadTaskRunnerHandle::Get()))); - } - - void ShutDown() { - if (!io_task_runner_) - return; - bool posted = io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&IOThreadContext::ShutDownOnIOThread, this)); - DCHECK(posted); - } - - void GetRemoteInterfaceOnIOThread( - const mojo::String& interface_name, - mojo::ScopedMessagePipeHandle request_handle) { - if (connection_) { - connection_->GetRemoteInterfaces()->GetInterface( - interface_name, std::move(request_handle)); - } - } - - void SetProcessHandle(base::ProcessHandle handle) { - DCHECK(io_task_runner_); - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&IOThreadContext::SetProcessHandleOnIOThread, this, handle)); - } - - private: - friend class base::RefCountedThreadSafe<IOThreadContext>; - - virtual ~IOThreadContext() {} - - void InitializeOnIOThread( - const std::string& application_name, - const std::string& instance_id, - std::unique_ptr<shell::Connector> connector, - mojo::ScopedMessagePipeHandle service_pipe, - const shell::InterfaceRegistry::Binder& default_binder) { - shell::mojom::ServicePtr service; - service.Bind(mojo::InterfacePtrInfo<shell::mojom::Service>( - std::move(service_pipe), 0u)); - shell::mojom::PIDReceiverRequest pid_receiver_request = - mojo::GetProxy(&pid_receiver_); - - shell::Identity target(application_name, shell::mojom::kInheritUserID, - instance_id); - shell::Connector::ConnectParams params(target); - params.set_client_process_connection(std::move(service), - std::move(pid_receiver_request)); - - // In some unit testing scenarios a null connector is passed. - if (!connector) - return; - - connection_ = connector->Connect(¶ms); - connection_->GetInterfaceRegistry()->set_default_binder(default_binder); - } - - void ShutDownOnIOThread() { - connection_.reset(); - pid_receiver_.reset(); - } - - void SetProcessHandleOnIOThread(base::ProcessHandle handle) { - DCHECK(pid_receiver_.is_bound()); - pid_receiver_->SetPID(base::GetProcId(handle)); - pid_receiver_.reset(); - } - - scoped_refptr<base::SequencedTaskRunner> io_task_runner_; - std::unique_ptr<shell::Connection> connection_; - shell::mojom::PIDReceiverPtr pid_receiver_; - - DISALLOW_COPY_AND_ASSIGN(IOThreadContext); -}; - -MojoChildConnection::MojoChildConnection( - const std::string& application_name, - const std::string& instance_id, - const std::string& child_token, - shell::Connector* connector, - scoped_refptr<base::SequencedTaskRunner> io_task_runner) - : context_(new IOThreadContext), - service_token_(mojo::edk::GenerateRandomToken()), - interface_registry_(nullptr), - weak_factory_(this) { +MojoChildConnection::MojoChildConnection(const std::string& application_name, + const std::string& instance_id, + const std::string& child_token, + shell::Connector* connector) + : service_token_(mojo::edk::GenerateRandomToken()) { mojo::ScopedMessagePipeHandle service_pipe = mojo::edk::CreateParentMessagePipe(service_token_, child_token); - context_ = new IOThreadContext; - context_->Initialize( - application_name, instance_id, connector, std::move(service_pipe), - io_task_runner, - base::Bind(&MojoChildConnection::GetInterface, - weak_factory_.GetWeakPtr())); - remote_interfaces_.Forward( - base::Bind(&CallBinderOnTaskRunner, - base::Bind(&IOThreadContext::GetRemoteInterfaceOnIOThread, - context_), io_task_runner)); + shell::mojom::ServicePtr service; + service.Bind(mojo::InterfacePtrInfo<shell::mojom::Service>( + std::move(service_pipe), 0u)); + shell::mojom::PIDReceiverRequest pid_receiver_request = + GetProxy(&pid_receiver_); + shell::Identity target(application_name, shell::mojom::kInheritUserID, + instance_id); + shell::Connector::ConnectParams params(target); + params.set_client_process_connection(std::move(service), + std::move(pid_receiver_request)); + + // In some unit testing scenarios a null connector is passed. + if (!connector) + return; + + connection_ = connector->Connect(¶ms); #if defined(OS_ANDROID) - service_registry_android_ = - ServiceRegistryAndroid::Create(&interface_registry_, &remote_interfaces_); + service_registry_android_ = ServiceRegistryAndroid::Create( + connection_->GetInterfaceRegistry(), connection_->GetRemoteInterfaces()); #endif } -MojoChildConnection::~MojoChildConnection() { - context_->ShutDown(); -} +MojoChildConnection::~MojoChildConnection() {} void MojoChildConnection::SetProcessHandle(base::ProcessHandle handle) { - context_->SetProcessHandle(handle); -} - -void MojoChildConnection::GetInterface( - const mojo::String& interface_name, - mojo::ScopedMessagePipeHandle request_handle) { - static_cast<shell::mojom::InterfaceProvider*>(&interface_registry_) - ->GetInterface(interface_name, std::move(request_handle)); + DCHECK(pid_receiver_.is_bound()); + pid_receiver_->SetPID(base::GetProcId(handle)); + pid_receiver_.reset(); } } // namespace content
diff --git a/content/browser/mojo/mojo_child_connection.h b/content/browser/mojo/mojo_child_connection.h index c51f67e4..9ed83da 100644 --- a/content/browser/mojo/mojo_child_connection.h +++ b/content/browser/mojo/mojo_child_connection.h
@@ -9,12 +9,7 @@ #include <string> #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" #include "base/process/process_handle.h" -#include "base/sequenced_task_runner.h" -#include "services/shell/public/cpp/interface_provider.h" -#include "services/shell/public/cpp/interface_registry.h" #include "services/shell/public/interfaces/connector.mojom.h" #if defined(OS_ANDROID) @@ -40,16 +35,11 @@ MojoChildConnection(const std::string& application_name, const std::string& instance_id, const std::string& child_token, - shell::Connector* connector, - scoped_refptr<base::SequencedTaskRunner> io_task_runner); + shell::Connector* connector); ~MojoChildConnection(); - shell::InterfaceRegistry* GetInterfaceRegistry() { - return &interface_registry_; - } - - shell::InterfaceProvider* GetRemoteInterfaces() { - return &remote_interfaces_; + shell::Connection* connection() const { + return connection_.get(); } // A token which must be passed to the child process via @@ -69,24 +59,13 @@ #endif private: - class IOThreadContext; - - void GetInterface(const mojo::String& interface_name, - mojo::ScopedMessagePipeHandle request_handle); - - scoped_refptr<IOThreadContext> context_; - const std::string service_token_; - - shell::InterfaceRegistry interface_registry_; - shell::InterfaceProvider remote_interfaces_; - + std::unique_ptr<shell::Connection> connection_; + shell::mojom::PIDReceiverPtr pid_receiver_; #if defined(OS_ANDROID) std::unique_ptr<ServiceRegistryAndroid> service_registry_android_; #endif - base::WeakPtrFactory<MojoChildConnection> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(MojoChildConnection); };
diff --git a/content/browser/mojo/mojo_shell_context.cc b/content/browser/mojo/mojo_shell_context.cc index 37b9e70..24e21ca 100644 --- a/content/browser/mojo/mojo_shell_context.cc +++ b/content/browser/mojo/mojo_shell_context.cc
@@ -49,10 +49,20 @@ namespace { -base::LazyInstance<std::unique_ptr<shell::Connector>>::Leaky - g_io_thread_connector = LAZY_INSTANCE_INITIALIZER; +using ConnectorPtr = base::ThreadLocalPointer<shell::Connector>; -void DestroyConnectorOnIOThread() { g_io_thread_connector.Get().reset(); } +base::LazyInstance<ConnectorPtr>::Leaky io_connector_tls_ptr = + LAZY_INSTANCE_INITIALIZER; + +void SetConnectorOnIOThread(std::unique_ptr<shell::Connector> connector) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + io_connector_tls_ptr.Pointer()->Set(connector.release()); +} + +void DestroyConnectorOnIOThread() { + delete MojoShellContext::GetConnectorForIOThread(); + io_connector_tls_ptr.Pointer()->Set(nullptr); +} void StartUtilityProcessOnIOThread( mojo::InterfaceRequest<mojom::ProcessControl> request, @@ -262,9 +272,14 @@ request = service_manager_->StartEmbedderService(kBrowserMojoApplicationName); } - MojoShellConnection::SetForProcess(MojoShellConnection::Create( - std::move(request), - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))); + MojoShellConnection::SetForProcess( + MojoShellConnection::Create(std::move(request))); + + std::unique_ptr<shell::Connector> io_connector = + MojoShellConnection::GetForProcess()->GetConnector()->Clone(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&SetConnectorOnIOThread, base::Passed(&io_connector))); ContentBrowserClient::StaticMojoApplicationMap apps; GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps); @@ -273,13 +288,6 @@ entry.second); } - // This is safe to assign directly from any thread, because MojoShellContext - // must be constructed before anyone can call GetConnectorForIOThread(). - g_io_thread_connector.Get() = - MojoShellConnection::GetForProcess()->GetConnector()->Clone(); - - MojoShellConnection::GetForProcess()->Start(); - ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps; GetContentClient() ->browser() @@ -332,7 +340,7 @@ // static shell::Connector* MojoShellContext::GetConnectorForIOThread() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - return g_io_thread_connector.Get().get(); + return io_connector_tls_ptr.Pointer()->Get(); } void MojoShellContext::ConnectToApplicationOnOwnThread(
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index c4b72a3..de830f4 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -169,8 +169,6 @@ #include "mojo/edk/embedder/embedder.h" #include "net/url_request/url_request_context_getter.h" #include "ppapi/shared_impl/ppapi_switches.h" -#include "services/shell/public/cpp/interface_provider.h" -#include "services/shell/public/cpp/interface_registry.h" #include "services/shell/runner/common/switches.h" #include "storage/browser/fileapi/sandbox_file_system_backend.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -602,8 +600,6 @@ #endif // defined(OS_MACOSX) #endif // USE_ATTACHMENT_BROKER - scoped_refptr<base::SequencedTaskRunner> io_task_runner = - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO); shell::Connector* connector = BrowserContext::GetShellConnectorFor(browser_context_); // Some embedders may not initialize Mojo or the shell connector for a browser @@ -616,14 +612,15 @@ if (!MojoShellConnection::GetForProcess()) { shell::mojom::ServiceRequest request = mojo::GetProxy(&test_service_); MojoShellConnection::SetForProcess(MojoShellConnection::Create( - std::move(request), io_task_runner)); + std::move(request))); } connector = MojoShellConnection::GetForProcess()->GetConnector(); } mojo_child_connection_.reset(new MojoChildConnection( kRendererMojoApplicationName, - base::StringPrintf("%d_%d", id_, instance_id_++), child_token_, connector, - io_task_runner)); + base::StringPrintf("%d_%d", id_, instance_id_++), + child_token_, + connector)); } // static @@ -763,7 +760,8 @@ in_process_renderer_.reset( g_renderer_main_thread_factory(InProcessChildThreadParams( channel_id, - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO) + ->task_runner(), mojo_channel_token_, mojo_child_connection_->service_token()))); @@ -1123,11 +1121,16 @@ } shell::InterfaceRegistry* RenderProcessHostImpl::GetInterfaceRegistry() { - return mojo_child_connection_->GetInterfaceRegistry(); + return GetChildConnection()->GetInterfaceRegistry(); } shell::InterfaceProvider* RenderProcessHostImpl::GetRemoteInterfaces() { - return mojo_child_connection_->GetRemoteInterfaces(); + return GetChildConnection()->GetRemoteInterfaces(); +} + +shell::Connection* RenderProcessHostImpl::GetChildConnection() { + DCHECK(mojo_child_connection_); + return mojo_child_connection_->connection(); } std::unique_ptr<base::SharedPersistentMemoryAllocator> @@ -2431,8 +2434,9 @@ connector = MojoShellConnection::GetForProcess()->GetConnector(); mojo_child_connection_.reset(new MojoChildConnection( kRendererMojoApplicationName, - base::StringPrintf("%d_%d", id_, instance_id_++), child_token_, connector, - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))); + base::StringPrintf("%d_%d", id_, instance_id_++), + child_token_, + connector)); within_process_died_observer_ = true; NotificationService::current()->Notify(
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 5a07a6c..3c754893 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -157,6 +157,7 @@ void NotifyTimezoneChange(const std::string& timezone) override; shell::InterfaceRegistry* GetInterfaceRegistry() override; shell::InterfaceProvider* GetRemoteInterfaces() override; + shell::Connection* GetChildConnection() override; std::unique_ptr<base::SharedPersistentMemoryAllocator> TakeMetricsAllocator() override; const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 7940896..94f1d0d 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -976,12 +976,6 @@ UpdateCursorIfOverSelf(); } -void RenderWidgetHostViewAura::ImeCompositionRangeChanged( - const gfx::Range& range, - const std::vector<gfx::Rect>& character_bounds) { - composition_character_bounds_ = character_bounds; -} - void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status, int error_code) { UpdateCursorIfOverSelf(); @@ -1533,9 +1527,15 @@ uint32_t index, gfx::Rect* rect) const { DCHECK(rect); - if (index >= composition_character_bounds_.size()) + + if (!text_input_manager_ || !text_input_manager_->GetActiveWidget()) return false; - *rect = ConvertRectToScreen(composition_character_bounds_[index]); + + const std::vector<gfx::Rect>* composition_character_bounds = + text_input_manager_->GetCompositionCharacterBounds(); + if (index >= composition_character_bounds->size()) + return false; + *rect = ConvertRectToScreen(composition_character_bounds->at(index)); return true; }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index b71e90c..6c06169 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -142,9 +142,6 @@ void Focus() override; void UpdateCursor(const WebCursor& cursor) override; void SetIsLoading(bool is_loading) override; - void ImeCompositionRangeChanged( - const gfx::Range& range, - const std::vector<gfx::Rect>& character_bounds) override; void RenderProcessGone(base::TerminationStatus status, int error_code) override; void Destroy() override; @@ -586,8 +583,6 @@ // object. ui::MotionEventAura pointer_state_; - // The current composition character bounds. - std::vector<gfx::Rect> composition_character_bounds_; // Indicates if there is onging composition text. bool has_composition_text_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 30defc8..47c1db5 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -4300,4 +4300,26 @@ } } +// This test activates child frames in a specific sequence and changes their +// composition range. Then it verifies that the ui::TextInputClient returns the +// correct character bound at the given indices. +TEST_F(InputMethodStateAuraTest, GetCompositionCharacterBounds) { + gfx::Rect bound; + // Initially, there should be no bounds. + EXPECT_FALSE(text_input_client()->GetCompositionCharacterBounds(0, &bound)); + for (auto index : active_view_sequence_) { + ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT); + // Simulate an IPC to set character bounds for the view. + views_[index]->ImeCompositionRangeChanged(gfx::Range(), + {gfx::Rect(1, 2, 3, 4 + index)}); + + // No bounds at index 1. + EXPECT_FALSE(text_input_client()->GetCompositionCharacterBounds(1, &bound)); + + // Valid bound at index 0. + EXPECT_TRUE(text_input_client()->GetCompositionCharacterBounds(0, &bound)); + EXPECT_EQ(4 + (int)index, bound.height()); + } +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index 41724ea..ab346c0 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -424,6 +424,18 @@ #endif } +void RenderWidgetHostViewBase::ImeCompositionRangeChanged( + const gfx::Range& range, + const std::vector<gfx::Rect>& character_bounds) { +// TODO(ekaramad): Use TextInputManager code paths for IME on other platforms. +#if defined(USE_AURA) + if (GetTextInputManager()) { + GetTextInputManager()->ImeCompositionRangeChanged(this, range, + character_bounds); + } +#endif +} + TextInputManager* RenderWidgetHostViewBase::GetTextInputManager() { if (text_input_manager_) return text_input_manager_;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index 756a7d8..185d11a6 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -272,6 +272,11 @@ virtual void SelectionBoundsChanged( const ViewHostMsg_SelectionBounds_Params& params); + // Updates the range of the marked text in an IME composition. + virtual void ImeCompositionRangeChanged( + const gfx::Range& range, + const std::vector<gfx::Rect>& character_bounds); + //---------------------------------------------------------------------------- // The following static methods are implemented by each platform. @@ -382,11 +387,6 @@ virtual void LockCompositingSurface() = 0; virtual void UnlockCompositingSurface() = 0; - // Updates the range of the marked text in an IME composition. - virtual void ImeCompositionRangeChanged( - const gfx::Range& range, - const std::vector<gfx::Rect>& character_bounds) = 0; - // Add and remove observers for lifetime event notifications. The order in // which notifications are sent to observers is undefined. Clients must be // sure to remove the observer before they go away.
diff --git a/content/browser/renderer_host/render_widget_host_view_mus.cc b/content/browser/renderer_host/render_widget_host_view_mus.cc index 1befbca3..3932681 100644 --- a/content/browser/renderer_host/render_widget_host_view_mus.cc +++ b/content/browser/renderer_host/render_widget_host_view_mus.cc
@@ -43,7 +43,7 @@ // Connect to the renderer, pass it a WindowTreeClient interface request // and embed that client inside our mus window. mojom::RenderWidgetWindowTreeClientFactoryPtr factory; - host_->GetProcess()->GetRemoteInterfaces()->GetInterface(&factory); + host_->GetProcess()->GetChildConnection()->GetInterface(&factory); ui::mojom::WindowTreeClientPtr window_tree_client; factory->CreateWindowTreeClientForRenderWidget(
diff --git a/content/browser/renderer_host/text_input_manager.cc b/content/browser/renderer_host/text_input_manager.cc index 3029d93..eed2012 100644 --- a/content/browser/renderer_host/text_input_manager.cc +++ b/content/browser/renderer_host/text_input_manager.cc
@@ -7,6 +7,7 @@ #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/common/view_messages.h" +#include "ui/gfx/geometry/rect.h" namespace content { @@ -45,16 +46,16 @@ Unregister(view); } -const TextInputState* TextInputManager::GetTextInputState() { - return !!active_view_ ? &text_input_state_map_[active_view_] : nullptr; -} - RenderWidgetHostImpl* TextInputManager::GetActiveWidget() const { return !!active_view_ ? static_cast<RenderWidgetHostImpl*>( active_view_->GetRenderWidgetHost()) : nullptr; } +const TextInputState* TextInputManager::GetTextInputState() { + return !!active_view_ ? &text_input_state_map_[active_view_] : nullptr; +} + gfx::Rect TextInputManager::GetSelectionBoundsRect() { if (!active_view_) return gfx::Rect(); @@ -64,6 +65,13 @@ selection_region_map_[active_view_].focus); } +const std::vector<gfx::Rect>* +TextInputManager::GetCompositionCharacterBounds() { + return !!active_view_ + ? &composition_range_info_map_[active_view_].character_bounds + : nullptr; +} + void TextInputManager::UpdateTextInputState( RenderWidgetHostViewBase* view, const TextInputState& text_input_state) { @@ -148,6 +156,24 @@ #endif } +void TextInputManager::ImeCompositionRangeChanged( + RenderWidgetHostViewBase* view, + const gfx::Range& range, + const std::vector<gfx::Rect>& character_bounds) { + DCHECK(IsRegistered(view)); + composition_range_info_map_[view].character_bounds.clear(); + + // The values for the bounds should be converted to root view's coordinates + // before being stored. + for (auto rect : character_bounds) { + composition_range_info_map_[view].character_bounds.emplace_back(gfx::Rect( + view->TransformPointToRootCoordSpace(rect.origin()), rect.size())); + } + + FOR_EACH_OBSERVER(Observer, observer_list_, + OnImeCompositionRangeChanged(this, view)); +} + void TextInputManager::Register(RenderWidgetHostViewBase* view) { DCHECK(!IsRegistered(view)); @@ -200,4 +226,11 @@ TextInputManager::SelectionRegion::SelectionRegion( const SelectionRegion& other) = default; +TextInputManager::CompositionRangeInfo::CompositionRangeInfo() {} + +TextInputManager::CompositionRangeInfo::CompositionRangeInfo( + const CompositionRangeInfo& other) = default; + +TextInputManager::CompositionRangeInfo::~CompositionRangeInfo() {} + } // namespace content \ No newline at end of file
diff --git a/content/browser/renderer_host/text_input_manager.h b/content/browser/renderer_host/text_input_manager.h index f240a1b..bef6e81 100644 --- a/content/browser/renderer_host/text_input_manager.h +++ b/content/browser/renderer_host/text_input_manager.h
@@ -16,7 +16,12 @@ struct ViewHostMsg_SelectionBounds_Params; +namespace gfx { +class Range; +} + namespace content { + class RenderWidgetHostImpl; class RenderWidgetHostView; class RenderWidgetHostViewBase; @@ -45,31 +50,40 @@ virtual void OnImeCancelComposition( TextInputManager* text_input_manager, RenderWidgetHostViewBase* updated_view) {} - // Called when the selection bounds for the |updated_view| has changed. + // Called when |updated_view| has changed its SelectionRegion. virtual void OnSelectionBoundsChanged( TextInputManager* text_input_manager, RenderWidgetHostViewBase* updated_view) {} + // Called when |updated_view| has changed its CompositionRangeInfo. + virtual void OnImeCompositionRangeChanged( + TextInputManager* text_input_manager, + RenderWidgetHostViewBase* updated_view) {} }; TextInputManager(); ~TextInputManager(); - // --------------------------------------------------------------------------- - // The following methods can be used to obtain information about IME-related - // state for the active RenderWidget. - // Returns the currently active widget, i.e., the RWH which is associated with // |active_view_|. RenderWidgetHostImpl* GetActiveWidget() const; - // Returns the TextInputState corresponding to |active_view_|. - // Users of this method should not hold on to the pointer as it might become - // dangling if the TextInputManager or |active_view_| might go away. + // --------------------------------------------------------------------------- + // The following methods can be used to obtain information about IME-related + // state for the active RenderWidgetHost. If the active widget is nullptr, the + // methods below will return nullptr as well. + // Users of these methods should not hold on to the pointers as they become + // dangling if the TextInputManager or |active_view_| are destroyed. + + // Returns the currently stored TextInputState. An state of nullptr can be + // interpreted as a ui::TextInputType of ui::TEXT_INPUT_TYPE_NONE. const TextInputState* GetTextInputState(); - // Returns the rect between selection bounds for the |active_view_|. + // Returns the rect between selection bounds. gfx::Rect GetSelectionBoundsRect(); + // Returns a vector of rects representing the character bounds. + const std::vector<gfx::Rect>* GetCompositionCharacterBounds(); + // --------------------------------------------------------------------------- // The following methods are called by RWHVs on the tab to update their IME- // related state. @@ -88,6 +102,12 @@ void SelectionBoundsChanged(RenderWidgetHostViewBase* view, const ViewHostMsg_SelectionBounds_Params& params); + // Called when the composition range and/or character bounds have changed. + void ImeCompositionRangeChanged( + RenderWidgetHostViewBase* view, + const gfx::Range& range, + const std::vector<gfx::Rect>& character_bounds); + // Registers the given |view| for tracking its TextInputState. This is called // by any view which has updates in its TextInputState (whether tab's RWHV or // that of a child frame). The |view| must unregister itself before being @@ -128,6 +148,15 @@ gfx::SelectionBound focus; }; + // Ccomposition range information. + struct CompositionRangeInfo { + CompositionRangeInfo(); + CompositionRangeInfo(const CompositionRangeInfo& other); + ~CompositionRangeInfo(); + + std::vector<gfx::Rect> character_bounds; + }; + // This class is used to create maps which hold specific IME state for a // view. template <class Value> @@ -146,6 +175,7 @@ // Text selection bounds information for registered views. ViewMap<SelectionRegion> selection_region_map_; + ViewMap<CompositionRangeInfo> composition_range_info_map_; base::ObserverList<Observer> observer_list_; @@ -153,4 +183,4 @@ }; } -#endif // CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__ \ No newline at end of file +#endif // CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc index ddab806..e4b8228 100644 --- a/content/browser/utility_process_host_impl.cc +++ b/content/browser/utility_process_host_impl.cc
@@ -172,10 +172,9 @@ child_token_)); mojo_child_connection_.reset(new MojoChildConnection( kUtilityMojoApplicationName, - base::StringPrintf("%d_0", process_->GetData().id), child_token_, - MojoShellContext::GetConnectorForIOThread(), - BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO) - ->task_runner())); + base::StringPrintf("%d_0", process_->GetData().id), + child_token_, + MojoShellContext::GetConnectorForIOThread())); } UtilityProcessHostImpl::~UtilityProcessHostImpl() { @@ -240,11 +239,11 @@ } shell::InterfaceRegistry* UtilityProcessHostImpl::GetInterfaceRegistry() { - return mojo_child_connection_->GetInterfaceRegistry(); + return mojo_child_connection_->connection()->GetInterfaceRegistry(); } shell::InterfaceProvider* UtilityProcessHostImpl::GetRemoteInterfaces() { - return mojo_child_connection_->GetRemoteInterfaces(); + return mojo_child_connection_->connection()->GetRemoteInterfaces(); } void UtilityProcessHostImpl::SetName(const base::string16& name) {
diff --git a/content/child/background_sync/background_sync_provider.cc b/content/child/background_sync/background_sync_provider.cc index b10a33c..517a6b61 100644 --- a/content/child/background_sync/background_sync_provider.cc +++ b/content/child/background_sync/background_sync_provider.cc
@@ -16,7 +16,6 @@ #include "content/child/background_sync/background_sync_type_converters.h" #include "content/child/child_thread_impl.h" #include "content/child/service_worker/web_service_worker_registration_impl.h" -#include "services/shell/public/cpp/interface_provider.h" #include "third_party/WebKit/public/platform/modules/background_sync/WebSyncError.h" #include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h"
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index d388d333..3bac8ae 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -68,8 +68,6 @@ #include "mojo/edk/embedder/named_platform_channel_pair.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/scoped_ipc_support.h" -#include "services/shell/public/cpp/interface_provider.h" -#include "services/shell/public/cpp/interface_registry.h" #include "services/shell/runner/common/client_util.h" #if defined(OS_POSIX) @@ -333,18 +331,14 @@ ChildThreadImpl::ChildThreadImpl() : router_(this), - channel_connected_factory_( - new base::WeakPtrFactory<ChildThreadImpl>(this)), - weak_factory_(this) { + channel_connected_factory_(this) { Init(Options::Builder().Build()); } ChildThreadImpl::ChildThreadImpl(const Options& options) : router_(this), browser_process_io_runner_(options.browser_process_io_runner), - channel_connected_factory_( - new base::WeakPtrFactory<ChildThreadImpl>(this)), - weak_factory_(this) { + channel_connected_factory_(this) { Init(options); } @@ -419,18 +413,8 @@ mojo::edk::CreateChildMessagePipe(mojo_application_token); DCHECK(handle.is_valid()); mojo_shell_connection_ = MojoShellConnection::Create( - mojo::MakeRequest<shell::mojom::Service>(std::move(handle)), - GetIOTaskRunner()); - - // TODO(rockot): Remove this once all child-to-browser interface connections - // are made via a Connector rather than directly through an - // InterfaceProvider, and all exposed interfaces are exposed via a - // ConnectionFilter. - mojo_shell_connection_->SetupInterfaceRequestProxies( - GetInterfaceRegistry(), GetRemoteInterfaces()); - - AddConnectionFilters(mojo_shell_connection_.get()); - mojo_shell_connection_->Start(); + mojo::MakeRequest<shell::mojom::Service>(std::move(handle))); + mojo_shell_connection_->MergeService(this); } sync_message_filter_ = channel_->CreateSyncMessageFilter(); @@ -515,7 +499,7 @@ message_loop_->task_runner()->PostDelayedTask( FROM_HERE, base::Bind(&ChildThreadImpl::EnsureConnected, - channel_connected_factory_->GetWeakPtr()), + channel_connected_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(connection_timeout)); #if defined(OS_ANDROID) @@ -533,6 +517,9 @@ } ChildThreadImpl::~ChildThreadImpl() { + if (MojoShellConnection::GetForProcess()) + MojoShellConnection::DestroyForProcess(); + #ifdef IPC_MESSAGE_LOG_ENABLED IPC::Logging::GetInstance()->SetIPCSender(NULL); #endif @@ -569,7 +556,7 @@ } void ChildThreadImpl::OnChannelConnected(int32_t peer_pid) { - channel_connected_factory_.reset(); + channel_connected_factory_.InvalidateWeakPtrs(); } void ChildThreadImpl::OnChannelError() { @@ -621,6 +608,14 @@ return remote_interfaces_.get(); } +shell::InterfaceRegistry* ChildThreadImpl::GetInterfaceRegistryForConnection() { + return GetInterfaceRegistry(); +} + +shell::InterfaceProvider* ChildThreadImpl::GetInterfaceProviderForConnection() { + return GetRemoteInterfaces(); +} + IPC::MessageRouter* ChildThreadImpl::GetRouter() { DCHECK(message_loop_->task_runner()->BelongsToCurrentThread()); return &router_; @@ -696,8 +691,6 @@ return router_.OnMessageReceived(msg); } -void ChildThreadImpl::AddConnectionFilters(MojoShellConnection* connection) {} - bool ChildThreadImpl::OnControlMessageReceived(const IPC::Message& msg) { return false; }
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h index e4447c9e..3680890 100644 --- a/content/child/child_thread_impl.h +++ b/content/child/child_thread_impl.h
@@ -23,6 +23,7 @@ #include "ipc/ipc_message.h" // For IPC_MESSAGE_LOG_ENABLED. #include "ipc/ipc_platform_file.h" #include "ipc/message_router.h" +#include "services/shell/public/cpp/service.h" namespace base { class MessageLoop; @@ -67,7 +68,8 @@ // The main thread of a child process derives from this class. class CONTENT_EXPORT ChildThreadImpl : public IPC::Listener, - virtual public ChildThread { + virtual public ChildThread, + public NON_EXPORTED_BASE(shell::Service){ public: struct CONTENT_EXPORT Options; @@ -99,6 +101,10 @@ shell::InterfaceRegistry* GetInterfaceRegistry() override; shell::InterfaceProvider* GetRemoteInterfaces() override; + // shell::Service: + shell::InterfaceRegistry* GetInterfaceRegistryForConnection() override; + shell::InterfaceProvider* GetInterfaceProviderForConnection() override; + IPC::SyncChannel* channel() { return channel_.get(); } IPC::MessageRouter* GetRouter(); @@ -203,10 +209,6 @@ // Called when the process refcount is 0. void OnProcessFinalRelease(); - // Implemented by subclasses to attach ConnectionFilters to the thread's - // shell connection. - virtual void AddConnectionFilters(MojoShellConnection* connection); - virtual bool OnControlMessageReceived(const IPC::Message& msg); virtual void OnProcessBackgrounded(bool backgrounded); virtual void OnProcessPurgeAndSuspend(); @@ -251,9 +253,9 @@ void EnsureConnected(); std::unique_ptr<mojo::edk::ScopedIPCSupport> mojo_ipc_support_; + std::unique_ptr<MojoShellConnection> mojo_shell_connection_; std::unique_ptr<shell::InterfaceRegistry> interface_registry_; std::unique_ptr<shell::InterfaceProvider> remote_interfaces_; - std::unique_ptr<MojoShellConnection> mojo_shell_connection_; std::string channel_name_; std::unique_ptr<IPC::SyncChannel> channel_; @@ -307,10 +309,7 @@ scoped_refptr<base::SequencedTaskRunner> browser_process_io_runner_; - std::unique_ptr<base::WeakPtrFactory<ChildThreadImpl>> - channel_connected_factory_; - - base::WeakPtrFactory<ChildThreadImpl> weak_factory_; + base::WeakPtrFactory<ChildThreadImpl> channel_connected_factory_; DISALLOW_COPY_AND_ASSIGN(ChildThreadImpl); };
diff --git a/content/common/content_switches_internal.cc b/content/common/content_switches_internal.cc index 2c385d5..fa7ab4b 100644 --- a/content/common/content_switches_internal.cc +++ b/content/common/content_switches_internal.cc
@@ -20,7 +20,7 @@ namespace { bool IsUseZoomForDSFEnabledByDefault() { -#if defined(OS_CHROMEOS) +#if defined(OS_CHROMEOS) || defined(OS_WIN) return true; #else return false;
diff --git a/content/common/mojo/mojo_shell_connection_impl.cc b/content/common/mojo/mojo_shell_connection_impl.cc index ee7ff97..5311ba6c 100644 --- a/content/common/mojo/mojo_shell_connection_impl.cc +++ b/content/common/mojo/mojo_shell_connection_impl.cc
@@ -4,327 +4,63 @@ #include "content/common/mojo/mojo_shell_connection_impl.h" -#include <queue> -#include <utility> -#include <vector> - #include "base/bind.h" -#include "base/callback_helpers.h" #include "base/lazy_instance.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/threading/thread_checker.h" +#include "base/threading/thread_local.h" #include "content/common/mojo/embedded_application_runner.h" -#include "content/public/common/connection_filter.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/system/message_pipe.h" #include "services/shell/public/cpp/service.h" #include "services/shell/public/cpp/service_context.h" -#include "services/shell/public/interfaces/service_factory.mojom.h" #include "services/shell/runner/common/client_util.h" namespace content { namespace { -base::LazyInstance<std::unique_ptr<MojoShellConnection>>::Leaky - g_connection_for_process = LAZY_INSTANCE_INITIALIZER; +using MojoShellConnectionPtr = + base::ThreadLocalPointer<MojoShellConnection>; + +// Env is thread local so that aura may be used on multiple threads. +base::LazyInstance<MojoShellConnectionPtr>::Leaky lazy_tls_ptr = + LAZY_INSTANCE_INITIALIZER; MojoShellConnection::Factory* mojo_shell_connection_factory = nullptr; } // namespace -// A ref-counted object which owns the IO thread state of a -// MojoShellConnectionImpl. This includes Service and ServiceFactory -// bindings. -class MojoShellConnectionImpl::IOThreadContext - : public base::RefCountedThreadSafe<IOThreadContext>, - public shell::Service, - public shell::InterfaceFactory<shell::mojom::ServiceFactory>, - public shell::mojom::ServiceFactory { - public: - using InitializeCallback = base::Callback<void(const shell::Identity&)>; - using ServiceFactoryCallback = - base::Callback<void(shell::mojom::ServiceRequest, const mojo::String&)>; - - IOThreadContext(shell::mojom::ServiceRequest service_request, - scoped_refptr<base::SequencedTaskRunner> io_task_runner, - std::unique_ptr<shell::Connector> io_thread_connector, - shell::mojom::ConnectorRequest connector_request) - : pending_service_request_(std::move(service_request)), - io_task_runner_(io_task_runner), - io_thread_connector_(std::move(io_thread_connector)), - pending_connector_request_(std::move(connector_request)) { - // This will be reattached by any of the IO thread functions on first call. - io_thread_checker_.DetachFromThread(); - } - - // Safe to call from any thread. - void Start(const InitializeCallback& initialize_callback, - const ServiceFactoryCallback& create_service_callback, - const base::Closure& stop_callback) { - DCHECK(!started_); - - started_ = true; - callback_task_runner_ = base::ThreadTaskRunnerHandle::Get(); - initialize_handler_ = initialize_callback; - create_service_callback_ = create_service_callback; - stop_callback_ = stop_callback; - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&IOThreadContext::StartOnIOThread, this)); - } - - // Safe to call from whichever thread called Start() (or may have called - // Start()). Must be called before IO thread shutdown. - void ShutDown() { - if (!started_) - return; - - bool posted = io_task_runner_->PostTask( - FROM_HERE, base::Bind(&IOThreadContext::ShutDownOnIOThread, this)); - DCHECK(posted); - } - - // Safe to call any time before Start() is called. - void AddConnectionFilter(std::unique_ptr<ConnectionFilter> filter) { - DCHECK(!started_); - connection_filters_.emplace_back(std::move(filter)); - } - - // Safe to call any time before Start() is called. - void SetDefaultBinderForBrowserConnection( - const shell::InterfaceRegistry::Binder& binder) { - DCHECK(!started_); - default_browser_binder_ = base::Bind( - &IOThreadContext::CallBinderOnTaskRunner, - base::ThreadTaskRunnerHandle::Get(), binder); - } - - // Safe to call any time after Start() is called. - void GetRemoteInterface(const mojo::String& interface_name, - mojo::ScopedMessagePipeHandle request_handle) { - DCHECK(started_); - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&IOThreadContext::GetRemoteInterfaceOnIOThread, this, - interface_name, base::Passed(&request_handle))); - } - - private: - friend class base::RefCountedThreadSafe<IOThreadContext>; - - ~IOThreadContext() override {} - - void StartOnIOThread() { - // Should bind |io_thread_checker_| to the context's thread. - DCHECK(io_thread_checker_.CalledOnValidThread()); - service_context_.reset(new shell::ServiceContext( - this, std::move(pending_service_request_), - std::move(io_thread_connector_), - std::move(pending_connector_request_))); - } - - void ShutDownOnIOThread() { - DCHECK(io_thread_checker_.CalledOnValidThread()); - service_context_.reset(); - factory_bindings_.CloseAllBindings(); - } - - void GetRemoteInterfaceOnIOThread( - const mojo::String& interface_name, - mojo::ScopedMessagePipeHandle request_handle) { - DCHECK(io_thread_checker_.CalledOnValidThread()); - if (browser_connection_) { - browser_connection_->GetRemoteInterfaces()->GetInterface( - interface_name, std::move(request_handle)); - } else { - pending_remote_interface_requests_.emplace(interface_name, - std::move(request_handle)); - } - } - - void OnBrowserConnectionLost() { - DCHECK(io_thread_checker_.CalledOnValidThread()); - browser_connection_ = nullptr; - } - - ///////////////////////////////////////////////////////////////////////////// - // shell::Service implementation - - void OnStart(shell::Connector* connector, - const shell::Identity& identity, - uint32_t id) override { - DCHECK(io_thread_checker_.CalledOnValidThread()); - DCHECK(!initialize_handler_.is_null()); - - InitializeCallback handler = base::ResetAndReturn(&initialize_handler_); - callback_task_runner_->PostTask(FROM_HERE, base::Bind(handler, identity)); - } - - bool OnConnect(shell::Connection* connection) override { - DCHECK(io_thread_checker_.CalledOnValidThread()); - std::string remote_app = connection->GetRemoteIdentity().name(); - if (remote_app == "mojo:shell") { - // Only expose the SCF interface to the shell. - connection->AddInterface<shell::mojom::ServiceFactory>(this); - return true; - } - - bool accept = false; - for (auto& filter : connection_filters_) { - accept = accept || - filter->OnConnect(connection, service_context_->connector()); - } - - // Capture the browser connection if possible. - if (remote_app == "exe:content_browser" && !browser_connection_) { - browser_connection_ = connection; - connection->GetInterfaceRegistry()->set_default_binder( - default_browser_binder_); - connection->SetConnectionLostClosure( - base::Bind(&IOThreadContext::OnBrowserConnectionLost, this)); - shell::InterfaceProvider* remote_interfaces = - connection->GetRemoteInterfaces(); - - // Flush any pending outgoing interface requests. - while (!pending_remote_interface_requests_.empty()) { - auto& request = pending_remote_interface_requests_.front(); - remote_interfaces->GetInterface( - request.first, std::move(request.second)); - pending_remote_interface_requests_.pop(); - } - return true; - } - - // If no filters were interested, reject the connection. - return accept; - } - - bool OnStop() override { - callback_task_runner_->PostTask(FROM_HERE, stop_callback_); - return true; - } - - ///////////////////////////////////////////////////////////////////////////// - // shell::InterfaceFactory<shell::mojom::ServiceFactory> implementation - - void Create(shell::Connection* connection, - shell::mojom::ServiceFactoryRequest request) override { - DCHECK(io_thread_checker_.CalledOnValidThread()); - factory_bindings_.AddBinding(this, std::move(request)); - } - - ///////////////////////////////////////////////////////////////////////////// - // shell::mojom::ServiceFactory implementation - - void CreateService(shell::mojom::ServiceRequest request, - const mojo::String& name) override { - DCHECK(io_thread_checker_.CalledOnValidThread()); - callback_task_runner_->PostTask( - FROM_HERE, - base::Bind(create_service_callback_, base::Passed(&request), name)); - } - - static void CallBinderOnTaskRunner( - scoped_refptr<base::SequencedTaskRunner> task_runner, - const shell::InterfaceRegistry::Binder& binder, - const mojo::String& interface_name, - mojo::ScopedMessagePipeHandle request_handle) { - task_runner->PostTask(FROM_HERE, base::Bind(binder, interface_name, - base::Passed(&request_handle))); - } - - base::ThreadChecker io_thread_checker_; - bool started_ = false; - - // Temporary state established on construction and consumed on the IO thread - // once the connection is started. - shell::mojom::ServiceRequest pending_service_request_; - scoped_refptr<base::SequencedTaskRunner> io_task_runner_; - std::unique_ptr<shell::Connector> io_thread_connector_; - shell::mojom::ConnectorRequest pending_connector_request_; - - // TaskRunner on which to run our owner's callbacks, i.e. the ones passed to - // Start(). - scoped_refptr<base::SequencedTaskRunner> callback_task_runner_; - - // Callback to run once Service::OnStart is invoked. - InitializeCallback initialize_handler_; - - // Callback to run when a new Service request is received. - ServiceFactoryCallback create_service_callback_; - - // Callback to run if the service is stopped by the service manager. - base::Closure stop_callback_; - - // The incoming Connection from the browser process. This is captured the - // first time the browser connects to this Service and persists until shutdown - // or a connection error is detected. This connection is used to fulfill - // remote interface requests from legacy code which does not use - // shell::Connector. - // - // TODO(rockot): Remove this once all child-to-browser interface connections - // are made via a Connector rather than directly through an InterfaceProvider - // and all interfaces exposed to the browser are exposed via a - // ConnectionFilter. - shell::Connection* browser_connection_ = nullptr; - - // A queue of remote interface requests destined for the browser, which will - // remain pending until an incoming connection is accepted from the browser. - // - // TODO(rockot): Remove this once all child-to-browser interface connections - // are made via a Connector rather than directly through an InterfaceProvider. - std::queue<std::pair<mojo::String, mojo::ScopedMessagePipeHandle>> - pending_remote_interface_requests_; - - // Default binder callback used for the browser connection's - // InterfaceRegistry. - // - // TODO(rockot): Remove this once all interfaces exposed to the browser are - // exposed via a ConnectionFilter. - shell::InterfaceRegistry::Binder default_browser_binder_; - - std::unique_ptr<shell::ServiceContext> service_context_; - mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_; - std::vector<std::unique_ptr<ConnectionFilter>> connection_filters_; - - DISALLOW_COPY_AND_ASSIGN(IOThreadContext); -}; - //////////////////////////////////////////////////////////////////////////////// // MojoShellConnection, public: // static void MojoShellConnection::SetForProcess( std::unique_ptr<MojoShellConnection> connection) { - DCHECK(!g_connection_for_process.Get()); - g_connection_for_process.Get() = std::move(connection); + DCHECK(!lazy_tls_ptr.Pointer()->Get()); + lazy_tls_ptr.Pointer()->Set(connection.release()); } // static MojoShellConnection* MojoShellConnection::GetForProcess() { - return g_connection_for_process.Get().get(); + return lazy_tls_ptr.Pointer()->Get(); } // static void MojoShellConnection::DestroyForProcess() { // This joins the shell controller thread. - g_connection_for_process.Get().reset(); + delete GetForProcess(); + lazy_tls_ptr.Pointer()->Set(nullptr); } // static void MojoShellConnection::SetFactoryForTest(Factory* factory) { - DCHECK(!g_connection_for_process.Get()); + DCHECK(!lazy_tls_ptr.Pointer()->Get()); mojo_shell_connection_factory = factory; } // static std::unique_ptr<MojoShellConnection> MojoShellConnection::Create( - shell::mojom::ServiceRequest request, - scoped_refptr<base::SequencedTaskRunner> io_task_runner) { + shell::mojom::ServiceRequest request) { if (mojo_shell_connection_factory) return mojo_shell_connection_factory->Run(); - return base::MakeUnique<MojoShellConnectionImpl>( - std::move(request), io_task_runner); + return base::WrapUnique(new MojoShellConnectionImpl(std::move(request))); } MojoShellConnection::~MojoShellConnection() {} @@ -333,72 +69,115 @@ // MojoShellConnectionImpl, public: MojoShellConnectionImpl::MojoShellConnectionImpl( - shell::mojom::ServiceRequest request, - scoped_refptr<base::SequencedTaskRunner> io_task_runner) - : weak_factory_(this) { - shell::mojom::ConnectorRequest connector_request; - connector_ = shell::Connector::Create(&connector_request); + shell::mojom::ServiceRequest request) + : shell_connection_(new shell::ServiceContext(this, std::move(request))) {} - std::unique_ptr<shell::Connector> io_thread_connector = connector_->Clone(); - context_ = new IOThreadContext( - std::move(request), io_task_runner, std::move(io_thread_connector), - std::move(connector_request)); +MojoShellConnectionImpl::~MojoShellConnectionImpl() {} + +//////////////////////////////////////////////////////////////////////////////// +// MojoShellConnectionImpl, shell::Service implementation: + +void MojoShellConnectionImpl::OnStart(shell::Connector* connector, + const shell::Identity& identity, + uint32_t id) { + for (auto& client : embedded_services_) + client->OnStart(connector, identity, id); } -MojoShellConnectionImpl::~MojoShellConnectionImpl() { - context_->ShutDown(); +bool MojoShellConnectionImpl::OnConnect(shell::Connection* connection) { + std::string remote_app = connection->GetRemoteIdentity().name(); + if (remote_app == "mojo:shell") { + // Only expose the SCF interface to the shell. + connection->AddInterface<shell::mojom::ServiceFactory>(this); + return true; + } + + bool accept = false; + for (auto& client : embedded_services_) + accept |= client->OnConnect(connection); + + // Reject all other connections to this application. + return accept; +} + +shell::InterfaceRegistry* +MojoShellConnectionImpl::GetInterfaceRegistryForConnection() { + // TODO(beng): This is really horrible since obviously subject to issues + // of ordering, but is no more horrible than this API is in general. + shell::InterfaceRegistry* registry = nullptr; + for (auto& client : embedded_services_) { + registry = client->GetInterfaceRegistryForConnection(); + if (registry) + return registry; + } + return nullptr; +} + +shell::InterfaceProvider* +MojoShellConnectionImpl::GetInterfaceProviderForConnection() { + // TODO(beng): This is really horrible since obviously subject to issues + // of ordering, but is no more horrible than this API is in general. + shell::InterfaceProvider* provider = nullptr; + for (auto& client : embedded_services_) { + provider = client->GetInterfaceProviderForConnection(); + if (provider) + return provider; + } + return nullptr; +} + +//////////////////////////////////////////////////////////////////////////////// +// MojoShellConnectionImpl, +// shell::InterfaceFactory<shell::mojom::ServiceFactory> implementation: + +void MojoShellConnectionImpl::Create( + shell::Connection* connection, + shell::mojom::ServiceFactoryRequest request) { + factory_bindings_.AddBinding(this, std::move(request)); +} + +//////////////////////////////////////////////////////////////////////////////// +// MojoShellConnectionImpl, shell::mojom::ServiceFactory implementation: + +void MojoShellConnectionImpl::CreateService( + shell::mojom::ServiceRequest request, + const mojo::String& name) { + auto it = request_handlers_.find(name); + if (it != request_handlers_.end()) + it->second.Run(std::move(request)); } //////////////////////////////////////////////////////////////////////////////// // MojoShellConnectionImpl, MojoShellConnection implementation: -void MojoShellConnectionImpl::Start() { - context_->Start( - base::Bind(&MojoShellConnectionImpl::OnContextInitialized, - weak_factory_.GetWeakPtr()), - base::Bind(&MojoShellConnectionImpl::CreateService, - weak_factory_.GetWeakPtr()), - base::Bind(&MojoShellConnectionImpl::OnConnectionLost, - weak_factory_.GetWeakPtr())); -} - -void MojoShellConnectionImpl::SetInitializeHandler( - const base::Closure& handler) { - DCHECK(initialize_handler_.is_null()); - initialize_handler_ = handler; +shell::ServiceContext* MojoShellConnectionImpl::GetShellConnection() { + return shell_connection_.get(); } shell::Connector* MojoShellConnectionImpl::GetConnector() { - return connector_.get(); + DCHECK(shell_connection_); + return shell_connection_->connector(); } const shell::Identity& MojoShellConnectionImpl::GetIdentity() const { - return identity_; + DCHECK(shell_connection_); + return shell_connection_->identity(); } void MojoShellConnectionImpl::SetConnectionLostClosure( const base::Closure& closure) { - connection_lost_handler_ = closure; + shell_connection_->SetConnectionLostClosure(closure); } -void MojoShellConnectionImpl::SetupInterfaceRequestProxies( - shell::InterfaceRegistry* registry, - shell::InterfaceProvider* provider) { - // It's safe to bind |registry| as a raw pointer because the caller must - // guarantee that it outlives |this|, and |this| is bound as a weak ptr here. - context_->SetDefaultBinderForBrowserConnection( - base::Bind(&MojoShellConnectionImpl::GetInterface, - weak_factory_.GetWeakPtr(), registry)); - - // Forward all remote interface requests on |provider| to our IO-thread - // context. This will ensure they're forwarded to the provider on the - // incoming browser connection. - provider->Forward(base::Bind(&IOThreadContext::GetRemoteInterface, context_)); +void MojoShellConnectionImpl::MergeService( + std::unique_ptr<shell::Service> service) { + embedded_services_.push_back(service.get()); + owned_services_.push_back(std::move(service)); } -void MojoShellConnectionImpl::AddConnectionFilter( - std::unique_ptr<ConnectionFilter> filter) { - context_->AddConnectionFilter(std::move(filter)); +void MojoShellConnectionImpl::MergeService( + shell::Service* service) { + embedded_services_.push_back(service); } void MojoShellConnectionImpl::AddEmbeddedService( @@ -420,31 +199,4 @@ DCHECK(result.second); } -void MojoShellConnectionImpl::CreateService( - shell::mojom::ServiceRequest request, - const mojo::String& name) { - auto it = request_handlers_.find(name); - if (it != request_handlers_.end()) - it->second.Run(std::move(request)); -} - -void MojoShellConnectionImpl::OnContextInitialized( - const shell::Identity& identity) { - identity_ = identity; - if (!initialize_handler_.is_null()) - base::ResetAndReturn(&initialize_handler_).Run(); -} - -void MojoShellConnectionImpl::OnConnectionLost() { - if (!connection_lost_handler_.is_null()) - connection_lost_handler_.Run(); -} - -void MojoShellConnectionImpl::GetInterface( - shell::mojom::InterfaceProvider* provider, - const mojo::String& interface_name, - mojo::ScopedMessagePipeHandle request_handle) { - provider->GetInterface(interface_name, std::move(request_handle)); -} - } // namespace content
diff --git a/content/common/mojo/mojo_shell_connection_impl.h b/content/common/mojo/mojo_shell_connection_impl.h index c262c9e..6a6882413 100644 --- a/content/common/mojo/mojo_shell_connection_impl.h +++ b/content/common/mojo/mojo_shell_connection_impl.h
@@ -6,73 +6,68 @@ #define CONTENT_COMMON_MOJO_SHELL_CONNECTION_IMPL_H_ #include <memory> +#include <vector> #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" #include "content/public/common/mojo_shell_connection.h" -#include "mojo/public/cpp/bindings/string.h" +#include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/system/message_pipe.h" -#include "services/shell/public/cpp/identity.h" -#include "services/shell/public/interfaces/service.mojom.h" - -namespace shell { -class Connector; -} +#include "services/shell/public/cpp/service.h" +#include "services/shell/public/cpp/service_context.h" +#include "services/shell/public/interfaces/service_factory.mojom.h" namespace content { class EmbeddedApplicationRunner; -class MojoShellConnectionImpl : public MojoShellConnection { +class MojoShellConnectionImpl + : public MojoShellConnection, + public shell::Service, + public shell::InterfaceFactory<shell::mojom::ServiceFactory>, + public shell::mojom::ServiceFactory { + public: - explicit MojoShellConnectionImpl( - shell::mojom::ServiceRequest request, - scoped_refptr<base::SequencedTaskRunner> io_task_runner); + explicit MojoShellConnectionImpl(shell::mojom::ServiceRequest request); ~MojoShellConnectionImpl() override; private: - class IOThreadContext; - // MojoShellConnection: - void Start() override; - void SetInitializeHandler(const base::Closure& handler) override; + shell::ServiceContext* GetShellConnection() override; shell::Connector* GetConnector() override; const shell::Identity& GetIdentity() const override; void SetConnectionLostClosure(const base::Closure& closure) override; - void SetupInterfaceRequestProxies( - shell::InterfaceRegistry* registry, - shell::InterfaceProvider* provider) override; - void AddConnectionFilter(std::unique_ptr<ConnectionFilter> filter) override; + void MergeService(std::unique_ptr<shell::Service> service) override; + void MergeService(shell::Service* service) override; void AddEmbeddedService(const std::string& name, const MojoApplicationInfo& info) override; void AddServiceRequestHandler( const std::string& name, const ServiceRequestHandler& handler) override; - void OnContextInitialized(const shell::Identity& identity); - void OnConnectionLost(); + // shell::Service: + void OnStart(shell::Connector* connector, + const shell::Identity& identity, + uint32_t id) override; + bool OnConnect(shell::Connection* connection) override; + shell::InterfaceRegistry* GetInterfaceRegistryForConnection() override; + shell::InterfaceProvider* GetInterfaceProviderForConnection() override; + + // shell::InterfaceFactory<shell::mojom::ServiceFactory>: + void Create(shell::Connection* connection, + shell::mojom::ServiceFactoryRequest request) override; + + // shell::mojom::ServiceFactory: void CreateService(shell::mojom::ServiceRequest request, - const mojo::String& name); - void GetInterface(shell::mojom::InterfaceProvider* provider, - const mojo::String& interface_name, - mojo::ScopedMessagePipeHandle request_handle); + const mojo::String& name) override; - shell::Identity identity_; - - std::unique_ptr<shell::Connector> connector_; - scoped_refptr<IOThreadContext> context_; - - base::Closure initialize_handler_; - base::Closure connection_lost_handler_; - + std::unique_ptr<shell::ServiceContext> shell_connection_; + mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_; + std::vector<shell::Service*> embedded_services_; + std::vector<std::unique_ptr<shell::Service>> owned_services_; std::unordered_map<std::string, std::unique_ptr<EmbeddedApplicationRunner>> embedded_apps_; std::unordered_map<std::string, ServiceRequestHandler> request_handlers_; - base::WeakPtrFactory<MojoShellConnectionImpl> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(MojoShellConnectionImpl); };
diff --git a/content/content_common.gypi b/content/content_common.gypi index 914b7fa..10cc09f7 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi
@@ -114,7 +114,6 @@ 'public/common/common_param_traits.h', 'public/common/common_param_traits_macros.h', 'public/common/console_message_level.h', - 'public/common/connection_filter.h', 'public/common/content_client.cc', 'public/common/content_client.h', 'public/common/content_constants.cc',
diff --git a/content/gpu/BUILD.gn b/content/gpu/BUILD.gn index 5b0f6b6..16c4aea 100644 --- a/content/gpu/BUILD.gn +++ b/content/gpu/BUILD.gn
@@ -57,7 +57,6 @@ "//ipc", "//media/gpu", "//media/gpu/ipc/service", - "//services/shell/public/cpp", "//services/shell/public/interfaces", "//skia", "//ui/events/ipc",
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc index 2c36e17d..af207ab 100644 --- a/content/gpu/gpu_child_thread.cc +++ b/content/gpu/gpu_child_thread.cc
@@ -22,7 +22,6 @@ #include "content/gpu/gpu_watchdog_thread.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" -#include "content/public/common/mojo_shell_connection.h" #include "content/public/gpu/content_gpu_client.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/sync_point_manager.h" @@ -37,7 +36,6 @@ #include "media/gpu/ipc/service/gpu_video_decode_accelerator.h" #include "media/gpu/ipc/service/gpu_video_encode_accelerator.h" #include "media/gpu/ipc/service/media_service.h" -#include "services/shell/public/cpp/interface_registry.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_switches.h" #include "ui/gl/gpu_switching_manager.h" @@ -223,18 +221,6 @@ // Only set once per process instance. process_control_.reset(new GpuProcessControlImpl()); - GetInterfaceRegistry()->AddInterface(base::Bind( - &GpuChildThread::BindProcessControlRequest, base::Unretained(this))); - - if (GetContentClient()->gpu()) { // NULL in tests. - GetContentClient()->gpu()->ExposeInterfacesToBrowser( - GetInterfaceRegistry()); - } - - // We don't want to process any incoming interface requests until - // OnInitialize() is invoked. - GetInterfaceRegistry()->PauseBinding(); - if (GetContentClient()->gpu()) // NULL in tests. GetContentClient()->gpu()->Initialize(this); } @@ -304,6 +290,37 @@ return false; } +bool GpuChildThread::OnConnect(shell::Connection* connection) { + // Use of base::Unretained(this) is safe here because |service_registry()| + // will be destroyed before GpuChildThread is destructed. + connection->GetInterfaceRegistry()->AddInterface(base::Bind( + &GpuChildThread::BindProcessControlRequest, base::Unretained(this))); + + if (GetContentClient()->gpu()) { // NULL in tests. + GetContentClient()->gpu()->ExposeInterfacesToBrowser( + connection->GetInterfaceRegistry()); + } + + // We don't want to process any incoming interface requests until + // OnInitialize(). + if (!gpu_channel_manager_) { + connection->GetInterfaceRegistry()->PauseBinding(); + resume_interface_bindings_callback_ = base::Bind( + &shell::InterfaceRegistry::ResumeBinding, + connection->GetInterfaceRegistry()->GetWeakPtr()); + } + + return true; +} + +shell::InterfaceRegistry* GpuChildThread::GetInterfaceRegistryForConnection() { + return nullptr; +} + +shell::InterfaceProvider* GpuChildThread::GetInterfaceProviderForConnection() { + return nullptr; +} + void GpuChildThread::SetActiveURL(const GURL& url) { GetContentClient()->SetActiveURL(url); } @@ -347,7 +364,8 @@ } void GpuChildThread::OnInitialize(const gpu::GpuPreferences& gpu_preferences) { - GetInterfaceRegistry()->ResumeBinding(); + if (!resume_interface_bindings_callback_.is_null()) + base::ResetAndReturn(&resume_interface_bindings_callback_).Run(); gpu_preferences_ = gpu_preferences; @@ -566,7 +584,7 @@ } void GpuChildThread::BindProcessControlRequest( - mojom::ProcessControlRequest request) { + mojo::InterfaceRequest<mojom::ProcessControl> request) { DVLOG(1) << "GPU: Binding ProcessControl request"; DCHECK(process_control_); process_control_bindings_.AddBinding(process_control_.get(),
diff --git a/content/gpu/gpu_child_thread.h b/content/gpu/gpu_child_thread.h index 7eb8c462..f51bba1 100644 --- a/content/gpu/gpu_child_thread.h +++ b/content/gpu/gpu_child_thread.h
@@ -28,6 +28,7 @@ #include "gpu/ipc/service/gpu_config.h" #include "gpu/ipc/service/x_util.h" #include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/interface_request.h" #include "ui/gfx/native_widget_types.h" namespace gpu { @@ -86,6 +87,9 @@ bool Send(IPC::Message* msg) override; bool OnControlMessageReceived(const IPC::Message& msg) override; bool OnMessageReceived(const IPC::Message& msg) override; + bool OnConnect(shell::Connection* connection) override; + shell::InterfaceRegistry* GetInterfaceRegistryForConnection() override; + shell::InterfaceProvider* GetInterfaceProviderForConnection() override; // gpu::GpuChannelManagerDelegate: void SetActiveURL(const GURL& url) override; @@ -134,7 +138,8 @@ #endif void OnLoseAllContexts(); - void BindProcessControlRequest(mojom::ProcessControlRequest request); + void BindProcessControlRequest( + mojo::InterfaceRequest<mojom::ProcessControl> request); gpu::GpuPreferences gpu_preferences_; @@ -174,6 +179,8 @@ // Bindings to the mojom::ProcessControl impl. mojo::BindingSet<mojom::ProcessControl> process_control_bindings_; + base::Closure resume_interface_bindings_callback_; + DISALLOW_COPY_AND_ASSIGN(GpuChildThread); };
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index e1ddb079..8526ef7e 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -270,6 +270,9 @@ // interfaces exposed to it from the renderer. virtual shell::InterfaceProvider* GetRemoteInterfaces() = 0; + // Returns the shell connection for this process. + virtual shell::Connection* GetChildConnection() = 0; + // Extracts any persistent-memory-allocator used for renderer metrics. // Ownership is passed to the caller. To support sharing of histogram data // between the Renderer and the Browser, the allocator is created when the
diff --git a/content/public/child/child_thread.h b/content/public/child/child_thread.h index 2a3c8d8..d3ad0ce 100644 --- a/content/public/child/child_thread.h +++ b/content/public/child/child_thread.h
@@ -5,7 +5,6 @@ #ifndef CONTENT_PUBLIC_CHILD_CHILD_THREAD_H_ #define CONTENT_PUBLIC_CHILD_CHILD_THREAD_H_ -#include <memory> #include <string> #include "base/logging.h" @@ -28,8 +27,7 @@ namespace content { -class ConnectionFilter; -class MojoShellConnection; + class MojoShellConnection; // An abstract base class that contains logic shared between most child // processes of the embedder.
diff --git a/content/public/common/connection_filter.h b/content/public/common/connection_filter.h deleted file mode 100644 index be8da3f..0000000 --- a/content/public/common/connection_filter.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_PUBLIC_COMMON_CONNECTION_FILTER_H_ -#define CONTENT_PUBLIC_COMMON_CONNECTION_FILTER_H_ - -#include "content/common/content_export.h" - -namespace shell { -class Connection; -class Connector; -} - -namespace content { - -// A ConnectionFilter may be used to conditionally expose interfaces on inbound -// connections accepted by MojoShellConnection. ConnectionFilters are used -// exclusively on the IO thread. See MojoShellConnection::AddConnectionFilter -// for details. -class CONTENT_EXPORT ConnectionFilter { - public: - virtual ~ConnectionFilter() {} - - // Called for every new connection accepted. Implementations may add - // interfaces to |connection|, in which case they should return |true|. - // |connector| is a corresponding outgoing Connector that may be used by any - // interfaces added to the connection. Note that references to |connector| - // must not be retained, but an owned copy may be obtained by calling - // |connector->Clone()|. - // - // If a ConnectionFilter is not interested in an incoming connection, it - // should return |false|. - virtual bool OnConnect(shell::Connection* connection, - shell::Connector* connector) = 0; -}; - -} // namespace content - -#endif // CONTENT_PUBLIC_COMMON_CONNECTION_FILTER_H_
diff --git a/content/public/common/mojo_shell_connection.h b/content/public/common/mojo_shell_connection.h index 577f128..7014034 100644 --- a/content/public/common/mojo_shell_connection.h +++ b/content/public/common/mojo_shell_connection.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/callback_forward.h" -#include "base/sequenced_task_runner.h" #include "content/common/content_export.h" #include "content/public/common/mojo_application_info.h" #include "services/shell/public/cpp/identity.h" @@ -17,14 +16,11 @@ namespace shell { class Connection; class Connector; -class InterfaceProvider; -class InterfaceRegistry; +class ServiceContext; } namespace content { -class ConnectionFilter; - // Encapsulates a connection to a //services/shell. // Access a global instance on the thread the ServiceContext was bound by // calling Holder::Get(). @@ -59,21 +55,13 @@ // called before the MojoShellConnection has been created. static void SetFactoryForTest(Factory* factory); - // Creates a MojoShellConnection from |request|. The connection binds - // its interfaces and accept new connections on |io_task_runner| only. Note - // that no incoming connections are accepted until Start() is called. + // Creates a MojoShellConnection from |request|. static std::unique_ptr<MojoShellConnection> Create( - shell::mojom::ServiceRequest request, - scoped_refptr<base::SequencedTaskRunner> io_task_runner); + shell::mojom::ServiceRequest request); - // Begins accepting incoming connections. Connection filters MUST be added - // before calling this in order to avoid races. See AddConnectionFilter() - // below. - virtual void Start() = 0; - - // Sets a closure to be invoked once the connection receives an Initialize() - // request from the shell. - virtual void SetInitializeHandler(const base::Closure& handler) = 0; + // Returns the bound shell::ServiceContext object. + // TODO(rockot): remove. + virtual shell::ServiceContext* GetShellConnection() = 0; // Returns the shell::Connector received via this connection's Service // implementation. Use this to initiate connections as this object's Identity. @@ -88,31 +76,12 @@ // run immediately before returning from this function. virtual void SetConnectionLostClosure(const base::Closure& closure) = 0; - // Provides an InterfaceRegistry to forward incoming interface requests to - // on the MojoShellConnection's own thread if they aren't bound by the - // connection's internal InterfaceRegistry on the IO thread. - // - // Also configures |interface_provider| to forward all of its outgoing - // interface requests to the connection's internal remote interface provider. - // - // Note that neither |interface_registry| or |interface_provider| is owned - // and both MUST outlive the MojoShellConnection. - // - // TODO(rockot): Remove this. It's a temporary solution to avoid porting all - // relevant code to ConnectionFilters at once. - virtual void SetupInterfaceRequestProxies( - shell::InterfaceRegistry* registry, - shell::InterfaceProvider* provider) = 0; - - // Allows the caller to filter inbound connections and/or expose interfaces - // on them. |filter| may be created on any thread, but will be used and - // destroyed exclusively on the IO thread (the thread corresponding to - // |io_task_runner| passed to Create() above.) - // - // Connection filters MUST be added before calling Start() in order to avoid - // races. - virtual void AddConnectionFilter( - std::unique_ptr<ConnectionFilter> filter) = 0; + // Allows the caller to expose interfaces to the caller using the identity of + // this object's Service. As distinct from MergeService() and + // AddServiceRequestHandler() which specify unique identities for the + // registered services. + virtual void MergeService(std::unique_ptr<shell::Service> service) = 0; + virtual void MergeService(shell::Service* service) = 0; // Adds an embedded service to this connection's ServiceFactory. // |info| provides details on how to construct new instances of the
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index 5924b51..a75a3f9 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -269,6 +269,10 @@ return remote_interfaces_.get(); } +shell::Connection* MockRenderProcessHost::GetChildConnection() { + return nullptr; +} + std::unique_ptr<base::SharedPersistentMemoryAllocator> MockRenderProcessHost::TakeMetricsAllocator() { return nullptr;
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index 770377d..38030657 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -96,6 +96,7 @@ void NotifyTimezoneChange(const std::string& zone_id) override; shell::InterfaceRegistry* GetInterfaceRegistry() override; shell::InterfaceProvider* GetRemoteInterfaces() override; + shell::Connection* GetChildConnection() override; std::unique_ptr<base::SharedPersistentMemoryAllocator> TakeMetricsAllocator() override; const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
diff --git a/content/public/test/text_input_test_utils.cc b/content/public/test/text_input_test_utils.cc index 594c4be..bc13104e 100644 --- a/content/public/test/text_input_test_utils.cc +++ b/content/public/test/text_input_test_utils.cc
@@ -18,6 +18,8 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/test/test_utils.h" +#include "third_party/WebKit/public/web/WebCompositionUnderline.h" +#include "ui/base/ime/composition_underline.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method_observer.h" @@ -58,6 +60,11 @@ on_selection_bounds_changed_callback_ = callback; } + void set_on_ime_composition_range_changed_callback( + const base::Closure& callback) { + on_ime_composition_range_changed_callback_ = callback; + } + const RenderWidgetHostView* GetUpdatedView() const { return updated_view_; } bool text_input_state_changed() const { return text_input_state_changed_; } @@ -84,6 +91,14 @@ on_selection_bounds_changed_callback_.Run(); } + void OnImeCompositionRangeChanged( + TextInputManager* text_input_manager, + RenderWidgetHostViewBase* updated_view) override { + updated_view_ = updated_view; + if (!on_ime_composition_range_changed_callback_.is_null()) + on_ime_composition_range_changed_callback_.Run(); + } + // WebContentsObserver implementation. void WebContentsDestroyed() override { text_input_manager_ = nullptr; } @@ -93,6 +108,7 @@ bool text_input_state_changed_; base::Closure update_text_input_state_callback_; base::Closure on_selection_bounds_changed_callback_; + base::Closure on_ime_composition_range_changed_callback_; DISALLOW_COPY_AND_ASSIGN(InternalObserver); }; @@ -216,6 +232,25 @@ return true; } +void SetCompositionForRenderWidgetHost( + RenderWidgetHost* render_widget_host, + const base::string16& text, + const std::vector<ui::CompositionUnderline>& underlines, + const gfx::Range& replacement_range, + int selection_start, + int selection_end) { + std::vector<blink::WebCompositionUnderline> web_underlines; + for (auto underline : underlines) { + web_underlines.emplace_back(blink::WebCompositionUnderline( + underline.start_offset, underline.end_offset, underline.color, + underline.thick, underline.background_color)); + } + + static_cast<RenderWidgetHostImpl*>(render_widget_host) + ->ImeSetComposition(text, web_underlines, replacement_range, + selection_start, selection_end); +} + size_t GetRegisteredViewsCountFromTextInputManager(WebContents* web_contents) { std::unordered_set<RenderWidgetHostView*> views; TextInputManager* manager = @@ -244,6 +279,11 @@ observer_->set_on_selection_bounds_changed_callback(callback); } +void TextInputManagerTester::SetOnImeCompositionRangeChangedCallback( + const base::Closure& callback) { + observer_->set_on_ime_composition_range_changed_callback(callback); +} + bool TextInputManagerTester::GetTextInputType(ui::TextInputType* type) { DCHECK(observer_->text_input_manager()); const TextInputState* state = @@ -351,4 +391,4 @@ return observer; } -} // namespace content \ No newline at end of file +} // namespace content
diff --git a/content/public/test/text_input_test_utils.h b/content/public/test/text_input_test_utils.h index f87e9fe..97b1da1 100644 --- a/content/public/test/text_input_test_utils.h +++ b/content/public/test/text_input_test_utils.h
@@ -6,13 +6,24 @@ #define CONTENT_PUBLIC_TEST_TEXT_INPUT_TEST_UTILS_H_ #include <string> +#include <vector> #include "base/callback.h" +#include "base/strings/string16.h" #include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" +namespace gfx { +class Range; +} + +namespace ui { +struct CompositionUnderline; +} + namespace content { +class RenderWidgetHost; class RenderWidgetHostView; class RenderWidgetHostViewBase; class WebContents; @@ -38,6 +49,16 @@ // given WebContents. RenderWidgetHostView* GetActiveViewFromWebContents(WebContents* web_contents); +// This method will send an InputMsg_ImeSetComposition IPC with the provided +// parameters to the |render_widget_host|. +void SetCompositionForRenderWidgetHost( + RenderWidgetHost* render_widget_host, + const base::string16& text, + const std::vector<ui::CompositionUnderline>& underlines, + const gfx::Range& replacement_range, + int selection_start, + int selection_end); + // This class provides the necessary API for accessing the state of and also // observing the TextInputManager for WebContents. class TextInputManagerTester { @@ -53,6 +74,10 @@ // on the TextInputManager which is being observed. void SetOnSelectionBoundsChangedCallback(const base::Closure& callback); + // Sets a callback which is invoked when a RWHV calls + // ImeCompositionRangeChanged on the TextInputManager that is being observed. + void SetOnImeCompositionRangeChangedCallback(const base::Closure& callback); + // Returns true if there is a focused <input> and populates |type| with // |TextInputState.type| of the TextInputManager. bool GetTextInputType(ui::TextInputType* type);
diff --git a/content/renderer/history_controller.cc b/content/renderer/history_controller.cc index 5f0f28b..14ced356 100644 --- a/content/renderer/history_controller.cc +++ b/content/renderer/history_controller.cc
@@ -201,7 +201,8 @@ // a different frame. For main frames, it is not safe to leave the // current_entry_ in place, which may have a cross-site page and will be // included in the PageState for this commit. Replace it with a new - // HistoryEntry corresponding to the commit. + // HistoryEntry corresponding to the commit, and clear any stale + // NavigationParams which might point to the wrong entry. // // This will lack any subframe history items that were in the original // provisional entry, but we don't know what those were after discarding @@ -214,8 +215,10 @@ // main frame case. Since this bug is not present in the new // FrameNavigationEntry-based navigation path (https://crbug.com/236848) // we'll wait for that to fix the subframe case. - if (frame->IsMainFrame()) + if (frame->IsMainFrame()) { current_entry_.reset(new HistoryEntry(item)); + navigation_params_.reset(); + } return; } @@ -251,6 +254,13 @@ if (HistoryEntry::HistoryNode* node = current_entry_->GetHistoryNodeForFrame(frame)) { + // Clear the children and any NavigationParams if this commit isn't for + // the same item. Otherwise we might have stale data from a race. + if (node->item().itemSequenceNumber() != item.itemSequenceNumber()) { + node->RemoveChildren(); + navigation_params_.reset(); + } + node->set_item(item); } break;
diff --git a/content/renderer/history_controller.h b/content/renderer/history_controller.h index ff205967..ac52241 100644 --- a/content/renderer/history_controller.h +++ b/content/renderer/history_controller.h
@@ -153,11 +153,15 @@ // A HistoryEntry representing the page that is being loaded, or an empty // scoped_ptr if no page is being loaded. std::unique_ptr<HistoryEntry> provisional_entry_; - // The NavigationParams corresponding to the last load that was initiated by - // |GoToEntry|. This is kept around so that it can be passed into existing - // frames modified during a history navigation in GoToEntry(), and can be + + // The NavigationParams corresponding to the last back/forward load that was + // initiated by |GoToEntry|. This is kept around so that it can be passed into + // existing frames affected by a history navigation in GoToEntry(), and can be // passed into frames created after the commit that resulted from the // navigation in GetItemForNewChildFrame(). + // + // This is reset in UpdateForCommit if we see a commit from a different + // navigation, to avoid using stale parameters. std::unique_ptr<NavigationParams> navigation_params_; DISALLOW_COPY_AND_ASSIGN(HistoryController);
diff --git a/content/renderer/media/webmediaplayer_ms_compositor.cc b/content/renderer/media/webmediaplayer_ms_compositor.cc index e337e64..7f95ba1 100644 --- a/content/renderer/media/webmediaplayer_ms_compositor.cc +++ b/content/renderer/media/webmediaplayer_ms_compositor.cc
@@ -24,6 +24,7 @@ #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" #include "third_party/libyuv/include/libyuv/convert.h" +#include "third_party/libyuv/include/libyuv/planar_functions.h" #include "third_party/libyuv/include/libyuv/video_common.h" namespace content {
diff --git a/content/renderer/mus/render_widget_window_tree_client_factory.cc b/content/renderer/mus/render_widget_window_tree_client_factory.cc index a068781..ef56edd 100644 --- a/content/renderer/mus/render_widget_window_tree_client_factory.cc +++ b/content/renderer/mus/render_widget_window_tree_client_factory.cc
@@ -9,14 +9,11 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" #include "content/common/render_widget_window_tree_client_factory.mojom.h" -#include "content/public/common/connection_filter.h" #include "content/public/common/mojo_shell_connection.h" #include "content/renderer/mus/render_widget_mus_connection.h" #include "mojo/public/cpp/bindings/binding_set.h" +#include "services/shell/public/cpp/connection.h" #include "services/shell/public/cpp/interface_factory.h" #include "services/shell/public/cpp/service.h" #include "services/ui/public/interfaces/window_tree.mojom.h" @@ -26,34 +23,23 @@ namespace { -void BindMusConnectionOnMainThread( - uint32_t routing_id, - ui::mojom::WindowTreeClientRequest request) { - RenderWidgetMusConnection* connection = - RenderWidgetMusConnection::GetOrCreate(routing_id); - connection->Bind(std::move(request)); -} - // This object's lifetime is managed by MojoShellConnection because it's a // registered with it. class RenderWidgetWindowTreeClientFactoryImpl - : public ConnectionFilter, + : public shell::Service, public shell::InterfaceFactory< mojom::RenderWidgetWindowTreeClientFactory>, public mojom::RenderWidgetWindowTreeClientFactory { public: RenderWidgetWindowTreeClientFactoryImpl() { DCHECK(MojoShellConnection::GetForProcess()); - - main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get(); } ~RenderWidgetWindowTreeClientFactoryImpl() override {} private: - // ConnectionFilter implementation: - bool OnConnect(shell::Connection* connection, - shell::Connector* connector) override { + // shell::Service implementation: + bool OnConnect(shell::Connection* connection) override { connection->AddInterface<mojom::RenderWidgetWindowTreeClientFactory>(this); return true; } @@ -68,13 +54,12 @@ // mojom::RenderWidgetWindowTreeClientFactory implementation. void CreateWindowTreeClientForRenderWidget( uint32_t routing_id, - ui::mojom::WindowTreeClientRequest request) override { - main_thread_task_runner_->PostTask( - FROM_HERE, base::Bind(&BindMusConnectionOnMainThread, routing_id, - base::Passed(&request))); + mojo::InterfaceRequest<ui::mojom::WindowTreeClient> request) override { + RenderWidgetMusConnection* connection = + RenderWidgetMusConnection::GetOrCreate(routing_id); + connection->Bind(std::move(request)); } - scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_; mojo::BindingSet<mojom::RenderWidgetWindowTreeClientFactory> bindings_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetWindowTreeClientFactoryImpl); @@ -82,10 +67,9 @@ } // namespace -void CreateRenderWidgetWindowTreeClientFactory( - MojoShellConnection* connection) { - connection->AddConnectionFilter( - base::MakeUnique<RenderWidgetWindowTreeClientFactoryImpl>()); +void CreateRenderWidgetWindowTreeClientFactory() { + MojoShellConnection::GetForProcess()->MergeService( + base::WrapUnique(new RenderWidgetWindowTreeClientFactoryImpl)); } } // namespace content
diff --git a/content/renderer/mus/render_widget_window_tree_client_factory.h b/content/renderer/mus/render_widget_window_tree_client_factory.h index f32e30fa8..f3b3b73 100644 --- a/content/renderer/mus/render_widget_window_tree_client_factory.h +++ b/content/renderer/mus/render_widget_window_tree_client_factory.h
@@ -7,9 +7,7 @@ namespace content { -class MojoShellConnection; - -void CreateRenderWidgetWindowTreeClientFactory(MojoShellConnection* connection); +void CreateRenderWidgetWindowTreeClientFactory(); } // namespace content
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index ef0fc885..660b52b 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -142,8 +142,6 @@ #include "net/base/port_util.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/url_util.h" -#include "services/shell/public/cpp/interface_provider.h" -#include "services/shell/public/cpp/interface_registry.h" #include "skia/ext/event_tracer_impl.h" #include "skia/ext/skia_memory_dump_provider.h" #include "third_party/WebKit/public/platform/WebImageGenerator.h" @@ -851,6 +849,15 @@ GetInterfaceRegistry()->AddInterface(base::Bind(CreateFrameFactory)); GetInterfaceRegistry()->AddInterface(base::Bind(CreateEmbeddedWorkerSetup)); +#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA) + // We may not have a MojoShellConnection object in tests that directly + // instantiate a RenderThreadImpl. + if (MojoShellConnection::GetForProcess() && + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUseMusInRenderer)) + CreateRenderWidgetWindowTreeClientFactory(); +#endif + GetRemoteInterfaces()->GetInterface( mojo::GetProxy(&storage_partition_service_)); @@ -987,15 +994,6 @@ lazy_tls.Pointer()->Set(nullptr); } -void RenderThreadImpl::AddConnectionFilters(MojoShellConnection* connection) { -#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA) - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kUseMusInRenderer)) { - CreateRenderWidgetWindowTreeClientFactory(connection); - } -#endif -} - bool RenderThreadImpl::Send(IPC::Message* msg) { // There are cases where we want to pump asynchronous messages while waiting // synchronously for the replies to the message to be sent here. However, this
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 19fb8087..9a3795f 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -166,9 +166,6 @@ // changed. static void NotifyTimezoneChange(); - // ChildThreadImpl implementation: - void AddConnectionFilters(MojoShellConnection* connection) override; - // RenderThread implementation: bool Send(IPC::Message* msg) override; IPC::SyncChannel* GetChannel() override;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 2fb3aac..7990efe5 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -84,7 +84,6 @@ #include "media/blink/webcontentdecryptionmodule_impl.h" #include "media/filters/stream_parser_factory.h" #include "mojo/common/common_type_converters.h" -#include "services/shell/public/cpp/interface_provider.h" #include "storage/common/database/database_identifier.h" #include "storage/common/quota/quota_types.h" #include "third_party/WebKit/public/platform/BlameContext.h"
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index 30d6abd6..7988b852 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -43,8 +43,6 @@ #include "ipc/ipc_message.h" #include "ipc/ipc_message_macros.h" #include "mojo/public/cpp/bindings/interface_request.h" -#include "services/shell/public/cpp/interface_provider.h" -#include "services/shell/public/cpp/interface_registry.h" #include "third_party/WebKit/public/platform/URLConversion.h" #include "third_party/WebKit/public/platform/WebMessagePortChannel.h" #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index c0d3c92..aac19a8 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -653,8 +653,6 @@ # AMD self.Flaky('conformance/more/functions/uniformi.html', ['linux', 'amd'], bug=550989) - self.Fail('conformance/textures/misc/tex-image-webgl.html', - ['linux', 'amd'], bug=626742) # AMD Radeon 6450 self.Fail('conformance/extensions/angle-instanced-arrays.html',
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h index b467c0e..a21fc48f 100644 --- a/content/test/test_render_view_host.h +++ b/content/test/test_render_view_host.h
@@ -101,9 +101,6 @@ void SetIsLoading(bool is_loading) override {} void UpdateCursor(const WebCursor& cursor) override {} void ImeCancelComposition() override {} - void ImeCompositionRangeChanged( - const gfx::Range& range, - const std::vector<gfx::Rect>& character_bounds) override {} void RenderProcessGone(base::TerminationStatus status, int error_code) override; void Destroy() override;
diff --git a/docs/clang_tidy.md b/docs/clang_tidy.md new file mode 100644 index 0000000..9265e0cbf --- /dev/null +++ b/docs/clang_tidy.md
@@ -0,0 +1,108 @@ +# Clang Tidy + +[TOC] + +## Danger, Will Robinson! + +Support for `clang-tidy` in Chromium is very experimental, and is somewhat +painful to use. We are exploring making it easier and integrating with existing +tools, but aren't there yet. If you don't want to wait and enjoy tinkering, +forge ahead. Otherwise, feel free to turn back now. + +## Introduction + +[clang-tidy](http://clang.llvm.org/extra/clang-tidy/) is a clang-based C++ +“linter” tool. Its purpose is to provide an extensible framework for diagnosing +and fixing typical programming errors, like style violations, interface misuse, +or bugs that can be deduced via static analysis. + +## Setting Up + +In addition to a full Chromium checkout, you need the clang-tidy binary. We +recommend checking llvm's clang source and building the clang-tidy binary +directly. Instructions for getting started with clang are available from +[llvm](http://clang.llvm.org/get_started.html). You'll need to get llvm, +clang, and the extra clang tools (you won't need Compiler-RT or libcxx). +If you don't have it, you'll also need to install cmake as a part of this +process. + +Instead of building with `"Unix Makefiles"`, generate build files for Ninja with +``` +cmake -GNinja ../llvm +``` + +Then, instead of using `make`, use ninja to build the clang-tidy binary with +``` +ninja clang-tidy +``` + +This binary will be at (build)/bin/clang-tidy. + +If you intend to use the `fix` feature of clang-tidy, you'll also need to build +the `clang-apply-replacements` binary. +``` +ninja clang-apply-replacements +``` + +## Running clang-tidy + +Running clang-tidy is (hopefully) simple. +1. Build chrome normally.\* +``` +ninja -C out/Release chrome +``` +2. Generate the compilation database +``` +ninja -C out/Release -t compdb objcxx cxx > compile_commands.json +``` +3. Enter the build directory. +``` +cd out/Release +``` +4. Run clang-tidy. +``` +<PATH_TO_LLVM_SRC>/tools/clang/tools/extra/clang-tidy/tools/run-clang-tidy.py \ + -p ../.. \# Set the root project directory, where compile_commands.json is. + # Set the clang-tidy binary path, if it's not in your $PATH. + -clang-tidy-binary <PATH_TO_LLVM_BUILD>/bin/clang-tidy \ + # Set the clang-apply-replacements binary path, if it's not in your $PATH + # and you are using the `fix` behavior of clang-tidy. + -clang-apply-replacements-binary \ + <PATH_TO_LLVM_BUILD>/bin/clang-apply-replacements \ + # The checks to employ in the build. Use `-*` to omit default checks. + -checks=<CHECKS> \ + -header-filter=<FILTER> \# Optional, limit results to only certain files. + -fix \# Optional, used if you want to have clang-tidy auto-fix errors. + chrome/browser # The path to the files you want to check. + +Copy-Paste Friendly (though you'll still need to stub in the variables): +<PATH_TO_LLVM_SRC>/tools/clang/tools/extra/clang-tidy/tools/run-clang-tidy.py \ + -p ../.. \ + -clang-tidy-binary <PATH_TO_LLVM_BUILD>/bin/clang-tidy \ + -clang-apply-replacements-binary \ + <PATH_TO_LLVM_BUILD>/bin/clang-apply-replacements \ + -checks=<CHECKS> \ + -header-filter=<FILTER> \ + -fix \ + chrome/browser +``` + +\*It's not clear which, if any, `gn` flags may cause issues for `clang-tidy`. +I've had no problems building a component release build, both with and without +goma. if you run into issues, let us know! + +## Troubleshooting + +If you see errors like +``` +src/build/linux/debian_wheezy_amd64-sysroot/usr/include/wchar.h:40:11: error: 'stdarg.h' file not found [clang-diagnostic-error] +``` + +then you should also build the `clang-headers` target in your llvm checkout. +This is fixed by http://reviews.llvm.org/D22046, so if your llvm checkout is +up-to-date, this shouldn't be needed. + +## Questions + +Questions? Reach out to rdevlin.cronin@chromium.org or thakis@chromium.org. +Discoveries? Update the doc!
diff --git a/extensions/browser/extension_icon_image.cc b/extensions/browser/extension_icon_image.cc index fc0bc0d..94e6489 100644 --- a/extensions/browser/extension_icon_image.cc +++ b/extensions/browser/extension_icon_image.cc
@@ -43,13 +43,13 @@ namespace { extensions::ExtensionResource GetExtensionIconResource( - const extensions::Extension* extension, + const extensions::Extension& extension, const ExtensionIconSet& icons, int size, ExtensionIconSet::MatchType match_type) { const std::string& path = icons.Get(size, match_type); return path.empty() ? extensions::ExtensionResource() - : extension->GetResource(path); + : extension.GetResource(path); } class BlankImageSource : public gfx::CanvasImageSource { @@ -180,15 +180,15 @@ extensions::ExtensionResource resource; // Find extension resource for non bundled component extensions. - resource = GetExtensionIconResource(extension_, - icon_set_, - resource_size_in_pixel, - ExtensionIconSet::MATCH_BIGGER); + resource = + GetExtensionIconResource(*extension_, icon_set_, resource_size_in_pixel, + ExtensionIconSet::MATCH_BIGGER); // If resource is not found by now, try matching smaller one. if (resource.empty()) { - resource = GetExtensionIconResource(extension_, icon_set_, - resource_size_in_pixel, ExtensionIconSet::MATCH_SMALLER); + resource = + GetExtensionIconResource(*extension_, icon_set_, resource_size_in_pixel, + ExtensionIconSet::MATCH_SMALLER); } // If there is no resource found, return default icon. @@ -204,10 +204,9 @@ extensions::ImageLoader* loader = extensions::ImageLoader::Get(browser_context_); - loader->LoadImagesAsync(extension_, info_list, + loader->LoadImagesAsync(extension_.get(), info_list, base::Bind(&IconImage::OnImageLoaded, - weak_ptr_factory_.GetWeakPtr(), - scale)); + weak_ptr_factory_.GetWeakPtr(), scale)); return gfx::ImageSkiaRep(); } @@ -258,8 +257,8 @@ const Extension* extension = content::Details<const Extension>(details).ptr(); - if (extension_ == extension) - extension_ = NULL; + if (extension_.get() == extension) + extension_ = nullptr; } } // namespace extensions
diff --git a/extensions/browser/extension_icon_image.h b/extensions/browser/extension_icon_image.h index 75a4c2d..e3e29a3 100644 --- a/extensions/browser/extension_icon_image.h +++ b/extensions/browser/extension_icon_image.h
@@ -101,8 +101,8 @@ const content::NotificationDetails& details) override; content::BrowserContext* browser_context_; - const Extension* extension_; - const ExtensionIconSet& icon_set_; + scoped_refptr<const Extension> extension_; + ExtensionIconSet icon_set_; const int resource_size_in_dip_; base::ObserverList<Observer> observers_;
diff --git a/headless/lib/headless_devtools_client_browsertest.cc b/headless/lib/headless_devtools_client_browsertest.cc index daceba5d..65e8145 100644 --- a/headless/lib/headless_devtools_client_browsertest.cc +++ b/headless/lib/headless_devtools_client_browsertest.cc
@@ -183,7 +183,7 @@ devtools_client_->GetBrowser()->GetExperimental()->CreateTarget( browser::CreateTargetParams::Builder() - .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec()) + .SetUrl(embedded_test_server()->GetURL("/hello.html").spec()) .SetWidth(1) .SetHeight(1) .Build(), @@ -229,7 +229,7 @@ devtools_client_->GetBrowser()->GetExperimental()->CreateTarget( browser::CreateTargetParams::Builder() - .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec()) + .SetUrl(embedded_test_server()->GetURL("/hello.html").spec()) .SetBrowserContextId(context_id_) .Build(), base::Bind( @@ -323,7 +323,7 @@ devtools_client_->GetBrowser()->GetExperimental()->CreateTarget( browser::CreateTargetParams::Builder() - .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec()) + .SetUrl(embedded_test_server()->GetURL("/hello.html").spec()) .SetBrowserContextId(context_id_one_) .Build(), base::Bind(&BrowserDomainCreateTwoContexts::OnCreateTargetOneResult, @@ -331,7 +331,7 @@ devtools_client_->GetBrowser()->GetExperimental()->CreateTarget( browser::CreateTargetParams::Builder() - .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec()) + .SetUrl(embedded_test_server()->GetURL("/hello.html").spec()) .SetBrowserContextId(context_id_two_) .Build(), base::Bind(&BrowserDomainCreateTwoContexts::OnCreateTargetTwoResult,
diff --git a/media/base/mac/avfoundation_glue.h b/media/base/mac/avfoundation_glue.h index a5b4304..fb76958ae 100644 --- a/media/base/mac/avfoundation_glue.h +++ b/media/base/mac/avfoundation_glue.h
@@ -2,12 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// AVFoundation API is only introduced in Mac OS X > 10.6, and there is only one -// build of Chromium, so the (potential) linking with AVFoundation has to happen -// in runtime. For this to be clean, an AVFoundationGlue class is defined to try -// and load these AVFoundation system libraries. If it succeeds, subsequent -// clients can use AVFoundation via the rest of the classes declared in this -// file. +// TODO(mcasas): Remove this whole glue, https://crbug.com/579648. This glue was +// introduced to support Mac OS X <= 10.6 where AVFoundation was not available, +// and had to happen in runtime. #ifndef MEDIA_BASE_MAC_AVFOUNDATION_GLUE_H_ #define MEDIA_BASE_MAC_AVFOUNDATION_GLUE_H_ @@ -51,6 +48,7 @@ static Class AVCaptureSessionClass(); static Class AVCaptureVideoDataOutputClass(); + static Class AVCaptureStillImageOutputClass(); #endif // defined(__OBJC__) private: @@ -95,6 +93,9 @@ MEDIA_EXPORT @interface CrAVCaptureOutput : NSObject // Originally from AVCaptureOutput.h. + +- (NSArray*)connections; + @end // Originally AVCaptureSession and coming from AVCaptureSession.h. @@ -104,6 +105,7 @@ - (void)release; - (void)addInput:(CrAVCaptureInput*)input; - (void)removeInput:(CrAVCaptureInput*)input; +- (NSArray*)outputs; - (void)addOutput:(CrAVCaptureOutput*)output; - (void)removeOutput:(CrAVCaptureOutput*)output; - (BOOL)isRunning; @@ -156,6 +158,17 @@ @end +// Originally AVCaptureStillImageOutput and coming from AVCaptureOutput.h. +MEDIA_EXPORT +@interface CrAVCaptureStillImageOutput : CrAVCaptureOutput + +typedef void (^CompletionHandler)(CoreMediaGlue::CMSampleBufferRef, NSError*); +- (void) +captureStillImageAsynchronouslyFromConnection:(CrAVCaptureConnection*)connection + completionHandler:(CompletionHandler)handler; + +@end + // Class to provide access to class methods of AVCaptureDevice. MEDIA_EXPORT @interface AVCaptureDeviceGlue : NSObject
diff --git a/media/base/mac/avfoundation_glue.mm b/media/base/mac/avfoundation_glue.mm index 56f51aa..4bd6d72 100644 --- a/media/base/mac/avfoundation_glue.mm +++ b/media/base/mac/avfoundation_glue.mm
@@ -167,6 +167,10 @@ return [AVFoundationBundle() classNamed:@"AVCaptureVideoDataOutput"]; } +Class AVFoundationGlue::AVCaptureStillImageOutputClass() { + return [AVFoundationBundle() classNamed:@"AVCaptureStillImageOutput"]; +} + @implementation AVCaptureDeviceGlue + (NSArray*)devices {
diff --git a/media/base/mac/coremedia_glue.h b/media/base/mac/coremedia_glue.h index 9f69f96f..093427cd 100644 --- a/media/base/mac/coremedia_glue.h +++ b/media/base/mac/coremedia_glue.h
@@ -52,6 +52,7 @@ kCMPixelFormat_422YpCbCr8_yuvs = 'yuvs', }; enum { + kCMVideoCodecType_JPEG = 'jpeg', kCMVideoCodecType_JPEG_OpenDML = 'dmb1', kCMVideoCodecType_H264 = 'avc1', };
diff --git a/media/blink/webmediaplayer_cast_android.cc b/media/blink/webmediaplayer_cast_android.cc index 8f073b95..5ad9565 100644 --- a/media/blink/webmediaplayer_cast_android.cc +++ b/media/blink/webmediaplayer_cast_android.cc
@@ -18,8 +18,6 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkTypeface.h" -#include "third_party/skia/include/gpu/GrContext.h" -#include "third_party/skia/include/gpu/SkGrPixelRef.h" using gpu::gles2::GLES2Interface;
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.h b/media/capture/video/mac/video_capture_device_avfoundation_mac.h index 8198bcd..69082e7a 100644 --- a/media/capture/video/mac/video_capture_device_avfoundation_mac.h +++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
@@ -21,8 +21,9 @@ @class CrAVCaptureDevice; @class CrAVCaptureSession; @class CrAVCaptureVideoDataOutput; +@class CrAVCaptureStillImageOutput; -// Class used by VideoCaptureDeviceMac (VCDM) for video capture using +// Class used by VideoCaptureDeviceMac (VCDM) for video and image capture using // AVFoundation API. This class lives inside the thread created by its owner // VCDM. // @@ -62,7 +63,7 @@ int frameHeight_; float frameRate_; - base::Lock lock_; // Protects concurrent setting and using of frameReceiver_. + base::Lock lock_; // Protects concurrent setting and using |frameReceiver_|. media::VideoCaptureDeviceMac* frameReceiver_; // weak. base::scoped_nsobject<CrAVCaptureSession> captureSession_; @@ -74,6 +75,9 @@ CrAVCaptureDeviceInput* captureDeviceInput_; base::scoped_nsobject<CrAVCaptureVideoDataOutput> captureVideoDataOutput_; + // An AVDataOutput specialized for taking pictures out of |captureSession_|. + base::scoped_nsobject<CrAVCaptureStillImageOutput> stillImageOutput_; + base::ThreadChecker main_thread_checker_; } @@ -114,6 +118,10 @@ // Stops video capturing and stops listening to notifications. - (void)stopCapture; +// Takes a photo. This method should only be called between -startCapture and +// -stopCapture. +- (void)takePhoto; + @end #endif // MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm index 0f89a031..c47ff9c4 100644 --- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm +++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -95,8 +95,6 @@ } } -} // anonymous namespace - // This function translates Mac Core Video pixel formats to Chromium pixel // formats. media::VideoPixelFormat FourCCToChromiumPixelFormat(FourCharCode code) { @@ -112,6 +110,26 @@ } } +// Extracts |base_address| and |length| out of a SampleBuffer. +void ExtractBaseAddressAndLength( + char** base_address, + size_t* length, + CoreMediaGlue::CMSampleBufferRef sample_buffer) { + CoreMediaGlue::CMBlockBufferRef block_buffer = + CoreMediaGlue::CMSampleBufferGetDataBuffer(sample_buffer); + DCHECK(block_buffer); + + size_t length_at_offset; + const OSStatus status = CoreMediaGlue::CMBlockBufferGetDataPointer( + block_buffer, 0, &length_at_offset, length, base_address); + DCHECK_EQ(noErr, status); + // Expect the (M)JPEG data to be available as a contiguous reference, i.e. + // not covered by multiple memory blocks. + DCHECK_EQ(length_at_offset, *length); +} + +} // anonymous namespace + @implementation VideoCaptureDeviceAVFoundation #pragma mark Class methods @@ -217,6 +235,8 @@ // No need to release |captureDeviceInput_|, is owned by the session. captureDeviceInput_ = nil; } + if (stillImageOutput_) + [captureSession_ removeOutput:stillImageOutput_]; return YES; } @@ -261,6 +281,13 @@ queue:dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; [captureSession_ addOutput:captureVideoDataOutput_]; + + // Create and plug the still image capture output. This should happen in + // advance of the actual picture to allow for the 3A to stabilize. + stillImageOutput_.reset( + [[AVFoundationGlue::AVCaptureStillImageOutputClass() alloc] init]); + [captureSession_ addOutput:stillImageOutput_]; + return YES; } @@ -359,6 +386,48 @@ [[NSNotificationCenter defaultCenter] removeObserver:self]; } +- (void)takePhoto { + DCHECK(main_thread_checker_.CalledOnValidThread()); + DCHECK([captureSession_ isRunning]); + + DCHECK_EQ(1u, [[stillImageOutput_ connections] count]); + CrAVCaptureConnection* const connection = + [[stillImageOutput_ connections] firstObject]; + if (!connection) { + base::AutoLock lock(lock_); + frameReceiver_->OnPhotoError(); + return; + } + + const auto handler = ^(CoreMediaGlue::CMSampleBufferRef sampleBuffer, + NSError* error) { + base::AutoLock lock(lock_); + if (!frameReceiver_) + return; + if (error != nil) { + frameReceiver_->OnPhotoError(); + return; + } + + // Recommended compressed pixel format is JPEG, we don't expect surprises. + // TODO(mcasas): Consider using [1] for merging EXIF output information: + // [1] +(NSData*)jpegStillImageNSDataRepresentation:jpegSampleBuffer; + DCHECK_EQ( + CoreMediaGlue::kCMVideoCodecType_JPEG, + CoreMediaGlue::CMFormatDescriptionGetMediaSubType( + CoreMediaGlue::CMSampleBufferGetFormatDescription(sampleBuffer))); + + char* baseAddress = 0; + size_t length = 0; + ExtractBaseAddressAndLength(&baseAddress, &length, sampleBuffer); + frameReceiver_->OnPhotoTaken(reinterpret_cast<uint8_t*>(baseAddress), + length, "image/jpeg"); + }; + + [stillImageOutput_ captureStillImageAsynchronouslyFromConnection:connection + completionHandler:handler]; +} + #pragma mark Private methods // |captureOutput| is called by the capture device to deliver a new frame. @@ -381,17 +450,7 @@ size_t frameSize = 0; CVImageBufferRef videoFrame = nil; if (fourcc == CoreMediaGlue::kCMVideoCodecType_JPEG_OpenDML) { - // If MJPEG, use block buffer instead of pixel buffer. - CoreMediaGlue::CMBlockBufferRef blockBuffer = - CoreMediaGlue::CMSampleBufferGetDataBuffer(sampleBuffer); - if (blockBuffer) { - size_t lengthAtOffset; - CoreMediaGlue::CMBlockBufferGetDataPointer( - blockBuffer, 0, &lengthAtOffset, &frameSize, &baseAddress); - // Expect the MJPEG data to be available as a contiguous reference, i.e. - // not covered by multiple memory blocks. - CHECK_EQ(lengthAtOffset, frameSize); - } + ExtractBaseAddressAndLength(&baseAddress, &frameSize, sampleBuffer); } else { videoFrame = CoreMediaGlue::CMSampleBufferGetImageBuffer(sampleBuffer); // Lock the frame and calculate frame size.
diff --git a/media/capture/video/mac/video_capture_device_mac.h b/media/capture/video/mac/video_capture_device_mac.h index 88b986b..7eff128 100644 --- a/media/capture/video/mac/video_capture_device_mac.h +++ b/media/capture/video/mac/video_capture_device_mac.h
@@ -62,10 +62,12 @@ const VideoCaptureParams& params, std::unique_ptr<VideoCaptureDevice::Client> client) override; void StopAndDeAllocate() override; + void TakePhoto(TakePhotoCallback callback) override; bool Init(VideoCaptureDevice::Name::CaptureApiType capture_api_type); - // Called to deliver captured video frames. + // Called to deliver captured video frames. It's safe to call this method + // from any thread, including those controlled by AVFoundation. void ReceiveFrame(const uint8_t* video_frame, int video_frame_length, const VideoCaptureFormat& frame_format, @@ -73,6 +75,13 @@ int aspect_denominator, base::TimeDelta timestamp); + // Callbacks with the result of a still image capture, or in case of error, + // respectively. It's safe to call these methods from any thread. + void OnPhotoTaken(const uint8_t* image_data, + size_t image_length, + const std::string& mime_type); + void OnPhotoError(); + // Forwarder to VideoCaptureDevice::Client::OnError(). void ReceiveError(const tracked_objects::Location& from_here, const std::string& reason); @@ -99,6 +108,9 @@ base::scoped_nsobject<VideoCaptureDeviceAVFoundation> capture_device_; + // To hold on to the TakePhotoCallback while the picture is being taken. + std::unique_ptr<TakePhotoCallback> photo_callback_; + // Used with Bind and PostTask to ensure that methods aren't called after the // VideoCaptureDeviceMac is destroyed. // NOTE: Weak pointers must be invalidated before all other member variables.
diff --git a/media/capture/video/mac/video_capture_device_mac.mm b/media/capture/video/mac/video_capture_device_mac.mm index f032280..6ae6b8c 100644 --- a/media/capture/video/mac/video_capture_device_mac.mm +++ b/media/capture/video/mac/video_capture_device_mac.mm
@@ -389,6 +389,17 @@ state_ = kIdle; } +void VideoCaptureDeviceMac::TakePhoto(TakePhotoCallback callback) { + DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(state_ == kCapturing) << state_; + + if (photo_callback_) // Only one picture can be in flight at a time. + return; + + photo_callback_.reset(new TakePhotoCallback(std::move(callback))); + [capture_device_ takePhoto]; +} + bool VideoCaptureDeviceMac::Init( VideoCaptureDevice::Name::CaptureApiType capture_api_type) { DCHECK(task_runner_->BelongsToCurrentThread()); @@ -413,8 +424,6 @@ int aspect_numerator, int aspect_denominator, base::TimeDelta timestamp) { - // This method is safe to call from a device capture thread, i.e. any thread - // controlled by AVFoundation. if (capture_format_.frame_size != frame_format.frame_size) { ReceiveError(FROM_HERE, "Captured resolution " + frame_format.frame_size.ToString() + @@ -426,6 +435,26 @@ 0, base::TimeTicks::Now(), timestamp); } +void VideoCaptureDeviceMac::OnPhotoTaken(const uint8_t* image_data, + size_t image_length, + const std::string& mime_type) { + DCHECK(photo_callback_); + if (!image_data || !image_length) { + OnPhotoError(); + return; + } + + photo_callback_->Run(mojo::String::From(mime_type), + mojo::Array<uint8_t>(std::vector<uint8_t>( + image_data, image_data + image_length))); + photo_callback_.reset(); +} + +void VideoCaptureDeviceMac::OnPhotoError() { + DLOG(ERROR) << __FUNCTION__ << " error taking picture"; + photo_callback_.reset(); +} + void VideoCaptureDeviceMac::ReceiveError( const tracked_objects::Location& from_here, const std::string& reason) {
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc index 0ea3fb9..e71fb71 100644 --- a/media/capture/video/video_capture_device_unittest.cc +++ b/media/capture/video/video_capture_device_unittest.cc
@@ -19,6 +19,7 @@ #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" +#include "media/base/bind_to_current_loop.h" #include "media/base/video_capture_types.h" #include "media/capture/video/video_capture_device_factory.h" #include "testing/gmock/include/gmock/gmock.h" @@ -45,9 +46,11 @@ #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize // We will always get YUYV from the Mac AVFoundation implementations. #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg +#define MAYBE_TakePhoto TakePhoto #elif defined(OS_WIN) #define MAYBE_AllocateBadSize AllocateBadSize #define MAYBE_CaptureMjpeg CaptureMjpeg +#define MAYBE_TakePhoto DISABLED_TakePhoto #elif defined(OS_ANDROID) // TODO(wjia): enable those tests on Android. // On Android, native camera (JAVA) delivers frames on UI thread which is the @@ -57,6 +60,7 @@ #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg +#define MAYBE_TakePhoto DISABLED_TakePhoto #elif defined(OS_LINUX) // AllocateBadSize will hang when a real camera is attached and if more than one // test is trying to use the camera (even across processes). Do NOT renable @@ -64,9 +68,11 @@ // http://crbug.com/94134 http://crbug.com/137260 http://crbug.com/417824 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize #define MAYBE_CaptureMjpeg CaptureMjpeg +#define MAYBE_TakePhoto DISABLED_TakePhoto #else #define MAYBE_AllocateBadSize AllocateBadSize #define MAYBE_CaptureMjpeg CaptureMjpeg +#define MAYBE_TakePhoto DISABLED_TakePhoto #endif using ::testing::_; @@ -136,6 +142,30 @@ base::Callback<void(const VideoCaptureFormat&)> frame_cb_; }; +class MockImageCaptureClient : public base::RefCounted<MockImageCaptureClient> { + public: + // GMock doesn't support move-only arguments, so we use this forward method. + void DoOnPhotoTaken(mojo::String mime_type, mojo::Array<uint8_t> data) { + EXPECT_STREQ("image/jpeg", mime_type.storage().c_str()); + ASSERT_GT(data.size(), 4u); + // Check some bytes that univocally identify |data| as a JPEG File. + // https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#File_format_structure + EXPECT_EQ(0xFF, data[0]); // First SOI byte + EXPECT_EQ(0xD8, data[1]); // Second SOI byte + EXPECT_EQ(0xFF, data[2]); // First JFIF-APP0 byte + EXPECT_EQ(0xE0, data[3]); // Second JFIF-APP0 byte + OnCorrectPhotoTaken(); + } + MOCK_METHOD0(OnCorrectPhotoTaken, void(void)); + MOCK_METHOD1( + OnTakePhotoFailure, + void(const base::Callback<void(mojo::String, mojo::Array<uint8_t>)>&)); + + private: + friend class base::RefCounted<MockImageCaptureClient>; + virtual ~MockImageCaptureClient() {} +}; + class DeviceEnumerationListener : public base::RefCounted<DeviceEnumerationListener> { public: @@ -163,10 +193,10 @@ video_capture_client_(new MockVideoCaptureClient( base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured, base::Unretained(this)))), + device_enumeration_listener_(new DeviceEnumerationListener()), + image_capture_client_(new MockImageCaptureClient()), video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory( - base::ThreadTaskRunnerHandle::Get())) { - device_enumeration_listener_ = new DeviceEnumerationListener(); - } + base::ThreadTaskRunnerHandle::Get())) {} void SetUp() override { #if defined(OS_ANDROID) @@ -255,12 +285,14 @@ base::win::ScopedCOMInitializer initialize_com_; #endif std::unique_ptr<VideoCaptureDevice::Names> names_; - std::unique_ptr<base::MessageLoop> loop_; + const std::unique_ptr<base::MessageLoop> loop_; std::unique_ptr<base::RunLoop> run_loop_; std::unique_ptr<MockVideoCaptureClient> video_capture_client_; - scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; + const scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; + const scoped_refptr<MockImageCaptureClient> image_capture_client_; VideoCaptureFormat last_format_; - std::unique_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_; + const std::unique_ptr<VideoCaptureDeviceFactory> + video_capture_device_factory_; }; // Cause hangs on Windows Debug. http://crbug.com/417824 @@ -325,8 +357,7 @@ VideoCaptureParams capture_params; capture_params.requested_format.frame_size.SetSize(width, height); capture_params.requested_format.frame_rate = 30.0f; - capture_params.requested_format.pixel_format = - PIXEL_FORMAT_I420; + capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; device->AllocateAndStart(capture_params, std::move(video_capture_client_)); // Get captured video frames. WaitForCapturedFrame(); @@ -361,8 +392,7 @@ VideoCaptureParams capture_params; capture_params.requested_format.frame_size.SetSize(637, 472); capture_params.requested_format.frame_rate = 35; - capture_params.requested_format.pixel_format = - PIXEL_FORMAT_I420; + capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; device->AllocateAndStart(capture_params, std::move(video_capture_client_)); WaitForCapturedFrame(); device->StopAndDeAllocate(); @@ -484,10 +514,42 @@ // GetDeviceSupportedFormats(). std::unique_ptr<VideoCaptureDevice::Name> name = GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MAX); - // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else - // to test here + // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else to test here // since we cannot forecast the hardware capabilities. ASSERT_FALSE(name); } +// Start the camera and take a photo. +TEST_F(VideoCaptureDeviceTest, MAYBE_TakePhoto) { + names_ = EnumerateDevices(); + if (names_->empty()) { + VLOG(1) << "No camera available. Exiting test."; + return; + } + std::unique_ptr<VideoCaptureDevice> device( + video_capture_device_factory_->Create(names_->front())); + ASSERT_TRUE(device); + + EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); + + VideoCaptureParams capture_params; + capture_params.requested_format.frame_size.SetSize(640, 480); + capture_params.requested_format.frame_rate = 30; + capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; + device->AllocateAndStart(capture_params, std::move(video_capture_client_)); + WaitForCapturedFrame(); + + VideoCaptureDevice::TakePhotoCallback scoped_callback( + base::Bind(&MockImageCaptureClient::DoOnPhotoTaken, + image_capture_client_), + media::BindToCurrentLoop(base::Bind( + &MockImageCaptureClient::OnTakePhotoFailure, image_capture_client_))); + + EXPECT_CALL(*image_capture_client_.get(), OnCorrectPhotoTaken()).Times(1); + device->TakePhoto(std::move(scoped_callback)); + WaitForCapturedFrame(); + + device->StopAndDeAllocate(); +} + }; // namespace media
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc index 2ff9393..75d3fb8a 100644 --- a/media/filters/vpx_video_decoder.cc +++ b/media/filters/vpx_video_decoder.cc
@@ -44,6 +44,7 @@ } #include "third_party/libyuv/include/libyuv/convert.h" +#include "third_party/libyuv/include/libyuv/planar_functions.h" namespace media {
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 501575ec..e44fff26 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -318,6 +318,16 @@ least_unacked, true); } + std::unique_ptr<QuicEncryptedPacket> ConstructClientAckPacket( + QuicPacketNumber packet_number, + QuicPacketNumber largest_received, + QuicPacketNumber ack_least_unacked, + QuicPacketNumber stop_least_unacked) { + return client_maker_.MakeAckPacket(packet_number, largest_received, + ack_least_unacked, stop_least_unacked, + true); + } + std::unique_ptr<QuicEncryptedPacket> ConstructClientAckAndRstPacket( QuicPacketNumber num, QuicStreamId stream_id, @@ -330,24 +340,6 @@ stop_least_unacked, true); } - std::unique_ptr<QuicEncryptedPacket> ConstructClientAckPacket( - QuicPacketNumber largest_received, - QuicPacketNumber least_unacked, - QuicTestPacketMaker* maker) { - return client_maker_.MakeAckPacket(2, largest_received, least_unacked, - least_unacked, true); - } - - std::unique_ptr<QuicEncryptedPacket> ConstructClientAckPacket( - QuicPacketNumber packet_number, - QuicPacketNumber largest_received, - QuicPacketNumber ack_least_unacked, - QuicPacketNumber stop_least_unacked) { - return client_maker_.MakeAckPacket(packet_number, largest_received, - ack_least_unacked, stop_least_unacked, - true); - } - std::unique_ptr<QuicEncryptedPacket> ConstructClientAckAndConnectionClosePacket( QuicPacketNumber packet_number, @@ -458,36 +450,10 @@ QuicStreamId stream_id, bool should_include_version, bool fin, - SpdyHeaderBlock headers, - QuicStreamOffset* offset, - QuicTestPacketMaker* maker) { - SpdyPriority priority = - ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY); - return client_maker_.MakeRequestHeadersPacketWithOffsetTracking( - packet_number, stream_id, should_include_version, fin, priority, - std::move(headers), offset); - } - - std::unique_ptr<QuicEncryptedPacket> ConstructClientRequestHeadersPacket( - QuicPacketNumber packet_number, - QuicStreamId stream_id, - bool should_include_version, - bool fin, SpdyHeaderBlock headers) { - return ConstructClientRequestHeadersPacket( - packet_number, stream_id, should_include_version, fin, - std::move(headers), nullptr, &client_maker_); - } - std::unique_ptr<QuicEncryptedPacket> ConstructClientRequestHeadersPacket( - QuicPacketNumber packet_number, - QuicStreamId stream_id, - bool should_include_version, - bool fin, - SpdyHeaderBlock headers, - QuicTestPacketMaker* maker) { - return ConstructClientRequestHeadersPacket( - packet_number, stream_id, should_include_version, fin, - std::move(headers), nullptr, maker); + return ConstructClientRequestHeadersPacket(packet_number, stream_id, + should_include_version, fin, + std::move(headers), nullptr); } std::unique_ptr<QuicEncryptedPacket> ConstructServerPushPromisePacket( @@ -509,21 +475,9 @@ bool should_include_version, bool fin, SpdyHeaderBlock headers) { - return ConstructServerResponseHeadersPacket( - packet_number, stream_id, should_include_version, fin, - std::move(headers), nullptr, &server_maker_); - } - - std::unique_ptr<QuicEncryptedPacket> ConstructServerResponseHeadersPacket( - QuicPacketNumber packet_number, - QuicStreamId stream_id, - bool should_include_version, - bool fin, - SpdyHeaderBlock headers, - QuicTestPacketMaker* maker) { - return ConstructServerResponseHeadersPacket( - packet_number, stream_id, should_include_version, fin, - std::move(headers), nullptr, maker); + return ConstructServerResponseHeadersPacket(packet_number, stream_id, + should_include_version, fin, + std::move(headers), nullptr); } std::unique_ptr<QuicEncryptedPacket> ConstructServerResponseHeadersPacket( @@ -538,19 +492,6 @@ std::move(headers), offset); } - std::unique_ptr<QuicEncryptedPacket> ConstructServerResponseHeadersPacket( - QuicPacketNumber packet_number, - QuicStreamId stream_id, - bool should_include_version, - bool fin, - SpdyHeaderBlock headers, - QuicStreamOffset* offset, - QuicTestPacketMaker* maker) { - return server_maker_.MakeResponseHeadersPacketWithOffsetTracking( - packet_number, stream_id, should_include_version, fin, - std::move(headers), offset); - } - void CreateSession() { params_.enable_quic = true; params_.quic_clock = clock_; @@ -1408,10 +1349,10 @@ mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket( 3, kClientDataStreamId2, false, true, GetRequestHeaders("GET", "https", "/", &client_maker2), - &request_header_offset, &client_maker2)); + &request_header_offset)); mock_quic_data.AddRead(ConstructServerResponseHeadersPacket( 3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"), - &response_header_offset, &server_maker2)); + &response_header_offset)); mock_quic_data.AddRead(ConstructServerDataPacket(4, kClientDataStreamId2, false, true, 0, "hello!")); mock_quic_data.AddWrite( @@ -1516,7 +1457,7 @@ mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket( 3, kClientDataStreamId2, false, true, GetRequestHeaders("GET", "https", "/", &client_maker), - &request_header_offset, &client_maker)); + &request_header_offset)); mock_quic_data.AddRead(ConstructServerResponseHeadersPacket( 3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"), &response_header_offset));
diff --git a/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java b/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java index 3f518a6f..4cbd35ed 100644 --- a/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java +++ b/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java
@@ -570,6 +570,9 @@ } if (!mInputStrategy.isIndirectInputMode()) { + if (!mapScreenPointToImage(x, y)) { + return false; + } moveCursorToScreenPoint(x, y); } @@ -592,6 +595,9 @@ } if (!mInputStrategy.isIndirectInputMode()) { + if (!mapScreenPointToImage(x, y)) { + return; + } moveCursorToScreenPoint(x, y); } @@ -619,5 +625,22 @@ return InputStub.BUTTON_UNDEFINED; } } + + /** Verifies the given point maps to a valid location within the desktop image. */ + private boolean mapScreenPointToImage(float screenX, float screenY) { + float[] mappedPoints = {screenX, screenY}; + int imageWidth; + int imageHeight; + Matrix screenToImage = new Matrix(); + synchronized (mRenderData) { + mRenderData.transform.invert(screenToImage); + imageWidth = mRenderData.imageWidth; + imageHeight = mRenderData.imageHeight; + } + screenToImage.mapPoints(mappedPoints); + + return (mappedPoints[0] >= 0 && mappedPoints[0] <= imageWidth) + && (mappedPoints[1] >= 0 && mappedPoints[1] <= imageHeight); + } } }
diff --git a/remoting/codec/video_decoder_vpx.cc b/remoting/codec/video_decoder_vpx.cc index 2d59cc6c..07b4dca 100644 --- a/remoting/codec/video_decoder_vpx.cc +++ b/remoting/codec/video_decoder_vpx.cc
@@ -12,6 +12,7 @@ #include "remoting/base/util.h" #include "remoting/proto/video.pb.h" #include "third_party/libyuv/include/libyuv/convert_argb.h" +#include "third_party/libyuv/include/libyuv/convert_from.h" #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
diff --git a/services/navigation/BUILD.gn b/services/navigation/BUILD.gn index d719ed4..4d84fa5 100644 --- a/services/navigation/BUILD.gn +++ b/services/navigation/BUILD.gn
@@ -58,17 +58,12 @@ "view_impl.h", ] - public_deps = [ + deps = [ "//base", - "//content/public/common", - "//mojo/public/cpp/bindings", + "//content/public/browser", "//services/navigation/public/interfaces", "//services/shell/public/cpp", "//services/ui/public/cpp", - ] - - deps = [ - "//content/public/browser", "//skia", "//ui/gfx/geometry/mojo", "//ui/views",
diff --git a/services/navigation/content_client/content_browser_client.cc b/services/navigation/content_client/content_browser_client.cc index 744a4f3..c59aead 100644 --- a/services/navigation/content_client/content_browser_client.cc +++ b/services/navigation/content_client/content_browser_client.cc
@@ -36,8 +36,8 @@ void ContentBrowserClient::RegisterInProcessMojoApplications( StaticMojoApplicationMap* apps) { - content::MojoShellConnection::GetForProcess()->AddConnectionFilter( - base::MakeUnique<Navigation>()); + content::MojoShellConnection::GetForProcess()->MergeService( + base::WrapUnique(new Navigation)); } } // namespace navigation
diff --git a/services/navigation/navigation.cc b/services/navigation/navigation.cc index 3a86644..91e46ce 100644 --- a/services/navigation/navigation.cc +++ b/services/navigation/navigation.cc
@@ -6,37 +6,24 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" -#include "base/threading/thread_task_runner_handle.h" #include "services/navigation/view_impl.h" -#include "services/shell/public/cpp/connector.h" namespace navigation { -namespace { - -void CreateViewOnViewTaskRunner( - std::unique_ptr<shell::Connector> connector, - const std::string& client_user_id, - mojom::ViewClientPtr client, - mojom::ViewRequest request, - std::unique_ptr<shell::ServiceContextRef> context_ref) { - // Owns itself. - new ViewImpl(std::move(connector), client_user_id, std::move(client), - std::move(request), std::move(context_ref)); -} - -} // namespace - Navigation::Navigation() - : view_task_runner_(base::ThreadTaskRunnerHandle::Get()), - ref_factory_(base::MessageLoop::QuitWhenIdleClosure()) { + : ref_factory_(base::MessageLoop::QuitWhenIdleClosure()) { bindings_.set_connection_error_handler( base::Bind(&Navigation::ViewFactoryLost, base::Unretained(this))); } Navigation::~Navigation() {} -bool Navigation::OnConnect(shell::Connection* connection, - shell::Connector* connector) { +void Navigation::OnStart(shell::Connector* connector, + const shell::Identity& identity, + uint32_t instance_id) { + connector_ = connector; +} + +bool Navigation::OnConnect(shell::Connection* connection) { std::string remote_user_id = connection->GetRemoteIdentity().user_id(); if (!client_user_id_.empty() && client_user_id_ != remote_user_id) { LOG(ERROR) << "Must have a separate Navigation service instance for " @@ -57,14 +44,8 @@ void Navigation::CreateView(mojom::ViewClientPtr client, mojom::ViewRequest request) { - std::unique_ptr<shell::Connector> new_connector = connector_->Clone(); - std::unique_ptr<shell::ServiceContextRef> context_ref = - ref_factory_.CreateRef(); - view_task_runner_->PostTask( - FROM_HERE, - base::Bind(&CreateViewOnViewTaskRunner, base::Passed(&new_connector), - client_user_id_, base::Passed(&client), base::Passed(&request), - base::Passed(&context_ref))); + new ViewImpl(connector_, client_user_id_, std::move(client), + std::move(request), ref_factory_.CreateRef()); } void Navigation::ViewFactoryLost() {
diff --git a/services/navigation/navigation.h b/services/navigation/navigation.h index ded2c7db..3a731dd6 100644 --- a/services/navigation/navigation.h +++ b/services/navigation/navigation.h
@@ -5,9 +5,6 @@ #ifndef SERVICES_NAVIGATION_NAVIGATION_H_ #define SERVICES_NAVIGATION_NAVIGATION_H_ -#include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" -#include "content/public/common/connection_filter.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/navigation/public/interfaces/view.mojom.h" #include "services/shell/public/cpp/interface_factory.h" @@ -20,7 +17,7 @@ namespace navigation { -class Navigation : public content::ConnectionFilter, +class Navigation : public shell::Service, public shell::InterfaceFactory<mojom::ViewFactory>, public mojom::ViewFactory { public: @@ -28,9 +25,11 @@ ~Navigation() override; private: - // content::ConnectionFilter: - bool OnConnect(shell::Connection* connection, - shell::Connector* connector) override; + // shell::Service: + void OnStart(shell::Connector* connector, + const shell::Identity& identity, + uint32_t instance_id) override; + bool OnConnect(shell::Connection* connection) override; // shell::InterfaceFactory<mojom::ViewFactory>: void Create(shell::Connection* connection, @@ -42,8 +41,6 @@ void ViewFactoryLost(); - scoped_refptr<base::SequencedTaskRunner> view_task_runner_; - shell::Connector* connector_ = nullptr; std::string client_user_id_;
diff --git a/services/navigation/view_impl.cc b/services/navigation/view_impl.cc index 9a85fec0..6bb54cf85 100644 --- a/services/navigation/view_impl.cc +++ b/services/navigation/view_impl.cc
@@ -15,7 +15,6 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/web_contents.h" -#include "services/shell/public/cpp/connector.h" #include "services/ui/public/cpp/window_tree_client.h" #include "ui/views/controls/webview/webview.h" #include "ui/views/mus/native_widget_mus.h" @@ -57,12 +56,12 @@ } // namespace -ViewImpl::ViewImpl(std::unique_ptr<shell::Connector> connector, +ViewImpl::ViewImpl(shell::Connector* connector, const std::string& client_user_id, mojom::ViewClientPtr client, mojom::ViewRequest request, std::unique_ptr<shell::ServiceContextRef> ref) - : connector_(std::move(connector)), + : connector_(connector), binding_(this, std::move(request)), client_(std::move(client)), ref_(std::move(ref)), @@ -149,9 +148,8 @@ const std::string new_user_id = content::BrowserContext::GetShellUserIdFor( new_contents->GetBrowserContext()); - ViewImpl* impl = new ViewImpl( - connector_->Clone(), new_user_id, std::move(client), - std::move(view_request), ref_->Clone()); + ViewImpl* impl = new ViewImpl(connector_, new_user_id, std::move(client), + std::move(view_request), ref_->Clone()); // TODO(beng): This is a bit crappy. should be able to create the ViewImpl // with |new_contents| instead. impl->web_view_->SetWebContents(new_contents); @@ -274,7 +272,7 @@ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.delegate = this; params.native_widget = new views::NativeWidgetMus( - widget_.get(), connector_.get(), root, ui::mojom::SurfaceType::DEFAULT); + widget_.get(), connector_, root, ui::mojom::SurfaceType::DEFAULT); widget_->Init(params); widget_->Show(); }
diff --git a/services/navigation/view_impl.h b/services/navigation/view_impl.h index ad9b7edc..427afa1 100644 --- a/services/navigation/view_impl.h +++ b/services/navigation/view_impl.h
@@ -5,8 +5,6 @@ #ifndef SERVICES_NAVIGATION_VIEW_IMPL_H_ #define SERVICES_NAVIGATION_VIEW_IMPL_H_ -#include <memory> - #include "base/macros.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -34,7 +32,7 @@ public ui::WindowTreeClientDelegate, public views::WidgetDelegate { public: - ViewImpl(std::unique_ptr<shell::Connector> connector, + ViewImpl(shell::Connector* connector, const std::string& client_user_id, mojom::ViewClientPtr client, mojom::ViewRequest request, @@ -89,7 +87,7 @@ views::Widget* GetWidget() override; const views::Widget* GetWidget() const override; - std::unique_ptr<shell::Connector> connector_; + shell::Connector* connector_; mojo::StrongBinding<mojom::View> binding_; mojom::ViewClientPtr client_; std::unique_ptr<shell::ServiceContextRef> ref_;
diff --git a/services/shell/public/cpp/connection.h b/services/shell/public/cpp/connection.h index 1c78c7a1..eb49c2c8 100644 --- a/services/shell/public/cpp/connection.h +++ b/services/shell/public/cpp/connection.h
@@ -37,7 +37,8 @@ // interface_registry.h for more information. // // A Connection returned via Shell::ConnectToApplication() is owned by the -// caller. A Connection received via OnConnect is owned by the ServiceContext. +// caller. +// An Connection received via OnConnect is owned by the ServiceContext. // To close a connection, call CloseConnection which will destroy this object. class Connection { public:
diff --git a/services/shell/public/cpp/connector.h b/services/shell/public/cpp/connector.h index dfc440b..2f26e4c 100644 --- a/services/shell/public/cpp/connector.h +++ b/services/shell/public/cpp/connector.h
@@ -72,10 +72,6 @@ DISALLOW_COPY_AND_ASSIGN(ConnectParams); }; - // Creates a new Connector instance and fills in |*request| with a request - // for the other end the Connector's interface. - static std::unique_ptr<Connector> Create(mojom::ConnectorRequest* request); - // Requests a new connection to an application. Returns a pointer to the // connection if the connection is permitted by this application's delegate, // or nullptr otherwise. Caller takes ownership.
diff --git a/services/shell/public/cpp/interface_provider.h b/services/shell/public/cpp/interface_provider.h index 865ab8b..fe6930e 100644 --- a/services/shell/public/cpp/interface_provider.h +++ b/services/shell/public/cpp/interface_provider.h
@@ -18,8 +18,6 @@ // Connection. class InterfaceProvider { public: - using ForwardCallback = base::Callback<void(const mojo::String&, - mojo::ScopedMessagePipeHandle)>; class TestApi { public: explicit TestApi(InterfaceProvider* provider) : provider_(provider) {} @@ -43,17 +41,8 @@ InterfaceProvider(); ~InterfaceProvider(); - // Binds this InterfaceProvider to an actual mojom::InterfaceProvider pipe. - // It is an error to call this on a forwarding InterfaceProvider, i.e. this - // call is exclusive to Forward(). void Bind(mojom::InterfaceProviderPtr interface_provider); - // Sets this InterfaceProvider to forward all GetInterface() requests to - // |callback|. It is an error to call this on a bound InterfaceProvider, i.e. - // this call is exclusive to Bind(). In addition, and unlike Bind(), this MUST - // be called before any calls to GetInterface() are made. - void Forward(const ForwardCallback& callback); - // Returns a raw pointer to the remote InterfaceProvider. mojom::InterfaceProvider* get() { return interface_provider_.get(); } @@ -94,10 +83,6 @@ mojom::InterfaceProviderPtr interface_provider_; mojom::InterfaceProviderRequest pending_request_; - // A callback to receive all GetInterface() requests in lieu of the - // InterfaceProvider pipe. - ForwardCallback forward_callback_; - base::WeakPtrFactory<InterfaceProvider> weak_factory_; DISALLOW_COPY_AND_ASSIGN(InterfaceProvider);
diff --git a/services/shell/public/cpp/interface_registry.h b/services/shell/public/cpp/interface_registry.h index 0c6624e..98f85550 100644 --- a/services/shell/public/cpp/interface_registry.h +++ b/services/shell/public/cpp/interface_registry.h
@@ -6,10 +6,7 @@ #define SERVICES_SHELL_PUBLIC_CPP_INTERFACE_REGISTRY_H_ #include <memory> -#include <queue> -#include <utility> -#include "base/callback.h" #include "base/memory/ptr_util.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/shell/public/cpp/lib/callback_binder.h" @@ -43,9 +40,6 @@ // class InterfaceRegistry : public mojom::InterfaceProvider { public: - using Binder = base::Callback<void(const mojo::String&, - mojo::ScopedMessagePipeHandle)>; - class TestApi { public: explicit TestApi(InterfaceRegistry* registry) : registry_(registry) {} @@ -70,10 +64,6 @@ explicit InterfaceRegistry(Connection* connection); ~InterfaceRegistry() override; - // Sets a default handler for incoming interface requests which are allowed by - // capability filters but have no registered handler in this registry. - void set_default_binder(const Binder& binder) { default_binder_ = binder; } - void Bind(mojom::InterfaceProviderRequest local_interfaces_request); base::WeakPtr<InterfaceRegistry> GetWeakPtr(); @@ -142,15 +132,6 @@ NameToInterfaceBinderMap name_to_binder_; - Binder default_binder_; - - bool is_paused_ = false; - - // Pending interface requests which can accumulate if GetInterface() is called - // while binding is paused. - std::queue<std::pair<mojo::String, mojo::ScopedMessagePipeHandle>> - pending_interface_requests_; - base::WeakPtrFactory<InterfaceRegistry> weak_factory_; DISALLOW_COPY_AND_ASSIGN(InterfaceRegistry);
diff --git a/services/shell/public/cpp/lib/connector_impl.cc b/services/shell/public/cpp/lib/connector_impl.cc index 84af886..73c6723e 100644 --- a/services/shell/public/cpp/lib/connector_impl.cc +++ b/services/shell/public/cpp/lib/connector_impl.cc
@@ -19,12 +19,11 @@ Connector::ConnectParams::~ConnectParams() {} ConnectorImpl::ConnectorImpl(mojom::ConnectorPtrInfo unbound_state) - : unbound_state_(std::move(unbound_state)) { - thread_checker_.DetachFromThread(); -} + : unbound_state_(std::move(unbound_state)) {} ConnectorImpl::ConnectorImpl(mojom::ConnectorPtr connector) : connector_(std::move(connector)) { + thread_checker_.reset(new base::ThreadChecker); connector_.set_connection_error_handler( base::Bind(&ConnectorImpl::OnConnectionError, base::Unretained(this))); } @@ -32,7 +31,7 @@ ConnectorImpl::~ConnectorImpl() {} void ConnectorImpl::OnConnectionError() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(thread_checker_->CalledOnValidThread()); connector_.reset(); } @@ -42,12 +41,23 @@ } std::unique_ptr<Connection> ConnectorImpl::Connect(ConnectParams* params) { - if (!BindIfNecessary()) - return nullptr; + // Bind this object to the current thread the first time it is used to + // connect. + if (!connector_.is_bound()) { + if (!unbound_state_.is_valid()) { + // It's possible to get here when the link to the shell has been severed + // (and so the connector pipe has been closed) but the app has chosen not + // to quit. + return nullptr; + } + connector_.Bind(std::move(unbound_state_)); + connector_.set_connection_error_handler( + base::Bind(&ConnectorImpl::OnConnectionError, base::Unretained(this))); + thread_checker_.reset(new base::ThreadChecker); + } + DCHECK(thread_checker_->CalledOnValidThread()); - DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(params); - // We allow all interfaces on outgoing connections since we are presumably in // a position to know who we're talking to. CapabilityRequest request; @@ -102,41 +112,9 @@ } std::unique_ptr<Connector> ConnectorImpl::Clone() { - if (!BindIfNecessary()) - return nullptr; - mojom::ConnectorPtr connector; - mojom::ConnectorRequest request = GetProxy(&connector); - connector_->Clone(std::move(request)); - return base::MakeUnique<ConnectorImpl>(connector.PassInterface()); -} - -bool ConnectorImpl::BindIfNecessary() { - // Bind this object to the current thread the first time it is used to - // connect. - if (!connector_.is_bound()) { - if (!unbound_state_.is_valid()) { - // It's possible to get here when the link to the shell has been severed - // (and so the connector pipe has been closed) but the app has chosen not - // to quit. - return false; - } - - // Bind the ThreadChecker to this thread. - DCHECK(thread_checker_.CalledOnValidThread()); - - connector_.Bind(std::move(unbound_state_)); - connector_.set_connection_error_handler( - base::Bind(&ConnectorImpl::OnConnectionError, base::Unretained(this))); - } - - return true; -} - -std::unique_ptr<Connector> Connector::Create(mojom::ConnectorRequest* request) { - mojom::ConnectorPtr proxy; - *request = mojo::GetProxy(&proxy); - return base::MakeUnique<ConnectorImpl>(proxy.PassInterface()); + connector_->Clone(GetProxy(&connector)); + return base::WrapUnique(new ConnectorImpl(connector.PassInterface())); } } // namespace shell
diff --git a/services/shell/public/cpp/lib/connector_impl.h b/services/shell/public/cpp/lib/connector_impl.h index 003e3fd..9ab5bebe 100644 --- a/services/shell/public/cpp/lib/connector_impl.h +++ b/services/shell/public/cpp/lib/connector_impl.h
@@ -28,12 +28,10 @@ std::unique_ptr<Connection> Connect(ConnectParams* params) override; std::unique_ptr<Connector> Clone() override; - bool BindIfNecessary(); - mojom::ConnectorPtrInfo unbound_state_; mojom::ConnectorPtr connector_; - base::ThreadChecker thread_checker_; + std::unique_ptr<base::ThreadChecker> thread_checker_; DISALLOW_COPY_AND_ASSIGN(ConnectorImpl); };
diff --git a/services/shell/public/cpp/lib/interface_provider.cc b/services/shell/public/cpp/lib/interface_provider.cc index 0934ee15..209d356 100644 --- a/services/shell/public/cpp/lib/interface_provider.cc +++ b/services/shell/public/cpp/lib/interface_provider.cc
@@ -4,32 +4,19 @@ #include "services/shell/public/cpp/interface_provider.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/strong_binding.h" - namespace shell { InterfaceProvider::InterfaceProvider() : weak_factory_(this) { pending_request_ = GetProxy(&interface_provider_); } - InterfaceProvider::~InterfaceProvider() {} void InterfaceProvider::Bind(mojom::InterfaceProviderPtr interface_provider) { DCHECK(pending_request_.is_pending()); - DCHECK(forward_callback_.is_null()); mojo::FuseInterface(std::move(pending_request_), interface_provider.PassInterface()); } -void InterfaceProvider::Forward(const ForwardCallback& callback) { - DCHECK(pending_request_.is_pending()); - DCHECK(forward_callback_.is_null()); - interface_provider_.reset(); - pending_request_.PassMessagePipe().reset(); - forward_callback_ = callback; -} - void InterfaceProvider::SetConnectionLostClosure( const base::Closure& connection_lost_closure) { interface_provider_.set_connection_error_handler(connection_lost_closure); @@ -48,14 +35,7 @@ it->second.Run(std::move(request_handle)); return; } - - if (!forward_callback_.is_null()) { - DCHECK(!interface_provider_.is_bound()); - forward_callback_.Run(name, std::move(request_handle)); - } else { - DCHECK(interface_provider_.is_bound()); - interface_provider_->GetInterface(name, std::move(request_handle)); - } + interface_provider_->GetInterface(name, std::move(request_handle)); } void InterfaceProvider::ClearBinders() {
diff --git a/services/shell/public/cpp/lib/interface_registry.cc b/services/shell/public/cpp/lib/interface_registry.cc index b585eae..ebfaddd 100644 --- a/services/shell/public/cpp/lib/interface_registry.cc +++ b/services/shell/public/cpp/lib/interface_registry.cc
@@ -39,29 +39,20 @@ } void InterfaceRegistry::PauseBinding() { - DCHECK(!is_paused_); - is_paused_ = true; + DCHECK(!pending_request_.is_pending()); + DCHECK(binding_.is_bound()); + pending_request_ = binding_.Unbind(); } void InterfaceRegistry::ResumeBinding() { - DCHECK(is_paused_); - is_paused_ = false; - - while (!pending_interface_requests_.empty()) { - auto& request = pending_interface_requests_.front(); - GetInterface(request.first, std::move(request.second)); - pending_interface_requests_.pop(); - } + DCHECK(pending_request_.is_pending()); + DCHECK(!binding_.is_bound()); + binding_.Bind(std::move(pending_request_)); } // mojom::InterfaceProvider: void InterfaceRegistry::GetInterface(const mojo::String& interface_name, mojo::ScopedMessagePipeHandle handle) { - if (is_paused_) { - pending_interface_requests_.emplace(interface_name, std::move(handle)); - return; - } - auto iter = name_to_binder_.find(interface_name); if (iter != name_to_binder_.end()) { iter->second->BindInterface(connection_, interface_name, std::move(handle)); @@ -70,8 +61,6 @@ << "interface: " << interface_name << " connection_name:" << connection_->GetConnectionName() << " remote_name:" << connection_->GetRemoteIdentity().name(); - } else if (!default_binder_.is_null()) { - default_binder_.Run(interface_name, std::move(handle)); } }
diff --git a/services/shell/public/cpp/lib/service_context.cc b/services/shell/public/cpp/lib/service_context.cc index 1a9cd42..e5458dd 100644 --- a/services/shell/public/cpp/lib/service_context.cc +++ b/services/shell/public/cpp/lib/service_context.cc
@@ -10,6 +10,7 @@ #include "mojo/public/cpp/bindings/interface_ptr.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "services/shell/public/cpp/capabilities.h" +#include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/lib/connection_impl.h" #include "services/shell/public/cpp/lib/connector_impl.h" #include "services/shell/public/cpp/service.h" @@ -19,24 +20,29 @@ //////////////////////////////////////////////////////////////////////////////// // ServiceContext, public: -ServiceContext::ServiceContext(shell::Service* service, - mojom::ServiceRequest request, - std::unique_ptr<Connector> connector, - mojom::ConnectorRequest connector_request) - : pending_connector_request_(std::move(connector_request)), - service_(service), - binding_(this, std::move(request)), - connector_(std::move(connector)) { - DCHECK(binding_.is_bound()); - if (!connector_) { - connector_ = Connector::Create(&pending_connector_request_); - } else { - DCHECK(pending_connector_request_.is_pending()); - } +ServiceContext::ServiceContext(shell::Service* client, + mojom::ServiceRequest request) + : client_(client), binding_(this) { + mojom::ConnectorPtr connector; + pending_connector_request_ = GetProxy(&connector); + connector_.reset(new ConnectorImpl(std::move(connector))); + + DCHECK(request.is_pending()); + binding_.Bind(std::move(request)); } ServiceContext::~ServiceContext() {} +void ServiceContext::set_initialize_handler(const base::Closure& callback) { + initialize_handler_ = callback; +} + +void ServiceContext::SetAppTestConnectorForTesting( + mojom::ConnectorPtr connector) { + pending_connector_request_ = nullptr; + connector_.reset(new ConnectorImpl(std::move(connector))); +} + void ServiceContext::SetConnectionLostClosure(const base::Closure& closure) { connection_lost_closure_ = closure; if (should_run_connection_lost_closure_ && @@ -60,7 +66,7 @@ binding_.set_connection_error_handler( base::Bind(&ServiceContext::OnConnectionError, base::Unretained(this))); - service_->OnStart(connector_.get(), identity_, id); + client_->OnStart(connector_.get(), identity_, id); } void ServiceContext::OnConnect( @@ -75,16 +81,29 @@ allowed_capabilities.To<CapabilityRequest>(), Connection::State::CONNECTED)); - std::unique_ptr<InterfaceRegistry> exposed_interfaces( - new InterfaceRegistry(registry.get())); - exposed_interfaces->Bind(std::move(local_interfaces)); - registry->SetExposedInterfaces(std::move(exposed_interfaces)); + InterfaceRegistry* exposed_interfaces = + client_->GetInterfaceRegistryForConnection(); + if (exposed_interfaces) { + exposed_interfaces->Bind(std::move(local_interfaces)); + registry->set_exposed_interfaces(exposed_interfaces); + } else { + std::unique_ptr<InterfaceRegistry> interfaces( + new InterfaceRegistry(registry.get())); + interfaces->Bind(std::move(local_interfaces)); + registry->SetExposedInterfaces(std::move(interfaces)); + } + shell::InterfaceProvider* remote_interface_provider = + client_->GetInterfaceProviderForConnection(); + if (remote_interface_provider) { + remote_interface_provider->Bind(std::move(remote_interfaces)); + registry->set_remote_interfaces(remote_interface_provider); + } else { + std::unique_ptr<InterfaceProvider> interfaces(new InterfaceProvider); + interfaces->Bind(std::move(remote_interfaces)); + registry->SetRemoteInterfaces(std::move(interfaces)); + } - std::unique_ptr<InterfaceProvider> interfaces(new InterfaceProvider); - interfaces->Bind(std::move(remote_interfaces)); - registry->SetRemoteInterfaces(std::move(interfaces)); - - if (!service_->OnConnect(registry.get())) + if (!client_->OnConnect(registry.get())) return; // TODO(beng): it appears we never prune this list. We should, when the @@ -99,7 +118,7 @@ // Note that the Service doesn't technically have to quit now, it may live // on to service existing connections. All existing Connectors however are // invalid. - should_run_connection_lost_closure_ = service_->OnStop(); + should_run_connection_lost_closure_ = client_->OnStop(); if (should_run_connection_lost_closure_ && !connection_lost_closure_.is_null()) connection_lost_closure_.Run();
diff --git a/services/shell/public/cpp/service_context.h b/services/shell/public/cpp/service_context.h index 504efd0f..2cad395 100644 --- a/services/shell/public/cpp/service_context.h +++ b/services/shell/public/cpp/service_context.h
@@ -11,15 +11,17 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/memory/scoped_vector.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/core.h" -#include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/service.h" #include "services/shell/public/interfaces/connector.mojom.h" #include "services/shell/public/interfaces/service.mojom.h" namespace shell { +class Connector; + // Encapsulates a connection to the Service Manager in two parts: // - a bound InterfacePtr to mojom::Connector, the primary mechanism // by which the instantiating service connects to other services, @@ -43,20 +45,22 @@ public: // Creates a new ServiceContext bound to |request|. This connection may be // used immediately to make outgoing connections via connector(). Does not - // take ownership of |service|, which must remain valid for the lifetime of - // ServiceContext. If either |connector| or |connector_request| is non-null - // both must be non-null. If both are null, the connection will create its own - // Connector and request to pass to the Service Manager on initialization. - ServiceContext(shell::Service* service, - mojom::ServiceRequest request, - std::unique_ptr<Connector> connector = nullptr, - mojom::ConnectorRequest connector_request = nullptr); + // take ownership of |client|, which must remain valid for the lifetime of + // ServiceContext. + ServiceContext(shell::Service* client, + mojom::ServiceRequest request); ~ServiceContext() override; Connector* connector() { return connector_.get(); } const Identity& identity() { return identity_; } + // TODO(rockot): Remove this. http://crbug.com/594852. + void set_initialize_handler(const base::Closure& callback); + + // TODO(rockot): Remove this once we get rid of app tests. + void SetAppTestConnectorForTesting(mojom::ConnectorPtr connector); + // Specify a function to be called when the connection to the shell is lost. // Note that if connection has already been lost, then |closure| is called // immediately. @@ -81,13 +85,13 @@ // We track the lifetime of incoming connection registries as it more // convenient for the client. - std::vector<std::unique_ptr<Connection>> incoming_connections_; + ScopedVector<Connection> incoming_connections_; // A pending Connector request which will eventually be passed to the Service // Manager. mojom::ConnectorRequest pending_connector_request_; - shell::Service* service_; + shell::Service* client_; mojo::Binding<mojom::Service> binding_; std::unique_ptr<Connector> connector_; shell::Identity identity_;
diff --git a/testing/android/native_test/native_test_launcher.cc b/testing/android/native_test/native_test_launcher.cc index 3b5ee83..aadf06a 100644 --- a/testing/android/native_test/native_test_launcher.cc +++ b/testing/android/native_test/native_test_launcher.cc
@@ -50,7 +50,7 @@ // This function runs in a compromised context. It should not allocate memory. void SignalHandler(int sig, siginfo_t* info, void* reserved) { // Output the crash marker. - write(STDOUT_FILENO, kCrashedMarker, sizeof(kCrashedMarker)); + write(STDOUT_FILENO, kCrashedMarker, sizeof(kCrashedMarker) - 1); g_old_sa[sig].sa_sigaction(sig, info, reserved); }
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 471589c..8e76b1d9 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -195,13 +195,34 @@ # TODO(oshima): Mac Android are currently not supported. crbug.com/567837 [ Mac Android ] virtual/scalefactor200withzoom/fast/hidpi/static [ Skip ] -# TODO(oshima): Debug build generates slightly different image for these tests due to different background color. -#crbug.com/593567 [ Debug ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ Skip ] -crbug.com/593567 [ Debug ] virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ Skip ] -crbug.com/593567 virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance.html [ Skip ] -crbug.com/593567 [ Debug ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ Skip ] -crbug.com/593567 [ Debug ] virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance.html [ Skip ] -crbug.com/593567 [ Debug ] virtual/scalefactor200withzoom/fast/hidpi/static/calendar-picker-appearance.html [ Skip ] +crbug.com/613414 [ Win ] fast/hidpi/broken-image-icon-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] svg/custom/masking-clipping-hidpi.svg [ NeedsRebaseline ] +crbug.com/613414 [ Win ] css3/filters/effect-reference-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/hidpi/device-scale-factor-paint.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/hidpi/focus-rings.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] css3/filters/effect-reference-hidpi-hw.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/hidpi/resize-corner-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/hidpi/broken-image-with-size-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] virtual/gpu/fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/sub-pixel/shadows-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] compositing/tiled-layers-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] svg/as-image/image-respects-deviceScaleFactor.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/hidpi/clip-text-in-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/backgrounds/gradient-background-leakage-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/hidpi/gradient-with-scaled-ancestor.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] editing/spelling/grammar-markers-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] editing/spelling/inline-spelling-markers-hidpi.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] editing/spelling/inline-spelling-markers-hidpi-composited.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] fast/hidpi/image-srcset-intrinsic-size-zero.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] svg/filters/filter-source-position.svg [ NeedsRebaseline ] +crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance.html [ NeedsRebaseline ] +crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance.html [ NeedsRebaseline ] # Mac does not support fractional scale factor. crbug.com/567837 [ Mac ] virtual/scalefactor150/fast/hidpi/static [ Skip ] @@ -1312,6 +1333,8 @@ crbug.com/624019 [ Mac ] bluetooth/notifications/stop-twice.html [ Skip ] crbug.com/624019 [ Mac ] bluetooth/notifications/stop-without-starting.html [ Skip ] +crbug.com/626992 paint/invalidation/outline-containing-image-in-non-standard-mode.html [ NeedsRebaseline ] + crbug.com/487344 compositing/video/video-controls-layer-creation.html [ Failure ] crbug.com/487344 fast/hidpi/video-controls-in-hidpi.html [ Failure ] crbug.com/487344 fast/layers/video-layer.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/element-animate-iterable-keyframes.html b/third_party/WebKit/LayoutTests/animations/element-animate-iterable-keyframes.html similarity index 100% rename from third_party/WebKit/LayoutTests/web-animations-api/element-animate-iterable-keyframes.html rename to third_party/WebKit/LayoutTests/animations/element-animate-iterable-keyframes.html
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/align-absolute-child.html b/third_party/WebKit/LayoutTests/css3/flexbox/align-absolute-child.html index 345ce2c..cbbc97eb 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/align-absolute-child.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/align-absolute-child.html
@@ -59,7 +59,6 @@ } </style> -<script src="../../resources/js-test.js"></script> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../resources/check-layout-th.js"></script> @@ -145,8 +144,11 @@ var afterPosition = absolute.getBoundingClientRect(); // Positioned element should not change position when the height of it's parent flexbox is changed. -for (key in beforePosition) - shouldBe('beforePosition[key]', 'afterPosition[key]'); +for (key in beforePosition) { + test(function() { + assert_equals(beforePosition[key], afterPosition[key]); + }, 'position of ' + key); +} </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button-expected.txt deleted file mode 100644 index 6c19de14..0000000 --- a/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button-expected.txt +++ /dev/null
@@ -1,14 +0,0 @@ -Check if box-orient is working in <button>. See https://bugs.webkit.org/show_bug.cgi?id=25406 - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -PASS gebi('default').clientHeight is referenceHorizontalHeight -PASS gebi('horizontal').clientHeight is referenceHorizontalHeight -PASS gebi('vertical').clientHeight is referenceVerticalHeight -PASS gebi('toHorizontal').clientHeight is referenceHorizontalHeight -PASS gebi('toVertical').clientHeight is referenceVerticalHeight -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button.html b/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button.html index e580d8c..16771c9 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/box-orient-button.html
@@ -19,10 +19,12 @@ display: flex; } </style> -<script src="../../resources/js-test.js"></script> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> </head> <body> -<p id="description"></p> +<p id="description">Check if box-orient is working in <button>. See https://bugs.webkit.org/show_bug.cgi?id=25406</p> +<div id="log"></p> <div id="main"> <p> reference of horizontal button:<br>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get-expected.txt deleted file mode 100644 index a0d1b61..0000000 --- a/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -Test that setting and getting display: flex and inline-flex works as expected - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -Test getting |display| set through CSS -PASS getComputedStyle(flexboxElement, '').getPropertyValue('display') is 'flex' -PASS getComputedStyle(inlineFlexboxElement, '').getPropertyValue('display') is 'inline-flex' - -Test getting and setting display through JS -PASS getComputedStyle(element, '').getPropertyValue('display') is 'block' -PASS getComputedStyle(element, '').getPropertyValue('display') is 'flex' -PASS getComputedStyle(element, '').getPropertyValue('display') is 'block' -PASS getComputedStyle(element, '').getPropertyValue('display') is 'inline-flex' -PASS getComputedStyle(element, '').getPropertyValue('display') is 'flex' -PASS getComputedStyle(element, '').getPropertyValue('display') is 'inline-flex' -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get.html b/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get.html index 0daa782..69f47f4a 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/display-flexbox-set-get.html
@@ -2,37 +2,41 @@ <html> <head> <link href="resources/flexbox.css" rel="stylesheet"> -<script src="../../resources/js-test.js"></script> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> </head> <body> +<p>Test that setting and getting display: flex and inline-flex works as expected</p> +<div id="log"></div> <div class="flexbox" id="flexbox"></div> <div class="inline-flexbox" id="flexboxInline"></div> <script> -description('Test that setting and getting display: flex and inline-flex works as expected'); -debug("Test getting |display| set through CSS"); +test(function() { var flexboxElement = document.getElementById("flexbox"); -shouldBe("getComputedStyle(flexboxElement, '').getPropertyValue('display')", "'flex'"); +assert_equals(getComputedStyle(flexboxElement, '').getPropertyValue('display'), 'flex'); var inlineFlexboxElement = document.getElementById("flexboxInline"); -shouldBe("getComputedStyle(inlineFlexboxElement, '').getPropertyValue('display')", "'inline-flex'"); +assert_equals(getComputedStyle(inlineFlexboxElement, '').getPropertyValue('display'), 'inline-flex'); +}, "Test getting |display| set through CSS"); -debug(""); -debug("Test getting and setting display through JS"); +test(function() { var element = document.createElement("div"); document.body.appendChild(element); -shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'block'"); +assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'block'); element.style.display = "flex"; -shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'flex'"); +assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'flex'); element = document.createElement("div"); document.body.appendChild(element); -shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'block'"); +assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'block'); element.style.display = "inline-flex"; -shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'inline-flex'"); +assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'inline-flex'); element.style.display = "-webkit-flex"; -shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'flex'"); +assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'flex'); element.style.display = "-webkit-inline-flex"; -shouldBe("getComputedStyle(element, '').getPropertyValue('display')", "'inline-flex'"); +assert_equals(getComputedStyle(element, '').getPropertyValue('display'), 'inline-flex'); + +}, "Test getting and setting display through JS"); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial-expected.txt deleted file mode 100644 index 14e54ea1..0000000 --- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -Tests that 'initial' is handled correctly for the flex-flow shorthand. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -PASS window.getComputedStyle(test1).flexDirection is "row" -PASS window.getComputedStyle(test2).flexDirection is "row" -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial.html index 35c5978..87f9b10 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-initial.html
@@ -13,15 +13,19 @@ flex-direction: initial; } </style> +<p>Tests that 'initial' is handled correctly for the flex-flow shorthand.</p> +<div id="log"></div> <span id="test1"></span> <span id="test2"></span> -<script src="../../resources/js-test.js"></script> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <script> -description("Tests that 'initial' is handled correctly for the flex-flow shorthand."); value1 = window.getComputedStyle(test1).flexDirection; value2 = window.getComputedStyle(test2).flexDirection; -shouldBeEqualToString('window.getComputedStyle(test1).flexDirection', 'row'); -shouldBeEqualToString('window.getComputedStyle(test2).flexDirection', 'row'); +test(function() { +assert_equals(window.getComputedStyle(test1).flexDirection, "row"); +assert_equals(window.getComputedStyle(test2).flexDirection, "row"); +}, "initial value is correct"); if (window.testRunner) testRunner.dumpAsText(); </script>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flexitem-no-margin-collapsing.html b/third_party/WebKit/LayoutTests/css3/flexbox/flexitem-no-margin-collapsing.html index 71ee9200..d21f5db 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/flexitem-no-margin-collapsing.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/flexitem-no-margin-collapsing.html
@@ -13,7 +13,6 @@ background-color: blue; } </style> -<script src="../../resources/js-test.js"></script> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../resources/check-layout-th.js"></script>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash-expected.txt index 4e8436fe..8b13789 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash-expected.txt +++ b/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash-expected.txt
@@ -1,9 +1 @@ -This test passes if it does not crash. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -PASS successfullyParsed is true - -TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash.html b/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash.html index 68be93b4..433e808 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/mainAxisExtent-crash.html
@@ -1,8 +1,9 @@ <!DOCTYPE html> <html style="display: inline-flex;"> -<script src="../../resources/js-test.js"></script> <script> -description('This test passes if it does not crash.'); +if (window.testRunner) + testRunner.dumpAsText(); </script> +<title>This test passes if it does not crash.</title> <frameset></frameset> -</html> \ No newline at end of file +</html>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/min-size-auto.html b/third_party/WebKit/LayoutTests/css3/flexbox/min-size-auto.html index a9c25860..0959549 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/min-size-auto.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/min-size-auto.html
@@ -1,7 +1,6 @@ <!DOCTYPE html> <link href="resources/flexbox.css" rel="stylesheet"> -<script src="../../resources/js-test.js"></script> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../resources/check-layout-th.js"></script>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos-expected.txt deleted file mode 100644 index 83a9959..0000000 --- a/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -PASS successfullyParsed is true - -TEST COMPLETE -PASS document.querySelector('.overflow-auto').scrollTop is 50 -
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos.html b/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos.html index 117db77..19ab2df 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/overflow-keep-scrollpos.html
@@ -1,7 +1,8 @@ <!DOCTYPE html> <html> <head> -<script src="../../resources/js-test.js"></script> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <style> div.flexbox { display: flex; @@ -21,12 +22,13 @@ function runTest() { document.querySelector('.overflow-auto').scrollTop = 50; document.querySelector('#sidebar').innerHTML = ''; - shouldBe("document.querySelector('.overflow-auto').scrollTop", "50"); + assert_equals(document.querySelector('.overflow-auto').scrollTop, 50); } </script> </head> -<body onload="runTest()"> +<body onload="test(runTest, 'Scroll position is correct')"> +<div id=log></div> <div class="container flexbox"> <div class="flex overflow-auto flexbox"> <div style="height: 400px"></div>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/resources/box-orient-button.js b/third_party/WebKit/LayoutTests/css3/flexbox/resources/box-orient-button.js index 84f135f..1e4a5eb 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/resources/box-orient-button.js +++ b/third_party/WebKit/LayoutTests/css3/flexbox/resources/box-orient-button.js
@@ -1,4 +1,3 @@ -description("Check if box-orient is working in <button>. See https://bugs.webkit.org/show_bug.cgi?id=25406"); function setFlexDirection(element, flexDirection) { element.style.webkitFlexDirection = flexDirection; @@ -14,12 +13,8 @@ var referenceHorizontalHeight = gebi("reference_horizontal").clientHeight; var referenceVerticalHeight = gebi("reference_vertical").clientHeight; -shouldBe("gebi('default').clientHeight", "referenceHorizontalHeight"); -shouldBe("gebi('horizontal').clientHeight", "referenceHorizontalHeight"); -shouldBe("gebi('vertical').clientHeight", "referenceVerticalHeight"); -shouldBe("gebi('toHorizontal').clientHeight", "referenceHorizontalHeight"); -shouldBe("gebi('toVertical').clientHeight", "referenceVerticalHeight"); - -// If we are in DRT, we don't need meaningless messages. -if (window.testRunner) - document.getElementById("main").innerHTML = ""; +test(function() { assert_equals(gebi('default').clientHeight, referenceHorizontalHeight); }, "default height"); +test(function() { assert_equals(gebi('horizontal').clientHeight, referenceHorizontalHeight); }, "horizontal height"); +test(function() { assert_equals(gebi('vertical').clientHeight, referenceVerticalHeight); }, "vertical height"); +test(function() { assert_equals(gebi('toHorizontal').clientHeight, referenceHorizontalHeight); }, "toHorizontal height"); +test(function() { assert_equals(gebi('toVertical').clientHeight, referenceVerticalHeight); }, "toVertical height");
diff --git a/third_party/WebKit/LayoutTests/fullscreen/full-screen-will-change.html b/third_party/WebKit/LayoutTests/fullscreen/full-screen-will-change.html index 38e68b6..9186be1 100644 --- a/third_party/WebKit/LayoutTests/fullscreen/full-screen-will-change.html +++ b/third_party/WebKit/LayoutTests/fullscreen/full-screen-will-change.html
@@ -1,26 +1,7 @@ <!DOCTYPE html> <html> <style> - #bad { - position: fixed; - top: 0px; - left: 0px; - background-color: red; - width: 100%; - height: 100%; - } - - #fixed-container { - position: fixed; - top: 0px; - left: 0px; - z-index: 0; - } - - #fullscreenme { - height: 400px; - width: 400px; - border: 0px; + #container { will-change: transform; } </style> @@ -51,10 +32,8 @@ window.addEventListener("load", doTest, false); </script> <body> - <!-- when full screening the iframe, bad should not be visible --> - <div id="fixed-container"> + <div id="container"> <iframe id="fullscreenme" src="resources/green.html"></iframe> </div> - <div id="bad"></div> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-multiple-attach.html b/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-multiple-attach.html index 6cc7bdc6..971198a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-multiple-attach.html +++ b/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-multiple-attach.html
@@ -108,6 +108,25 @@ test.done(); }); }, 'Test that MediaSource can reattach if closed first'); + + mediasource_test(function(test, mediaElement, mediaSource) { + assert_equals(mediaSource.readyState, 'open', 'Source open'); + // Generate two different unique URLs for MediaSource + var url1 = URL.createObjectURL(mediaSource); + var url2 = URL.createObjectURL(mediaSource); + assert_not_equals(url1, url2, 'URLs not unique'); + // Revoke the first url + URL.revokeObjectURL(url1); + // And use the second, non-revoked URL to reopen the media source + test.expectEvent(mediaSource, 'sourceopen', 'Source reopened'); + mediaElement.src = url2; + assert_equals(mediaSource.readyState, 'closed', 'Source closed'); + test.waitForExpectedEvents(function() + { + assert_equals(mediaSource.readyState, 'open', 'Source opened'); + test.done(); + }); + }, 'Generate multiple unique URLs via URL.createObjectURL and revoke an URL'); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation-expected.txt deleted file mode 100644 index 4675af2..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation-expected.txt +++ /dev/null
@@ -1,3 +0,0 @@ -Tests that we don't crash when detaching on pause from instrumentation call. -Paused on the innerHTML assignment: modifyHTML@:7 -
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation.html deleted file mode 100644 index 47c38d7..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/detach-when-paused-in-instrumentation.html +++ /dev/null
@@ -1,33 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script> -<script> - -function modifyHTML() -{ - document.getElementById("divUnderTest").innerHTML = "innerHTML"; -} - -function test() -{ - InspectorTest.sendCommand("Debugger.enable", {}); - InspectorTest.sendCommand("DOM.enable", {}); - InspectorTest.sendCommand("DOMDebugger.enable", {}); - InspectorTest.sendCommand("DOMDebugger.setInstrumentationBreakpoint", {"eventName":"setInnerHTML"}); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "modifyHTML()" }); - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedOne; - - function handleDebuggerPausedOne(messageObject) - { - var callFrame = messageObject.params.callFrames[0]; - InspectorTest.log("Paused on the innerHTML assignment: " + callFrame.functionName + "@:" + callFrame.location.lineNumber); - InspectorTest.completeTest(); - } -} -</script> -</head> -<body onLoad="runTest();"> -<div id="divUnderTest"></div> -Tests that we don't crash when detaching on pause from instrumentation call. -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal-expected.txt index d88e126..9bb1912f 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal-expected.txt
@@ -4,8 +4,25 @@ Object {a: 1, b: 2} {a:1} Object {a: 1} -{var a = 1; eval("{a :1, b:2 }");} -VM:1 Uncaught SyntaxError: Unexpected identifier +{var a = 1; eval("{ a:1, b:2 }");} + VM:1 Uncaught SyntaxError: Unexpected token :(…) +(anonymous function) @ VM:1 { for (var i = 0; i < 5; ++i); } -VM:1 Uncaught SyntaxError: Unexpected token var +undefined +{ a: 4 }),({ b: 7 } +VM:1 Uncaught SyntaxError: Unexpected token ) +{ let a = 4; a; } +4 +{ let a = 4; }; { let b = 5; }; +undefined +{ a: 4 } + { a: 5 } +"[object Object][object Object]" +{ a: 4 }, { a: 5 } +Object {a: 5} +var foo = 4; +undefined +{ a: foo++ } +Object {a: 4} +foo; +5
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal.html b/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal.html index afa3fd3..ac1c2e5 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal.html +++ b/third_party/WebKit/LayoutTests/inspector/console/console-eval-object-literal.html
@@ -5,7 +5,22 @@ <script> function test() { - var commands = ["{a:1, b:2}", "{a:1}", "{var a = 1; eval(\"{a :1, b:2 }\");}", "{ for (var i = 0; i < 5; ++i); }"]; + var commands = [ + "{a:1, b:2}", + "{a:1}", + "{var a = 1; eval(\"{ a:1, b:2 }\");}", + "{ for (var i = 0; i < 5; ++i); }", + "{ a: 4 }),({ b: 7 }", + "{ let a = 4; a; }", + "{ let a = 4; }; { let b = 5; };", + "{ a: 4 } + { a: 5 }", + "{ a: 4 }, { a: 5 }", + + // Test that detection doesn't incur side effects. + "var foo = 4;", + "{ a: foo++ }", + "foo;" + ]; var current = -1; loopOverCommands(); function loopOverCommands()
diff --git a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt index ba9cfe33..d56aeaa 100644 --- a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt +++ b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt
@@ -2,8 +2,6 @@ CONSOLE ERROR: line 71: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture. CONSOLE WARNING: line 71: Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture. CONSOLE ERROR: line 71: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture. -CONSOLE WARNING: IntersectionObserver.observe(target): target element is not a descendant of root. -CONSOLE WARNING: IntersectionObserver.observe(target): target element is not a descendant of root. CONSOLE WARNING: line 71: Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture. CONSOLE ERROR: line 71: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture. CONSOLE WARNING: line 71: Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture.
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.html new file mode 100644 index 0000000..b82cd951 --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.html
@@ -0,0 +1,3 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<!-- Almost Standards mode --> +<span id="target" style="outline: 2px solid green"><img style="width: 200px; height: 50px"></span>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt new file mode 100644 index 0000000..28ceb64 --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt
@@ -0,0 +1,47 @@ +{ + "name": "Content Root Layer", + "bounds": [800, 600], + "children": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "drawsContent": true, + "paintInvalidations": [ + { + "object": "LayoutInline SPAN id='target'", + "rect": [6, 6, 204, 58], + "reason": "style change" + }, + { + "object": "LayoutImage IMG", + "rect": [8, 8, 200, 50], + "reason": "forced by layout" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutBlockFlow BODY", + "reason": "forced by layout" + }, + { + "object": "RootInlineBox", + "reason": "forced by layout" + }, + { + "object": "LayoutInline SPAN id='target'", + "reason": "style change" + }, + { + "object": "InlineFlowBox", + "reason": "style change" + }, + { + "object": "LayoutImage IMG", + "reason": "forced by layout" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode.html b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode.html new file mode 100644 index 0000000..f2e17f2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/outline-containing-image-in-non-standard-mode.html
@@ -0,0 +1,12 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<!-- Almost Standards mode --> +<script src="../../fast/repaint/resources/text-based-repaint.js"></script> +<script> +function repaintTest() { + target.style.outlineColor = "green"; +} +onload = runRepaintAndPixelTest; +</script> +<body style="height: 0"> + <span id="target" style="outline: 2px solid red"><img style="width: 200px; height: 50px"></span> +</body>
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png deleted file mode 100644 index dc0df09..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/image-object-in-canvas-expected.png deleted file mode 100644 index 7ed279a..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux-precise/fast/canvas/image-object-in-canvas-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png new file mode 100644 index 0000000..a1ae22d --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes-expected.txt new file mode 100644 index 0000000..cb3ff3a --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +FAIL Custom iterator with basic keyframes. effect.getKeyframes is not a function +FAIL easing and offset are ignored on iterable objects. effect.getKeyframes is not a function +FAIL Custom iterator with multiple properties specified. effect.getKeyframes is not a function +FAIL Custom iterator with offset specified. effect.getKeyframes is not a function +PASS Custom iterator with non object keyframe should throw. +FAIL Custom iterator with value list in keyframe should give bizarre string representation of list. effect.getKeyframes is not a function +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes.html new file mode 100644 index 0000000..1cd20ff --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/keyframe-effect-iterable-keyframes.html
@@ -0,0 +1,122 @@ +<!DOCTYPE html> +<meta charset='utf-8'> +<title>Test that KeyframeEffect can take iterable objects as keyframes</title> +<link rel='help' href='https://w3c.github.io/web-animations/#processing-a-keyframes-argument'> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<body></body> +<script> +function assertAnimationEffect({keyframes, expect}) { + var effect = new KeyframeEffect(null, keyframes); + var frames = effect.getKeyframes(); + for (let i = 0; i < expect.length; i++) { + assert_equals(frames[i].computedOffset, expect[i].at); + for (var property in expect[i].is) + assert_equals(frames[i][property], expect[i].is[property], + `${property} is ${expect[i].is[property]} at ${expect[i].at}`); + } + return frames; +} + +function createIterable(iterations) { + return { + [Symbol.iterator]() { + var i = 0; + return {next: () => iterations[i++]}; + }, + }; +} + +test(() => { + assertAnimationEffect({ + keyframes: createIterable([ + {done: false, value: {left: '100px'}}, + {done: false, value: {left: '300px'}}, + {done: false, value: {left: '200px'}}, + {done: true}, + ]), + expect: [ + {at: 0, is: {left: '100px'}}, + {at: 0.5, is: {left: '300px'}}, + {at: 1, is: {left: '200px'}}, + ], + }); +}, 'Custom iterator with basic keyframes.'); + +test(() => { + var keyframes = createIterable([ + {done: false, value: {left: '100px'}}, + {done: false, value: {left: '300px'}}, + {done: false, value: {left: '200px'}}, + {done: true}, + ]); + keyframes.easing = 'ease-in-out'; + keyframes.offset = '0.1'; + let frames = assertAnimationEffect({ + keyframes, + expect: [ + {at: 0, is: {left: '100px'}}, + {at: 0.5, is: {left: '300px'}}, + {at: 1, is: {left: '200px'}}, + ], + }); + assert_equals(frames[0].easing, 'linear'); + assert_equals(frames[0].offset, null); +}, 'easing and offset are ignored on iterable objects.'); + +test(() => { + assertAnimationEffect({ + keyframes: createIterable([ + {done: false, value: {left: '100px', top: '200px'}}, + {done: false, value: {left: '300px'}}, + {done: false, value: {left: '200px', top: '100px'}}, + {done: true}, + ]), + expect: [ + {at: 0, is: {left: '100px', top: '200px'}}, + {at: 0.5, is: {left: '300px'}}, + {at: 1, is: {left: '200px', top: '100px'}}, + ], + }); +}, 'Custom iterator with multiple properties specified.'); + +test(() => { + assertAnimationEffect({ + keyframes: createIterable([ + {done: false, value: {left: '100px'}}, + {done: false, value: {left: '250px', offset: 0.75}}, + {done: false, value: {left: '200px'}}, + {done: true}, + ]), + expect: [ + {at: 0, is: {left: '100px'}}, + {at: 0.75, is: {left: '250px'}}, + {at: 1, is: {left: '200px'}}, + ], + }); +}, 'Custom iterator with offset specified.'); + +test(() => { + assert_throws({name: 'TypeError'}, () => { + assertAnimationEffect({ + keyframes: createIterable([ + {done: false, value: {left: '100px'}}, + {done: false, value: 1234}, + {done: false, value: {left: '200px'}}, + {done: true}, + ]), + expect: [], + }); + }); +}, 'Custom iterator with non object keyframe should throw.'); + +test(() => { + assertAnimationEffect({ + keyframes: createIterable([ + {done: false, value: {left: ['100px', '200px']}}, + {done: true}, + ]), + expect: [{at: 1, is: {left: "100px,200px"}}], + }); +}, 'Custom iterator with value list in keyframe should give bizarre string representation of list.'); +</script>
diff --git a/third_party/WebKit/PRESUBMIT.py b/third_party/WebKit/PRESUBMIT.py index b6d2afc1..5f060cc 100644 --- a/third_party/WebKit/PRESUBMIT.py +++ b/third_party/WebKit/PRESUBMIT.py
@@ -206,8 +206,8 @@ 'instead, as these can be more easily upstreamed to Web Platform ' 'Tests for cross-vendor compatibility testing. If you\'re not ' 'already familiar with this framework, a tutorial is available at ' - 'https://darobin.github.io/test-harness-tutorial/docs/using-testharness.html.' - 'with the new framework.\n\n%s' % '\n'.join(errors))] + 'https://darobin.github.io/test-harness-tutorial/docs/using-testharness.html' + '\n\n%s' % '\n'.join(errors))] return [] def _CheckForFailInFile(input_api, f):
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp b/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp index 7230fd4..2c1739f 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
@@ -125,8 +125,12 @@ } const DOMWrapperWorld& currentWorld = DOMWrapperWorld::world(m_context); RELEASE_ASSERT(currentWorld.worldId() == DOMWrapperWorld::world(contextForWrapper).worldId()); - if (currentWorld.isMainWorld()) { - RELEASE_ASSERT(BindingSecurity::shouldAllowAccessToFrame(isolate, currentDOMWindow(isolate), frame, DoNotReportSecurityError)); + if (currentWorld.isMainWorld() && !BindingSecurity::shouldAllowAccessToFrame(isolate, currentDOMWindow(isolate), frame, DoNotReportSecurityError)) { + // TODO(jochen): Add the interface name here once this is generalized. + ExceptionState exceptionState(ExceptionState::ConstructionContext, nullptr, contextForWrapper->Global(), isolate); + exceptionState.throwSecurityError(String(), String()); + exceptionState.throwIfNeeded(); + return; } }
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi index 1dbdbf37..aec61cf8 100644 --- a/third_party/WebKit/Source/core/core.gypi +++ b/third_party/WebKit/Source/core/core.gypi
@@ -2845,8 +2845,6 @@ 'webcore_html_files': [ 'html/AutoplayExperimentHelper.cpp', 'html/AutoplayExperimentHelper.h', - 'html/AutoplayUmaHelper.cpp', - 'html/AutoplayUmaHelper.h', 'html/ClassList.cpp', 'html/ClassList.h', 'html/CrossOriginAttribute.cpp',
diff --git a/third_party/WebKit/Source/core/css/fullscreen.css b/third_party/WebKit/Source/core/css/fullscreen.css index 1ff986e2..f6a773a7 100644 --- a/third_party/WebKit/Source/core/css/fullscreen.css +++ b/third_party/WebKit/Source/core/css/fullscreen.css
@@ -19,7 +19,7 @@ -webkit-box-reflect: none !important; -webkit-perspective: none !important; -webkit-transform-style: flat !important; - will-change: none !important; + will-change: auto !important; } video:-webkit-full-screen, audio:-webkit-full-screen {
diff --git a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp deleted file mode 100644 index e9be0cc..0000000 --- a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "core/html/AutoplayUmaHelper.h" - -#include "core/dom/ElementVisibilityObserver.h" -#include "core/events/Event.h" -#include "core/html/HTMLMediaElement.h" -#include "platform/Histogram.h" - -namespace blink { - -namespace { - -void recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(bool visible) -{ - DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, ("Media.Video.Autoplay.Muted.PlayMethod.BecomesVisible")); - histogram.count(visible); -} - -} // namespace - -AutoplayUmaHelper* AutoplayUmaHelper::create(HTMLMediaElement* element) -{ - return new AutoplayUmaHelper(element); -} - -AutoplayUmaHelper::AutoplayUmaHelper(HTMLMediaElement* element) - : EventListener(CPPEventListenerType) - , m_source(AutoplaySource::NumberOfSources) - , m_element(element) - , m_videoMutedPlayMethodVisibilityObserver(nullptr) { } - -AutoplayUmaHelper::~AutoplayUmaHelper() = default; - -bool AutoplayUmaHelper::operator==(const EventListener& other) const -{ - return this == &other; -} - -void AutoplayUmaHelper::onAutoplayInitiated(AutoplaySource source) -{ - DEFINE_STATIC_LOCAL(EnumerationHistogram, videoHistogram, ("Media.Video.Autoplay", static_cast<int>(AutoplaySource::NumberOfSources))); - DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, ("Media.Video.Autoplay.Muted", static_cast<int>(AutoplaySource::NumberOfSources))); - DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, ("Media.Audio.Autoplay", static_cast<int>(AutoplaySource::NumberOfSources))); - - m_source = source; - - if (m_element->isHTMLVideoElement()) { - videoHistogram.count(static_cast<int>(m_source)); - if (m_element->muted()) - mutedVideoHistogram.count(static_cast<int>(m_source)); - } else { - audioHistogram.count(static_cast<int>(m_source)); - } - - if (m_source == AutoplaySource::Method && m_element->isHTMLVideoElement() && m_element->muted()) - m_element->addEventListener(EventTypeNames::playing, this, false); -} - -void AutoplayUmaHelper::onElementDestroyed() -{ - if (m_videoMutedPlayMethodVisibilityObserver) { - recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(false); - m_videoMutedPlayMethodVisibilityObserver->stop(); - m_videoMutedPlayMethodVisibilityObserver = nullptr; - } -} - -void AutoplayUmaHelper::recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus status) -{ - DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayUnmuteHistogram, ("Media.Video.Autoplay.Muted.UnmuteAction", static_cast<int>(AutoplayUnmuteActionStatus::NumberOfStatus))); - - autoplayUnmuteHistogram.count(static_cast<int>(status)); -} - -void AutoplayUmaHelper::onVisibilityChangedForVideoMutedPlayMethod(bool isVisible) -{ - if (!isVisible) - return; - - recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(true); - m_videoMutedPlayMethodVisibilityObserver->stop(); - m_videoMutedPlayMethodVisibilityObserver = nullptr; -} - -void AutoplayUmaHelper::handleEvent(ExecutionContext* executionContext, Event* event) -{ - DCHECK(event->type() == EventTypeNames::playing); - handlePlayingEvent(); -} - -void AutoplayUmaHelper::handlePlayingEvent() -{ - if (m_source == AutoplaySource::Method && m_element->isHTMLVideoElement() && m_element->muted()) { - if (!m_videoMutedPlayMethodVisibilityObserver) { - m_videoMutedPlayMethodVisibilityObserver = new ElementVisibilityObserver(m_element, WTF::bind(&AutoplayUmaHelper::onVisibilityChangedForVideoMutedPlayMethod, wrapPersistent(this))); - m_videoMutedPlayMethodVisibilityObserver->start(); - } - } - m_element->removeEventListener(EventTypeNames::playing, this, false); -} - -DEFINE_TRACE(AutoplayUmaHelper) -{ - EventListener::trace(visitor); - visitor->trace(m_element); - visitor->trace(m_videoMutedPlayMethodVisibilityObserver); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h deleted file mode 100644 index 913b74e..0000000 --- a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2016 The Chromium 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 AutoplayUmaHelper_h -#define AutoplayUmaHelper_h - -#include "core/events/EventListener.h" -#include "platform/heap/Handle.h" - -namespace blink { - -// These values are used for histograms. Do not reorder. -enum class AutoplaySource { - // Autoplay comes from HTMLMediaElement `autoplay` attribute. - Attribute = 0, - // Autoplay comes from `play()` method. - Method = 1, - // This enum value must be last. - NumberOfSources = 2, -}; - -// These values are used for histograms. Do not reorder. -enum class AutoplayUnmuteActionStatus { - Failure = 0, - Success = 1, - NumberOfStatus = 2, -}; - -class ElementVisibilityObserver; -class HTMLMediaElement; - -class AutoplayUmaHelper final : public EventListener { -public: - static AutoplayUmaHelper* create(HTMLMediaElement*); - - ~AutoplayUmaHelper(); - - bool operator==(const EventListener&) const override; - - void onAutoplayInitiated(AutoplaySource); - void onElementDestroyed(); - - void recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus); - - void onVisibilityChangedForVideoMutedPlayMethod(bool isVisible); - - DECLARE_VIRTUAL_TRACE(); - -private: - explicit AutoplayUmaHelper(HTMLMediaElement*); - - void handleEvent(ExecutionContext*, Event*) override; - - void handlePlayingEvent(); - - // The autoplay source. Use AutoplaySource::NumberOfSources for invalid source. - AutoplaySource m_source; - // The media element this UMA helper is attached to. |m_element| owns |this|. - WeakMember<HTMLMediaElement> m_element; - // The observer is used to observe whether a muted video autoplaying by play() method become visible at some point. - Member<ElementVisibilityObserver> m_videoMutedPlayMethodVisibilityObserver; -}; - -} // namespace blink - -#endif // AutoplayUmaHelper_h
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp index 07dba32..5a63b92 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -44,7 +44,6 @@ #include "core/frame/Settings.h" #include "core/frame/UseCounter.h" #include "core/frame/csp/ContentSecurityPolicy.h" -#include "core/html/AutoplayUmaHelper.h" #include "core/html/HTMLMediaSource.h" #include "core/html/HTMLSourceElement.h" #include "core/html/HTMLTrackElement.h" @@ -281,6 +280,16 @@ return String(); } +// These values are used for histograms. Do not reorder. +enum AutoplaySource { + // Autoplay comes from HTMLMediaElement `autoplay` attribute. + AutoplaySourceAttribute = 0, + // Autoplay comes from `play()` method. + AutoplaySourceMethod = 1, + // This enum value must be last. + NumberOfAutoplaySources = 2, +}; + } // anonymous namespace class HTMLMediaElement::AutoplayHelperClientImpl : @@ -438,7 +447,6 @@ , m_audioSourceNode(nullptr) , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)) , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient.get())) - , m_autoplayUmaHelper(AutoplayUmaHelper::create(this)) , m_remotePlaybackClient(nullptr) , m_autoplayVisibilityObserver(nullptr) { @@ -482,8 +490,6 @@ // See Document::isDelayingLoadEvent(). // Also see http://crbug.com/275223 for more details. clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); - - m_autoplayUmaHelper->onElementDestroyed(); } void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) @@ -1620,7 +1626,7 @@ // Check for autoplay, and record metrics about it if needed. if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { - m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); + recordAutoplaySourceMetric(AutoplaySourceAttribute); // If the autoplay experiment says that it's okay to play now, // then don't require a user gesture. @@ -2075,7 +2081,7 @@ m_autoplayHelper->playMethodCalled(); if (!UserGestureIndicator::processingUserGesture()) { - m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Method); + recordAutoplaySourceMetric(AutoplaySourceMethod); if (isGestureNeededForPlayback()) { // If playback is deferred, then don't start playback but don't // fail yet either. @@ -2300,9 +2306,9 @@ if (wasAutoplayingMuted) { if (isGestureNeededForPlayback()) { pause(); - m_autoplayUmaHelper->recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus::Failure); + recordAutoplayUnmuteStatus(AutoplayUnmuteActionFailure); } else { - m_autoplayUmaHelper->recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus::Success); + recordAutoplayUnmuteStatus(AutoplayUnmuteActionSuccess); } } } @@ -3660,7 +3666,6 @@ visitor->trace(m_audioSourceProvider); visitor->trace(m_autoplayHelperClient); visitor->trace(m_autoplayHelper); - visitor->trace(m_autoplayUmaHelper); visitor->trace(m_srcObject); visitor->trace(m_autoplayVisibilityObserver); visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::clearWeakMembers>(this); @@ -3881,6 +3886,28 @@ return histogram; } +void HTMLMediaElement::recordAutoplaySourceMetric(int source) +{ + DEFINE_STATIC_LOCAL(EnumerationHistogram, videoHistogram, ("Media.Video.Autoplay", NumberOfAutoplaySources)); + DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, ("Media.Video.Autoplay.Muted", NumberOfAutoplaySources)); + DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, ("Media.Audio.Autoplay", NumberOfAutoplaySources)); + + if (isHTMLVideoElement()) { + videoHistogram.count(source); + if (muted()) + mutedVideoHistogram.count(source); + } else { + audioHistogram.count(source); + } +} + +void HTMLMediaElement::recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus status) +{ + DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayUnmuteHistogram, ("Media.Video.Autoplay.Muted.UnmuteAction", AutoplayUnmuteActionMax)); + + autoplayUnmuteHistogram.count(status); +} + void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) { if (!isVisible)
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h index f488f66..9863e39 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -46,7 +46,6 @@ class AudioSourceProviderClient; class AudioTrackList; -class AutoplayUmaHelper; class ContentType; class CueTimeline; class ElementVisibilityObserver; @@ -299,6 +298,13 @@ void recordAutoplayMetric(AutoplayMetrics); private: + // These values are used for histograms. Do not reorder. + enum AutoplayUnmuteActionStatus { + AutoplayUnmuteActionFailure = 0, + AutoplayUnmuteActionSuccess = 1, + AutoplayUnmuteActionMax + }; + void resetMediaPlayerAndMediaSource(); bool alwaysCreateUserAgentShadowRoot() const final { return true; } @@ -493,6 +499,9 @@ EnumerationHistogram& showControlsHistogram() const; + void recordAutoplaySourceMetric(int source); + void recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus); + void onVisibilityChangedForAutoplay(bool isVisible); UnthrottledTimer<HTMLMediaElement> m_loadTimer; @@ -669,7 +678,6 @@ Member<AutoplayExperimentHelper::Client> m_autoplayHelperClient; Member<AutoplayExperimentHelper> m_autoplayHelper; - Member<AutoplayUmaHelper> m_autoplayUmaHelper; WebRemotePlaybackClient* m_remotePlaybackClient;
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp index b62b61d..b660dce 100644 --- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
@@ -517,24 +517,11 @@ bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback) { - // Allow other plugins to win over QuickTime because if the user has - // installed a plugin that can handle TIFF (which QuickTime can also - // handle) they probably intended to override QT. - if (document().frame()->page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) { - const PluginData* pluginData = document().frame()->pluginData(); - String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String(); - if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", TextCaseInsensitive)) { - useFallback = false; - return true; - } - } - ObjectContentType objectType = document().frame()->loader().client()->getObjectContentType(url, mimeType, shouldPreferPlugInsForImages()); // If an object's content can't be handled and it has no fallback, let // it be handled as a plugin to show the broken plugin icon. useFallback = objectType == ObjectContentNone && hasFallback; return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin; - } void HTMLPlugInElement::dispatchErrorEvent()
diff --git a/third_party/WebKit/Source/core/html/OWNERS b/third_party/WebKit/Source/core/html/OWNERS index ab32e99..c877bae 100644 --- a/third_party/WebKit/Source/core/html/OWNERS +++ b/third_party/WebKit/Source/core/html/OWNERS
@@ -1,4 +1,3 @@ per-file Autoplay*=mlamouri@chromium.org -per-file AutoplayUmaHelper=zqzhang@chromium.org per-file Media*=mlamouri@chromium.org per-file HTMLMedia*=mlamouri@chromium.org
diff --git a/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py b/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py index eaf7a60..188ed26 100755 --- a/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py +++ b/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py
@@ -102,72 +102,6 @@ public: InstrumentingAgents(); DECLARE_TRACE(); - - template <class T> - class AgentsList { - DISALLOW_NEW(); - private: - using AgentsVector = HeapVector<Member<T>>; - using InnerIterator = typename AgentsVector::iterator; - - public: - class Iterator { - STACK_ALLOCATED(); - public: - Iterator operator++(int) { InnerIterator value = m_value; ++*this; return Iterator(value, m_list); } - Iterator& operator++() { if (!isEnd()) ++m_value; return *this; } - bool operator==(const Iterator& other) const { return (isEnd() && other.isEnd()) || m_value == other.m_value; } - bool operator!=(const Iterator& other) const { return !(*this == other); } - T* operator*() { return *m_value; } - T* operator->() { return *m_value; } - - private: - friend class AgentsList; - Iterator(InnerIterator value, AgentsList* list) : m_value(value), m_list(list), m_version(m_list->m_version) { } - bool isEnd() const { return m_list->m_version != m_version || m_value == m_list->m_vector.end(); } - - InnerIterator m_value; - Member<AgentsList> m_list; - int m_version; - }; - - Iterator begin() { return Iterator(m_vector.begin(), this); } - Iterator end() { return Iterator(m_vector.end(), this); } - - DEFINE_INLINE_TRACE() - { - visitor->trace(m_vector); - } - - private: - friend class InstrumentingAgents; - friend class Iterator; - - AgentsList() : m_version(0) { } - - bool isEmpty() const { return m_vector.isEmpty(); } - - void add(T* value) - { - if (m_vector.contains(value)) - return; - ++m_version; - m_vector.append(value); - } - - void remove(T* value) - { - size_t index = m_vector.find(value); - if (index == WTF::kNotFound) - return; - ++m_version; - m_vector.remove(index); - } - - AgentsVector m_vector; - int m_version; - }; - ${accessor_list} private: @@ -181,7 +115,7 @@ template_instrumenting_agent_accessor = string.Template(""" bool has${class_name}s() const { return ${has_member_name}; } - AgentsList<${class_name}>& ${getter_name}s() { return ${member_name}; } + const HeapHashSet<Member<${class_name}>>& ${getter_name}s() const { return ${member_name}; } void add${class_name}(${class_name}* agent); void remove${class_name}(${class_name}* agent);""") @@ -189,7 +123,7 @@ void InstrumentingAgents::add${class_name}(${class_name}* agent) { ${member_name}.add(agent); - ${has_member_name} = !${member_name}.isEmpty(); + ${has_member_name} = true; } void InstrumentingAgents::remove${class_name}(${class_name}* agent) @@ -455,7 +389,7 @@ getter_name=getter_name, member_name=member_name, has_member_name=has_member_name)) - member_list.append(" AgentsList<%s> %s;" % (class_name, member_name)) + member_list.append(" HeapHashSet<Member<%s>> %s;" % (class_name, member_name)) member_list.append(" bool %s;" % has_member_name) init_list.append("%s(false)" % has_member_name) trace_list.append("visitor->trace(%s);" % member_name)
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 7de6c22a..f4a2de9 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -4230,7 +4230,7 @@ "name": "createTarget", "description": "Creates a new page.", "parameters": [ - { "name": "initialUrl", "type": "string", "description": "The initial URL the page will be navigated to." }, + { "name": "url", "type": "string", "description": "The initial URL the page will be navigated to." }, { "name": "width", "type": "integer", "description": "Window width (headless chrome only).", "optional": true }, { "name": "height", "type": "integer", "description": "Window height (headless chrome only).", "optional": true }, { "name": "browserContextId", "$ref": "BrowserContextID", "description": "The browser context to create the page in (headless chrome only).", "optional": true }
diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.cpp b/third_party/WebKit/Source/core/layout/LayoutInline.cpp index fefc372..5d11e8f 100644 --- a/third_party/WebKit/Source/core/layout/LayoutInline.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
@@ -1062,9 +1062,15 @@ LayoutUnit outlineOutset(style()->outlineOutsetExtent()); if (outlineOutset) { Vector<LayoutRect> rects; - // We have already included outline extents of line boxes in linesVisualOverflowBoundingBox(), - // so the following just add outline rects for children and continuations. - addOutlineRectsForChildrenAndContinuations(rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow()); + if (document().inNoQuirksMode()) { + // We have already included outline extents of line boxes in linesVisualOverflowBoundingBox(), + // so the following just add outline rects for children and continuations. + addOutlineRectsForChildrenAndContinuations(rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow()); + } else { + // In non-standard mode, because the difference in LayoutBlock::minLineHeightForReplacedObject(), + // linesVisualOverflowBoundingBox() may not cover outline rects of lines containing replaced objects. + addOutlineRects(rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow()); + } if (!rects.isEmpty()) { LayoutRect outlineRect = unionRectEvenIfEmpty(rects); outlineRect.inflate(outlineOutset);
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp index c6cae63..14efaeeb 100644 --- a/third_party/WebKit/Source/core/page/DragController.cpp +++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -584,7 +584,7 @@ return DragOperationCopy; if (srcOpMask == DragOperationNone) return DragOperationNone; - if (srcOpMask & DragOperationMove || srcOpMask & DragOperationGeneric) + if (srcOpMask & DragOperationMove) return DragOperationMove; if (srcOpMask & DragOperationCopy) return DragOperationCopy;
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi index 97666e3..f4a0c08 100644 --- a/third_party/WebKit/Source/devtools/devtools.gypi +++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -432,7 +432,6 @@ ], 'devtools_devices_js_files': [ 'front_end/devices/devicesView.css', - 'front_end/devices/DevicesDialog.js', 'front_end/devices/DevicesView.js', ], 'devtools_diff_js_files': [
diff --git a/third_party/WebKit/Source/devtools/front_end/Runtime.js b/third_party/WebKit/Source/devtools/front_end/Runtime.js index a1e681f..e79325f 100644 --- a/third_party/WebKit/Source/devtools/front_end/Runtime.js +++ b/third_party/WebKit/Source/devtools/front_end/Runtime.js
@@ -455,6 +455,16 @@ Runtime._originalAssert.call(Runtime._console, value, message + " " + new Error().stack); } +Runtime._platform = ""; + +/** + * @param {string} platform + */ +Runtime.setPlatform = function(platform) +{ + Runtime._platform = platform; +} + Runtime.prototype = { useTestBase: function() { @@ -563,11 +573,12 @@ /** * @param {*} type * @param {?Object=} context + * @param {boolean=} sortByTitle * @return {!Array.<!Runtime.Extension>} */ - extensions: function(type, context) + extensions: function(type, context, sortByTitle) { - return this._extensions.filter(filter).sort(orderComparator); + return this._extensions.filter(filter).sort(sortByTitle ? titleComparator : orderComparator); /** * @param {!Runtime.Extension} extension @@ -593,6 +604,18 @@ var order2 = extension2.descriptor()["order"] || 0; return order1 - order2; } + + /** + * @param {!Runtime.Extension} extension1 + * @param {!Runtime.Extension} extension2 + * @return {number} + */ + function titleComparator(extension1, extension2) + { + var title1 = extension1.title() || ""; + var title2 = extension2.title() || ""; + return title1.localeCompare(title2); + } }, /** @@ -978,13 +1001,12 @@ }, /** - * @param {string} platform * @return {string} */ - title: function(platform) + title: function() { // FIXME: should be WebInspector.UIString() but runtime is not l10n aware yet. - return this._descriptor["title-" + platform] || this._descriptor["title"]; + return this._descriptor["title-" + Runtime._platform] || this._descriptor["title"]; } }
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 16653bc5d..6db738a 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
@@ -758,29 +758,3 @@ return new WebInspector.AnimationTimeline.StepTimingFunction(parseInt(match[1], 10), match[2]); return null; } - -/** - * @constructor - * @implements {WebInspector.ToolbarItem.Provider} - */ -WebInspector.AnimationTimeline.ButtonProvider = function() -{ - this._button = new WebInspector.ToolbarButton(WebInspector.UIString("Animations"), "animation-toolbar-item"); - this._button.addEventListener("click", this._clicked, this); -} - -WebInspector.AnimationTimeline.ButtonProvider.prototype = { - _clicked: function() - { - WebInspector.inspectorView.showViewInDrawer("animations"); - }, - - /** - * @override - * @return {!WebInspector.ToolbarItem} - */ - item: function() - { - return this._button; - } -}
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/module.json b/third_party/WebKit/Source/devtools/front_end/animation/module.json index 236b476..0e03f47 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/module.json +++ b/third_party/WebKit/Source/devtools/front_end/animation/module.json
@@ -1,12 +1,6 @@ { "extensions": [ { - "type": "@WebInspector.ToolbarItem.Provider", - "className": "WebInspector.AnimationTimeline.ButtonProvider", - "order": 2, - "location": "styles-sidebarpane-toolbar" - }, - { "type": "drawer-view", "name": "animations", "title": "Animations",
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js index a299b322..2e2a94bc 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
@@ -645,7 +645,7 @@ */ WebInspector.DOMPresentationUtils.GenericDecorator = function(extension) { - this._title = WebInspector.UIString(extension.title(WebInspector.platform())); + this._title = WebInspector.UIString(extension.title()); this._color = extension.descriptor()["color"]; }
diff --git a/third_party/WebKit/Source/devtools/front_end/devices/DevicesDialog.js b/third_party/WebKit/Source/devtools/front_end/devices/DevicesDialog.js deleted file mode 100644 index 05fdade..0000000 --- a/third_party/WebKit/Source/devtools/front_end/devices/DevicesDialog.js +++ /dev/null
@@ -1,44 +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. - -/** - * @constructor - */ -WebInspector.DevicesDialog = function() -{ -} - -/** - * @constructor - * @implements {WebInspector.ActionDelegate} - */ -WebInspector.DevicesDialog.ActionDelegate = function() -{ - /** @type {?WebInspector.DevicesView} */ - this._view = null; -} - -WebInspector.DevicesDialog.ActionDelegate.prototype = { - /** - * @override - * @param {!WebInspector.Context} context - * @param {string} actionId - * @return {boolean} - */ - handleAction: function(context, actionId) - { - if (actionId === "devices.dialog.show") { - if (!this._view) - this._view = new WebInspector.DevicesView(); - - var dialog = new WebInspector.Dialog(); - dialog.addCloseButton(); - this._view.show(dialog.element); - dialog.setMaxSize(new Size(700, 500)); - dialog.show(); - return true; - } - return false; - } -}
diff --git a/third_party/WebKit/Source/devtools/front_end/devices/devicesView.css b/third_party/WebKit/Source/devtools/front_end/devices/devicesView.css index e9930d6e..19cf476 100644 --- a/third_party/WebKit/Source/devtools/front_end/devices/devicesView.css +++ b/third_party/WebKit/Source/devtools/front_end/devices/devicesView.css
@@ -85,6 +85,14 @@ white-space: pre; } +.discovery-view { + overflow: auto; +} + +.discovery-view > * { + flex: none; +} + .usb-checkbox { padding-bottom: 8px; margin-top: 20px; @@ -113,7 +121,7 @@ .port-forwarding-list { margin: 10px 0 0 25px; max-width: 500px; - flex: 0 1 auto; + flex: none; } .port-forwarding-list-empty { @@ -206,7 +214,7 @@ flex: auto; overflow: auto; padding-right: 10px; - margin-top: 20px; + margin-top: 30px; } .device-browser-list > div { @@ -273,7 +281,7 @@ } .device-page-url { - margin: 3px 0; + margin: 3px 100px 3px 0; } .device-page-url a {
diff --git a/third_party/WebKit/Source/devtools/front_end/devices/module.json b/third_party/WebKit/Source/devtools/front_end/devices/module.json index 42a7695b..f253327 100644 --- a/third_party/WebKit/Source/devtools/front_end/devices/module.json +++ b/third_party/WebKit/Source/devtools/front_end/devices/module.json
@@ -1,23 +1,18 @@ { "extensions": [ { - "type": "@WebInspector.ActionDelegate", - "category": "Mobile", - "actionId": "devices.dialog.show", - "className": "WebInspector.DevicesDialog.ActionDelegate", - "title": "Inspect devices\u2026" - }, - { - "type": "context-menu-item", - "location": "mainMenu/tools/open", + "type": "drawer-view", + "name": "remote-devices", + "title": "Remote devices", + "persistence": "closeable", "order": 50, - "actionId": "devices.dialog.show" + "className": "WebInspector.DevicesView", + "tags": "usb, android, mobile" } ], "dependencies": ["platform", "ui", "host", "components"], "scripts": [ - "DevicesView.js", - "DevicesDialog.js" + "DevicesView.js" ], "resources": [ "devicesView.css"
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js index 1d15b64..b187427d 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
@@ -4,24 +4,24 @@ /** * @constructor - * @extends {WebInspector.ElementsPanel.BaseToolbarPaneWidget} - * @param {!WebInspector.ToolbarItem} toolbarItem + * @extends {WebInspector.Widget} */ -WebInspector.ClassesPaneWidget = function(toolbarItem) +WebInspector.ClassesPaneWidget = function() { - WebInspector.ElementsPanel.BaseToolbarPaneWidget.call(this, toolbarItem); + WebInspector.Widget.call(this); this.element.className = "styles-element-classes-pane"; var container = this.element.createChild("div", "title-container"); - var input = container.createChild("input", "new-class-input monospace"); - input.placeholder = WebInspector.UIString("Add new class"); - input.addEventListener("keydown", this._onKeyDown.bind(this), false); - this.setDefaultFocusedElement(input); + this._input = container.createChild("input", "new-class-input monospace"); + this._input.placeholder = WebInspector.UIString("Add new class"); + this._input.addEventListener("keydown", this._onKeyDown.bind(this), false); + this.setDefaultFocusedElement(this._input); this._classesContainer = this.element.createChild("div", "source-code"); this._classesContainer.classList.add("styles-element-classes-container"); WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.DOMMutated, this._onDOMMutated, this); /** @type {!Set<!WebInspector.DOMNode>} */ this._mutatingNodes = new Set(); + WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._update, this); } WebInspector.ClassesPaneWidget._classesSymbol = Symbol("WebInspector.ClassesPaneWidget._classesSymbol"); @@ -55,7 +55,7 @@ this._toggleClass(node, className, true); } this._installNodeClasses(node); - this.update(); + this._update(); event.consume(true); }, @@ -68,19 +68,31 @@ if (this._mutatingNodes.has(node)) return; delete node[WebInspector.ClassesPaneWidget._classesSymbol]; - this.update(); + this._update(); }, /** * @override - * @return {!Promise.<?>} */ - doUpdate: function() + wasShown: function() { - this._classesContainer.removeChildren(); + this._update(); + }, + + _update: function() + { + if (!this.isShowing()) + return; + var node = WebInspector.context.flavor(WebInspector.DOMNode); + if (node) + node = node.enclosingElementOrSelf(); + + this._classesContainer.removeChildren(); + this._input.disabled = !node; + if (!node) - return Promise.resolve(); + return; var classes = this._nodeClasses(node); var keys = classes.keysArray(); @@ -92,7 +104,6 @@ label.checkboxElement.addEventListener("click", this._onClick.bind(this, className), false); this._classesContainer.appendChild(label); } - return Promise.resolve(); }, /** @@ -168,16 +179,7 @@ } }, - /** - * @override - * @param {?WebInspector.DOMNode} newNode - */ - onNodeChanged: function(newNode) - { - this.update(); - }, - - __proto__: WebInspector.ElementsPanel.BaseToolbarPaneWidget.prototype + __proto__: WebInspector.Widget.prototype } /** @@ -190,15 +192,13 @@ this._button.setText(".cls"); this._button.element.classList.add("monospace"); this._button.addEventListener("click", this._clicked, this); - this._view = new WebInspector.ClassesPaneWidget(this.item()); - WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._nodeChanged, this); - this._nodeChanged(); + this._view = new WebInspector.ClassesPaneWidget(); } WebInspector.ClassesPaneWidget.ButtonProvider.prototype = { _clicked: function() { - WebInspector.ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null); + WebInspector.ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null, this._button); }, /** @@ -208,14 +208,5 @@ item: function() { return this._button; - }, - - _nodeChanged: function() - { - var node = WebInspector.context.flavor(WebInspector.DOMNode); - var enabled = !!node; - this._button.setEnabled(enabled); - if (!enabled && this._button.toggled()) - WebInspector.ElementsPanel.instance().showToolbarPane(null); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js index 17da5ab..b008343bf 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js
@@ -4,12 +4,11 @@ /** * @constructor - * @extends {WebInspector.ElementsPanel.BaseToolbarPaneWidget} - * @param {!WebInspector.ToolbarItem} toolbarItem + * @extends {WebInspector.Widget} */ -WebInspector.ElementStatePaneWidget = function(toolbarItem) +WebInspector.ElementStatePaneWidget = function() { - WebInspector.ElementsPanel.BaseToolbarPaneWidget.call(this, toolbarItem); + WebInspector.Widget.call(this); this.element.className = "styles-element-state-pane"; this.element.createChild("div").createTextChild(WebInspector.UIString("Force element state")); var table = createElementWithClass("table", "source-code"); @@ -53,6 +52,7 @@ tr.appendChild(createCheckbox.call(null, "visited")); this.element.appendChild(table); + WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._update, this); } WebInspector.ElementStatePaneWidget.prototype = { @@ -66,40 +66,33 @@ if (this._target) { var cssModel = WebInspector.CSSModel.fromTarget(this._target); - cssModel.removeEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._pseudoStateForced, this) + cssModel.removeEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._update, this) } this._target = target; if (target) { var cssModel = WebInspector.CSSModel.fromTarget(target); - cssModel.addEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._pseudoStateForced, this) + cssModel.addEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._update, this) } }, /** - * @param {!WebInspector.Event} event + * @override */ - _pseudoStateForced: function(event) + wasShown: function() { - this.update(); + this._update(); }, - /** - * @override - * @param {?WebInspector.DOMNode} newNode - */ - onNodeChanged: function(newNode) + _update: function() { - this._updateTarget(newNode ? newNode.target() : null); - this.update(); - }, + if (!this.isShowing()) + return; - /** - * @override - * @return {!Promise.<?>} - */ - doUpdate: function() - { var node = WebInspector.context.flavor(WebInspector.DOMNode); + if (node) + node = node.enclosingElementOrSelf(); + + this._updateTarget(node ? node.target() : null); if (node) { var nodePseudoState = WebInspector.CSSModel.fromNode(node).pseudoState(node); for (var input of this._inputs) { @@ -112,10 +105,9 @@ input.checked = false; } } - return Promise.resolve(); }, - __proto__: WebInspector.ElementsPanel.BaseToolbarPaneWidget.prototype + __proto__: WebInspector.Widget.prototype } /** @@ -127,15 +119,13 @@ this._button = new WebInspector.ToolbarToggle(WebInspector.UIString("Toggle Element State"), "", WebInspector.UIString(":hov")); this._button.addEventListener("click", this._clicked, this); this._button.element.classList.add("monospace"); - this._view = new WebInspector.ElementStatePaneWidget(this.item()); - WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._nodeChanged, this); - this._nodeChanged(); + this._view = new WebInspector.ElementStatePaneWidget(); } WebInspector.ElementStatePaneWidget.ButtonProvider.prototype = { _clicked: function() { - WebInspector.ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null); + WebInspector.ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null, this._button); }, /** @@ -145,13 +135,5 @@ item: function() { return this._button; - }, - - _nodeChanged: function() - { - var enabled = !!WebInspector.context.flavor(WebInspector.DOMNode); - this._button.setEnabled(enabled); - if (!enabled && this._button.toggled()) - WebInspector.ElementsPanel.instance().showToolbarPane(null); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js index 5da3bbe..bc5f4de 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -134,13 +134,21 @@ /** * @param {?WebInspector.Widget} widget + * @param {!WebInspector.ToolbarToggle=} toggle */ - showToolbarPane: function(widget) + showToolbarPane: function(widget, toggle) { + if (this._pendingWidgetToggle) + this._pendingWidgetToggle.setToggled(false); + this._pendingWidgetToggle = toggle; + if (this._animatedToolbarPane !== undefined) this._pendingWidget = widget; else this._startToolbarPaneAnimation(widget); + + if (widget && toggle) + toggle.setToggled(true); }, /** @@ -291,7 +299,6 @@ width -= this._splitWidget.sidebarSize(); for (var i = 0; i < this._treeOutlines.length; ++i) { this._treeOutlines[i].setVisibleWidth(width); - this._treeOutlines[i].updateSelection(); } this._breadcrumbs.updateSizes(); }, @@ -329,7 +336,6 @@ for (var i = 0; i < this._treeOutlines.length; ++i) { var treeOutline = this._treeOutlines[i]; - treeOutline.updateSelection(); treeOutline.setVisible(true); if (!treeOutline.rootDOMNode) @@ -551,14 +557,6 @@ this._contentElement.classList.toggle("elements-wrap", event.data); for (var i = 0; i < this._treeOutlines.length; ++i) this._treeOutlines[i].setWordWrap(/** @type {boolean} */ (event.data)); - - var selectedNode = this.selectedDOMNode(); - if (!selectedNode) - return; - - var treeElement = this._treeElementForNode(selectedNode); - if (treeElement) - treeElement.updateSelection(); // Recalculate selection highlight dimensions. }, switchToAndFocus: function(node) @@ -1244,55 +1242,3 @@ return { color: "orange", title: WebInspector.UIString("Element state: %s", ":" + WebInspector.CSSModel.fromNode(node).pseudoState(node).join(", :")) }; } } - -/** - * @constructor - * @extends {WebInspector.ThrottledWidget} - * @param {!WebInspector.ToolbarItem} toolbarItem - */ -WebInspector.ElementsPanel.BaseToolbarPaneWidget = function(toolbarItem) -{ - WebInspector.ThrottledWidget.call(this); - this._toolbarItem = toolbarItem; - WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._nodeChanged, this); -} - -WebInspector.ElementsPanel.BaseToolbarPaneWidget.prototype = { - _nodeChanged: function() - { - if (!this.isShowing()) - return; - - var elementNode = WebInspector.SharedSidebarModel.elementNode(WebInspector.context.flavor(WebInspector.DOMNode)); - this.onNodeChanged(elementNode); - }, - - /** - * @param {?WebInspector.DOMNode} newNode - * @protected - */ - onNodeChanged: function(newNode) - { - }, - - /** - * @override - */ - willHide: function() - { - this._toolbarItem.setToggled(false); - WebInspector.ThrottledWidget.prototype.willHide.call(this); - }, - - /** - * @override - */ - wasShown: function() - { - this._toolbarItem.setToggled(true); - this._nodeChanged(); - WebInspector.ThrottledWidget.prototype.wasShown.call(this); - }, - - __proto__: WebInspector.ThrottledWidget.prototype -}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js index 39b1dca5..bf14bffc 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
@@ -229,7 +229,7 @@ if (this.listItemElement) { if (x) { - this.updateSelection(); + this._createSelection(); this.listItemElement.classList.add("hovered"); } else { this.listItemElement.classList.remove("hovered"); @@ -253,7 +253,7 @@ this._expandedChildrenLimit = expandedChildrenLimit; }, - updateSelection: function() + _createSelection: function() { var listItemElement = this.listItemElement; if (!listItemElement) @@ -290,7 +290,7 @@ onattach: function() { if (this._hovered) { - this.updateSelection(); + this._createSelection(); this.listItemElement.classList.add("hovered"); } @@ -337,7 +337,6 @@ return; this.updateTitle(); - this.treeOutline.updateSelection(); }, oncollapse: function() @@ -346,7 +345,6 @@ return; this.updateTitle(); - this.treeOutline.updateSelection(); }, /** @@ -373,7 +371,7 @@ this.treeOutline.selectDOMNode(this._node, selectedByUser); if (selectedByUser) this._node.highlight(); - this.updateSelection(); + this._createSelection(); this.treeOutline.suppressRevealAndSelect = false; return true; }, @@ -454,8 +452,6 @@ tag.appendChild(node); tag.createTextChild(">"); } - - this.updateSelection(); }, /** @@ -810,8 +806,6 @@ this.listItemElement.classList.add("editing-as-html"); this.treeOutline.element.addEventListener("mousedown", consume, false); - this.updateSelection(); - /** * @param {!Element} element * @param {string} newValue @@ -847,7 +841,6 @@ } this.treeOutline.element.removeEventListener("mousedown", consume, false); - this.updateSelection(); this.treeOutline.focus(); } @@ -1079,7 +1072,7 @@ delete this.selectionElement; if (this.selected) - this.updateSelection(); + this._createSelection(); this._preventFollowingLinksOnDoubleClick(); this._highlightSearchResults(); },
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js index 8f653af..4b56b65 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -439,14 +439,6 @@ this._revealAndSelectNode(selectedNode, true); }, - updateSelection: function() - { - if (!this.selectedTreeElement) - return; - var element = this.selectedTreeElement; - element.updateSelection(); - }, - _selectedNodeChanged: function() { this.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedDOMNode); @@ -743,7 +735,6 @@ node = node.parentNode; } - treeElement.updateSelection(); treeElement.listItemElement.classList.add("elements-drag-over"); this._dragOverTreeElement = treeElement; event.preventDefault(); @@ -822,7 +813,6 @@ _clearDragOverTreeElementMarker: function() { if (this._dragOverTreeElement) { - this._dragOverTreeElement.updateSelection(); this._dragOverTreeElement.listItemElement.classList.remove("elements-drag-over"); delete this._dragOverTreeElement; } @@ -1243,7 +1233,6 @@ this._element.classList.remove("hidden"); if (originalScrollTop) treeOutlineContainerElement.scrollTop = originalScrollTop; - this.updateSelection(); } this._updateRecords.clear(); @@ -1750,10 +1739,6 @@ this.listItemElement.classList.toggle("hovered", x); }, - updateSelection: function() - { - }, - /** * @return {number} */
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js b/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js index bcf26d33..1eb7e82 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js
@@ -13,20 +13,6 @@ WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._onNodeChanged, this); } -/** - * @param {?WebInspector.DOMNode} node - * @return {?WebInspector.DOMNode} - */ -WebInspector.SharedSidebarModel.elementNode = function(node) -{ - if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode) - node = node.parentNode; - - if (node && node.nodeType() !== Node.ELEMENT_NODE) - node = null; - return node; -} - WebInspector.SharedSidebarModel.Events = { ComputedStyleChanged: "ComputedStyleChanged" } @@ -94,7 +80,7 @@ */ _elementNode: function() { - return WebInspector.SharedSidebarModel.elementNode(this.node()); + return this.node() ? this.node().enclosingElementOrSelf() : null; }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js index a2f9a35..4304ea08 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -206,7 +206,7 @@ setNode: function(node) { this._stylesPopoverHelper.hide(); - node = WebInspector.SharedSidebarModel.elementNode(node); + node = node ? node.enclosingElementOrSelf() : null; this._resetCache(); WebInspector.ElementsSidebarPane.prototype.setNode.call(this, node);
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/module.json b/third_party/WebKit/Source/devtools/front_end/emulation/module.json index 45c8602..b1381de5 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/module.json +++ b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
@@ -100,12 +100,6 @@ "className": "WebInspector.SensorsView.ShowActionDelegate" }, { - "type": "context-menu-item", - "location": "mainMenu/tools/open", - "order": 100, - "actionId": "emulation.show-sensors" - }, - { "type": "drawer-view", "name": "sensors", "title": "Sensors",
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js index 8c8748bf..1e7cf982 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -57,6 +57,7 @@ if (InspectorFrontendHost.isUnderTest()) self.runtime.useTestBase(); + Runtime.setPlatform(WebInspector.platform()); InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this)); }, @@ -883,6 +884,13 @@ contextMenu.appendAction("main.toggle-drawer", WebInspector.inspectorView.drawerVisible() ? WebInspector.UIString("Hide console") : WebInspector.UIString("Show console")); contextMenu.appendItemsAtLocation("mainMenu"); + var moreTools = contextMenu.namedSubMenu("mainMenuMoreTools"); + var extensions = self.runtime.extensions("drawer-view", undefined, true); + for (var extension of extensions) { + var descriptor = extension.descriptor(); + moreTools.appendItem(extension.title(), WebInspector.inspectorView.showViewInDrawer.bind(WebInspector.inspectorView, descriptor["name"])); + } + contextMenu.show(); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js b/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js index 83ffccc..05914662 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js +++ b/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js
@@ -166,25 +166,3 @@ WebInspector.RenderingOptionsView._instanceObject = new WebInspector.RenderingOptionsView(); return WebInspector.RenderingOptionsView._instanceObject; } - -/** - * @constructor - * @implements {WebInspector.ActionDelegate} - */ -WebInspector.RenderingOptionsView.ShowActionDelegate = function() -{ -} - -WebInspector.RenderingOptionsView.ShowActionDelegate.prototype = { - /** - * @override - * @param {!WebInspector.Context} context - * @param {string} actionId - * @return {boolean} - */ - handleAction: function(context, actionId) - { - WebInspector.inspectorView.showViewInDrawer("rendering"); - return true; - } -}
diff --git a/third_party/WebKit/Source/devtools/front_end/main/module.json b/third_party/WebKit/Source/devtools/front_end/main/module.json index 9c4c309..cb9cd42 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/module.json +++ b/third_party/WebKit/Source/devtools/front_end/main/module.json
@@ -178,12 +178,6 @@ ] }, { - "type": "@WebInspector.ActionDelegate", - "actionId": "main.show-rendering-options", - "title": "Rendering settings", - "className": "WebInspector.RenderingOptionsView.ShowActionDelegate" - }, - { "type": "@WebInspector.ToolbarItem.Provider", "separator": true, "location": "main-toolbar-left", @@ -321,16 +315,10 @@ "type": "context-menu-item", "location": "mainMenu/navigate", "title": "More tools", - "subMenuId": "mainMenu/tools", + "subMenuId": "mainMenuMoreTools", "order": 80 }, { - "type": "context-menu-item", - "location": "mainMenu/tools/open", - "order": 80, - "actionId": "main.show-rendering-options" - }, - { "type": "drawer-view", "name": "rendering", "title": "Rendering",
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js index 36ebc177..ba8ae54c 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js
@@ -244,25 +244,3 @@ ] } ] - -/** - * @constructor - * @implements {WebInspector.ActionDelegate} - */ -WebInspector.NetworkConfigView.ShowActionDelegate = function() -{ -} - -WebInspector.NetworkConfigView.ShowActionDelegate.prototype = { - /** - * @override - * @param {!WebInspector.Context} context - * @param {string} actionId - * @return {boolean} - */ - handleAction: function(context, actionId) - { - WebInspector.inspectorView.showViewInDrawer("network.config"); - return true; - } -}
diff --git a/third_party/WebKit/Source/devtools/front_end/network/module.json b/third_party/WebKit/Source/devtools/front_end/network/module.json index 63f5ac7..45e11269 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/module.json +++ b/third_party/WebKit/Source/devtools/front_end/network/module.json
@@ -68,18 +68,6 @@ "experiment": "requestBlocking" }, { - "type": "@WebInspector.ActionDelegate", - "actionId": "network.show-config", - "title": "Network conditions", - "className": "WebInspector.NetworkConfigView.ShowActionDelegate" - }, - { - "type": "context-menu-item", - "location": "mainMenu/tools/open", - "order": 60, - "actionId": "network.show-config" - }, - { "type": "drawer-view", "name": "network.config", "title": "Network conditions",
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/module.json b/third_party/WebKit/Source/devtools/front_end/screencast/module.json index 64f46d99..e2d451f 100644 --- a/third_party/WebKit/Source/devtools/front_end/screencast/module.json +++ b/third_party/WebKit/Source/devtools/front_end/screencast/module.json
@@ -14,7 +14,7 @@ { "type": "context-menu-item", "condition": "remoteFrontend", - "location": "mainMenu/tools", + "location": "mainMenu", "order": 10, "actionId": "components.request-app-banner" }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js index 44f865d7..03e46ff 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
@@ -213,10 +213,35 @@ target.consoleModel.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, {result: result, wasThrown: wasThrown, text: requestedText, commandMessage: commandMessage, exceptionDetails: exceptionDetails}); } } - if (/^\s*\{/.test(text) && /\}\s*$/.test(text)) - text = "(" + text + ")"; - executionContext.evaluate(text, "console", !!useCommandLineAPI, false, false, true, true, printResult); + /** + * @param {string} code + * @suppress {uselessCode} + * @return {boolean} + */ + function looksLikeAnObjectLiteral(code) + { + // Only parenthesize what appears to be an object literal. + if (!(/^\s*\{/.test(code) && /\}\s*$/.test(code))) + return false; + + try { + // Check if the code can be interpreted as an expression. + Function("return " + code + ";"); + + // No syntax error! Does it work parenthesized? + Function("(" + code + ")"); + + return true; + } catch (e) { + return false; + } + } + + if (looksLikeAnObjectLiteral(text)) + text = "(" + text + ")"; + + executionContext.evaluate(text, "console", !!useCommandLineAPI, false, false, true, true, printResult); WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.ConsoleEvaluated); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js index bfa5d48..01b031b 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
@@ -961,6 +961,20 @@ this._agent.setInspectedNode(node.id); }, + /** + * @return {?WebInspector.DOMNode} + */ + enclosingElementOrSelf: function() + { + var node = this; + if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode) + node = node.parentNode; + + if (node && node.nodeType() !== Node.ELEMENT_NODE) + node = null; + return node; + }, + __proto__: WebInspector.SDKObject.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js index 38aa0d4..e4a5580b 100644 --- a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js +++ b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
@@ -204,7 +204,7 @@ var sectionName = descriptor["category"]; var settingName = descriptor["settingName"]; var setting = WebInspector.moduleSetting(settingName); - var uiTitle = WebInspector.UIString(extension.title(WebInspector.platform())); + var uiTitle = WebInspector.UIString(extension.title()); var sectionElement = this._sectionElement(sectionName); var settingControl;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ActionRegistry.js b/third_party/WebKit/Source/devtools/front_end/ui/ActionRegistry.js index e21053c..afc737b 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ActionRegistry.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ActionRegistry.js
@@ -170,7 +170,7 @@ */ title: function() { - var title = this._extension.title(WebInspector.platform()); + var title = this._extension.title(); var options = this._extension.descriptor()["options"]; if (options) { for (var pair of options) {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js b/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js index b46e31b..c48d5c87 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ContextMenu.js
@@ -171,11 +171,14 @@ /** * @param {string} label * @param {boolean=} disabled + * @param {string=} subMenuId * @return {!WebInspector.ContextSubMenuItem} */ - appendSubMenuItem: function(label, disabled) + appendSubMenuItem: function(label, disabled, subMenuId) { var item = new WebInspector.ContextSubMenuItem(this._contextMenu, label, disabled); + if (subMenuId) + this._contextMenu._namedSubMenus.set(subMenuId, item); this._pushItem(item); return item; }, @@ -246,7 +249,7 @@ { var subMenuId = extension.descriptor()["subMenuId"]; if (subMenuId) { - var subMenuItem = menu.appendSubMenuItem(extension.title(WebInspector.platform())); + var subMenuItem = menu.appendSubMenuItem(extension.title(), false, subMenuId); subMenuItem.appendItemsAtLocation(subMenuId); } else { menu.appendAction(extension.descriptor()["actionId"]); @@ -309,6 +312,8 @@ this._y = y === undefined ? event.y : y; this._handlers = {}; this._id = 0; + /** @type {!Map<string, !WebInspector.ContextSubMenuItem>} */ + this._namedSubMenus = new Map(); } WebInspector.ContextMenu.initialize = function() @@ -483,6 +488,15 @@ this._pendingTargets.push(target); }, + /** + * @param {string} name + * @return {?WebInspector.ContextSubMenuItem} + */ + namedSubMenu: function(name) + { + return this._namedSubMenus.get(name) || null; + }, + __proto__: WebInspector.ContextSubMenuItem.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js index c20310c..d4aaba3 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js
@@ -391,7 +391,8 @@ { if (this._subMenu) this._subMenu._discardSubMenus(); - this.element.remove(); + if (this.element) + this.element.remove(); if (this._parentMenu) delete this._parentMenu._subMenu; }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js index 9f3fb088..5ab0706 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
@@ -1273,11 +1273,7 @@ this._extensions.set(id, extensions[i]); if (this._isPermanentTab(id)) this._appendTab(extensions[i]); - } - - for (var i = 0; i < extensions.length; i++) { - var id = extensions[i].descriptor()["name"]; - if (this._isCloseableTab(id) && this._closeableTabSetting.get()[id]) + else if (this._isCloseableTab(id) && this._closeableTabSetting.get()[id]) this._appendTab(extensions[i]); } }, @@ -1313,13 +1309,10 @@ */ _appendTabsToMenu: function(contextMenu) { - for (var id of this._extensions.keysArray().filter(this._isPermanentTab.bind(this))) { - var title = WebInspector.UIString(this._extensions.get(id).title(WebInspector.platform())); - contextMenu.appendItem(title, this.showTab.bind(this, id)); - } - for (var id of this._extensions.keysArray().filter(this._isCloseableTab.bind(this))) { - var title = WebInspector.UIString(this._extensions.get(id).title(WebInspector.platform())); - contextMenu.appendItem(title, this.showTab.bind(this, id)); + var extensions = self.runtime.extensions(this._extensionPoint, undefined, true); + for (var extension of extensions) { + var title = WebInspector.UIString(extension.title()); + contextMenu.appendItem(title, this.showTab.bind(this, extension.descriptor()["name"])); } }, @@ -1330,7 +1323,7 @@ { var descriptor = extension.descriptor(); var id = descriptor["name"]; - var title = WebInspector.UIString(extension.title(WebInspector.platform())); + var title = WebInspector.UIString(extension.title()); var closeable = descriptor["persistence"] === "closeable" || descriptor["persistence"] === "temporary"; this._tabbedPane.appendTab(id, title, this._views.get(id) || new WebInspector.Widget(), undefined, false, closeable); },
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js index 76bac863..39788fa5 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js +++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js
@@ -307,7 +307,7 @@ { var panelName = extension.descriptor()["name"]; var tags = extension.descriptor()["tags"] || ""; - return WebInspector.CommandMenu.createCommand(WebInspector.UIString("Panel"), tags, WebInspector.UIString("Show %s", extension.title(WebInspector.platform())), "", executeHandler, availableHandler); + return WebInspector.CommandMenu.createCommand(WebInspector.UIString("Panel"), tags, WebInspector.UIString("Show %s", extension.title()), "", executeHandler, availableHandler); /** * @return {boolean} @@ -332,7 +332,7 @@ var drawerId = extension.descriptor()["name"]; var executeHandler = WebInspector.inspectorView.showViewInDrawer.bind(WebInspector.inspectorView, drawerId); var tags = extension.descriptor()["tags"] || ""; - return WebInspector.CommandMenu.createCommand(WebInspector.UIString("Drawer"), tags, WebInspector.UIString("Show %s", extension.title(WebInspector.platform())), "", executeHandler); + return WebInspector.CommandMenu.createCommand(WebInspector.UIString("Drawer"), tags, WebInspector.UIString("Show %s", extension.title()), "", executeHandler); } /** @type {!WebInspector.CommandMenu} */
diff --git a/third_party/WebKit/Source/modules/OWNERS b/third_party/WebKit/Source/modules/OWNERS index 72f11c26..6244e25 100644 --- a/third_party/WebKit/Source/modules/OWNERS +++ b/third_party/WebKit/Source/modules/OWNERS
@@ -1,3 +1,4 @@ +esprehn@chromium.org haraken@chromium.org mkwst@chromium.org mlamouri@chromium.org
diff --git a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp index 16149c1..ba29649 100644 --- a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp +++ b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp
@@ -106,7 +106,7 @@ , m_sourceBuffers(SourceBufferList::create(getExecutionContext(), m_asyncEventQueue.get())) , m_activeSourceBuffers(SourceBufferList::create(getExecutionContext(), m_asyncEventQueue.get())) , m_liveSeekableRange(TimeRanges::create()) - , m_isAddedToRegistry(false) + , m_addedToRegistryCounter(0) { MSLOG << __FUNCTION__ << " this=" << this; } @@ -302,14 +302,15 @@ void MediaSource::addedToRegistry() { - DCHECK(!m_isAddedToRegistry); - m_isAddedToRegistry = true; + ++m_addedToRegistryCounter; + // Ensure there's no counter overflow. + CHECK_GT(m_addedToRegistryCounter, 0); } void MediaSource::removedFromRegistry() { - DCHECK(m_isAddedToRegistry); - m_isAddedToRegistry = false; + DCHECK_GT(m_addedToRegistryCounter, 0); + --m_addedToRegistryCounter; } double MediaSource::duration() const @@ -648,7 +649,7 @@ { return m_attachedElement || m_webMediaSource || m_asyncEventQueue->hasPendingEvents() - || m_isAddedToRegistry; + || m_addedToRegistryCounter > 0; } void MediaSource::stop()
diff --git a/third_party/WebKit/Source/modules/mediasource/MediaSource.h b/third_party/WebKit/Source/modules/mediasource/MediaSource.h index a82b36bec..e6abbb5 100644 --- a/third_party/WebKit/Source/modules/mediasource/MediaSource.h +++ b/third_party/WebKit/Source/modules/mediasource/MediaSource.h
@@ -145,7 +145,7 @@ Member<TimeRanges> m_liveSeekableRange; - bool m_isAddedToRegistry; + int m_addedToRegistryCounter; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp index ebed1a6..382461c7 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -6152,7 +6152,7 @@ std::unique_ptr<WebGraphicsContext3DProvider> contextProvider = wrapUnique(Platform::current()->createOffscreenGraphicsContext3DProvider( attributes, canvas()->document().topDocument().url(), 0, &glInfo)); RefPtr<DrawingBuffer> buffer; - if (contextProvider->bindToCurrentThread()) { + if (contextProvider && contextProvider->bindToCurrentThread()) { // Construct a new drawing buffer with the new GL context. buffer = createDrawingBuffer(std::move(contextProvider)); // If DrawingBuffer::create() fails to allocate a fbo, |drawingBuffer| is set to null.
diff --git a/third_party/WebKit/Source/platform/inspector_protocol/String16STL.h b/third_party/WebKit/Source/platform/inspector_protocol/String16STL.h index 7b185a2..e86c405 100644 --- a/third_party/WebKit/Source/platform/inspector_protocol/String16STL.h +++ b/third_party/WebKit/Source/platform/inspector_protocol/String16STL.h
@@ -243,6 +243,17 @@ }; } // namespace WTF + +namespace std { +template<> struct hash<String16> { + std::size_t operator()(const String16& string) const + { + return string.hash(); + } +}; + +} // namespace std + using String = WTF::String; #endif // !defined(String16STL_h)
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InspectedContext.h b/third_party/WebKit/Source/platform/v8_inspector/InspectedContext.h index 16a2326..ecff5e4 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/InspectedContext.h +++ b/third_party/WebKit/Source/platform/v8_inspector/InspectedContext.h
@@ -6,6 +6,7 @@ #define InspectedContext_h #include "platform/inspector_protocol/Allocator.h" +#include "platform/inspector_protocol/Platform.h" #include "platform/inspector_protocol/String16.h" #include <v8.h>
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp index e4c9083..d59b983a 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
@@ -17,7 +17,7 @@ namespace { -String messageSourceValue(MessageSource source) +String16 messageSourceValue(MessageSource source) { switch (source) { case XMLMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Xml; @@ -35,7 +35,7 @@ } -String messageTypeValue(MessageType type) +String16 messageTypeValue(MessageType type) { switch (type) { case LogMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Log; @@ -54,7 +54,7 @@ return protocol::Console::ConsoleMessage::TypeEnum::Log; } -String messageLevelValue(MessageLevel level) +String16 messageLevelValue(MessageLevel level) { switch (level) { case DebugMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum::Debug; @@ -141,8 +141,10 @@ bool append(v8::Local<v8::Array> array) { - if (m_visitedArrays.contains(array)) - return true; + for (const auto& it : m_visitedArrays) { + if (it == array) + return true; + } uint32_t length = array->Length(); if (length > m_arrayLimit) return false; @@ -151,7 +153,7 @@ bool result = true; m_arrayLimit -= length; - m_visitedArrays.append(array); + m_visitedArrays.push_back(array); for (uint32_t i = 0; i < length; ++i) { if (i) m_builder.append(','); @@ -160,7 +162,7 @@ break; } } - m_visitedArrays.removeLast(); + m_visitedArrays.pop_back(); return result; } @@ -191,7 +193,7 @@ uint32_t m_arrayLimit; v8::Isolate* m_isolate; String16Builder m_builder; - Vector<v8::Local<v8::Array>> m_visitedArrays; + std::vector<v8::Local<v8::Array>> m_visitedArrays; v8::TryCatch m_tryCatch; }; @@ -244,7 +246,7 @@ result->setLine(static_cast<int>(m_lineNumber)); result->setColumn(static_cast<int>(m_columnNumber)); if (m_scriptId) - result->setScriptId(String::number(m_scriptId)); + result->setScriptId(String16::number(m_scriptId)); result->setUrl(m_url); if (m_source == NetworkMessageSource && !m_requestIdentifier.isEmpty()) result->setNetworkRequestId(m_requestIdentifier); @@ -303,7 +305,7 @@ if (m_columnNumber) details->setColumnNumber(static_cast<int>(m_columnNumber) - 1); if (m_scriptId) - details->setScriptId(String::number(m_scriptId)); + details->setScriptId(String16::number(m_scriptId)); if (m_stackTrace) details->setStack(m_stackTrace->buildInspectorObject());
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp index 23ed3fa4..1bc5962 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
@@ -21,6 +21,8 @@ #include "platform/v8_inspector/public/V8DebuggerClient.h" #include "platform/v8_inspector/public/V8ToProtocolValue.h" +#include <algorithm> + using blink::protocol::Array; using blink::protocol::Maybe; using blink::protocol::Debugger::BreakpointId;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerScript.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerScript.cpp index cc1b251..487fa25 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerScript.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerScript.cpp
@@ -5,6 +5,7 @@ #include "platform/v8_inspector/V8DebuggerScript.h" #include "platform/inspector_protocol/Collections.h" +#include "platform/inspector_protocol/Platform.h" #include "platform/v8_inspector/V8StringUtil.h" namespace blink {
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h index f32d0e5..dff99a2 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h
@@ -13,6 +13,8 @@ namespace blink { +class V8StackTrace; + class PLATFORM_EXPORT V8DebuggerClient { public: virtual ~V8DebuggerClient() { }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.cpp b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.cpp index fadab16d..f118dca 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.cpp
@@ -13,6 +13,7 @@ namespace blink { V8Inspector::V8Inspector(v8::Isolate* isolate, v8::Local<v8::Context> context) + : m_context(context) { m_debugger = V8Debugger::create(isolate, this); m_debugger->contextCreated(V8ContextInfo(context, 1, true, "", @@ -55,18 +56,9 @@ m_session->dispatchProtocolMessage(message); } -int V8Inspector::ensureDefaultContextInGroup(int contextGroupId) +v8::Local<v8::Context> V8Inspector::ensureDefaultContextInGroup(int) { - return 1; -} - -void V8Inspector::muteConsole() -{ -} - -void V8Inspector::unmuteConsole() -{ - + return m_context; } bool V8Inspector::isExecutionAllowed() @@ -74,4 +66,9 @@ return true; } +bool V8Inspector::canExecuteScripts() +{ + return true; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h index 38bbc88..3f689ae 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h
@@ -42,36 +42,39 @@ void unmuteWarningsAndDeprecations() override { } double currentTimeMS() override { return 0; }; - void muteConsole() override; - void unmuteConsole() override; bool isExecutionAllowed() override; - int ensureDefaultContextInGroup(int contextGroupId) override; + v8::Local<v8::Context> ensureDefaultContextInGroup(int contextGroupId) override; void beginUserGesture() override { } void endUserGesture() override { } bool isInspectableHeapObject(v8::Local<v8::Object>) override { return true; } void consoleTime(const String16& title) override { } void consoleTimeEnd(const String16& title) override { } void consoleTimeStamp(const String16& title) override { } + void messageAddedToConsole(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, V8StackTrace*) override { } v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*, v8::Local<v8::Context>) override { return v8::MaybeLocal<v8::Value>(); } - void reportMessageToConsole(v8::Local<v8::Context>, MessageType, MessageLevel, const String16& message, const v8::FunctionCallbackInfo<v8::Value>* arguments, unsigned skipArgumentCount) override { } void installAdditionalCommandLineAPI(v8::Local<v8::Context>, v8::Local<v8::Object>) override { } - - // V8InspectorSessionClient - void startInstrumenting() override { } - void stopInstrumenting() override { } - void resumeStartup() override { } - bool canExecuteScripts() override { return true; } - void profilingStarted() override { } - void profilingStopped() override { } + void enableAsyncInstrumentation() override { } + void disableAsyncInstrumentation() override { } void startRepeatingTimer(double, TimerCallback, void* data) override { } void cancelTimer(void* data) override { } + // V8InspectorSessionClient + void runtimeEnabled() override { }; + void runtimeDisabled() override { }; + void resumeStartup() override { }; + bool canExecuteScripts() override; + void profilingStarted() override { }; + void profilingStopped() override { }; + void consoleEnabled() override { }; + void consoleCleared() override { }; + std::unique_ptr<V8Debugger> m_debugger; std::unique_ptr<V8InspectorSession> m_session; String16 m_state; + v8::Local<v8::Context> m_context; }; }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp b/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp index f6b39a7f..4433b04 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp +++ b/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp
@@ -150,6 +150,8 @@ '<(SHARED_INTERMEDIATE_DIR)/blink', ], 'sources': [ + '<(blink_platform_output_dir)/v8_inspector/protocol/Console.cpp', + '<(blink_platform_output_dir)/v8_inspector/protocol/Console.h', '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.cpp', '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.h', '<(blink_platform_output_dir)/v8_inspector/protocol/HeapProfiler.cpp', @@ -194,6 +196,10 @@ 'RemoteObjectId.h', 'V8Console.cpp', 'V8Console.h', + 'V8ConsoleAgentImpl.cpp', + 'V8ConsoleAgentImpl.h', + 'V8ConsoleMessage.cpp', + 'V8ConsoleMessage.h', 'V8DebuggerAgentImpl.cpp', 'V8DebuggerAgentImpl.h', 'V8DebuggerImpl.cpp',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py index 77424eec..de91521 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py
@@ -285,18 +285,18 @@ def __init__(self, options=None): super(AbstractParallelRebaselineCommand, self).__init__(options=options) - self._builder_data = {} + @memoized def builder_data(self): - if not self._builder_data: - for builder_name in self._release_builders(): - builder = self._tool.buildbot.builder_with_name(builder_name) - builder_results = builder.latest_layout_test_results() - if builder_results: - self._builder_data[builder_name] = builder_results - else: - raise Exception("No result for builder %s." % builder_name) - return self._builder_data + builder_to_results = {} + for builder_name in self._release_builders(): + builder = self._tool.buildbot.builder_with_name(builder_name) + builder_results = builder.latest_layout_test_results() + if builder_results: + builder_to_results[builder_name] = builder_results + else: + raise Exception("No result for builder %s." % builder_name) + return builder_to_results # The release builders cycle much faster than the debug ones and cover all the platforms. def _release_builders(self): @@ -346,7 +346,7 @@ builders_to_fallback_paths[builder] = fallback_path return builders_to_fallback_paths.keys() - def _rebaseline_commands(self, test_prefix_list, options): + def _rebaseline_commands(self, test_prefix_list, options, skip_checking_actual_results=False): path_to_webkit_patch = self._tool.path() cwd = self._tool.scm().checkout_root copy_baseline_commands = [] @@ -357,8 +357,13 @@ for test_prefix in test_prefix_list: for test in port.tests([test_prefix]): for builder in self._builders_to_fetch_from(test_prefix_list[test_prefix]): - actual_failures_suffixes = self._suffixes_for_actual_failures( - test, builder, test_prefix_list[test_prefix][builder]) + # TODO(qyearsley): Remove the parameter skip_checking_actual_results + # and instead refactor the existing code so that this is not necessary. + if skip_checking_actual_results: + actual_failures_suffixes = test_prefix_list[test_prefix][builder] + else: + actual_failures_suffixes = self._suffixes_for_actual_failures( + test, builder, test_prefix_list[test_prefix][builder]) if not actual_failures_suffixes: # If we're not going to rebaseline the test because it's passing on this # builder, we still want to remove the line from TestExpectations. @@ -491,7 +496,7 @@ self._tool.scm().add_list(files_to_add) return lines_to_remove - def _rebaseline(self, options, test_prefix_list): + def _rebaseline(self, options, test_prefix_list, skip_checking_actual_results=False): """Downloads new baselines in parallel, then updates expectations files and optimizes baselines. @@ -507,13 +512,18 @@ "some/test.html" on both builder-1 and builder-2, and new text baselines should be downloaded for "some/other.html" but only from builder-1. + skip_checking_actual_results: If True, then the lists of suffixes + to rebaseline from |test_prefix_list| will be used directly; + if False, then the list of suffixes will filtered to include + suffixes with mismatches in actual results. """ for test, builders_to_check in sorted(test_prefix_list.items()): _log.info("Rebaselining %s" % test) for builder, suffixes in sorted(builders_to_check.items()): _log.debug(" %s: %s" % (builder, ",".join(suffixes))) - copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = self._rebaseline_commands(test_prefix_list, options) + copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = self._rebaseline_commands( + test_prefix_list, options, skip_checking_actual_results) lines_to_remove = {} self._run_in_parallel_and_update_scm(copy_baseline_commands)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py index 879285b..bd8cdf11 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
@@ -6,18 +6,15 @@ This command interacts with the Rietveld API to get information about try jobs with layout test results. - -TODO(qyearsley): Finish this module. After getting a list of try bots: - - For each bot get the list of tests to rebaseline. - - Invoke webkit-patch rebaseline-test-internal to fetch the baselines. """ import logging import optparse from webkitpy.common.net.rietveld import latest_try_jobs -from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand from webkitpy.common.net.web import Web +from webkitpy.layout_tests.models.test_expectations import BASELINE_SUFFIX_LIST +from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand _log = logging.getLogger(__name__) @@ -32,12 +29,65 @@ super(RebaselineFromTryJobs, self).__init__(options=[ optparse.make_option( '--issue', type='int', default=None, - help="Rietveld issue number."), + help='Rietveld issue number.'), + optparse.make_option( + '--dry-run', action='store_true', default=False, + help='Dry run mode; list actions that would be performed but do not do anything.'), + self.no_optimize_option, + self.results_directory_option, ]) self.web = Web() + def execute(self, options, args, tool): + if not options.issue: + # TODO(qyearsley): If no issue number is given, get the one for the current branch. + _log.info('No issue number provided.') + return + + if args: + test_prefix_list = {} + try_jobs = latest_try_jobs(options.issue, self._try_bots(), self.web) + builders = [j.builder_name for j in try_jobs] + for t in args: + test_prefix_list[t] = {b: BASELINE_SUFFIX_LIST for b in builders} + else: + test_prefix_list = self._test_prefix_list(options.issue) + self._log_test_prefix_list(test_prefix_list) + + if options.dry_run: + return + self._rebaseline(options, test_prefix_list, skip_checking_actual_results=True) + + def _test_prefix_list(self, issue_number): + """Returns a collection of test, builder and file extensions to get new baselines for.""" + builders_to_tests = self._builders_to_tests(issue_number) + result = {} + for builder, tests in builders_to_tests.iteritems(): + for test in tests: + if test not in result: + result[test] = {} + # TODO(qyearsley): Consider using TestExpectations.suffixes_for_test_result. + result[test][builder] = BASELINE_SUFFIX_LIST + return result + + def _builders_to_tests(self, issue_number): + """Fetches a list of try bots, and for each, fetches tests with new baselines.""" + _log.debug('Getting results for Rietveld issue %d.' % issue_number) + try_jobs = latest_try_jobs(issue_number, self._try_bots(), self.web) + if not try_jobs: + _log.debug('No try job results for builders in: %r.' % (self._try_bots(),)) + builders_to_tests = {} + for job in try_jobs: + test_results = self._unexpected_mismatch_results(job) + builders_to_tests[job.builder_name] = sorted(r.test_name() for r in test_results) + return builders_to_tests + + def _try_bots(self): + """Retuns a collection of try bot builders to fetch results for.""" + return self._tool.builders.all_try_builder_names() def _unexpected_mismatch_results(self, try_job): + """Fetches a list of LayoutTestResult objects for unexpected results with new baselines.""" results_url = self._results_url(try_job.builder_name, try_job.build_number) builder = self._tool.buildbot.builder_with_name(try_job.builder_name) layout_test_results = builder.fetch_layout_test_results(results_url) @@ -46,28 +96,12 @@ return [] return layout_test_results.unexpected_mismatch_results() - def try_bots(self): - return self._tool.builders.all_try_builder_names() - - def execute(self, options, args, tool): - if not options.issue: - # TODO(qyearsley): Later, the default behavior will be to run - # git cl issue to get the issue number, then get lists of tests - # to rebaseline and download new baselines. - _log.info('No issue number provided.') + @staticmethod + def _log_test_prefix_list(test_prefix_list): + """Logs the tests to download new baselines for.""" + if not test_prefix_list: + _log.info('No tests to rebaseline.') return - _log.info('Getting results for Rietveld issue %d.' % options.issue) - - jobs = latest_try_jobs(options.issue, self.try_bots(), self.web) - - for job in jobs: - _log.info(' Builder: %s', job.builder_name) - _log.info(' Build: %s', job.build_number) - test_results = self._unexpected_mismatch_results(job) - if test_results: - for result in test_results: - _log.info( - '%s (actual: %s, expected: %s)', result.test_name(), - result.actual_results(), result.expected_results()) - else: - _log.info('No unexpected test results.') + _log.info('Tests to rebaseline:') + for test, builders in test_prefix_list.iteritems(): + _log.info(' %s: %s', test, ', '.join(sorted(builders)))
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py index 68bd5817..30820fca 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
@@ -10,6 +10,7 @@ from webkitpy.tool.commands.rebaseline_from_try_jobs import RebaselineFromTryJobs from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase from webkitpy.tool.mock_tool import MockOptions +from webkitpy.layout_tests.builder_list import BuilderList class RebaselineFromTryJobsTest(BaseTestCase): @@ -27,6 +28,10 @@ 'builder': 'MOCK Try Win', 'buildnumber': 5000, }, + { + 'builder': 'MOCK Mac Try', + 'buildnumber': 4000, + }, ], }), }) @@ -47,17 +52,19 @@ oc = OutputCapture() try: oc.capture_output() - self.command.execute(MockOptions(issue=11112222), [], self.tool) + options = MockOptions(issue=11112222, dry_run=False, optimize=True, verbose=False) + self.command.execute(options, [], self.tool) finally: _, _, logs = oc.restore_output() self.assertEqual( logs, - ('Getting results for Rietveld issue 11112222.\n' - ' Builder: MOCK Try Win\n' - ' Build: 5000\n' - 'fast/dom/prototype-inheritance.html (actual: TEXT, expected: PASS)\n' - 'fast/dom/prototype-taco.html (actual: PASS TEXT, expected: PASS)\n' - 'svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html (actual: IMAGE, expected: PASS)\n')) + ('Tests to rebaseline:\n' + ' svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html: MOCK Try Win\n' + ' fast/dom/prototype-inheritance.html: MOCK Try Win\n' + ' fast/dom/prototype-taco.html: MOCK Try Win\n' + 'Rebaselining fast/dom/prototype-inheritance.html\n' + 'Rebaselining fast/dom/prototype-taco.html\n' + 'Rebaselining svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html\n')) def test_execute_with_no_issue_number(self): oc = OutputCapture()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py index ec999679..2a9632b 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
@@ -52,6 +52,7 @@ # we can make the default port also a "test" port. self.original_port_factory_get = self.tool.port_factory.get test_port = self.tool.port_factory.get('test') + self._builder_data = {} def get_test_port(port_name=None, options=None, **kwargs): if not port_name: @@ -96,8 +97,14 @@ } } }) - for builder in ['MOCK Win7', 'MOCK Win7 (dbg)', 'MOCK Mac10.11']: - self.command._builder_data[builder] = data + + def builder_data(): + self._builder_data = {} + for builder in ['MOCK Win7', 'MOCK Win7 (dbg)', 'MOCK Mac10.11']: + self._builder_data[builder] = data + return self._builder_data + + self.command.builder_data = builder_data class TestCopyExistingBaselinesInternal(BaseTestCase): command_constructor = CopyExistingBaselinesInternal @@ -337,7 +344,7 @@ self._setup_mock_builder_data() def builder_data(): - self.command._builder_data['MOCK Win7'] = LayoutTestResults({ + self._builder_data['MOCK Win7'] = LayoutTestResults({ "tests": { "userscripts": { "first-test.html": { @@ -347,7 +354,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -602,7 +609,7 @@ self.tool.executive = MockExecutive2() def builder_data(): - self.command._builder_data['MOCK Mac10.11'] = self.command._builder_data['MOCK Mac10.10'] = LayoutTestResults({ + self._builder_data['MOCK Mac10.11'] = self._builder_data['MOCK Mac10.10'] = LayoutTestResults({ "tests": { "userscripts": { "another-test.html": { @@ -616,7 +623,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -659,7 +666,7 @@ self.tool.executive = MockExecutive2() def builder_data(): - self.command._builder_data['MOCK Mac10.10'] = self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({ + self._builder_data['MOCK Mac10.10'] = self._builder_data['MOCK Mac10.11'] = LayoutTestResults({ "tests": { "userscripts": { "reftest-text.html": { @@ -677,7 +684,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -745,7 +752,7 @@ test_port = self.tool.port_factory.get('test') def builder_data(): - self.command._builder_data['MOCK Mac10.10'] = self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({ + self._builder_data['MOCK Mac10.10'] = self._builder_data['MOCK Mac10.11'] = LayoutTestResults({ "tests": { "fast": { "dom": { @@ -758,7 +765,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -785,7 +792,7 @@ def test_rebaseline_missing(self): def builder_data(): - self.command._builder_data['MOCK Mac10.10'] = LayoutTestResults({ + self._builder_data['MOCK Mac10.10'] = LayoutTestResults({ "tests": { "fast": { "dom": { @@ -812,7 +819,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -1049,11 +1056,9 @@ test_port = self.tool.port_factory.get('test') - original_builder_data = self.command.builder_data def builder_data(): - original_builder_data() # Have prototype-chocolate only fail on "MOCK Mac10.11". - self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({ + self._builder_data['MOCK Mac10.11'] = LayoutTestResults({ "tests": { "fast": { "dom": { @@ -1075,7 +1080,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -1109,31 +1114,22 @@ self.assertEqual(self.tool.executive.calls, [ [ - ['python', 'echo', 'copy-existing-baselines-internal', '--suffixes', 'txt,png', - '--builder', 'MOCK Mac10.10', '--test', 'fast/dom/prototype-chocolate.html'], ['python', 'echo', 'copy-existing-baselines-internal', '--suffixes', 'png', '--builder', 'MOCK Mac10.11', '--test', 'fast/dom/prototype-strawberry.html'], ['python', 'echo', 'copy-existing-baselines-internal', '--suffixes', 'txt', - '--builder', 'MOCK Mac10.10', '--test', 'fast/dom/prototype-taco.html'], - ['python', 'echo', 'copy-existing-baselines-internal', '--suffixes', 'txt', '--builder', 'MOCK Mac10.11', '--test', 'fast/dom/prototype-taco.html'], ], [ - ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'txt,png', - '--builder', 'MOCK Mac10.10', '--test', 'fast/dom/prototype-chocolate.html'], - ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'png', '--builder', - 'MOCK Mac10.11', '--test', 'fast/dom/prototype-strawberry.html'], - ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'txt', - '--builder', 'MOCK Mac10.10', '--test', 'fast/dom/prototype-taco.html'], + ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'png', + '--builder', 'MOCK Mac10.11', '--test', 'fast/dom/prototype-strawberry.html'], ['python', 'echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK Mac10.11', '--test', 'fast/dom/prototype-taco.html'], ], [ ['python', 'echo', 'optimize-baselines', '--no-modify-scm', - '--suffixes', 'txt,png', 'fast/dom/prototype-chocolate.html'], - ['python', 'echo', 'optimize-baselines', '--no-modify-scm', '--suffixes', 'png', 'fast/dom/prototype-strawberry.html'], - ['python', 'echo', 'optimize-baselines', '--no-modify-scm', '--suffixes', 'txt', 'fast/dom/prototype-taco.html'], + ['python', 'echo', 'optimize-baselines', '--no-modify-scm', + '--suffixes', 'txt', 'fast/dom/prototype-taco.html'], ], ['git', 'cl', 'upload', '-f'], ['git', 'pull'], @@ -1162,8 +1158,8 @@ original_builder_data = self.command.builder_data def builder_data(): original_builder_data() - # have prototype-chocolate only fail on "MOCK Mac10.10". - self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({ + # Have prototype-chocolate only fail on "MOCK Mac10.11". + self._builder_data['MOCK Mac10.11'] = LayoutTestResults({ "tests": { "fast": { "dom": { @@ -1176,7 +1172,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -1219,7 +1215,7 @@ test_port = self.tool.port_factory.get('test') def builder_data(): - self.command._builder_data['MOCK Mac10.10'] = self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({ + self._builder_data['MOCK Mac10.10'] = self._builder_data['MOCK Mac10.11'] = LayoutTestResults({ "tests": { "fast": { "dom": { @@ -1232,7 +1228,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -1273,7 +1269,7 @@ test_port = self.tool.port_factory.get('test') def builder_data(): - self.command._builder_data['MOCK Win'] = LayoutTestResults({ + self._builder_data['MOCK Win'] = LayoutTestResults({ "tests": { "fast": { "dom": { @@ -1286,7 +1282,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -1329,7 +1325,7 @@ test_port = self.tool.port_factory.get('test') def builder_data(): - self.command._builder_data['MOCK Win'] = LayoutTestResults({ + self._builder_data['MOCK Win'] = LayoutTestResults({ "tests": { "fast": { "dom": { @@ -1342,7 +1338,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data @@ -1386,7 +1382,7 @@ test_port = self.tool.port_factory.get('test') def builder_data(): - self.command._builder_data['MOCK Mac10.10'] = self.command._builder_data['MOCK Mac10.11'] = LayoutTestResults({ + self._builder_data['MOCK Mac10.10'] = self._builder_data['MOCK Mac10.11'] = LayoutTestResults({ "tests": { "fast": { "dom": { @@ -1399,7 +1395,7 @@ } } }) - return self.command._builder_data + return self._builder_data self.command.builder_data = builder_data
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py index db9fda2..03a437f 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
@@ -191,9 +191,23 @@ else: self.print_('## Done: no changes to import.') - def is_manual_test(self, fs, dirname, basename): # Callback for FileSystem.files_under; not all arguments used - pylint: disable=unused-argument - # We are importing manual pointer event tests and we are automating them. - return ("pointerevents" not in dirname) and (basename.endswith('-manual.html') or basename.endswith('-manual.htm')) + def is_manual_test(self, fs, dirname, basename): + """Returns True if the file should be removed because it's a manual test. + + Tests with "-manual" in the name are not considered manual tests + if there is a corresponding JS automation file. + """ + basename_without_extension, _ = basename.rsplit('.', 1) + if not basename_without_extension.endswith('-manual'): + return False + dir_from_wpt = fs.relpath(dirname, self.path_from_webkit_base('LayoutTests', 'imported', 'wpt')) + automation_dir = self.path_from_webkit_base('LayoutTests', 'imported', 'wpt_automation', dir_from_wpt) + # TODO(qyearsley): Update this when all *-input.js are renamed to *-automation.js. + if fs.isfile(fs.join(automation_dir, '%s-input.js' % basename_without_extension)): + return False + if fs.isfile(fs.join(automation_dir, '%s-automation.js' % basename_without_extension)): + return False + return True def is_baseline(self, fs, dirname, basename): # Callback for FileSystem.files_under; not all arguments used - pylint: disable=unused-argument return basename.endswith('-expected.txt')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py index 50da6a5b..5789130 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
@@ -6,6 +6,7 @@ from webkitpy.w3c.deps_updater import DepsUpdater from webkitpy.common.host_mock import MockHost +from webkitpy.common.system.filesystem_mock import MockFileSystem class DepsUpdaterTest(unittest.TestCase): @@ -41,3 +42,29 @@ 'chromeos_daisy' ]) }) + + def test_is_manual_test_regular_test(self): + updater = DepsUpdater(MockHost()) + fs = MockFileSystem() + dirname = '/mock-checkout/third_party/WebKit/LayoutTests/imported/wpt/a' + self.assertFalse(updater.is_manual_test(fs, dirname, 'test.html')) + self.assertFalse(updater.is_manual_test(fs, dirname, 'manual-foo.htm')) + self.assertFalse(updater.is_manual_test(fs, dirname, 'script.js')) + + def test_is_manual_test_no_automation_file(self): + updater = DepsUpdater(MockHost()) + fs = MockFileSystem() + dirname = '/mock-checkout/third_party/WebKit/LayoutTests/imported/wpt/a' + self.assertTrue(updater.is_manual_test(fs, dirname, 'test-manual.html')) + self.assertTrue(updater.is_manual_test(fs, dirname, 'test-manual.htm')) + self.assertTrue(updater.is_manual_test(fs, dirname, 'test-manual.xht')) + + def test_is_manual_test_with_corresponding_automation_file(self): + updater = DepsUpdater(MockHost()) + imported_dir = '/mock-checkout/third_party/WebKit/LayoutTests/imported/' + fs = MockFileSystem(files={ + imported_dir + 'wpt_automation/a/x-manual-input.js': '', + imported_dir + 'wpt_automation/a/y-manual-automation.js': '', + }) + self.assertFalse(updater.is_manual_test(fs, imported_dir + 'wpt/a', 'y-manual.html')) + self.assertFalse(updater.is_manual_test(fs, imported_dir + 'wpt/a', 'x-manual.html'))
diff --git a/tools/bisect-builds.py b/tools/bisect-builds.py index f080e18f..e89ce104 100755 --- a/tools/bisect-builds.py +++ b/tools/bisect-builds.py
@@ -894,7 +894,7 @@ m = blink_re.search(url.read()) url.close() if m: - return m.group(1)] + return m.group(1) url = urllib.urlopen(DEPS_FILE % GetGitHashFromSVNRevision(rev)) if url.getcode() == 200:
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py index cc4415b..fb958605 100755 --- a/tools/clang/scripts/package.py +++ b/tools/clang/scripts/package.py
@@ -288,6 +288,17 @@ filter=PrintTarProgress) MaybeUpload(args, golddir, platform) + # Zip up llvm-objdump for sanitizer coverage. + objdumpdir = 'llvmobjdump-' + stamp + shutil.rmtree(objdumpdir, ignore_errors=True) + os.makedirs(os.path.join(objdumpdir, 'bin')) + shutil.copy(os.path.join(LLVM_RELEASE_DIR, 'bin', 'llvm-objdump' + exe_ext), + os.path.join(objdumpdir, 'bin')) + with tarfile.open(objdumpdir + '.tgz', 'w:gz') as tar: + tar.add(os.path.join(objdumpdir, 'bin'), arcname='bin', + filter=PrintTarProgress) + MaybeUpload(args, objdumpdir, platform) + # FIXME: Warn if the file already exists on the server.
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc index 90642d4..7fe64fd 100644 --- a/tools/gn/target_generator.cc +++ b/tools/gn/target_generator.cc
@@ -305,7 +305,7 @@ if (!outputs.required_types().empty()) { *err_ = Err(*value, "Source expansions not allowed here.", "The outputs of this target used source {{expansions}} but this " - "targe type\ndoesn't support them. Just express the outputs " + "target type\ndoesn't support them. Just express the outputs " "literally."); return false; }
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 84a0cdd..78e185b6 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -22700,20 +22700,6 @@ <summary>Records the autoplay source of muted videos.</summary> </histogram> -<histogram name="Media.Video.Autoplay.Muted.PlayMethod.BecomesVisible" - enum="Boolean"> - <owner>avayvod@chromium.org</owner> - <owner>mlamouri@chromium.org</owner> - <owner>zqzhang@chromium.org</owner> - <summary> - Records muted video started playing with play() become visible at some - point. The UMA for false is not complete since it is recorded in a - destructor which is garbage-collected. Please subtract - Media.Video.Autoplay.Muted "play() method" count with the true - count of this histogram to obtain the real false count. - </summary> -</histogram> - <histogram name="Media.Video.Autoplay.Muted.UnmuteAction" enum="BooleanSuccess"> <owner>avayvod@chromium.org</owner> <owner>mlamouri@chromium.org</owner>
diff --git a/tools/perf/page_sets/tough_scheduling_cases/raf_touch_animation.html b/tools/perf/page_sets/tough_scheduling_cases/raf_touch_animation.html index c2757f2..2e199d6 100644 --- a/tools/perf/page_sets/tough_scheduling_cases/raf_touch_animation.html +++ b/tools/perf/page_sets/tough_scheduling_cases/raf_touch_animation.html
@@ -59,12 +59,13 @@ function startExperiment() { g_status = document.getElementById('status'); - window.addEventListener('touchstart', onTouchStart); - window.addEventListener('touchmove', onTouchMove); + // Pass 'passive' false in to prevent any intervention. + window.addEventListener('touchstart', onTouchStart, {passive: false}); + window.addEventListener('touchmove', onTouchMove, {passive: false}); window.addEventListener('touchend', onTouchEnd); window.addEventListener('touchleave', onTouchEnd); window.addEventListener('touchcancel', onTouchEnd); - window.addEventListener('wheel', onMouseWheel); + window.addEventListener('wheel', onMouseWheel, {passive: false}); window.requestAnimationFrame(onAnimationFrame); }
diff --git a/tools/perf/page_sets/tough_scheduling_cases/touch_handler_scrolling.html b/tools/perf/page_sets/tough_scheduling_cases/touch_handler_scrolling.html index c49833b..1a0552d 100644 --- a/tools/perf/page_sets/tough_scheduling_cases/touch_handler_scrolling.html +++ b/tools/perf/page_sets/tough_scheduling_cases/touch_handler_scrolling.html
@@ -38,12 +38,13 @@ } function startExperiment() { - window.addEventListener('touchstart', onTouchStart); - window.addEventListener('touchmove', onTouchMove); + // Pass 'passive' false in to prevent any intervention. + window.addEventListener('touchstart', onTouchStart, {passive: false}); + window.addEventListener('touchmove', onTouchMove, {passive: false}); window.addEventListener('touchend', onTouchEnd); window.addEventListener('touchleave', onTouchEnd); window.addEventListener('touchcancel', onTouchEnd); - window.addEventListener('wheel', onMouseWheel); + window.addEventListener('wheel', onMouseWheel, {passive: false}); } window.addEventListener('load', startExperiment);
diff --git a/tools/resources/list_resources_removed_by_repack.py b/tools/resources/list_resources_removed_by_repack.py index a009ead..db3b4abc 100755 --- a/tools/resources/list_resources_removed_by_repack.py +++ b/tools/resources/list_resources_removed_by_repack.py
@@ -54,18 +54,21 @@ sys.stderr.write('Cannot find gen dir %s' % generated_output_dir) return 1 - if build_type == 'chromium': - excluded_header = 'google_chrome_strings.h' - else: - excluded_header = 'chromium_strings.h' + product = 'chromium' if build_type == 'chromium' else 'google_chrome' + suffix = product + '_strings.h' + excluded_headers = set([s % suffix for s in ( + '%s', + 'components_%s', + 'settings_%s' + )]) + data_files = [] for root, dirs, files in os.walk(generated_output_dir): if os.path.basename(root) != 'grit': continue - header_files = [header for header in files if header.endswith('.h')] - if excluded_header in header_files: - header_files.remove(excluded_header) + header_files = set([header for header in files if header.endswith('.h')]) + header_files -= excluded_headers data_files.extend([os.path.join(root, header) for header in header_files]) resource_id_to_name_file_map = {}
diff --git a/ui/login/account_picker/user_pod_row.js b/ui/login/account_picker/user_pod_row.js index 48a7073ad1..912c21b 100644 --- a/ui/login/account_picker/user_pod_row.js +++ b/ui/login/account_picker/user_pod_row.js
@@ -748,11 +748,6 @@ this.passwordElement.addEventListener('keypress', this.handlePasswordKeyPress_.bind(this)); - if (this.pinKeyboard) { - this.pinKeyboard.addEventListener('submit', - this.handlePinSubmitted_.bind(this)); - } - this.imageElement.addEventListener('load', this.parentNode.handlePodImageLoad.bind(this.parentNode, this)); @@ -773,16 +768,6 @@ }, /** - * Handles the user hitting 'submit' on the PIN keyboard. - * @param {Event} e Submit event object. - * @private - */ - handlePinSubmitted_: function(e) { - var pin = e.detail.pin; - chrome.send('authenticateUser', [this.user.username, pin]); - }, - - /** * Handles keypress event (i.e. any textual input) on password input. * @param {Event} e Keypress Event object. * @private @@ -1188,6 +1173,8 @@ */ get mainInput() { if (this.isAuthTypePassword) { + if (this.pinContainer.classList.contains('pin-enabled')) + return this.pinKeyboard.inputElement; return this.passwordElement; } else if (this.isAuthTypeOnlineSignIn) { return this; @@ -1354,11 +1341,11 @@ this.classList.toggle('signing-in', true); chrome.send('attemptUnlock', [this.user.username]); } else if (this.isAuthTypePassword) { - if (!this.passwordElement.value) + var password = this.passwordElement.value || this.pinKeyboard.value; + if (!password) return false; Oobe.disableSigninUI(); - chrome.send('authenticateUser', - [this.user.username, this.passwordElement.value]); + chrome.send('authenticateUser', [this.user.username, password]); } else { console.error('Activating user pod with invalid authentication type: ' + this.authType); @@ -1420,6 +1407,7 @@ */ reset: function(takeFocus) { this.passwordElement.value = ''; + this.pinKeyboard.value = ''; this.classList.toggle('signing-in', false); if (takeFocus) { if (!this.multiProfilesPolicyApplied) @@ -1817,6 +1805,11 @@ // Note that this.userClickAuthAllowed_ is set in mouse down event // handler. this.parentNode.setActivatedPod(this); + } else if (this.pinKeyboard.submitButton && + e.target == this.pinKeyboard.submitButton) { + // Sets the pod as activated if the submit button is clicked so that + // it simulates what the enter button does for the password/pin. + this.parentNode.setActivatedPod(this); } if (this.multiProfilesPolicyApplied) @@ -3413,6 +3406,7 @@ if (this.focusedPod_) { var targetTag = e.target.tagName; if (e.target == this.focusedPod_.passwordElement || + e.target == this.focusedPod_.pinKeyboard.inputElement || (targetTag != 'INPUT' && targetTag != 'BUTTON' && targetTag != 'A')) {
diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc index 876c6c2..b990372 100644 --- a/ui/views/bubble/tray_bubble_view.cc +++ b/ui/views/bubble/tray_bubble_view.cc
@@ -200,6 +200,7 @@ : layer_(ui::LAYER_TEXTURED), corner_radius_(corner_radius) { layer_.set_delegate(this); + layer_.SetFillsBoundsOpaquely(false); } TrayBubbleContentMask::~TrayBubbleContentMask() {