diff --git a/android_webview/glue/java/src/com/android/webview/chromium/ContentSettingsAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/ContentSettingsAdapter.java index a07d349..4aa7a48 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/ContentSettingsAdapter.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/ContentSettingsAdapter.java
@@ -611,10 +611,12 @@ return mAwSettings.getOffscreenPreRaster(); } + @Override public void setDisabledActionModeMenuItems(int menuItems) { mAwSettings.setDisabledActionModeMenuItems(menuItems); } + @Override public int getDisabledActionModeMenuItems() { return mAwSettings.getDisabledActionModeMenuItems(); }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerClientAdapter.java index a1e272dc..8f44de5 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerClientAdapter.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerClientAdapter.java
@@ -82,8 +82,7 @@ return mRequest.requestHeaders; } - // TODO(mnaganov): Uncomment when we completely switch builds to the next API level. - //@Override + @Override public boolean isRedirect() { return mRequest.isRedirect; }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebMessagePortAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/WebMessagePortAdapter.java index 31a293d..7d343b8 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebMessagePortAdapter.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebMessagePortAdapter.java
@@ -25,18 +25,22 @@ mPort = port; } + @Override public void postMessage(WebMessage message) { mPort.postMessage(message.getData(), toMessagePorts(message.getPorts())); } + @Override public void close() { mPort.close(); } + @Override public void setWebMessageCallback(WebMessageCallback callback) { setWebMessageCallback(callback, null); } + @Override public void setWebMessageCallback(final WebMessageCallback callback, final Handler handler) { mPort.setMessageCallback(new MessagePort.MessageCallback() { @Override
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java index 2cde933..a6747a0fa 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
@@ -1541,6 +1541,7 @@ return (TextClassifier) mAwContents.getTextClassifier(); } + @Override public void autofill(final SparseArray<AutofillValue> values) { mFactory.startYourEngines(false); if (checkNeedsPost()) { @@ -2128,26 +2129,31 @@ // Overrides method added to WebViewProvider.ViewDelegate interface // (not called in M and below) + @Override public Handler getHandler(Handler originalHandler) { return originalHandler; } // Overrides method added to WebViewProvider.ViewDelegate interface // (not called in M and below) + @Override public View findFocus(View originalFocusedView) { return originalFocusedView; } // Remove from superclass + @Override public void preDispatchDraw(Canvas canvas) { // TODO(leandrogracia): remove this method from WebViewProvider if we think // we won't need it again. } + @Override public void onStartTemporaryDetach() { mAwContents.onStartTemporaryDetach(); } + @Override public void onFinishTemporaryDetach() { mAwContents.onFinishTemporaryDetach(); }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java index 32419e1f..5d1e621 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -687,6 +687,7 @@ return (ServiceWorkerController) mServiceWorkerController; } + @Override public TokenBindingService getTokenBindingService() { synchronized (mLock) { if (mTokenBindingManager == null) {
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java index 9b727c6..62fd224 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
@@ -295,8 +295,7 @@ return mRequest.requestHeaders; } - // TODO(mnaganov): Uncomment when we completely switch builds to the next API level. - //@Override + @Override public boolean isRedirect() { return mRequest.isRedirect; } @@ -310,10 +309,12 @@ mError = error; } + @Override public int getErrorCode() { return mError.errorCode; } + @Override public CharSequence getDescription() { return mError.description; }
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc index 6ebbf37..8a9d929 100644 --- a/ash/wm/splitview/split_view_controller.cc +++ b/ash/wm/splitview/split_view_controller.cc
@@ -65,6 +65,11 @@ blink::kWebScreenOrientationLockPortraitSecondary; } +// Transpose the given |rect|. +void TransposeRect(gfx::Rect* rect) { + rect->SetRect(rect->y(), rect->x(), rect->height(), rect->width()); +} + } // namespace SplitViewController::SplitViewController() { @@ -235,6 +240,14 @@ IsCurrentScreenOrientationLandscape(), &left_or_top_rect, &right_or_bottom_rect); + // Only need to adjust the bounds for |left_or_top_rect| since the origin of + // the left or top snapped window's bounds is always the origin of the work + // area's bounds. It can not be moved to outside of the work area when the + // window's minimum size is larger than current acquired window bounds, which + // will lead to the divider pass over the window. This is no need for + // |right_or_bottom_rect| since its origin of the bounds is flexible. + AdjustLeftOrTopSnappedWindowBoundsDuringResizing(&left_or_top_rect); + if (IsLeftWindowOnTopOrLeftOfScreen(screen_orientation_)) return (snap_position == LEFT) ? left_or_top_rect : right_or_bottom_rect; else @@ -274,13 +287,9 @@ GetBoundedPosition(location_in_screen, work_area_bounds); // Update |divider_position_|. - const int previous_divider_position = divider_position_; UpdateDividerPosition(modified_location_in_screen); NotifyDividerPositionChanged(); - // Restack windows order if necessary. - RestackWindows(previous_divider_position, divider_position_); - // Update the black scrim layer's bounds and opacity. UpdateBlackScrim(modified_location_in_screen); @@ -580,29 +589,6 @@ black_scrim_layer_->SetOpacity(opacity); } -void SplitViewController::RestackWindows(const int previous_divider_position, - const int current_divider_position) { - if (!left_window_ || !right_window_) - return; - DCHECK(IsSplitViewModeActive()); - DCHECK_EQ(left_window_->parent(), right_window_->parent()); - - const int mid_position = GetDefaultDividerPosition(GetDefaultSnappedWindow()); - if (std::signbit(previous_divider_position - mid_position) == - std::signbit(current_divider_position - mid_position)) { - // No need to restack windows if the divider position doesn't pass over the - // middle position. - return; - } - - if ((current_divider_position < mid_position) == - IsLeftWindowOnTopOrLeftOfScreen(screen_orientation_)) { - left_window_->parent()->StackChildAbove(right_window_, left_window_); - } else { - left_window_->parent()->StackChildAbove(left_window_, right_window_); - } -} - void SplitViewController::UpdateSnappedWindowsAndDividerBounds() { DCHECK(IsSplitViewModeActive()); @@ -776,4 +762,32 @@ } } +void SplitViewController::AdjustLeftOrTopSnappedWindowBoundsDuringResizing( + gfx::Rect* left_or_top_rect) { + if (!is_resizing_) + return; + + aura::Window* left_or_top_window = + IsLeftWindowOnTopOrLeftOfScreen(screen_orientation_) ? left_window_ + : right_window_; + bool is_landscape = IsCurrentScreenOrientationLandscape(); + int minimum_width = 0; + if (left_or_top_window && left_or_top_window->delegate()) { + gfx::Size minimum_size = left_or_top_window->delegate()->GetMinimumSize(); + minimum_width = is_landscape ? minimum_size.width() : minimum_size.height(); + } + + if (!is_landscape) + TransposeRect(left_or_top_rect); + + if (left_or_top_rect->width() < minimum_width) { + left_or_top_rect->set_x(left_or_top_rect->x() - + (minimum_width - left_or_top_rect->width())); + left_or_top_rect->set_width(minimum_width); + } + + if (!is_landscape) + TransposeRect(left_or_top_rect); +} + } // namespace ash
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h index a50d3f3..33e9218 100644 --- a/ash/wm/splitview/split_view_controller.h +++ b/ash/wm/splitview/split_view_controller.h
@@ -164,14 +164,6 @@ // of the screen. void UpdateBlackScrim(const gfx::Point& location_in_screen); - // Restacks the two snapped windows while dragging the divider. If the divider - // was in the left side of the screen, stack |right_window_| above - // |left_window_|, otherwise, stack |left_window_| above |right_window_|. It's - // necessary since we want the top window increasingly cover the entire - // screen as the divider gets closer to the edge of the screen. - void RestackWindows(const int previous_divider_position, - const int current_divider_position); - // Updates the bounds for the snapped windows and divider according to the // current snap direction. void UpdateSnappedWindowsAndDividerBounds(); @@ -215,6 +207,14 @@ // overview mode is active at that moment. void OnSnappedWindowMinimizedOrDestroyed(aura::Window* window); + // Adjust the bounds of the left or top snapped window during resizing when + // its minimum size is larger than current window bounds to make sure it can + // be moved outside of the work area in this case. Note, no need to adjust + // when it is not during resizing since the window will not be snapped to a + // position that smaller than its minimum size. + void AdjustLeftOrTopSnappedWindowBoundsDuringResizing( + gfx::Rect* left_or_top_rect); + // The current left/right snapped window. aura::Window* left_window_ = nullptr; aura::Window* right_window_ = nullptr;
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index 950485a..2aa4db7 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -837,4 +837,126 @@ EXPECT_FALSE(split_view_controller()->CanSnap(window1.get())); } +// Tests that the left or top snapped window can be moved outside of work area +// when its minimum size is larger than its current bounds. +TEST_F(SplitViewControllerTest, SnapWindowBoundsWithMinimumSizeTest) { + int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + display::DisplayManager* display_manager = Shell::Get()->display_manager(); + display::test::ScopedSetInternalDisplayId set_internal(display_manager, + display_id); + ScreenOrientationControllerTestApi test_api( + Shell::Get()->screen_orientation_controller()); + + const gfx::Rect bounds(0, 0, 300, 200); + std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + aura::test::TestWindowDelegate* delegate1 = + static_cast<aura::test::TestWindowDelegate*>(window1->delegate()); + + // Set the screen orientation to LANDSCAPE_PRIMARY + test_api.SetDisplayRotation(display::Display::ROTATE_0, + display::Display::ROTATION_SOURCE_ACTIVE); + EXPECT_EQ(test_api.GetCurrentOrientation(), + blink::kWebScreenOrientationLockLandscapePrimary); + + gfx::Rect display_bounds = + split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get()); + EXPECT_TRUE(split_view_controller()->CanSnap(window1.get())); + split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT); + delegate1->set_minimum_size( + gfx::Size(display_bounds.width() * 0.4f, display_bounds.height())); + + gfx::Rect divider_bounds = + split_view_divider()->GetDividerBoundsInScreen(false); + split_view_controller()->StartResize(divider_bounds.CenterPoint()); + gfx::Point resize_point(display_bounds.width() * 0.33f, 0); + split_view_controller()->Resize(resize_point); + + gfx::Rect snapped_window_bounds = + split_view_controller()->GetSnappedWindowBoundsInScreen( + window1.get(), SplitViewController::LEFT); + EXPECT_LT(snapped_window_bounds.x(), display_bounds.x()); + EXPECT_EQ(snapped_window_bounds.width(), + window1->delegate()->GetMinimumSize().width()); + EndSplitView(); + + // Rotate the screen by 90 degree. + test_api.SetDisplayRotation(display::Display::ROTATE_90, + display::Display::ROTATION_SOURCE_ACTIVE); + EXPECT_EQ(test_api.GetCurrentOrientation(), + blink::kWebScreenOrientationLockPortraitPrimary); + + display_bounds = + split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get()); + delegate1->set_minimum_size( + gfx::Size(display_bounds.width(), display_bounds.height() * 0.4f)); + EXPECT_TRUE(split_view_controller()->CanSnap(window1.get())); + split_view_controller()->SnapWindow(window1.get(), + SplitViewController::RIGHT); + divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false); + split_view_controller()->StartResize(divider_bounds.CenterPoint()); + resize_point.SetPoint(0, display_bounds.height() * 0.33f); + split_view_controller()->Resize(resize_point); + + snapped_window_bounds = + split_view_controller()->GetSnappedWindowBoundsInScreen( + window1.get(), SplitViewController::RIGHT); + EXPECT_LT(snapped_window_bounds.y(), display_bounds.y()); + EXPECT_EQ(snapped_window_bounds.height(), + window1->delegate()->GetMinimumSize().height()); + EndSplitView(); + + // Rotate the screen by 180 degree. + test_api.SetDisplayRotation(display::Display::ROTATE_180, + display::Display::ROTATION_SOURCE_ACTIVE); + EXPECT_EQ(test_api.GetCurrentOrientation(), + blink::kWebScreenOrientationLockLandscapeSecondary); + + display_bounds = + split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get()); + delegate1->set_minimum_size( + gfx::Size(display_bounds.width() * 0.4f, display_bounds.height())); + EXPECT_TRUE(split_view_controller()->CanSnap(window1.get())); + split_view_controller()->SnapWindow(window1.get(), + SplitViewController::RIGHT); + + divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false); + split_view_controller()->StartResize(divider_bounds.CenterPoint()); + resize_point.SetPoint(display_bounds.width() * 0.33f, 0); + split_view_controller()->Resize(resize_point); + + snapped_window_bounds = + split_view_controller()->GetSnappedWindowBoundsInScreen( + window1.get(), SplitViewController::RIGHT); + EXPECT_LT(snapped_window_bounds.x(), display_bounds.x()); + EXPECT_EQ(snapped_window_bounds.width(), + window1->delegate()->GetMinimumSize().width()); + EndSplitView(); + + // Rotate the screen by 270 degree. + test_api.SetDisplayRotation(display::Display::ROTATE_270, + display::Display::ROTATION_SOURCE_ACTIVE); + EXPECT_EQ(test_api.GetCurrentOrientation(), + blink::kWebScreenOrientationLockPortraitSecondary); + + display_bounds = + split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get()); + delegate1->set_minimum_size( + gfx::Size(display_bounds.width(), display_bounds.height() * 0.4f)); + EXPECT_TRUE(split_view_controller()->CanSnap(window1.get())); + split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT); + + divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false); + split_view_controller()->StartResize(divider_bounds.CenterPoint()); + resize_point.SetPoint(0, display_bounds.height() * 0.33f); + split_view_controller()->Resize(resize_point); + + snapped_window_bounds = + split_view_controller()->GetSnappedWindowBoundsInScreen( + window1.get(), SplitViewController::LEFT); + EXPECT_LT(snapped_window_bounds.y(), display_bounds.y()); + EXPECT_EQ(snapped_window_bounds.height(), + window1->delegate()->GetMinimumSize().height()); + EndSplitView(); +} + } // namespace ash
diff --git a/base/metrics/histogram_samples.cc b/base/metrics/histogram_samples.cc index f12cdc9..10243bb 100644 --- a/base/metrics/histogram_samples.cc +++ b/base/metrics/histogram_samples.cc
@@ -7,6 +7,7 @@ #include <limits> #include "base/compiler_specific.h" +#include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "base/numerics/safe_math.h" #include "base/pickle.h" @@ -251,6 +252,16 @@ subtle::NoBarrier_AtomicIncrement(&meta_->redundant_count, count); } +void HistogramSamples::RecordNegativeSample(NegativeSampleReason reason, + HistogramBase::Count increment) { + UMA_HISTOGRAM_ENUMERATION("UMA.NegativeSamples.Reason", reason, + MAX_NEGATIVE_SAMPLE_REASONS); + UMA_HISTOGRAM_CUSTOM_COUNTS("UMA.NegativeSamples.Increment", increment, 1, + 1 << 30, 100); + UMA_HISTOGRAM_SPARSE_SLOWLY("UMA.NegativeSamples.Histogram", + static_cast<int32_t>(id())); +} + SampleCountIterator::~SampleCountIterator() {} bool SampleCountIterator::GetBucketIndex(size_t* index) const {
diff --git a/base/metrics/histogram_samples.h b/base/metrics/histogram_samples.h index d1f95a4..23237b0 100644 --- a/base/metrics/histogram_samples.h +++ b/base/metrics/histogram_samples.h
@@ -160,6 +160,19 @@ } protected: + enum NegativeSampleReason { + SAMPLES_HAVE_LOGGED_BUT_NOT_SAMPLE, + SAMPLES_SAMPLE_LESS_THAN_LOGGED, + SAMPLES_ADDED_NEGATIVE_COUNT, + SAMPLES_ADD_WENT_NEGATIVE, + SAMPLES_ADD_OVERFLOW, + SAMPLES_ACCUMULATE_NEGATIVE_COUNT, + SAMPLES_ACCUMULATE_WENT_NEGATIVE, + DEPRECATED_SAMPLES_ACCUMULATE_OVERFLOW, + SAMPLES_ACCUMULATE_OVERFLOW, + MAX_NEGATIVE_SAMPLE_REASONS + }; + // Based on |op| type, add or subtract sample counts data from the iterator. enum Operator { ADD, SUBTRACT }; virtual bool AddSubtractImpl(SampleCountIterator* iter, Operator op) = 0; @@ -174,6 +187,10 @@ // Atomically adjust the sum and redundant-count. void IncreaseSumAndCount(int64_t sum, HistogramBase::Count count); + // Record a negative-sample observation and the reason why. + void RecordNegativeSample(NegativeSampleReason reason, + HistogramBase::Count increment); + AtomicSingleSample& single_sample() { return meta_->single_sample; } const AtomicSingleSample& single_sample() const { return meta_->single_sample;
diff --git a/base/metrics/persistent_sample_map.cc b/base/metrics/persistent_sample_map.cc index 1b319a9..817702f 100644 --- a/base/metrics/persistent_sample_map.cc +++ b/base/metrics/persistent_sample_map.cc
@@ -18,19 +18,6 @@ namespace { -enum NegativeSampleReason { - PERSISTENT_SPARSE_HAVE_LOGGED_BUT_NOT_SAMPLE, - PERSISTENT_SPARSE_SAMPLE_LESS_THAN_LOGGED, - PERSISTENT_SPARSE_ADDED_NEGATIVE_COUNT, - PERSISTENT_SPARSE_ADD_WENT_NEGATIVE, - PERSISTENT_SPARSE_ADD_OVERFLOW, - PERSISTENT_SPARSE_ACCUMULATE_NEGATIVE_COUNT, - PERSISTENT_SPARSE_ACCUMULATE_WENT_NEGATIVE, - DEPRECATED_PERSISTENT_SPARSE_ACCUMULATE_OVERFLOW, - PERSISTENT_SPARSE_ACCUMULATE_OVERFLOW, - MAX_NEGATIVE_SAMPLE_REASONS -}; - // An iterator for going through a PersistentSampleMap. The logic here is // identical to that of SampleMapIterator but with different data structures. // Changes here likely need to be duplicated there. @@ -125,27 +112,19 @@ #if 0 // TODO(bcwhite) Re-enable efficient version after crbug.com/682680. *GetOrCreateSampleCountStorage(value) += count; #else - NegativeSampleReason reason = MAX_NEGATIVE_SAMPLE_REASONS; Count* local_count_ptr = GetOrCreateSampleCountStorage(value); if (count < 0) { - reason = PERSISTENT_SPARSE_ACCUMULATE_NEGATIVE_COUNT; if (*local_count_ptr < -count) - reason = PERSISTENT_SPARSE_ACCUMULATE_WENT_NEGATIVE; + RecordNegativeSample(SAMPLES_ACCUMULATE_WENT_NEGATIVE, -count); + else + RecordNegativeSample(SAMPLES_ACCUMULATE_NEGATIVE_COUNT, -count); *local_count_ptr += count; } else { Sample old_value = *local_count_ptr; Sample new_value = old_value + count; *local_count_ptr = new_value; if ((new_value >= 0) != (old_value >= 0)) - reason = PERSISTENT_SPARSE_ACCUMULATE_OVERFLOW; - } - if (reason != MAX_NEGATIVE_SAMPLE_REASONS) { - UMA_HISTOGRAM_ENUMERATION("UMA.NegativeSamples.Reason", reason, - MAX_NEGATIVE_SAMPLE_REASONS); - UMA_HISTOGRAM_CUSTOM_COUNTS("UMA.NegativeSamples.Increment", count, 1, - 1 << 30, 100); - UMA_HISTOGRAM_SPARSE_SLOWLY("UMA.NegativeSamples.Histogram", - static_cast<int32_t>(id())); + RecordNegativeSample(SAMPLES_ACCUMULATE_OVERFLOW, count); } #endif IncreaseSumAndCount(strict_cast<int64_t>(count) * value, count);
diff --git a/base/metrics/sample_vector.cc b/base/metrics/sample_vector.cc index c484ed74..c8b1ac7a 100644 --- a/base/metrics/sample_vector.cc +++ b/base/metrics/sample_vector.cc
@@ -55,8 +55,14 @@ } // Handle the multi-sample case. - subtle::NoBarrier_AtomicIncrement(&counts()[bucket_index], count); + Count new_value = + subtle::NoBarrier_AtomicIncrement(&counts()[bucket_index], count); IncreaseSumAndCount(strict_cast<int64_t>(count) * value, count); + + // TODO(bcwhite) Remove after crbug.com/682680. + Count old_value = new_value - count; + if ((new_value >= 0) != (old_value >= 0) && count > 0) + RecordNegativeSample(SAMPLES_ACCUMULATE_OVERFLOW, count); } Count SampleVectorBase::GetCount(Sample value) const {
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index a3227d5..22412e3 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -7,6 +7,7 @@ import("//build/config/chromecast_build.gni") import("//build/config/compiler/compiler.gni") import("//build/config/coverage/coverage.gni") +import("//build/config/host_byteorder.gni") import("//build/toolchain/cc_wrapper.gni") import("//build/toolchain/toolchain.gni") import("//build_overrides/build.gni") @@ -890,6 +891,25 @@ "--target=armv7-unknown-nacl-gnueabihf", ] } + } else if (current_cpu == "ppc64") { + if (v8_current_cpu == "ppc") { + cflags += [ "-m32" ] + ldflags += [ "-m32" ] + } else if (v8_current_cpu == "ppc64") { + cflags += [ "-m64" ] + ldflags += [ "-m64" ] + } + } else if (current_cpu == "s390x") { + if (v8_current_cpu == "s390" && host_byteorder == "little") { + cflags += [ "-m32" ] + ldflags += [ "-m32" ] + } else if (v8_current_cpu == "s390") { + cflags += [ "-m31" ] + ldflags += [ "-m31" ] + } else if (v8_current_cpu == "s390x") { + cflags += [ "-m64" ] + ldflags += [ "-m64" ] + } } }
diff --git a/chrome/VERSION b/chrome/VERSION index 2dc2585..8c9901d 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=64 MINOR=0 -BUILD=3255 +BUILD=3256 PATCH=0
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index a2d918dc..834d298 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h
@@ -71,6 +71,11 @@ #define IDC_USE_SYSTEM_TITLE_BAR 34051 #endif +// Hosted app commands +#define IDC_COPY_URL 34060 +#define IDC_OPEN_IN_CHROME 34061 +#define IDC_SITE_SETTINGS 34062 + // Page-related commands #define IDC_BOOKMARK_PAGE 35000 #define IDC_BOOKMARK_ALL_TABS 35001
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 736f8a2..16cbf49 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -86,7 +86,7 @@ Zip Archiver - Open and pack ZIP files in Files app. </message> <message desc="Title of the password input dialog." name="IDS_ZIP_ARCHIVER_PASSPHRASE_TITLE"> - Enter your password to gain access + Enter your password </message> <message desc="Label of the password input field." name="IDS_ZIP_ARCHIVER_PASSPHRASE_INPUT_LABEL"> Password
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index 123f90e..0b7c680 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd
@@ -606,6 +606,10 @@ Customize and control Chromium </message> + <message name="IDS_OPEN_IN_CHROME" desc="The text label of the Open in Chrome menu item for the Hosted App app menu"> + &Open in Chromium + </message> + <if expr="use_titlecase and not chromeos"> <message name="IDS_ABOUT" desc="In Title Case: The text label of the About Chrome menu item"> About &Chromium
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 754156c..b3342fc 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -867,6 +867,12 @@ <message name="IDS_ZOOM_MINUS2" desc="The text label of the Make Text Smaller menu item in the merged menu"> − </message> + <message name="IDS_COPY_URL" desc="The text label of the Copy URL menu item for the Hosted App app menu"> + Copy &URL + </message> + <message name="IDS_SITE_SETTINGS" desc="The text label of the Site Settings menu item for the Hosted App app menu"> + &Site settings + </message> </if> <if expr="use_titlecase"> <message name="IDS_NEW_TAB" desc="In Title Case: The text label of a menu item for opening a new tab"> @@ -932,6 +938,12 @@ <message name="IDS_ZOOM_MINUS2" desc="The text label of the Make Text Smaller menu item in the merged menu"> − </message> + <message name="IDS_COPY_URL" desc="In Title Case: The text label of the Copy URL menu item for the Hosted App app menu"> + Copy &URL + </message> + <message name="IDS_SITE_SETTINGS" desc="In Title Case: The text label of the Site Settings menu item for the Hosted App app menu"> + &Site Settings + </message> </if> </if>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index a80472b..4d43bb7f 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd
@@ -616,6 +616,10 @@ Customize and control Google Chrome </message> + <message name="IDS_OPEN_IN_CHROME" desc="The text label of the Open in Chrome menu item for the Hosted App app menu"> + &Open in Chrome + </message> + <if expr="use_titlecase and not chromeos"> <message name="IDS_ABOUT" desc="In Title Case: The text label of the About Chrome menu item"> About &Google Chrome
diff --git a/chrome/browser/chrome_content_gpu_manifest_overlay.json b/chrome/browser/chrome_content_gpu_manifest_overlay.json index 6398526a..0d7c7c1 100644 --- a/chrome/browser/chrome_content_gpu_manifest_overlay.json +++ b/chrome/browser/chrome_content_gpu_manifest_overlay.json
@@ -4,12 +4,12 @@ "service_manager:connector": { "provides": { "browser": [ + "arc::mojom::ProtectedBufferManager", "arc::mojom::VideoDecodeAccelerator", "arc::mojom::VideoDecodeClient", "arc::mojom::VideoEncodeAccelerator", "arc::mojom::VideoEncodeClient", "chrome::mojom::ResourceUsageReporter", - "media::mojom::ProtectedBufferManager", "profiling::mojom::ProfilingClient" ] }
diff --git a/chrome/browser/chromeos/arc/oemcrypto/arc_oemcrypto_bridge.cc b/chrome/browser/chromeos/arc/oemcrypto/arc_oemcrypto_bridge.cc index 030cad8..4505e33 100644 --- a/chrome/browser/chromeos/arc/oemcrypto/arc_oemcrypto_bridge.cc +++ b/chrome/browser/chromeos/arc/oemcrypto/arc_oemcrypto_bridge.cc
@@ -149,7 +149,7 @@ mojom::OemCryptoServiceRequest request) { // Get the Mojo interface from the GPU for dealing with secure buffers and // pass that to the daemon as well in our Connect call. - media::mojom::ProtectedBufferManagerPtr gpu_buffer_manager; + mojom::ProtectedBufferManagerPtr gpu_buffer_manager; content::BindInterfaceInGpuProcess(mojo::MakeRequest(&gpu_buffer_manager)); oemcrypto_host_daemon_ptr_->Connect(std::move(request), std::move(gpu_buffer_manager));
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc index 4d6db15..9bd8286 100644 --- a/chrome/browser/profiles/profile_window_browsertest.cc +++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -225,6 +225,7 @@ EmptyAcceleratorHandler accelerator_handler; // Verify the normal browser has a bookmark menu. AppMenuModel model_normal_profile(&accelerator_handler, browser()); + model_normal_profile.Init(); EXPECT_NE(-1, model_normal_profile.GetIndexOfCommandId(IDC_BOOKMARKS_MENU)); // Guest browser has no bookmark menu.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index d42b724fa..0032699 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3421,6 +3421,8 @@ "extensions/extension_message_bubble_factory.h", "extensions/hosted_app_browser_controller.cc", "extensions/hosted_app_browser_controller.h", + "extensions/hosted_app_menu_model.cc", + "extensions/hosted_app_menu_model.h", "extensions/icon_with_badge_image_source.cc", "extensions/icon_with_badge_image_source.h", "extensions/settings_api_bubble_helpers.cc",
diff --git a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm index d5159bd..a61925c 100644 --- a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm +++ b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
@@ -481,6 +481,7 @@ DCHECK(browser_); recentTabsMenuModelDelegate_.reset(); appMenuModel_.reset(new AppMenuModel(acceleratorDelegate_.get(), browser_)); + appMenuModel_->Init(); [self setModel:appMenuModel_.get()]; buttonViewController_.reset(
diff --git a/chrome/browser/ui/cocoa/app_menu/app_menu_controller_unittest.mm b/chrome/browser/ui/cocoa/app_menu/app_menu_controller_unittest.mm index 8be7748..e013e5a 100644 --- a/chrome/browser/ui/cocoa/app_menu/app_menu_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/app_menu/app_menu_controller_unittest.mm
@@ -51,7 +51,7 @@ class MockAppMenuModel : public AppMenuModel { public: - MockAppMenuModel() : AppMenuModel() {} + MockAppMenuModel() : AppMenuModel(nullptr, nullptr) {} ~MockAppMenuModel() {} MOCK_METHOD2(ExecuteCommand, void(int command_id, int event_flags)); };
diff --git a/chrome/browser/ui/extensions/hosted_app_menu_model.cc b/chrome/browser/ui/extensions/hosted_app_menu_model.cc new file mode 100644 index 0000000..bf26c02 --- /dev/null +++ b/chrome/browser/ui/extensions/hosted_app_menu_model.cc
@@ -0,0 +1,32 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/extensions/hosted_app_menu_model.h" + +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/media/router/media_router_feature.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/grit/generated_resources.h" +#include "components/strings/grit/components_strings.h" + +HostedAppMenuModel::HostedAppMenuModel(ui::AcceleratorProvider* provider, + Browser* browser) + : AppMenuModel(provider, browser) {} + +HostedAppMenuModel::~HostedAppMenuModel() {} + +void HostedAppMenuModel::Build() { + AddItemWithStringId(IDC_COPY_URL, IDS_COPY_URL); + AddItemWithStringId(IDC_OPEN_IN_CHROME, IDS_OPEN_IN_CHROME); + CreateActionToolbarOverflowMenu(); + CreateZoomMenu(); + AddItemWithStringId(IDC_PRINT, IDS_PRINT); + AddItemWithStringId(IDC_FIND, IDS_FIND); + if (media_router::MediaRouterEnabled(browser()->profile())) + AddItemWithStringId(IDC_ROUTE_MEDIA, IDS_MEDIA_ROUTER_MENU_ITEM_TITLE); + CreateCutCopyPasteMenu(); + AddItemWithStringId(IDC_SITE_SETTINGS, IDS_SITE_SETTINGS); +}
diff --git a/chrome/browser/ui/extensions/hosted_app_menu_model.h b/chrome/browser/ui/extensions/hosted_app_menu_model.h new file mode 100644 index 0000000..a79026bc --- /dev/null +++ b/chrome/browser/ui/extensions/hosted_app_menu_model.h
@@ -0,0 +1,24 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_EXTENSIONS_HOSTED_APP_MENU_MODEL_H_ +#define CHROME_BROWSER_UI_EXTENSIONS_HOSTED_APP_MENU_MODEL_H_ + +#include "base/macros.h" +#include "chrome/browser/ui/toolbar/app_menu_model.h" + +// Menu model for the menu button in a hosted app browser window. +class HostedAppMenuModel : public AppMenuModel { + public: + HostedAppMenuModel(ui::AcceleratorProvider* provider, Browser* browser); + ~HostedAppMenuModel() override; + + private: + // AppMenuModel: + void Build() override; + + DISALLOW_COPY_AND_ASSIGN(HostedAppMenuModel); +}; + +#endif // CHROME_BROWSER_UI_EXTENSIONS_HOSTED_APP_MENU_MODEL_H_
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index 5f2158a..b900df0b 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -216,12 +216,19 @@ : ui::SimpleMenuModel(this), uma_action_recorded_(false), provider_(provider), - browser_(browser) { + browser_(browser) {} + +AppMenuModel::~AppMenuModel() { + if (browser_) // Null in Cocoa tests. + browser_->tab_strip_model()->RemoveObserver(this); +} + +void AppMenuModel::Init() { Build(); UpdateZoomControls(); browser_zoom_subscription_ = - zoom::ZoomEventManager::GetForBrowserContext(browser->profile()) + zoom::ZoomEventManager::GetForBrowserContext(browser_->profile()) ->AddZoomLevelChangedCallback(base::Bind( &AppMenuModel::OnZoomLevelChanged, base::Unretained(this))); @@ -231,11 +238,6 @@ content::NotificationService::AllSources()); } -AppMenuModel::~AppMenuModel() { - if (browser_) // Null in tests. - browser_->tab_strip_model()->RemoveObserver(this); -} - bool AppMenuModel::DoesCommandIdDismissMenu(int command_id) const { return command_id != IDC_ZOOM_MINUS && command_id != IDC_ZOOM_PLUS; } @@ -661,21 +663,6 @@ UpdateZoomControls(); } -// For testing. -AppMenuModel::AppMenuModel() - : ui::SimpleMenuModel(this), - uma_action_recorded_(false), - provider_(nullptr), - browser_(nullptr) {} - -bool AppMenuModel::ShouldShowNewIncognitoWindowMenuItem() { - if (browser_->profile()->IsGuestSession()) - return false; - - return IncognitoModePrefs::GetAvailability(browser_->profile()->GetPrefs()) != - IncognitoModePrefs::DISABLED; -} - // Note: When adding new menu items please place under an appropriate section. // Menu is organised as follows: // - Extension toolbar overflow. @@ -766,32 +753,6 @@ uma_action_recorded_ = false; } -bool AppMenuModel::AddGlobalErrorMenuItems() { - // TODO(sail): Currently we only build the app menu once per browser - // window. This means that if a new error is added after the menu is built - // it won't show in the existing app menu. To fix this we need to some - // how update the menu if new errors are added. - const GlobalErrorService::GlobalErrorList& errors = - GlobalErrorServiceFactory::GetForProfile(browser_->profile())->errors(); - bool menu_items_added = false; - for (GlobalErrorService::GlobalErrorList::const_iterator - it = errors.begin(); it != errors.end(); ++it) { - GlobalError* error = *it; - DCHECK(error); - if (error->HasMenuItem()) { - AddItem(error->MenuItemCommandID(), error->MenuItemLabel()); - SetIcon(GetIndexOfCommandId(error->MenuItemCommandID()), - error->MenuItemIcon()); - menu_items_added = true; - if (IDC_SHOW_SIGNIN_ERROR == error->MenuItemCommandID()) { - base::RecordAction( - base::UserMetricsAction("Signin_Impression_FromMenu")); - } - } - } - return menu_items_added; -} - void AppMenuModel::CreateActionToolbarOverflowMenu() { // We only add the extensions overflow container if there are any icons that // aren't shown in the main container. @@ -858,6 +819,40 @@ zoom_label_ = base::FormatPercent(zoom_percent); } +bool AppMenuModel::ShouldShowNewIncognitoWindowMenuItem() { + if (browser_->profile()->IsGuestSession()) + return false; + + return IncognitoModePrefs::GetAvailability(browser_->profile()->GetPrefs()) != + IncognitoModePrefs::DISABLED; +} + +bool AppMenuModel::AddGlobalErrorMenuItems() { + // TODO(sail): Currently we only build the app menu once per browser + // window. This means that if a new error is added after the menu is built + // it won't show in the existing app menu. To fix this we need to some + // how update the menu if new errors are added. + const GlobalErrorService::GlobalErrorList& errors = + GlobalErrorServiceFactory::GetForProfile(browser_->profile())->errors(); + bool menu_items_added = false; + for (GlobalErrorService::GlobalErrorList::const_iterator it = errors.begin(); + it != errors.end(); ++it) { + GlobalError* error = *it; + DCHECK(error); + if (error->HasMenuItem()) { + AddItem(error->MenuItemCommandID(), error->MenuItemLabel()); + SetIcon(GetIndexOfCommandId(error->MenuItemCommandID()), + error->MenuItemIcon()); + menu_items_added = true; + if (IDC_SHOW_SIGNIN_ERROR == error->MenuItemCommandID()) { + base::RecordAction( + base::UserMetricsAction("Signin_Impression_FromMenu")); + } + } + } + return menu_items_added; +} + void AppMenuModel::OnZoomLevelChanged( const content::HostZoomMap::ZoomLevelChange& change) { UpdateZoomControls();
diff --git a/chrome/browser/ui/toolbar/app_menu_model.h b/chrome/browser/ui/toolbar/app_menu_model.h index 980ba8b..47eb2f7 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.h +++ b/chrome/browser/ui/toolbar/app_menu_model.h
@@ -109,9 +109,14 @@ static const int kMinRecentTabsCommandId = 1001; static const int kMaxRecentTabsCommandId = 1200; + // Creates an app menu model for the given browser. Init() must be called + // before passing this to an AppMenu. AppMenuModel(ui::AcceleratorProvider* provider, Browser* browser); ~AppMenuModel() override; + // Runs Build() and registers observers. + void Init(); + // Overridden for ButtonMenuItemModel::Delegate: bool DoesCommandIdDismissMenu(int command_id) const override; @@ -151,19 +156,9 @@ // Calculates |zoom_label_| in response to a zoom change. void UpdateZoomControls(); - private: - class HelpMenuModel; - // Testing constructor used for mocking. - friend class ::MockAppMenuModel; - - AppMenuModel(); - - void Build(); - - // Adds actionable global error menu items to the menu. - // Examples: Extension permissions and sign in errors. - // Returns a boolean indicating whether any menu items were added. - bool AddGlobalErrorMenuItems(); + protected: + // Builds the menu model, adding appropriate menu items. + virtual void Build(); // Appends everything needed for the clipboard menu: a menu break, the // clipboard menu content and the finalizing menu break. @@ -176,10 +171,19 @@ // menu content and then another menu break. void CreateZoomMenu(); - void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change); + private: + class HelpMenuModel; + friend class ::MockAppMenuModel; bool ShouldShowNewIncognitoWindowMenuItem(); + // Adds actionable global error menu items to the menu. + // Examples: Extension permissions and sign in errors. + // Returns a boolean indicating whether any menu items were added. + bool AddGlobalErrorMenuItems(); + + void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change); + // Called when a command is selected. // Logs UMA metrics about which command was chosen and how long the user // took to select the command.
diff --git a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc index 5c8659c..c16bd77 100644 --- a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc +++ b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
@@ -116,6 +116,7 @@ TEST_F(AppMenuModelTest, Basics) { TestAppMenuModel model(this, browser()); + model.Init(); int itemCount = model.GetItemCount(); // Verify it has items. The number varies by platform, so we don't check @@ -182,6 +183,7 @@ service->AddGlobalError(base::WrapUnique(error2)); AppMenuModel model(this, browser()); + model.Init(); int index1 = model.GetIndexOfCommandId(command1); EXPECT_GT(index1, -1); int index2 = model.GetIndexOfCommandId(command2);
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.cc b/chrome/browser/ui/views/frame/hosted_app_button_container.cc index f5b3462c..f011b041 100644 --- a/chrome/browser/ui/views/frame/hosted_app_button_container.cc +++ b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/ui/views/frame/hosted_app_button_container.h" #include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/ui/toolbar/app_menu_model.h" +#include "chrome/browser/ui/extensions/hosted_app_menu_model.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/toolbar/app_menu.h" #include "ui/gfx/color_palette.h" @@ -31,9 +31,9 @@ const gfx::Point& point, const ui::Event* event) { Browser* browser = browser_view_->browser(); - menu_.reset(new AppMenu(browser, 0)); - // TODO(calamity): Use custom menu model here. - menu_model_.reset(new AppMenuModel(browser_view_, browser)); + menu_ = std::make_unique<AppMenu>(browser, 0); + menu_model_ = std::make_unique<HostedAppMenuModel>(browser_view_, browser); + menu_model_->Init(); menu_->Init(menu_model_.get()); menu_->RunMenu(this);
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.h b/chrome/browser/ui/views/frame/hosted_app_button_container.h index fe13c87..aae9a09 100644 --- a/chrome/browser/ui/views/frame/hosted_app_button_container.h +++ b/chrome/browser/ui/views/frame/hosted_app_button_container.h
@@ -13,7 +13,7 @@ #include "ui/views/view.h" class AppMenu; -class AppMenuModel; +class HostedAppMenuModel; class BrowserView; // A container for hosted app buttons in the title bar. @@ -48,7 +48,7 @@ // App model and menu. // Note that the menu should be destroyed before the model it uses, so the // menu should be listed later. - std::unique_ptr<AppMenuModel> menu_model_; + std::unique_ptr<HostedAppMenuModel> menu_model_; std::unique_ptr<AppMenu> menu_; DISALLOW_COPY_AND_ASSIGN(AppMenuButton);
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc index 20a197c..b47b416 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -770,6 +770,25 @@ selector_rows_.push_back(std::move(selector)); } + // In Harmony, ensure most comboboxes are the same width by setting them all + // to the widest combobox size, provided it does not exceed a maximum width. + // For selected options that are over the maximum width, allow them to assume + // their full width. If the combobox selection is changed, this may make the + // widths inconsistent again, but that is OK since the widths will be updated + // on the next time the bubble is opened. + if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { + const int maximum_width = ChromeLayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_BUTTON_MAX_LINKABLE_WIDTH); + int combobox_width = 0; + for (const auto& selector : selector_rows_) { + int curr_width = selector->GetComboboxWidth(); + if (maximum_width >= curr_width) + combobox_width = std::max(combobox_width, curr_width); + } + for (const auto& selector : selector_rows_) + selector->SetMinComboboxWidth(combobox_width); + } + for (auto& object : chosen_object_info_list) { // Since chosen objects are presented after permissions in the same list, // make sure its height is the same as the permissions row's minimum height
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row.cc b/chrome/browser/ui/views/page_info/permission_selector_row.cc index 43b399a..195d898 100644 --- a/chrome/browser/ui/views/page_info/permission_selector_row.cc +++ b/chrome/browser/ui/views/page_info/permission_selector_row.cc
@@ -213,11 +213,21 @@ void UpdateSelectedIndex(bool use_default); + void set_min_width(int width) { min_width_ = width; } + + // views::Combobox: + gfx::Size CalculatePreferredSize() const override; + private: // views::ComboboxListener: void OnPerformAction(Combobox* combobox) override; ComboboxModelAdapter* model_; + + // Minimum width for |PermissionCombobox|. + int min_width_ = 0; + + DISALLOW_COPY_AND_ASSIGN(PermissionCombobox); }; PermissionCombobox::PermissionCombobox(ComboboxModelAdapter* model, @@ -243,6 +253,12 @@ SetSelectedIndex(index); } +gfx::Size PermissionCombobox::CalculatePreferredSize() const { + gfx::Size preferred_size = Combobox::CalculatePreferredSize(); + preferred_size.SetToMax(gfx::Size(min_width_, 0)); + return preferred_size; +} + void PermissionCombobox::OnPerformAction(Combobox* combobox) { model_->OnPerformAction(combobox->selected_index()); } @@ -404,6 +420,16 @@ } } +int PermissionSelectorRow::GetComboboxWidth() const { + DCHECK(combobox_); + return combobox_->Combobox::GetPreferredSize().width(); +} + +void PermissionSelectorRow::SetMinComboboxWidth(int width) { + DCHECK(combobox_); + combobox_->set_min_width(width); +} + views::View* PermissionSelectorRow::button() { // These casts are required because the two arms of a ?: cannot have different // types T1 and T2, even if the resulting value of the ?: is about to be a T
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row.h b/chrome/browser/ui/views/page_info/permission_selector_row.h index d9cea6f..17ff487 100644 --- a/chrome/browser/ui/views/page_info/permission_selector_row.h +++ b/chrome/browser/ui/views/page_info/permission_selector_row.h
@@ -57,6 +57,13 @@ void PermissionChanged(const PageInfoUI::PermissionInfo& permission); + // Returns the preferred width for the currently selected combobox option + // (unchanged by any minimum width set using SetMinComboboxWidth()). + int GetComboboxWidth() const; + + // Sets the minimum width for |combobox_|. + void SetMinComboboxWidth(int width); + private: friend class test::PageInfoBubbleViewTestApi;
diff --git a/chrome/browser/ui/views/toolbar/app_menu_button.cc b/chrome/browser/ui/views/toolbar/app_menu_button.cc index a11dde4..70f6884 100644 --- a/chrome/browser/ui/views/toolbar/app_menu_button.cc +++ b/chrome/browser/ui/views/toolbar/app_menu_button.cc
@@ -94,6 +94,7 @@ menu_.reset(new AppMenu(browser, for_drop ? AppMenu::FOR_DROP : 0)); menu_model_.reset(new AppMenuModel(toolbar_view_, browser)); + menu_model_->Init(); menu_->Init(menu_model_.get()); for (views::MenuListener& observer : menu_listeners_)
diff --git a/chrome/gpu/BUILD.gn b/chrome/gpu/BUILD.gn index 93bdd8a..4581690 100644 --- a/chrome/gpu/BUILD.gn +++ b/chrome/gpu/BUILD.gn
@@ -27,6 +27,10 @@ "gpu_arc_video_decode_accelerator.h", "gpu_arc_video_encode_accelerator.cc", "gpu_arc_video_encode_accelerator.h", + "protected_buffer_manager.cc", + "protected_buffer_manager.h", + "protected_buffer_manager_proxy.cc", + "protected_buffer_manager_proxy.h", ] } }
diff --git a/chrome/gpu/arc_video_decode_accelerator.h b/chrome/gpu/arc_video_decode_accelerator.h index c56d5df..bd1104e 100644 --- a/chrome/gpu/arc_video_decode_accelerator.h +++ b/chrome/gpu/arc_video_decode_accelerator.h
@@ -72,6 +72,8 @@ struct Config { size_t num_input_buffers = 0; uint32_t input_pixel_format = 0; + // If true, only buffers created via AllocateProtectedBuffer() may be used. + bool secure_mode = false; // TODO(owenlin): Add output_pixel_format. For now only the native pixel // format of each VDA on Chromium is supported. }; @@ -111,10 +113,27 @@ // returns SUCCESS iff initialization is successful. virtual Result Initialize(const Config& config, Client* client) = 0; + // Allocates a new protected buffer on accelerator side for the given |port| + // and |index|, the contents of which will be inaccessible to the client. + // The protected buffer will remain valid for at least as long as the resource + // backing the passed |handle_fd| is not released (i.e. there is at least one + // reference on the file backing |handle_fd|. + // + // Usable only if the accelerator has been initialized to run in secure mode. + // Allocation for input will create a protected buffer of at least |size|; + // for output, |size| is ignored, and the currently configured output format + // is used instead to determine the required buffer size and format. + virtual bool AllocateProtectedBuffer(PortType port, + uint32_t index, + base::ScopedFD handle_fd, + size_t size) = 0; + // Assigns a shared memory to be used for the accelerator at the specified // port and index. A buffer must be successfully bound before it can be passed // to the accelerator via UseBuffer(). Already bound buffers may be reused // multiple times without additional bindings. + // Not allowed in secure_mode, where protected buffers have to be allocated + // instead. virtual void BindSharedMemory(PortType port, uint32_t index, base::ScopedFD ashmem_fd, @@ -125,6 +144,8 @@ // port and index. A buffer must be successfully bound before it can be // passed to the accelerator via UseBuffer(). Already bound buffers may be // reused multiple times without additional bindings. + // Not allowed in secure_mode, where protected buffers have to be allocated + // instead. virtual void BindDmabuf( PortType port, uint32_t index, @@ -134,6 +155,8 @@ // Passes a buffer to the accelerator. For input buffer, the accelerator // will process it. For output buffer, the accelerator will output content // to it. + // In secure mode, |port| and |index| must correspond to a protected buffer + // allocated using AllocateProtectedBuffer(). virtual void UseBuffer(PortType port, uint32_t index, const BufferMetadata& metadata) = 0;
diff --git a/chrome/gpu/chrome_arc_video_decode_accelerator.cc b/chrome/gpu/chrome_arc_video_decode_accelerator.cc index 16715b663..1cda9c3 100644 --- a/chrome/gpu/chrome_arc_video_decode_accelerator.cc +++ b/chrome/gpu/chrome_arc_video_decode_accelerator.cc
@@ -10,7 +10,9 @@ #include "base/numerics/safe_math.h" #include "base/run_loop.h" #include "base/unguessable_token.h" +#include "chrome/gpu/protected_buffer_manager.h" #include "media/base/video_frame.h" +#include "media/gpu/format_utils.h" #include "media/gpu/gpu_video_decode_accelerator_factory.h" namespace chromeos { @@ -41,27 +43,33 @@ ChromeArcVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo() = default; -ChromeArcVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo( - InputBufferInfo&& other) = default; - -ChromeArcVideoDecodeAccelerator::InputBufferInfo::~InputBufferInfo() = default; +ChromeArcVideoDecodeAccelerator::InputBufferInfo::~InputBufferInfo() { + if (shm_handle.OwnershipPassesToIPC()) + shm_handle.Close(); +} ChromeArcVideoDecodeAccelerator::OutputBufferInfo::OutputBufferInfo() = default; -ChromeArcVideoDecodeAccelerator::OutputBufferInfo::OutputBufferInfo( - OutputBufferInfo&& other) = default; - -ChromeArcVideoDecodeAccelerator::OutputBufferInfo::~OutputBufferInfo() = - default; +ChromeArcVideoDecodeAccelerator::OutputBufferInfo::~OutputBufferInfo() { + if (!gpu_memory_buffer_handle.is_null()) { + for (const auto& fd : gpu_memory_buffer_handle.native_pixmap_handle.fds) { + // Close the fd by wrapping it in a ScopedFD and letting + // it fall out of scope. + base::ScopedFD scoped_fd(fd.fd); + } + } +} ChromeArcVideoDecodeAccelerator::ChromeArcVideoDecodeAccelerator( - const gpu::GpuPreferences& gpu_preferences) + const gpu::GpuPreferences& gpu_preferences, + ProtectedBufferManager* protected_buffer_manager) : arc_client_(nullptr), next_bitstream_buffer_id_(0), output_pixel_format_(media::PIXEL_FORMAT_UNKNOWN), output_buffer_size_(0), requested_num_of_output_buffers_(0), - gpu_preferences_(gpu_preferences) {} + gpu_preferences_(gpu_preferences), + protected_buffer_manager_(protected_buffer_manager) {} ChromeArcVideoDecodeAccelerator::~ChromeArcVideoDecodeAccelerator() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -95,13 +103,20 @@ return ILLEGAL_STATE; } + arc_client_ = client; + if (client_count_ >= kMaxConcurrentClients) { LOG(WARNING) << "Reject to Initialize() due to too many clients: " << client_count_; return INSUFFICIENT_RESOURCES; } - arc_client_ = client; + if (config.secure_mode && !protected_buffer_manager_) { + DLOG(ERROR) << "Secure mode unsupported"; + return PLATFORM_FAILURE; + } + + secure_mode_ = config.secure_mode; if (config.num_input_buffers > kMaxBufferCount) { DLOG(ERROR) << "Request too many buffers: " << config.num_input_buffers; @@ -168,6 +183,60 @@ buffers_pending_import_.resize(number); } +bool ChromeArcVideoDecodeAccelerator::AllocateProtectedBuffer( + PortType port, + uint32_t index, + base::ScopedFD handle_fd, + size_t size) { + DVLOG(5) << "port=" << port << " index=" << index + << " handle=" << handle_fd.get() << " size=" << size; + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + if (!secure_mode_) { + DLOG(ERROR) << "Not in secure mode"; + arc_client_->OnError(INVALID_ARGUMENT); + return false; + } + + if (!ValidatePortAndIndex(port, index)) { + arc_client_->OnError(INVALID_ARGUMENT); + return false; + } + + if (port == PORT_INPUT) { + auto protected_shmem = + protected_buffer_manager_->AllocateProtectedSharedMemory( + std::move(handle_fd), size); + if (!protected_shmem) { + DLOG(ERROR) << "Failed allocating protected shared memory"; + return false; + } + + auto input_info = std::make_unique<InputBufferInfo>(); + input_info->shm_handle = protected_shmem->shm_handle(); + input_info->protected_buffer_handle = std::move(protected_shmem); + input_buffer_info_[index] = std::move(input_info); + } else if (port == PORT_OUTPUT) { + auto protected_pixmap = + protected_buffer_manager_->AllocateProtectedNativePixmap( + std::move(handle_fd), + media::VideoPixelFormatToGfxBufferFormat(output_pixel_format_), + coded_size_); + if (!protected_pixmap) { + DLOG(ERROR) << "Failed allocating a protected pixmap"; + return false; + } + auto output_info = std::make_unique<OutputBufferInfo>(); + output_info->gpu_memory_buffer_handle.type = gfx::NATIVE_PIXMAP; + output_info->gpu_memory_buffer_handle.native_pixmap_handle = + gfx::CloneHandleForIPC(protected_pixmap->native_pixmap_handle()); + output_info->protected_buffer_handle = std::move(protected_pixmap); + buffers_pending_import_[index] = std::move(output_info); + } + + return true; +} + void ChromeArcVideoDecodeAccelerator::BindSharedMemory(PortType port, uint32_t index, base::ScopedFD ashmem_fd, @@ -176,6 +245,13 @@ DVLOG(5) << "ArcGVDA::BindSharedMemory, offset: " << offset << ", length: " << length; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + if (secure_mode_) { + DLOG(ERROR) << "not allowed in secure mode"; + arc_client_->OnError(INVALID_ARGUMENT); + return; + } + if (!vda_) { DLOG(ERROR) << "VDA not initialized"; return; @@ -190,10 +266,14 @@ arc_client_->OnError(INVALID_ARGUMENT); return; } - InputBufferInfo* input_info = &input_buffer_info_[index]; - input_info->handle = std::move(ashmem_fd); + + auto input_info = std::make_unique<InputBufferInfo>(); + input_info->shm_handle = + base::SharedMemoryHandle(base::FileDescriptor(ashmem_fd.release(), true), + length, base::UnguessableToken::Create()); + DCHECK(input_info->shm_handle.OwnershipPassesToIPC()); input_info->offset = offset; - input_info->length = length; + input_buffer_info_[index] = std::move(input_info); } bool ChromeArcVideoDecodeAccelerator::VerifyDmabuf( @@ -241,6 +321,12 @@ const std::vector<::arc::VideoFramePlane>& planes) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (secure_mode_) { + DLOG(ERROR) << "not allowed in secure mode"; + arc_client_->OnError(INVALID_ARGUMENT); + return; + } + if (!vda_) { DLOG(ERROR) << "VDA not initialized"; return; @@ -260,9 +346,19 @@ return; } - OutputBufferInfo& info = buffers_pending_import_[index]; - info.handle = std::move(dmabuf_fd); - info.planes = planes; +#if defined(USE_OZONE) + auto output_info = std::make_unique<OutputBufferInfo>(); + output_info->gpu_memory_buffer_handle.type = gfx::NATIVE_PIXMAP; + output_info->gpu_memory_buffer_handle.native_pixmap_handle.fds.emplace_back( + base::FileDescriptor(dmabuf_fd.release(), true)); + for (const auto& plane : planes) { + output_info->gpu_memory_buffer_handle.native_pixmap_handle.planes + .emplace_back(plane.stride, plane.offset, 0, 0); + } + buffers_pending_import_[index] = std::move(output_info); +#else + arc_client_->OnError(PLATFORM_FAILURE); +#endif } void ChromeArcVideoDecodeAccelerator::UseBuffer( @@ -283,41 +379,44 @@ } switch (port) { case PORT_INPUT: { - InputBufferInfo* input_info = &input_buffer_info_[index]; + auto& input_info = input_buffer_info_[index]; + if (!input_info) { + DLOG(ERROR) << "Buffer not initialized"; + arc_client_->OnError(INVALID_ARGUMENT); + return; + } + int32_t bitstream_buffer_id = next_bitstream_buffer_id_; // Mask against 30 bits, to avoid (undefined) wraparound on signed // integer. next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; - int dup_fd = HANDLE_EINTR(dup(input_info->handle.get())); - if (dup_fd < 0) { - DLOG(ERROR) << "dup() failed."; + + auto duplicated_handle = input_info->shm_handle.Duplicate(); + if (!duplicated_handle.IsValid()) { arc_client_->OnError(PLATFORM_FAILURE); return; } + CreateInputRecord(bitstream_buffer_id, index, metadata.timestamp); - base::UnguessableToken guid = base::UnguessableToken::Create(); - vda_->Decode(media::BitstreamBuffer( - bitstream_buffer_id, - base::SharedMemoryHandle(base::FileDescriptor(dup_fd, true), 0u, - guid), - metadata.bytes_used, input_info->offset)); + vda_->Decode( + media::BitstreamBuffer(bitstream_buffer_id, duplicated_handle, + metadata.bytes_used, input_info->offset)); break; } case PORT_OUTPUT: { - // is_valid() is true for the first time the buffer is passed to the VDA. + auto& output_info = buffers_pending_import_[index]; + if (!output_info) { + DLOG(ERROR) << "Buffer not initialized"; + arc_client_->OnError(INVALID_ARGUMENT); + return; + } + // is_null() is false the first time the buffer is passed to the VDA. // In that case, VDA needs to import the buffer first. - OutputBufferInfo& info = buffers_pending_import_[index]; - if (info.handle.is_valid()) { - gfx::GpuMemoryBufferHandle handle; -#if defined(USE_OZONE) - handle.native_pixmap_handle.fds.emplace_back( - base::FileDescriptor(info.handle.release(), true)); - for (const auto& plane : info.planes) { - handle.native_pixmap_handle.planes.emplace_back(plane.stride, - plane.offset, 0, 0); - } -#endif - vda_->ImportBufferForPicture(index, handle); + if (!output_info->gpu_memory_buffer_handle.is_null()) { + vda_->ImportBufferForPicture(index, + output_info->gpu_memory_buffer_handle); + // VDA takes ownership, so just clear out, don't close the handle. + output_info->gpu_memory_buffer_handle = gfx::GpuMemoryBufferHandle(); } else { vda_->ReusePictureBuffer(index); }
diff --git a/chrome/gpu/chrome_arc_video_decode_accelerator.h b/chrome/gpu/chrome_arc_video_decode_accelerator.h index a520398..2da28c2 100644 --- a/chrome/gpu/chrome_arc_video_decode_accelerator.h +++ b/chrome/gpu/chrome_arc_video_decode_accelerator.h
@@ -19,6 +19,9 @@ namespace chromeos { namespace arc { +class ProtectedBufferManager; +class ProtectedBufferHandle; + // This class is executed in the GPU process. It takes decoding requests from // ARC via IPC channels and translates and sends those requests to an // implementation of media::VideoDecodeAccelerator. It also returns the decoded @@ -28,8 +31,9 @@ public media::VideoDecodeAccelerator::Client, public base::SupportsWeakPtr<ChromeArcVideoDecodeAccelerator> { public: - explicit ChromeArcVideoDecodeAccelerator( - const gpu::GpuPreferences& gpu_preferences); + ChromeArcVideoDecodeAccelerator( + const gpu::GpuPreferences& gpu_preferences, + ProtectedBufferManager* protected_buffer_manager); ~ChromeArcVideoDecodeAccelerator() override; // Implementation of the ArcVideoDecodeAccelerator interface. @@ -37,6 +41,10 @@ const Config& config, ArcVideoDecodeAccelerator::Client* client) override; void SetNumberOfOutputBuffers(size_t number) override; + bool AllocateProtectedBuffer(PortType port, + uint32_t index, + base::ScopedFD handle_fd, + size_t size) override; void BindSharedMemory(PortType port, uint32_t index, base::ScopedFD ashmem_fd, @@ -80,28 +88,34 @@ // The information about the shared memory used as an input buffer. struct InputBufferInfo { - // The file handle to access the buffer. It is owned by this class and - // should be closed after use. - base::ScopedFD handle; + // SharedMemoryHandle for this buffer to be passed to accelerator. + // In non-secure mode, received via BindSharedMemory from the client, + // in secure mode, a handle for the SharedMemory in protected_shmem. + base::SharedMemoryHandle shm_handle; - // The offset of the payload to the beginning of the shared memory. + // Used only in secure mode; handle to the protected buffer backing + // this input buffer. + std::unique_ptr<ProtectedBufferHandle> protected_buffer_handle; + + // Offset to the payload from the beginning of the shared memory buffer. off_t offset = 0; - // The size of the payload in bytes. - size_t length = 0; - InputBufferInfo(); - InputBufferInfo(InputBufferInfo&& other); ~InputBufferInfo(); }; - // The information about the dmabuf used as an output buffer. + // The information about the native pixmap used as an output buffer. struct OutputBufferInfo { - base::ScopedFD handle; - std::vector<::arc::VideoFramePlane> planes; + // GpuMemoryBufferHandle for this buffer to be passed to accelerator. + // In non-secure mode, received via BindDmabuf from the client, + // in secure mode, a handle to the NativePixmap in protected_pixmap. + gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle; + + // Used only in secure mode; handle to the protected buffer backing + // this output buffer. + std::unique_ptr<ProtectedBufferHandle> protected_buffer_handle; OutputBufferInfo(); - OutputBufferInfo(OutputBufferInfo&& other); ~OutputBufferInfo(); }; @@ -155,12 +169,12 @@ std::list<InputRecord> input_records_; // The details of the shared memory of each input buffers. - std::vector<InputBufferInfo> input_buffer_info_; + std::vector<std::unique_ptr<InputBufferInfo>> input_buffer_info_; // To keep those output buffers which have been bound by bindDmabuf() but // haven't been passed to VDA yet. Will call VDA::ImportBufferForPicture() // when those buffers are used for the first time. - std::vector<OutputBufferInfo> buffers_pending_import_; + std::vector<std::unique_ptr<OutputBufferInfo>> buffers_pending_import_; THREAD_CHECKER(thread_checker_); size_t output_buffer_size_; @@ -168,7 +182,10 @@ // The minimal number of requested output buffers. uint32_t requested_num_of_output_buffers_; + bool secure_mode_ = false; + gpu::GpuPreferences gpu_preferences_; + ProtectedBufferManager* protected_buffer_manager_; DISALLOW_COPY_AND_ASSIGN(ChromeArcVideoDecodeAccelerator); };
diff --git a/chrome/gpu/chrome_content_gpu_client.cc b/chrome/gpu/chrome_content_gpu_client.cc index bcd0060..ae7e058c 100644 --- a/chrome/gpu/chrome_content_gpu_client.cc +++ b/chrome/gpu/chrome_content_gpu_client.cc
@@ -22,8 +22,14 @@ #if defined(OS_CHROMEOS) #include "chrome/gpu/gpu_arc_video_decode_accelerator.h" #include "chrome/gpu/gpu_arc_video_encode_accelerator.h" +#include "chrome/gpu/protected_buffer_manager.h" +#include "chrome/gpu/protected_buffer_manager_proxy.h" #include "content/public/common/service_manager_connection.h" #include "services/service_manager/public/cpp/binder_registry.h" +#if defined(USE_OZONE) +#include "ui/ozone/public/ozone_platform.h" +#include "ui/ozone/public/surface_factory_ozone.h" +#endif #endif namespace { @@ -46,6 +52,10 @@ metrics::CallStackProfileParams::MAY_SHUFFLE))) { if (StackSamplingConfiguration::Get()->IsProfilerEnabledForCurrentProcess()) stack_sampling_profiler_.Start(); + +#if defined(OS_CHROMEOS) + protected_buffer_manager_.reset(new chromeos::arc::ProtectedBufferManager()); +#endif } ChromeContentGpuClient::~ChromeContentGpuClient() {} @@ -61,6 +71,10 @@ base::Bind(&ChromeContentGpuClient::CreateArcVideoEncodeAccelerator, base::Unretained(this)), base::ThreadTaskRunnerHandle::Get()); + registry->AddInterface( + base::Bind(&ChromeContentGpuClient::CreateProtectedBufferManager, + base::Unretained(this)), + base::ThreadTaskRunnerHandle::Get()); #endif } @@ -68,6 +82,13 @@ const gpu::GpuPreferences& gpu_preferences) { #if defined(OS_CHROMEOS) gpu_preferences_ = gpu_preferences; +#if defined(USE_OZONE) + ui::OzonePlatform::GetInstance() + ->GetSurfaceFactoryOzone() + ->SetGetProtectedNativePixmapDelegate(base::Bind( + &chromeos::arc::ProtectedBufferManager::GetProtectedNativePixmapFor, + base::Unretained(protected_buffer_manager_.get()))); +#endif #endif metrics::mojom::CallStackProfileCollectorPtr browser_interface; @@ -78,12 +99,11 @@ } #if defined(OS_CHROMEOS) - void ChromeContentGpuClient::CreateArcVideoDecodeAccelerator( ::arc::mojom::VideoDecodeAcceleratorRequest request) { mojo::MakeStrongBinding( base::MakeUnique<chromeos::arc::GpuArcVideoDecodeAccelerator>( - gpu_preferences_), + gpu_preferences_, protected_buffer_manager_.get()), std::move(request)); } @@ -94,4 +114,12 @@ gpu_preferences_), std::move(request)); } + +void ChromeContentGpuClient::CreateProtectedBufferManager( + ::arc::mojom::ProtectedBufferManagerRequest request) { + mojo::MakeStrongBinding( + base::MakeUnique<chromeos::arc::GpuArcProtectedBufferManagerProxy>( + protected_buffer_manager_.get()), + std::move(request)); +} #endif
diff --git a/chrome/gpu/chrome_content_gpu_client.h b/chrome/gpu/chrome_content_gpu_client.h index 78abc0e..bbc731f 100644 --- a/chrome/gpu/chrome_content_gpu_client.h +++ b/chrome/gpu/chrome_content_gpu_client.h
@@ -12,10 +12,16 @@ #include "content/public/gpu/content_gpu_client.h" #if defined(OS_CHROMEOS) +#include "components/arc/common/protected_buffer_manager.mojom.h" #include "components/arc/common/video_decode_accelerator.mojom.h" #include "components/arc/common/video_encode_accelerator.mojom.h" #include "gpu/command_buffer/service/gpu_preferences.h" +namespace chromeos { +namespace arc { +class ProtectedBufferManager; +} // namespace arc +} // namespace chromeos #endif class ChromeContentGpuClient : public content::ContentGpuClient { @@ -35,6 +41,9 @@ void CreateArcVideoEncodeAccelerator( ::arc::mojom::VideoEncodeAcceleratorRequest request); + + void CreateProtectedBufferManager( + ::arc::mojom::ProtectedBufferManagerRequest request); #endif // Used to profile process startup. @@ -42,6 +51,8 @@ #if defined(OS_CHROMEOS) gpu::GpuPreferences gpu_preferences_; + std::unique_ptr<chromeos::arc::ProtectedBufferManager> + protected_buffer_manager_; #endif DISALLOW_COPY_AND_ASSIGN(ChromeContentGpuClient);
diff --git a/chrome/gpu/gpu_arc_video_decode_accelerator.cc b/chrome/gpu/gpu_arc_video_decode_accelerator.cc index d53c3c0..b94aa8f 100644 --- a/chrome/gpu/gpu_arc_video_decode_accelerator.cc +++ b/chrome/gpu/gpu_arc_video_decode_accelerator.cc
@@ -98,6 +98,7 @@ chromeos::arc::ArcVideoDecodeAccelerator::Config result; result.num_input_buffers = input->num_input_buffers; result.input_pixel_format = input->input_pixel_format; + result.secure_mode = input->secure_mode; return result; } }; @@ -108,9 +109,12 @@ namespace arc { GpuArcVideoDecodeAccelerator::GpuArcVideoDecodeAccelerator( - const gpu::GpuPreferences& gpu_preferences) + const gpu::GpuPreferences& gpu_preferences, + ProtectedBufferManager* protected_buffer_manager) : gpu_preferences_(gpu_preferences), - accelerator_(new ChromeArcVideoDecodeAccelerator(gpu_preferences_)) {} + accelerator_(std::make_unique<ChromeArcVideoDecodeAccelerator>( + gpu_preferences_, + protected_buffer_manager)) {} GpuArcVideoDecodeAccelerator::~GpuArcVideoDecodeAccelerator() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -166,7 +170,9 @@ LOG(ERROR) << "only decoder is supported"; std::move(callback).Run( ::arc::mojom::VideoDecodeAccelerator::Result::INVALID_ARGUMENT); + return; } + client_ = std::move(client); ArcVideoDecodeAccelerator::Result result = accelerator_->Initialize( config.To<ArcVideoDecodeAccelerator::Config>(), this); @@ -197,6 +203,26 @@ return base::ScopedFD(platform_file); } +void GpuArcVideoDecodeAccelerator::AllocateProtectedBuffer( + ::arc::mojom::PortType port, + uint32_t index, + mojo::ScopedHandle handle, + uint64_t size, + AllocateProtectedBufferCallback callback) { + DVLOG(2) << "port=" << port << ", index=" << index << ", size=" << size; + + base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(handle)); + if (!fd.is_valid()) { + std::move(callback).Run(false); + return; + } + + bool result = accelerator_->AllocateProtectedBuffer( + static_cast<PortType>(port), index, std::move(fd), size); + + std::move(callback).Run(result); +} + void GpuArcVideoDecodeAccelerator::BindSharedMemory( ::arc::mojom::PortType port, uint32_t index,
diff --git a/chrome/gpu/gpu_arc_video_decode_accelerator.h b/chrome/gpu/gpu_arc_video_decode_accelerator.h index 078c17d1..daf6088 100644 --- a/chrome/gpu/gpu_arc_video_decode_accelerator.h +++ b/chrome/gpu/gpu_arc_video_decode_accelerator.h
@@ -19,6 +19,8 @@ namespace chromeos { namespace arc { +class ProtectedBufferManager; + // GpuArcVideoDecodeAccelerator manages life-cycle and IPC message translation // for ArcVideoDecodeAccelerator. // @@ -28,8 +30,9 @@ : public ::arc::mojom::VideoDecodeAccelerator, public ArcVideoDecodeAccelerator::Client { public: - explicit GpuArcVideoDecodeAccelerator( - const gpu::GpuPreferences& gpu_preferences); + GpuArcVideoDecodeAccelerator( + const gpu::GpuPreferences& gpu_preferences, + ProtectedBufferManager* protected_buffer_manager); ~GpuArcVideoDecodeAccelerator() override; private: @@ -46,6 +49,14 @@ void Initialize(::arc::mojom::VideoDecodeAcceleratorConfigPtr config, ::arc::mojom::VideoDecodeClientPtr client, InitializeCallback callback) override; + + void AllocateProtectedBuffer( + ::arc::mojom::PortType port, + uint32_t index, + mojo::ScopedHandle handle, + uint64_t size, + AllocateProtectedBufferCallback callback) override; + void BindSharedMemory(::arc::mojom::PortType port, uint32_t index, mojo::ScopedHandle ashmem_handle,
diff --git a/chrome/gpu/protected_buffer_manager.cc b/chrome/gpu/protected_buffer_manager.cc new file mode 100644 index 0000000..47bcdaf --- /dev/null +++ b/chrome/gpu/protected_buffer_manager.cc
@@ -0,0 +1,411 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/gpu/protected_buffer_manager.h" + +#include "base/bits.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/memory/shared_memory.h" +#include "base/sys_info.h" +#include "mojo/public/cpp/system/buffer.h" +#include "mojo/public/cpp/system/platform_handle.h" +#include "ui/gfx/geometry/size.h" +#include "ui/ozone/public/ozone_platform.h" +#include "ui/ozone/public/surface_factory_ozone.h" + +#define VLOGF(level) VLOG(level) << __func__ << "(): " + +namespace chromeos { +namespace arc { + +namespace { +// Size of the pixmap to be used as the dummy handle for protected buffers. +constexpr gfx::Size kDummyBufferSize(32, 32); +} // namespace + +ProtectedBufferHandle::ProtectedBufferHandle( + base::OnceClosure destruction_cb, + const base::SharedMemoryHandle& shm_handle) + : shm_handle_(shm_handle), destruction_cb_(std::move(destruction_cb)) { + DCHECK(shm_handle_.IsValid()); + DCHECK(shm_handle.OwnershipPassesToIPC()); +} + +ProtectedBufferHandle::ProtectedBufferHandle( + base::OnceClosure destruction_cb, + const gfx::NativePixmapHandle& native_pixmap_handle) + : native_pixmap_handle_(native_pixmap_handle), + destruction_cb_(std::move(destruction_cb)) { + DCHECK(!native_pixmap_handle_.fds.empty()); + for (const auto& fd : native_pixmap_handle_.fds) + DCHECK(fd.auto_close); +} + +ProtectedBufferHandle::~ProtectedBufferHandle() { + if (shm_handle_.OwnershipPassesToIPC()) + shm_handle_.Close(); + + for (const auto& fd : native_pixmap_handle_.fds) { + // Close the fd by wrapping it in a ScopedFD and letting + // it fall out of scope. + base::ScopedFD scoped_fd(fd.fd); + } + + std::move(destruction_cb_).Run(); +} + +base::SharedMemoryHandle ProtectedBufferHandle::shm_handle() const { + base::SharedMemoryHandle handle = shm_handle_; + handle.SetOwnershipPassesToIPC(false); + return handle; +} + +gfx::NativePixmapHandle ProtectedBufferHandle::native_pixmap_handle() const { + return native_pixmap_handle_; +} + +class ProtectedBufferManager::ProtectedBuffer { + public: + virtual ~ProtectedBuffer() {} + + // Downcasting methods to return duplicated handles to the underlying + // protected buffers for each buffer type, or empty/null handles if not + // applicable. + virtual base::SharedMemoryHandle DuplicateSharedMemoryHandle() const { + return base::SharedMemoryHandle(); + } + virtual gfx::NativePixmapHandle DuplicateNativePixmapHandle() const { + return gfx::NativePixmapHandle(); + } + + // Downcasting method to return a scoped_refptr to the underlying + // NativePixmap, or null if not applicable. + virtual scoped_refptr<gfx::NativePixmap> GetNativePixmap() const { + return nullptr; + } + + protected: + explicit ProtectedBuffer(scoped_refptr<gfx::NativePixmap> dummy_handle) + : dummy_handle_(std::move(dummy_handle)) {} + + private: + scoped_refptr<gfx::NativePixmap> dummy_handle_; + + DISALLOW_COPY_AND_ASSIGN(ProtectedBuffer); +}; + +class ProtectedBufferManager::ProtectedSharedMemory + : public ProtectedBufferManager::ProtectedBuffer { + public: + ~ProtectedSharedMemory() override; + + // Allocate a ProtectedSharedMemory buffer of |size| bytes. + static std::unique_ptr<ProtectedSharedMemory> Create( + scoped_refptr<gfx::NativePixmap> dummy_handle, + size_t size); + + base::SharedMemoryHandle DuplicateSharedMemoryHandle() const override { + return base::SharedMemory::DuplicateHandle(shmem_->handle()); + } + + private: + explicit ProtectedSharedMemory(scoped_refptr<gfx::NativePixmap> dummy_handle); + + std::unique_ptr<base::SharedMemory> shmem_; +}; + +ProtectedBufferManager::ProtectedSharedMemory::ProtectedSharedMemory( + scoped_refptr<gfx::NativePixmap> dummy_handle) + : ProtectedBuffer(std::move(dummy_handle)) {} + +ProtectedBufferManager::ProtectedSharedMemory::~ProtectedSharedMemory() {} + +// static +std::unique_ptr<ProtectedBufferManager::ProtectedSharedMemory> +ProtectedBufferManager::ProtectedSharedMemory::Create( + scoped_refptr<gfx::NativePixmap> dummy_handle, + size_t size) { + std::unique_ptr<ProtectedSharedMemory> protected_shmem( + new ProtectedSharedMemory(std::move(dummy_handle))); + + size_t aligned_size = + base::bits::Align(size, base::SysInfo::VMAllocationGranularity()); + + mojo::ScopedSharedBufferHandle mojo_shared_buffer = + mojo::SharedBufferHandle::Create(aligned_size); + if (!mojo_shared_buffer->is_valid()) { + VLOGF(1) << "Failed to allocate shared memory"; + return nullptr; + } + + base::SharedMemoryHandle shm_handle; + MojoResult mojo_result = mojo::UnwrapSharedMemoryHandle( + std::move(mojo_shared_buffer), &shm_handle, nullptr, nullptr); + if (mojo_result != MOJO_RESULT_OK) { + VLOGF(1) << "Failed to unwrap a mojo shared memory handle"; + return nullptr; + } + + protected_shmem->shmem_ = + std::make_unique<base::SharedMemory>(shm_handle, false); + return protected_shmem; +} + +class ProtectedBufferManager::ProtectedNativePixmap + : public ProtectedBufferManager::ProtectedBuffer { + public: + ~ProtectedNativePixmap() override; + + // Allocate a ProtectedNativePixmap of |format| and |size|. + static std::unique_ptr<ProtectedNativePixmap> Create( + scoped_refptr<gfx::NativePixmap> dummy_handle, + gfx::BufferFormat format, + const gfx::Size& size); + + gfx::NativePixmapHandle DuplicateNativePixmapHandle() const override { + return native_pixmap_->ExportHandle(); + } + + scoped_refptr<gfx::NativePixmap> GetNativePixmap() const override { + return native_pixmap_; + } + + private: + explicit ProtectedNativePixmap(scoped_refptr<gfx::NativePixmap> dummy_handle); + + scoped_refptr<gfx::NativePixmap> native_pixmap_; +}; + +ProtectedBufferManager::ProtectedNativePixmap::ProtectedNativePixmap( + scoped_refptr<gfx::NativePixmap> dummy_handle) + : ProtectedBuffer(std::move(dummy_handle)) {} + +ProtectedBufferManager::ProtectedNativePixmap::~ProtectedNativePixmap() {} + +// static +std::unique_ptr<ProtectedBufferManager::ProtectedNativePixmap> +ProtectedBufferManager::ProtectedNativePixmap::Create( + scoped_refptr<gfx::NativePixmap> dummy_handle, + gfx::BufferFormat format, + const gfx::Size& size) { + std::unique_ptr<ProtectedNativePixmap> protected_pixmap( + new ProtectedNativePixmap(std::move(dummy_handle))); + + ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); + ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); + protected_pixmap->native_pixmap_ = + factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, format, + gfx::BufferUsage::SCANOUT_VDA_WRITE); + + if (!protected_pixmap->native_pixmap_) { + VLOGF(1) << "Failed allocating a native pixmap"; + return nullptr; + } + + return protected_pixmap; +} + +ProtectedBufferManager::ProtectedBufferManager() : weak_factory_(this) { + VLOGF(2); + weak_this_ = weak_factory_.GetWeakPtr(); +} + +ProtectedBufferManager::~ProtectedBufferManager() { + VLOGF(2); +} + +std::unique_ptr<ProtectedBufferHandle> +ProtectedBufferManager::AllocateProtectedSharedMemory(base::ScopedFD dummy_fd, + size_t size) { + VLOGF(2) << "dummy_fd: " << dummy_fd.get() << ", size: " << size; + + // Import the |dummy_fd| to produce a unique id for it. + uint32_t id; + auto pixmap = ImportDummyFd(std::move(dummy_fd), &id); + if (!pixmap) + return nullptr; + + base::AutoLock lock(buffer_map_lock_); + + if (buffer_map_.find(id) != buffer_map_.end()) { + VLOGF(1) << "A protected buffer for this handle already exists"; + return nullptr; + } + + // Allocate a protected buffer and associate it with the dummy pixmap. + // The pixmap needs to be stored to ensure the id remains the same for + // the entire lifetime of the dummy pixmap. + auto protected_shmem = ProtectedSharedMemory::Create(pixmap, size); + if (!protected_shmem) { + VLOGF(1) << "Failed allocating a protected shared memory buffer"; + return nullptr; + } + + auto shm_handle = protected_shmem->DuplicateSharedMemoryHandle(); + if (!shm_handle.IsValid()) { + VLOGF(1) << "Failed duplicating SharedMemoryHandle"; + return nullptr; + } + + // Store the buffer in the buffer_map_, and return a handle to it to the + // client. The buffer will be permanently removed from the map when the + // handle is destroyed. + VLOGF(2) << "New protected shared memory buffer, handle id: " << id; + auto protected_buffer_handle = base::MakeUnique<ProtectedBufferHandle>( + base::BindOnce(&ProtectedBufferManager::RemoveEntry, weak_this_, id), + shm_handle); + + // This will always succeed as we find() first above. + buffer_map_.emplace(id, std::move(protected_shmem)); + + return protected_buffer_handle; +} + +std::unique_ptr<ProtectedBufferHandle> +ProtectedBufferManager::AllocateProtectedNativePixmap(base::ScopedFD dummy_fd, + gfx::BufferFormat format, + const gfx::Size& size) { + VLOGF(2) << "dummy_fd: " << dummy_fd.get() << ", format: " << (int)format + << ", size: " << size.ToString(); + + // Import the |dummy_fd| to produce a unique id for it. + uint32_t id = 0; + auto pixmap = ImportDummyFd(std::move(dummy_fd), &id); + if (!pixmap) + return nullptr; + + base::AutoLock lock(buffer_map_lock_); + + if (buffer_map_.find(id) != buffer_map_.end()) { + VLOGF(1) << "A protected buffer for this handle already exists"; + return nullptr; + } + + // Allocate a protected buffer and associate it with the dummy pixmap. + // The pixmap needs to be stored to ensure the id remains the same for + // the entire lifetime of the dummy pixmap. + auto protected_pixmap = ProtectedNativePixmap::Create(pixmap, format, size); + if (!protected_pixmap) { + VLOGF(1) << "Failed allocating a protected native pixmap"; + return nullptr; + } + + auto native_pixmap_handle = protected_pixmap->DuplicateNativePixmapHandle(); + if (native_pixmap_handle.planes.empty()) { + VLOGF(1) << "Failed duplicating NativePixmapHandle"; + return nullptr; + } + + // Store the buffer in the buffer_map_, and return a handle to it to the + // client. The buffer will be permanently removed from the map when the + // handle is destroyed. + VLOGF(2) << "New protected native pixmap, handle id: " << id; + auto protected_buffer_handle = base::MakeUnique<ProtectedBufferHandle>( + base::BindOnce(&ProtectedBufferManager::RemoveEntry, weak_this_, id), + native_pixmap_handle); + + // This will always succeed as we find() first above. + buffer_map_.emplace(id, std::move(protected_pixmap)); + + return protected_buffer_handle; +} + +base::SharedMemoryHandle +ProtectedBufferManager::GetProtectedSharedMemoryHandleFor( + base::ScopedFD dummy_fd) { + uint32_t id = 0; + auto pixmap = ImportDummyFd(std::move(dummy_fd), &id); + + base::AutoLock lock(buffer_map_lock_); + const auto& iter = buffer_map_.find(id); + if (iter == buffer_map_.end()) + return base::SharedMemoryHandle(); + + return iter->second->DuplicateSharedMemoryHandle(); +} + +gfx::NativePixmapHandle +ProtectedBufferManager::GetProtectedNativePixmapHandleFor( + base::ScopedFD dummy_fd) { + uint32_t id = 0; + auto pixmap = ImportDummyFd(std::move(dummy_fd), &id); + + base::AutoLock lock(buffer_map_lock_); + const auto& iter = buffer_map_.find(id); + if (iter == buffer_map_.end()) + return gfx::NativePixmapHandle(); + + return iter->second->DuplicateNativePixmapHandle(); +} + +scoped_refptr<gfx::NativePixmap> +ProtectedBufferManager::GetProtectedNativePixmapFor( + const gfx::NativePixmapHandle& handle) { + // Only the first fd is used for lookup. + if (handle.fds.empty()) + return nullptr; + + base::ScopedFD dummy_fd(HANDLE_EINTR(dup(handle.fds[0].fd))); + uint32_t id = 0; + auto pixmap = ImportDummyFd(std::move(dummy_fd), &id); + + base::AutoLock lock(buffer_map_lock_); + const auto& iter = buffer_map_.find(id); + if (iter == buffer_map_.end()) + return nullptr; + + auto native_pixmap = iter->second->GetNativePixmap(); + if (native_pixmap) { + for (const auto& fd : handle.fds) + base::ScopedFD scoped_fd(fd.fd); + } + + return native_pixmap; +} + +scoped_refptr<gfx::NativePixmap> ProtectedBufferManager::ImportDummyFd( + base::ScopedFD dummy_fd, + uint32_t* id) const { + // 0 is an invalid handle id. + *id = 0; + + // Import dummy_fd to acquire its unique id. + // CreateNativePixmapFromHandle() takes ownership and will close the handle + // also on failure. + gfx::NativePixmapHandle pixmap_handle; + pixmap_handle.fds.emplace_back( + base::FileDescriptor(dummy_fd.release(), true)); + pixmap_handle.planes.emplace_back(gfx::NativePixmapPlane()); + ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); + ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); + scoped_refptr<gfx::NativePixmap> pixmap = + factory->CreateNativePixmapForProtectedBufferHandle( + gfx::kNullAcceleratedWidget, kDummyBufferSize, gfx::BufferFormat::R_8, + pixmap_handle); + if (!pixmap) { + VLOGF(1) << "Failed importing dummy handle"; + return nullptr; + } + + *id = pixmap->GetUniqueId(); + if (*id == 0) { + VLOGF(1) << "Failed acquiring unique id for handle"; + return nullptr; + } + + return pixmap; +} + +void ProtectedBufferManager::RemoveEntry(uint32_t id) { + VLOGF(2) << "id: " << id; + + base::AutoLock lock(buffer_map_lock_); + auto num_erased = buffer_map_.erase(id); + if (num_erased != 1) + VLOGF(1) << "No buffer id " << id << " to destroy"; +} + +} // namespace arc +} // namespace chromeos
diff --git a/chrome/gpu/protected_buffer_manager.h b/chrome/gpu/protected_buffer_manager.h new file mode 100644 index 0000000..40a5e01 --- /dev/null +++ b/chrome/gpu/protected_buffer_manager.h
@@ -0,0 +1,145 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_GPU_PROTECTED_BUFFER_MANAGER_H_ +#define CHROME_GPU_PROTECTED_BUFFER_MANAGER_H_ + +#include <map> + +#include "base/memory/ref_counted.h" +#include "base/memory/shared_memory.h" +#include "base/memory/weak_ptr.h" +#include "base/synchronization/lock.h" +#include "ui/gfx/gpu_memory_buffer.h" +#include "ui/gfx/native_pixmap.h" + +namespace chromeos { +namespace arc { + +// A ProtectedBufferHandle is returned to the owning client that requested +// the underlying ProtectedBuffer to be allocated. +// +// A ProtectedBuffer is a buffer that can be referred to via a handle (a dummy +// handle), which does not provide access to the actual contents of the buffer. +// +// The client should release this handle once the buffer is no longer needed. +// Releasing triggers destruction of the ProtectedBuffer instance stored in +// the ProtectedBufferManager, via the destruction callback passed to the +// ProtectedBufferHandle's constructor. +class ProtectedBufferHandle { + public: + // ProtectedBufferHandle takes ownership of the passed |shm_handle|. + ProtectedBufferHandle(base::OnceClosure destruction_cb, + const base::SharedMemoryHandle& shm_handle); + + // ProtectedBufferHandle takes ownership of the passed |native_pixmap_handle|. + ProtectedBufferHandle(base::OnceClosure destruction_cb, + const gfx::NativePixmapHandle& native_pixmap_handle); + + // Closes the underlying handle. + ~ProtectedBufferHandle(); + + // Return a non-owned SharedMemoryHandle or NativePixmapHandle for this + // ProtectedBufferHandle, or an invalid/null handle if not applicable for the + // underlying type. + base::SharedMemoryHandle shm_handle() const; + gfx::NativePixmapHandle native_pixmap_handle() const; + + private: + // The underlying, owning handles to the protected buffer. + // Only one of the handles is valid for each instance of this class. + // Closed on destruction of this ProtectedBufferHandle. + base::SharedMemoryHandle shm_handle_; + gfx::NativePixmapHandle native_pixmap_handle_; + + base::OnceClosure destruction_cb_; +}; + +class ProtectedBufferManager { + public: + ProtectedBufferManager(); + ~ProtectedBufferManager(); + + // Allocate a ProtectedSharedMemory buffer of |size| bytes, to be referred to + // via |dummy_fd| as the dummy handle, returning a ProtectedBufferHandle to + // it. + // Destroying the ProtectedBufferHandle will result in permanently + // disassociating the |dummy_fd| with the underlying ProtectedBuffer, but may + // not free the underlying protected memory, which will remain valid as long + // as any SharedMemoryHandles to it are still in use. + // Return nullptr on failure. + std::unique_ptr<ProtectedBufferHandle> AllocateProtectedSharedMemory( + base::ScopedFD dummy_fd, + size_t size); + + // Allocate a ProtectedNativePixmap of |format| and |size|, to be referred to + // via |dummy_fd| as the dummy handle, returning a ProtectedBufferHandle to + // it. + // Destroying the ProtectedBufferHandle will result in permanently + // disassociating the |dummy_fd| with the underlying ProtectedBuffer, but may + // not free the underlying protected memory, which will remain valid as long + // as any NativePixmapHandles to it are still in use. + // Return nullptr on failure. + std::unique_ptr<ProtectedBufferHandle> AllocateProtectedNativePixmap( + base::ScopedFD dummy_fd, + gfx::BufferFormat format, + const gfx::Size& size); + + // Return a duplicated SharedMemoryHandle associated with the |dummy_fd|, + // if one exists, or an invalid handle otherwise. + // The client is responsible for closing the handle after use. + base::SharedMemoryHandle GetProtectedSharedMemoryHandleFor( + base::ScopedFD dummy_fd); + + // Return a duplicated NativePixmapHandle associated with the |dummy_fd|, + // if one exists, or an empty handle otherwise. + // The client is responsible for closing the handle after use. + gfx::NativePixmapHandle GetProtectedNativePixmapHandleFor( + base::ScopedFD dummy_fd); + + // Return a protected NativePixmap for a dummy |handle|, if one exists, or + // nullptr otherwise. On success, the |handle| is closed. + scoped_refptr<gfx::NativePixmap> GetProtectedNativePixmapFor( + const gfx::NativePixmapHandle& handle); + + private: + // Used internally to maintain the association between the dummy handle and + // the underlying buffer. + class ProtectedBuffer; + class ProtectedSharedMemory; + class ProtectedNativePixmap; + + // Imports the |dummy_fd| as a NativePixmap. This returns a unique |id|, + // which is guaranteed to be the same for all future imports of any fd + // referring to the buffer to which |dummy_fd| refers to, regardless of + // whether it is the same fd as the original one, or not, for the lifetime + // of the buffer. + // + // This allows us to have an unambiguous mapping from any fd referring to + // the same memory buffer to the same unique id. + // + // Returns nullptr on failure, in which case the returned id is not valid. + scoped_refptr<gfx::NativePixmap> ImportDummyFd(base::ScopedFD dummy_fd, + uint32_t* id) const; + + // Removes an entry for given |id| from buffer_map_, to be called when the + // last reference to the buffer is dropped. + void RemoveEntry(uint32_t id); + + // A map of unique ids to the ProtectedBuffers associated with them. + using ProtectedBufferMap = + std::map<uint32_t, std::unique_ptr<ProtectedBuffer>>; + ProtectedBufferMap buffer_map_; + base::Lock buffer_map_lock_; + + base::WeakPtr<ProtectedBufferManager> weak_this_; + base::WeakPtrFactory<ProtectedBufferManager> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(ProtectedBufferManager); +}; + +} // namespace arc +} // namespace chromeos + +#endif // CHROME_GPU_PROTECTED_BUFFER_MANAGER_H_
diff --git a/chrome/gpu/protected_buffer_manager_proxy.cc b/chrome/gpu/protected_buffer_manager_proxy.cc new file mode 100644 index 0000000..8080ed1 --- /dev/null +++ b/chrome/gpu/protected_buffer_manager_proxy.cc
@@ -0,0 +1,53 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/gpu/protected_buffer_manager_proxy.h" + +#include "chrome/gpu/protected_buffer_manager.h" +#include "mojo/public/cpp/system/platform_handle.h" + +#define VLOGF(level) VLOG(level) << __func__ << "(): " + +namespace chromeos { +namespace arc { + +GpuArcProtectedBufferManagerProxy::GpuArcProtectedBufferManagerProxy( + chromeos::arc::ProtectedBufferManager* protected_buffer_manager) + : protected_buffer_manager_(protected_buffer_manager) { + DCHECK(protected_buffer_manager_); +} + +base::ScopedFD GpuArcProtectedBufferManagerProxy::UnwrapFdFromMojoHandle( + mojo::ScopedHandle handle) { + base::PlatformFile platform_file; + MojoResult mojo_result = + mojo::UnwrapPlatformFile(std::move(handle), &platform_file); + if (mojo_result != MOJO_RESULT_OK) { + VLOGF(1) << "UnwrapPlatformFile failed: " << mojo_result; + return base::ScopedFD(); + } + + return base::ScopedFD(platform_file); +} + +mojo::ScopedHandle GpuArcProtectedBufferManagerProxy::WrapFdInMojoHandle( + base::ScopedFD fd) { + return mojo::WrapPlatformFile(fd.release()); +} + +void GpuArcProtectedBufferManagerProxy::GetProtectedSharedMemoryFromHandle( + mojo::ScopedHandle dummy_handle, + GetProtectedSharedMemoryFromHandleCallback callback) { + base::ScopedFD unwrapped_fd = UnwrapFdFromMojoHandle(std::move(dummy_handle)); + + base::ScopedFD shmem_fd( + protected_buffer_manager_ + ->GetProtectedSharedMemoryHandleFor(std::move(unwrapped_fd)) + .Release()); + + std::move(callback).Run(WrapFdInMojoHandle(std::move(shmem_fd))); +} + +} // namespace arc +} // namespace chromeos
diff --git a/chrome/gpu/protected_buffer_manager_proxy.h b/chrome/gpu/protected_buffer_manager_proxy.h new file mode 100644 index 0000000..324065c --- /dev/null +++ b/chrome/gpu/protected_buffer_manager_proxy.h
@@ -0,0 +1,39 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_GPU_PROTECTED_BUFFER_MANAGER_PROXY_H_ +#define CHROME_GPU_PROTECTED_BUFFER_MANAGER_PROXY_H_ + +#include "components/arc/common/protected_buffer_manager.mojom.h" + +namespace chromeos { +namespace arc { + +class ProtectedBufferManager; + +// Manages mojo IPC translation for chromeos::arc::ProtectedBufferManager. +class GpuArcProtectedBufferManagerProxy + : public ::arc::mojom::ProtectedBufferManager { + public: + explicit GpuArcProtectedBufferManagerProxy( + chromeos::arc::ProtectedBufferManager* protected_buffer_manager); + + // arc::mojom::ProtectedBufferManager implementation. + void GetProtectedSharedMemoryFromHandle( + mojo::ScopedHandle dummy_handle, + GetProtectedSharedMemoryFromHandleCallback callback) override; + + private: + base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle); + mojo::ScopedHandle WrapFdInMojoHandle(base::ScopedFD fd); + + chromeos::arc::ProtectedBufferManager* protected_buffer_manager_; + + DISALLOW_COPY_AND_ASSIGN(GpuArcProtectedBufferManagerProxy); +}; + +} // namespace arc +} // namespace chromeos + +#endif // CHROME_GPU_PROTECTED_BUFFER_MANAGER_PROXY_H_
diff --git a/components/arc/common/oemcrypto_daemon.mojom b/components/arc/common/oemcrypto_daemon.mojom index 5b2b782..b75db2d 100644 --- a/components/arc/common/oemcrypto_daemon.mojom +++ b/components/arc/common/oemcrypto_daemon.mojom
@@ -21,5 +21,5 @@ // Next Method ID: 1 interface OemCryptoHostDaemon { Connect@0(arc.mojom.OemCryptoService& oemcryptor, - media.mojom.ProtectedBufferManager protected_buffer_manager); + arc.mojom.ProtectedBufferManager protected_buffer_manager); };
diff --git a/components/arc/common/protected_buffer_manager.mojom b/components/arc/common/protected_buffer_manager.mojom index b226ea3d..298f6d3 100644 --- a/components/arc/common/protected_buffer_manager.mojom +++ b/components/arc/common/protected_buffer_manager.mojom
@@ -5,7 +5,7 @@ // The original version of this file lives in the Chromium repository at: // src/components/arc/common/protected_buffer_manager.mojom -module media.mojom; +module arc.mojom; // This interface is exposed by the GPU process for translating dummy handles // for secure buffers into a usable shared memory handle. The output of a
diff --git a/components/arc/common/video_decode_accelerator.mojom b/components/arc/common/video_decode_accelerator.mojom index bb732f9..5307594 100644 --- a/components/arc/common/video_decode_accelerator.mojom +++ b/components/arc/common/video_decode_accelerator.mojom
@@ -40,6 +40,7 @@ uint32 crop_height; }; +// Next MinVersion: 2 struct VideoDecodeAcceleratorConfig { // Deprecated. This config struct is used for decoder only. enum DeviceTypeDeprecated { @@ -51,11 +52,12 @@ DeviceTypeDeprecated device_type_deprecated; uint32 num_input_buffers; uint32 input_pixel_format; + [MinVersion=1] bool secure_mode; }; -// Next MinVersion: 4 +// Next MinVersion: 5 // Deprecated method IDs: 2, 7 -// Next method ID: 10 +// Next method ID: 11 interface VideoDecodeAccelerator { enum Result { SUCCESS = 0, @@ -70,6 +72,10 @@ Initialize@8(VideoDecodeAcceleratorConfig config, VideoDecodeClient client) => (Result result); + [MinVersion=4] + AllocateProtectedBuffer@10(PortType port, uint32 index, handle handle_fd, + uint64 size) => (bool result); + BindSharedMemory@1(PortType port, uint32 index, handle ashmem_fd, uint32 offset, uint32 length);
diff --git a/components/viz/host/server_gpu_memory_buffer_manager.cc b/components/viz/host/server_gpu_memory_buffer_manager.cc index dc4a48fc..3a045ac 100644 --- a/components/viz/host/server_gpu_memory_buffer_manager.cc +++ b/components/viz/host/server_gpu_memory_buffer_manager.cc
@@ -75,7 +75,7 @@ gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format)) { buffer_handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( - id, size, format); + id, size, format, usage); BufferInfo buffer_info; DCHECK_EQ(gfx::SHARED_MEMORY_BUFFER, buffer_handle.type); buffer_info.type = gfx::SHARED_MEMORY_BUFFER;
diff --git a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc index ba34e09..bab50551 100644 --- a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc +++ b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -136,7 +136,7 @@ } auto handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( - id, size, format); + id, size, format, usage); buffers.find(id)->second.shared_memory_guid = handle.handle.GetGUID(); callback.Run(handle); } @@ -292,7 +292,7 @@ // Note: Unretained is safe as IO thread is stopped before manager is // destroyed. request->result = gpu::GpuMemoryBufferImplSharedMemory::Create( - new_id, request->size, request->format, + new_id, request->size, request->format, request->usage, base::Bind( &GpuMemoryBufferDeleted, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 6978fc34..0c7e2e9 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1792,17 +1792,6 @@ AddUIThreadInterface( registry.get(), - base::Bind(&PermissionServiceContext::CreateService, - base::Unretained(permission_service_context_.get()))); - - AddUIThreadInterface( - registry.get(), - base::Bind( - &PaymentAppContextImpl::CreatePaymentManager, - base::Unretained(storage_partition_impl_->GetPaymentAppContext()))); - - AddUIThreadInterface( - registry.get(), base::Bind(&RenderProcessHostImpl::CreateOffscreenCanvasProvider, base::Unretained(this))); @@ -1912,12 +1901,6 @@ registry->AddInterface( base::Bind(&CreateReportingServiceProxy, storage_partition_impl_)); - // This is to support usage of WebSockets in cases in which there is no - // associated RenderFrame (e.g., Shared Workers). - AddUIThreadInterface(registry.get(), - base::Bind(&WebSocketManager::CreateWebSocket, GetID(), - MSG_ROUTING_NONE)); - AddUIThreadInterface(registry.get(), base::Bind(&FieldTrialRecorder::Create)); associated_interfaces_.reset(new AssociatedInterfaceRegistryImpl());
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 005ca0d..d13ab263 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -388,6 +388,10 @@ // globally-used spare RenderProcessHost at any time. static RenderProcessHost* GetSpareRenderProcessHostForTesting(); + PermissionServiceContext& permission_service_context() { + return *permission_service_context_; + }; + protected: // A proxy for our IPC::Channel that lives on the IO thread. std::unique_ptr<IPC::ChannelProxy> channel_;
diff --git a/content/browser/worker_interface_binders.cc b/content/browser/worker_interface_binders.cc index f6338ae..5485a55 100644 --- a/content/browser/worker_interface_binders.cc +++ b/content/browser/worker_interface_binders.cc
@@ -6,6 +6,12 @@ #include <utility> +#include "base/bind.h" +#include "content/browser/payments/payment_manager.h" +#include "content/browser/permissions/permission_service_context.h" +#include "content/browser/renderer_host/render_process_host_impl.h" +#include "content/browser/storage_partition_impl.h" +#include "content/browser/websockets/websocket_manager.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" @@ -71,6 +77,26 @@ parameterized_binder_registry_.AddInterface( base::Bind(&ForwardRequest<shape_detection::mojom::TextDetection>, shape_detection::mojom::kServiceName)); + parameterized_binder_registry_.AddInterface( + base::Bind([](blink::mojom::WebSocketRequest request, + RenderProcessHost* host, const url::Origin& origin) { + WebSocketManager::CreateWebSocket(host->GetID(), MSG_ROUTING_NONE, + std::move(request)); + })); + parameterized_binder_registry_.AddInterface( + base::Bind([](payments::mojom::PaymentManagerRequest request, + RenderProcessHost* host, const url::Origin& origin) { + static_cast<StoragePartitionImpl*>(host->GetStoragePartition()) + ->GetPaymentAppContext() + ->CreatePaymentManager(std::move(request)); + })); + parameterized_binder_registry_.AddInterface( + base::Bind([](blink::mojom::PermissionServiceRequest request, + RenderProcessHost* host, const url::Origin& origin) { + static_cast<RenderProcessHostImpl*>(host) + ->permission_service_context() + .CreateService(std::move(request)); + })); } } // namespace
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index b18a7a8..987ac0594 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -26,10 +26,8 @@ "blink::mojom::MimeRegistry", "blink::mojom::NotificationService", "blink::mojom::OffscreenCanvasProvider", - "blink::mojom::PermissionService", "blink::mojom::ReportingServiceProxy", "blink::mojom::WebDatabaseHost", - "blink::mojom::WebSocket", "content::mojom::FieldTrialRecorder", "content::mojom::FileUtilitiesHost", "content::mojom::FrameSinkProvider", @@ -49,11 +47,7 @@ "media::mojom::VideoDecodePerfHistory", "memory_coordinator::mojom::MemoryCoordinatorHandle", "metrics::mojom::SingleSampleMetricsProvider", - "payments::mojom::PaymentManager", "resource_coordinator::mojom::ProcessCoordinationUnit", - "shape_detection::mojom::BarcodeDetection", - "shape_detection::mojom::FaceDetectionProvider", - "shape_detection::mojom::TextDetection", "ui::mojom::Gpu", "viz::mojom::SharedBitmapAllocationNotifier", "viz::mojom::CompositingModeReporter" @@ -177,6 +171,8 @@ "navigation:dedicated_worker": { "provides": { "renderer": [ + "blink::mojom::PermissionService", + "payments::mojom::PaymentManager", "shape_detection::mojom::BarcodeDetection", "shape_detection::mojom::FaceDetectionProvider", "shape_detection::mojom::TextDetection" @@ -186,6 +182,9 @@ "navigation:service_worker": { "provides": { "renderer": [ + "blink::mojom::PermissionService", + "blink::mojom::WebSocket", + "payments::mojom::PaymentManager", "shape_detection::mojom::BarcodeDetection", "shape_detection::mojom::FaceDetectionProvider", "shape_detection::mojom::TextDetection" @@ -195,6 +194,9 @@ "navigation:shared_worker": { "provides": { "renderer": [ + "blink::mojom::PermissionService", + "blink::mojom::WebSocket", + "payments::mojom::PaymentManager", "shape_detection::mojom::BarcodeDetection", "shape_detection::mojom::FaceDetectionProvider", "shape_detection::mojom::TextDetection"
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 7fa3ad2c..2a37e0f 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -100,45 +100,45 @@ self.Flaky('deqp/functional/gles3/textureshadow/*.html', ['win', 'nvidia', 'd3d11'], bug=735464) - # Win10 / NVIDIA Quadro P400 / D3D11 flaky failures + # Win / NVIDIA Quadro P400 / D3D11 flaky failures self.Fail('deqp/functional/gles3/transformfeedback/' + 'basic_types_interleaved_lines.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) self.Fail('deqp/functional/gles3/transformfeedback/' + 'basic_types_interleaved_triangles.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) self.Fail('deqp/functional/gles3/transformfeedback/' + 'basic_types_separate_lines.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) self.Fail('deqp/functional/gles3/transformfeedback/' + 'basic_types_separate_triangles.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) self.Fail('deqp/functional/gles3/transformfeedback/' + 'random_interleaved_lines.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) self.Fail('deqp/functional/gles3/transformfeedback/' + 'random_interleaved_triangles.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) self.Fail('deqp/functional/gles3/transformfeedback/' + 'random_separate_lines.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) self.Fail('deqp/functional/gles3/transformfeedback/' + 'random_separate_triangles.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) self.Fail('deqp/functional/gles3/transformfeedback/interpolation_flat.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=680754) self.Flaky('conformance/textures/image_bitmap_from_video/' + 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) self.Flaky('conformance/textures/image_bitmap_from_video/' + 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) self.Flaky('conformance2/textures/video/*', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) self.Flaky('conformance2/textures/image_bitmap_from_video/*', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) self.Flaky('conformance/extensions/oes-texture-half-float-with-video.html', - ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) + ['win', ('nvidia', 0x1cb3), 'd3d11'], bug=728670) # Win / NVIDIA / OpenGL self.Fail('conformance2/glsl3/vector-dynamic-indexing-nv-driver-bug.html', @@ -725,6 +725,17 @@ self.Skip('conformance2/rendering/blitframebuffer-size-overflow.html', ['linux', ('nvidia', 0x1cb3)], bug=709320) + # Linux NVIDIA Quadro P400, OpenGL backend + self.Fail('conformance/limits/gl-max-texture-dimensions.html', + ['linux', ('nvidia', 0x1cb3)], bug=715001) + self.Fail('conformance/textures/misc/texture-size.html', + ['linux', ('nvidia', 0x1cb3), 'opengl'], bug=703779) + self.Fail('conformance/extensions/webgl-compressed-texture-size-limit.html', + ['linux', ('nvidia', 0x1cb3), 'opengl'], bug=703779) + self.Fail('conformance/textures/misc/texture-size-limit.html', + ['linux', ('nvidia', 0x1cb3), 'opengl'], bug=703779) + + # Linux Intel self.Fail('conformance2/extensions/ext-color-buffer-float.html', ['linux', 'intel'], bug=640389)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index d9eb018d..117f907 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -300,11 +300,11 @@ # WIN / OpenGL / NVIDIA failures self.Fail('conformance/textures/misc/texture-size.html', - ['win10', ('nvidia', 0x1cb3), 'opengl'], bug=703779) + ['win', ('nvidia', 0x1cb3), 'opengl'], bug=703779) self.Fail('conformance/extensions/webgl-compressed-texture-size-limit.html', - ['win10', ('nvidia', 0x1cb3), 'opengl'], bug=703779) + ['win', ('nvidia', 0x1cb3), 'opengl'], bug=703779) self.Fail('conformance/textures/misc/texture-size-limit.html', - ['win10', ('nvidia', 0x1cb3), 'opengl'], bug=703779) + ['win', ('nvidia', 0x1cb3), 'opengl'], bug=703779) # Mark ANGLE's OpenGL as flaky on Windows Nvidia self.Flaky('conformance/*', ['win', 'nvidia', 'opengl'], bug=582083)
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc index 0ffa7560..e629a5f 100644 --- a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc +++ b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc
@@ -22,6 +22,7 @@ gfx::GpuMemoryBufferId id, const gfx::Size& size, gfx::BufferFormat format, + gfx::BufferUsage usage, const DestructionCallback& callback, std::unique_ptr<base::SharedMemory> shared_memory, size_t offset, @@ -30,6 +31,7 @@ shared_memory_(std::move(shared_memory)), offset_(offset), stride_(stride) { + DCHECK(IsUsageSupported(usage)); DCHECK(IsSizeValidForFormat(size, format)); } @@ -40,7 +42,10 @@ GpuMemoryBufferImplSharedMemory::Create(gfx::GpuMemoryBufferId id, const gfx::Size& size, gfx::BufferFormat format, + gfx::BufferUsage usage, const DestructionCallback& callback) { + if (!IsUsageSupported(usage)) + return nullptr; size_t buffer_size = 0u; if (!gfx::BufferSizeForBufferFormatChecked(size, format, &buffer_size)) return nullptr; @@ -50,7 +55,7 @@ return nullptr; return base::WrapUnique(new GpuMemoryBufferImplSharedMemory( - id, size, format, callback, std::move(shared_memory), 0, + id, size, format, usage, callback, std::move(shared_memory), 0, gfx::RowSizeForBufferFormat(size.width(), format, 0))); } @@ -59,7 +64,10 @@ GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( gfx::GpuMemoryBufferId id, const gfx::Size& size, - gfx::BufferFormat format) { + gfx::BufferFormat format, + gfx::BufferUsage usage) { + if (!IsUsageSupported(usage)) + return gfx::GpuMemoryBufferHandle(); size_t buffer_size = 0u; if (!gfx::BufferSizeForBufferFormatChecked(size, format, &buffer_size)) return gfx::GpuMemoryBufferHandle(); @@ -89,7 +97,7 @@ DCHECK(base::SharedMemory::IsHandleValid(handle.handle)); return base::WrapUnique(new GpuMemoryBufferImplSharedMemory( - handle.id, size, format, callback, + handle.id, size, format, usage, callback, std::make_unique<base::SharedMemory>(handle.handle, false), handle.offset, handle.stride)); } @@ -167,7 +175,7 @@ gfx::BufferFormat format, gfx::BufferUsage usage, gfx::GpuMemoryBufferHandle* handle) { - *handle = CreateGpuMemoryBuffer(handle->id, size, format); + *handle = CreateGpuMemoryBuffer(handle->id, size, format, usage); return base::Bind(&base::DoNothing); }
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h index 47577fa..3c2504d 100644 --- a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h +++ b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h
@@ -24,12 +24,14 @@ gfx::GpuMemoryBufferId id, const gfx::Size& size, gfx::BufferFormat format, + gfx::BufferUsage usage, const DestructionCallback& callback); static gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer( gfx::GpuMemoryBufferId id, const gfx::Size& size, - gfx::BufferFormat format); + gfx::BufferFormat format, + gfx::BufferUsage usage); static std::unique_ptr<GpuMemoryBufferImplSharedMemory> CreateFromHandle( const gfx::GpuMemoryBufferHandle& handle, @@ -63,6 +65,7 @@ gfx::GpuMemoryBufferId id, const gfx::Size& size, gfx::BufferFormat format, + gfx::BufferUsage usage, const DestructionCallback& callback, std::unique_ptr<base::SharedMemory> shared_memory, size_t offset,
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc index 257b64e..268d5f8 100644 --- a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc +++ b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc
@@ -22,12 +22,13 @@ const gfx::GpuMemoryBufferId kBufferId(1); gfx::Size buffer_size(8, 8); + gfx::BufferUsage usage = gfx::BufferUsage::GPU_READ; for (auto format : gfx::GetBufferFormatsForTesting()) { bool destroyed = false; std::unique_ptr<GpuMemoryBufferImplSharedMemory> buffer( GpuMemoryBufferImplSharedMemory::Create( - kBufferId, buffer_size, format, + kBufferId, buffer_size, format, usage, base::Bind(&BufferDestroyed, base::Unretained(&destroyed)))); ASSERT_TRUE(buffer); EXPECT_EQ(buffer->GetFormat(), format);
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 0135d9c..d600ff1 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -132,6 +132,8 @@ "fake_jpeg_decode_accelerator.h", "fake_video_decode_accelerator.cc", "fake_video_decode_accelerator.h", + "format_utils.cc", + "format_utils.h", "gles2_decoder_helper.cc", "gles2_decoder_helper.h", "gpu_video_accelerator_util.cc",
diff --git a/media/gpu/format_utils.cc b/media/gpu/format_utils.cc new file mode 100644 index 0000000..70745366b --- /dev/null +++ b/media/gpu/format_utils.cc
@@ -0,0 +1,51 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/gpu/format_utils.h" +#include "base/logging.h" + +namespace media { + +VideoPixelFormat GfxBufferFormatToVideoPixelFormat(gfx::BufferFormat format) { + switch (format) { + case gfx::BufferFormat::BGRX_8888: + return PIXEL_FORMAT_XRGB; + + case gfx::BufferFormat::BGRA_8888: + return PIXEL_FORMAT_ARGB; + + case gfx::BufferFormat::YVU_420: + return PIXEL_FORMAT_YV12; + + case gfx::BufferFormat::YUV_420_BIPLANAR: + return PIXEL_FORMAT_NV12; + + default: + LOG(FATAL) << "Add more cases as needed"; + return PIXEL_FORMAT_UNKNOWN; + } +} + +gfx::BufferFormat VideoPixelFormatToGfxBufferFormat( + VideoPixelFormat pixel_format) { + switch (pixel_format) { + case PIXEL_FORMAT_ARGB: + return gfx::BufferFormat::BGRA_8888; + + case PIXEL_FORMAT_XRGB: + return gfx::BufferFormat::BGRX_8888; + + case PIXEL_FORMAT_YV12: + return gfx::BufferFormat::YVU_420; + + case PIXEL_FORMAT_NV12: + return gfx::BufferFormat::YUV_420_BIPLANAR; + + default: + LOG(FATAL) << "Add more cases as needed"; + return gfx::BufferFormat::BGRX_8888; + } +} + +} // namespace media
diff --git a/media/gpu/format_utils.h b/media/gpu/format_utils.h new file mode 100644 index 0000000..7044bba --- /dev/null +++ b/media/gpu/format_utils.h
@@ -0,0 +1,22 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_GPU_FORMAT_UTILS_H_ +#define MEDIA_GPU_FORMAT_UTILS_H_ + +#include "media/base/video_types.h" +#include "media/gpu/media_gpu_export.h" +#include "ui/gfx/buffer_types.h" + +namespace media { + +MEDIA_GPU_EXPORT VideoPixelFormat +GfxBufferFormatToVideoPixelFormat(gfx::BufferFormat format); + +MEDIA_GPU_EXPORT gfx::BufferFormat VideoPixelFormatToGfxBufferFormat( + VideoPixelFormat pixel_format); + +} // namespace media + +#endif // MEDIA_GPU_FORMAT_UTILS_H_
diff --git a/media/gpu/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi_video_decode_accelerator.cc index 10bcbde..608959e 100644 --- a/media/gpu/vaapi_video_decode_accelerator.cc +++ b/media/gpu/vaapi_video_decode_accelerator.cc
@@ -23,6 +23,7 @@ #include "gpu/ipc/service/gpu_channel.h" #include "media/base/bind_to_current_loop.h" #include "media/gpu/accelerated_video_decoder.h" +#include "media/gpu/format_utils.h" #include "media/gpu/h264_decoder.h" #include "media/gpu/vaapi_picture.h" #include "media/gpu/vp8_decoder.h" @@ -706,24 +707,6 @@ TryFinishSurfaceSetChange(); } -static VideoPixelFormat BufferFormatToVideoPixelFormat( - gfx::BufferFormat format) { - switch (format) { - case gfx::BufferFormat::BGRX_8888: - return PIXEL_FORMAT_XRGB; - - case gfx::BufferFormat::BGRA_8888: - return PIXEL_FORMAT_ARGB; - - case gfx::BufferFormat::YVU_420: - return PIXEL_FORMAT_YV12; - - default: - LOG(FATAL) << "Add more cases as needed"; - return PIXEL_FORMAT_UNKNOWN; - } -} - void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() { DCHECK(task_runner_->BelongsToCurrentThread()); @@ -763,7 +746,7 @@ VLOGF(2) << "Requesting " << requested_num_pics_ << " pictures of size: " << requested_pic_size_.ToString(); - VideoPixelFormat format = BufferFormatToVideoPixelFormat(output_format_); + VideoPixelFormat format = GfxBufferFormatToVideoPixelFormat(output_format_); task_runner_->PostTask( FROM_HERE, base::Bind(&Client::ProvidePictureBuffers, client_, requested_num_pics_, format, 1, requested_pic_size_,
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc index 4fd451b..8cf966aa 100644 --- a/media/gpu/video_decode_accelerator_unittest.cc +++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -61,6 +61,7 @@ #include "media/base/test_data_util.h" #include "media/gpu/fake_video_decode_accelerator.h" #include "media/gpu/features.h" +#include "media/gpu/format_utils.h" #include "media/gpu/gpu_video_decode_accelerator_factory.h" #include "media/gpu/rendering_helper.h" #include "media/gpu/video_accelerator_unittest_helpers.h" @@ -340,23 +341,6 @@ return base::WrapRefCounted(new TextureRef(texture_id, no_longer_needed_cb)); } -#if defined(OS_CHROMEOS) -gfx::BufferFormat VideoPixelFormatToGfxBufferFormat( - VideoPixelFormat pixel_format) { - switch (pixel_format) { - case VideoPixelFormat::PIXEL_FORMAT_ARGB: - return gfx::BufferFormat::BGRA_8888; - case VideoPixelFormat::PIXEL_FORMAT_XRGB: - return gfx::BufferFormat::BGRX_8888; - case VideoPixelFormat::PIXEL_FORMAT_NV12: - return gfx::BufferFormat::YUV_420_BIPLANAR; - default: - LOG_ASSERT(false) << "Unknown VideoPixelFormat"; - return gfx::BufferFormat::BGRX_8888; - } -} -#endif - // static scoped_refptr<TextureRef> TextureRef::CreatePreallocated( uint32_t texture_id,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 2be015e4..6490106 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -4128,10 +4128,7 @@ "gl_unittests", "headless_shell", "media_unittests", - "net_unittests", - "skia_unittests", - "service_manager_unittests", - "ui_base_unittests" + "net_unittests" ], "gtest_tests": [ { @@ -4193,6 +4190,30 @@ "can_use_on_swarming_builders": true }, "test": "mojo_system_unittests" + }, + { + "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.service_manager_unittests.filter" + ], + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "service_manager_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "skia_unittests" + }, + { + "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter" + ], + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ui_base_unittests" } ] },
diff --git a/testing/buildbot/filters/fuchsia.mojo_system_unittests.filter b/testing/buildbot/filters/fuchsia.mojo_system_unittests.filter index bfce535..9379ac5 100644 --- a/testing/buildbot/filters/fuchsia.mojo_system_unittests.filter +++ b/testing/buildbot/filters/fuchsia.mojo_system_unittests.filter
@@ -7,3 +7,7 @@ # These tests require support for named channels. See crbug.com/754038. -MultiprocessMessagePipeTestWithPeerSupport*/2 -MultiprocessMessagePipeTestWithPeerSupport*/3 + +# crbug.com/780317 - These timeout under QEMU s/w emulation of ARM64. +-MultiprocessMessagePipeTestWithPeerSupport.PingPongPipe* +-MessagePipeTest.SharedBufferHandlePingPong
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls index c4d909f..d496e27 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls +++ b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
@@ -30,11 +30,9 @@ crbug.com/417782 compositing/squashing/squash-above-fixed-3.html [ Failure ] crbug.com/417782 compositing/squashing/squashing-print.html [ Failure ] crbug.com/417782 compositing/visibility/visibility-image-layers-dynamic.html [ Failure ] -crbug.com/417782 css3/filters/nested-filter.html [ Failure ] crbug.com/417782 editing/input/scroll-viewport-page-up-down.html [ Failure ] crbug.com/417782 external/wpt/css/css-position-3/position-sticky-root-scroller.html [ Failure ] crbug.com/417782 [ Mac ] fast/body-propagation/background-image/007.html [ Failure ] -crbug.com/417782 fast/css/resize-corner-tracking-transformed.html [ Failure ] crbug.com/417782 fast/css/sticky/replaced-sticky.html [ Failure ] crbug.com/417782 fast/css/sticky/sticky-style-change.html [ Failure ] crbug.com/417782 fast/css/zoom-body-scroll.html [ Failure ] @@ -61,7 +59,6 @@ crbug.com/417782 [ Linux Win ] fast/forms/select-popup/popup-menu-appearance-transform.html [ Failure ] crbug.com/417782 fast/frames/iframe-scaling-with-scroll.html [ Failure ] crbug.com/417782 fast/layers/scroll-rect-to-visible.html [ Failure ] -crbug.com/417782 fast/layers/scroll-with-transform-layer.html [ Failure ] crbug.com/417782 fast/layout/scroll-anchoring/history-restore-anchors.html [ Failure ] crbug.com/417782 fast/loader/scroll-position-restoration-without-premature-clamping.html [ Failure ] crbug.com/417782 fast/loader/scroll-position-restored-on-back-at-load-event.html [ Failure ] @@ -105,7 +102,6 @@ crbug.com/417782 paint/invalidation/overflow-scroll-body-appear.html [ Failure ] crbug.com/417782 paint/invalidation/positioned-document-element.html [ Crash ] crbug.com/417782 paint/invalidation/resize-iframe-text.html [ Failure ] -crbug.com/417782 paint/invalidation/scroll-in-transformed-layer.html [ Failure ] crbug.com/417782 paint/invalidation/subpixel-shadow-included-in-invalidation.html [ Failure ] crbug.com/417782 paint/invalidation/svg/absolute-sized-document-no-scrollbars.svg [ Failure ] crbug.com/417782 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ] @@ -140,7 +136,6 @@ crbug.com/417782 svg/W3C-SVG-1.1/masking-path-04-b.svg [ Failure ] crbug.com/417782 svg/custom/mask-with-default-value.svg [ Failure ] crbug.com/417782 [ Mac ] svg/custom/masking-clipping-hidpi.svg [ Failure ] -crbug.com/417782 transforms/overflow-with-transform.html [ Failure ] crbug.com/417782 transforms/selection-bounds-in-transformed-view.html [ Failure ] crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/browser-controls-background-iframe.html [ Failure ] crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe-scroller.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/nested-overflow-clip-expected.html b/third_party/WebKit/LayoutTests/compositing/overflow/nested-overflow-clip-expected.html new file mode 100644 index 0000000..e891fac7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/overflow/nested-overflow-clip-expected.html
@@ -0,0 +1,2 @@ +<!doctype html> +This test passes if there is no red.
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/nested-overflow-clip.html b/third_party/WebKit/LayoutTests/compositing/overflow/nested-overflow-clip.html new file mode 100644 index 0000000..4990c85 --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/overflow/nested-overflow-clip.html
@@ -0,0 +1,14 @@ +<!doctype html> +<style> + ::-webkit-scrollbar { + display: none; + } +</style> +This test passes if there is no red. +<div id="scroller" style="position: absolute; width: 400px; height: 400px; overflow-y: scroll; will-change: transform;"> + <div id="transformed" style="width: 100px; height: 100px; top: 100px; left: 50px; position: absolute; overflow: hidden; transform: rotate(45deg);"> + <!-- This rect should be entirely clipped out. --> + <div style="width: 100px; height: 100px; top: 100px; left: 50px; position: absolute; background: red;"></div> + </div> + <div id="forcescroll" style="height: 1000px;"></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/copy-null-characters-expected.txt b/third_party/WebKit/LayoutTests/editing/pasteboard/copy-null-characters-expected.txt deleted file mode 100644 index 04b3208..0000000 --- a/third_party/WebKit/LayoutTests/editing/pasteboard/copy-null-characters-expected.txt +++ /dev/null
@@ -1,54 +0,0 @@ -If there are NULL characters in text nodes, they should not be copied to the clipboard. This test requires DumpRenderTree. -| " -" -| <div> -| id="outerSource" -| <p> -| <b> -| "bold" -| " - " -| " - " -| <p> -| style="color: green" -| "green" -| " -" -| " -" -| <div> -| contenteditable="true" -| id="destination-rich-text" -| <p> -| <b> -| "bold" -| <div> -| id="source" -| "Copy paste me" -| <span> -| style="color: green;" -| "green" -| "Copy paste me" -| " -" -| <textarea> -| id="destination-plain-text" -| this.value="Copy paste mebold - -Copy paste me -green" -| <shadow:root> -| <div> -| "Copy paste mebold - -Copy paste me -green" -| " -" -| <div> -| id="results" -| "PASSED" -| " - -"
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/copy-null-characters.html b/third_party/WebKit/LayoutTests/editing/pasteboard/copy-null-characters.html index 189c8c95..1ebad7eef 100644 --- a/third_party/WebKit/LayoutTests/editing/pasteboard/copy-null-characters.html +++ b/third_party/WebKit/LayoutTests/editing/pasteboard/copy-null-characters.html
@@ -1,89 +1,14 @@ -<head> -<script src="../../resources/dump-as-markup.js"></script> +<!doctype html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../assert_selection.js"></script> <script> -Markup.description('If there are NULL characters in text nodes, they should not be copied to the clipboard. This test requires DumpRenderTree.'); -Markup.noAutoDump(); - -function runTest() -{ - var sel = window.getSelection(); - - var source = document.getElementById("source"); - var textWithNull = "Copy\0 paste me"; - source.textContent = textWithNull; - - var results = document.getElementById("results"); - // Make sure innerHTML still has the NULL. - if (source.innerHTML != textWithNull) { - results.innerText = "source.innerHTML has the wrong value (expected " + - JSON.stringify(textWithNull) + " but found " + - JSON.stringify(source.innerHTML) + ")."; - Markup.dump(document.body); - Markup.notifyDone(); - return; - } - - sel.collapse(source, 0); - document.execCommand("SelectAll"); - document.execCommand("Copy"); - - var destinationRichText = document.getElementById("destination-rich-text"); - sel.collapse(destinationRichText, 0); - document.execCommand("Paste"); - - var destinationPlainText = document.getElementById("destination-plain-text"); - destinationPlainText.focus(); - document.execCommand("Paste"); - - var expectedPlainTextValue = "Copy paste me"; - if (expectedPlainTextValue != destinationPlainText.value) { - results.innerText = "Plain text field has the wrong value (expected " + - JSON.stringify(expectedPlainTextValue) + " but found " + - JSON.stringify(destinationPlainText.value) + ")."; - Markup.dump(document.body); - Markup.notifyDone(); - return; - } - - // Run the same test but include some richly formatted text. - var outerSource = document.getElementById("outerSource"); - sel.setBaseAndExtent(outerSource, 0, destinationRichText, 0); - document.execCommand("Copy"); - - // Remove the source text so we don't end up with a null character in the - // expected output file. - source.parentNode.removeChild(source); - - sel.collapse(destinationRichText, 0); - document.execCommand("Paste"); - - destinationPlainText.focus(); - document.execCommand("Paste"); - - var expectedPlainTextValue2 = "Copy paste mebold\n\nCopy paste me\ngreen"; - if (expectedPlainTextValue2 != destinationPlainText.value) { - results.innerText = "Plain text field has the wrong value (expected " + - JSON.stringify(expectedPlainTextValue2) + " but found " + - JSON.stringify(destinationPlainText.value) + ")."; - Markup.dump(document.body); - Markup.notifyDone(); - return; - } - - results.innerText = "PASSED"; - - Markup.dump(document.body); - Markup.notifyDone(); -} +selection_test( + '<div contenteditable>|</div>', + selection => { + selection.setClipboardData('foo\0bar'); + selection.document.execCommand("paste"); + }, + '<div contenteditable>foobar|</div>', + 'NULL characters should not be copied'); </script> -</head> - -<body onload="runTest()"> -<div id="outerSource"><p><b>bold</b></p> - <div id="source" contentEditable="true"></div> - <p style="color: green">green</p> -</div> -<div id="destination-rich-text" contentEditable="true"></div> -<textarea id="destination-plain-text"></textarea> -<div id="results">FAILED</div> -</body>
diff --git a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt index 072db6d..f5a4c69 100644 --- a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt +++ b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt
@@ -3,17 +3,17 @@ PASS Calling CSSStyleValue.parse with an unsupported CSS property throws a TypeError PASS Calling CSSStyleValue.parse with a CSS shorthand throws a TypeError PASS Calling CSSStyleValue.parse with an invalid cssText for the given property throws a SyntaxError -PASS Calling CSSStyleValue.parse with a valid cssText for the given property returns a valid CSSStyleValue -PASS Calling CSSStyleValue.parse with a mixed case cssText returns a valid CSSStyleValue -FAIL Calling CSSStyleValue.parse with a custom property returns a valid CSSStyleValue Failed to execute 'parse' on 'CSSStyleValue': Invalid property name PASS Calling CSSStyleValue.parseAll with an empty string throws a TypeError PASS Calling CSSStyleValue.parseAll with an unsupported CSS property throws a TypeError PASS Calling CSSStyleValue.parseAll with a CSS shorthand throws a TypeError -FAIL Calling CSSStyleValue.parseAll with an invalid cssText for the given property throws a SyntaxError assert_throws: function "() => CSSStyleValue[parseMethod]('width', '10deg')" threw object "TypeError: CSSStyleValue[parseMethod] is not a function" ("TypeError") expected object "SyntaxError" ("SyntaxError") -FAIL Calling CSSStyleValue.parseAll with a valid cssText for the given property returns a valid CSSStyleValue CSSStyleValue[parseMethod] is not a function -FAIL Calling CSSStyleValue.parseAll with a mixed case cssText returns a valid CSSStyleValue CSSStyleValue[parseMethod] is not a function -FAIL Calling CSSStyleValue.parseAll with a custom property returns a valid CSSStyleValue CSSStyleValue[parseMethod] is not a function +PASS Calling CSSStyleValue.parseAll with an invalid cssText for the given property throws a SyntaxError +PASS Calling CSSStyleValue.parse with a valid cssText for the given property returns a valid CSSStyleValue +PASS Calling CSSStyleValue.parse with a mixed case cssText returns a valid CSSStyleValue +FAIL Calling CSSStyleValue.parse with a custom property returns a valid CSSStyleValue Failed to execute 'parse' on 'CSSStyleValue': Invalid property name +PASS Calling CSSStyleValue.parseAll with a valid cssText for the given property returns a single-element list containing a valid CSSStyleValue +PASS Calling CSSStyleValue.parseAll with a mixed case cssText returns a single-element list containing a valid CSSStyleValue +FAIL Calling CSSStyleValue.parseAll with a custom property returns a single-element list containing a valid CSSStyleValue Failed to execute 'parseAll' on 'CSSStyleValue': Invalid property name PASS Calling CSSStyleValue.parse with a list-value property returns first list value -FAIL Calling CSSStyleValue.parseAll with a list-value property returns a sequence of values CSSStyleValue.parseAll is not a function +PASS Calling CSSStyleValue.parseAll with a list-value property returns a sequence of values Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll.html b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll.html index 97c12c08..1a9530e 100644 --- a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll.html +++ b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll.html
@@ -25,21 +25,26 @@ test(() => { assert_throws(new SyntaxError(), () => CSSStyleValue[parseMethod]('width', '10deg')); }, 'Calling CSSStyleValue.' + parseMethod + ' with an invalid cssText for the given property throws a SyntaxError'); +} - test(() => { - const result = CSSStyleValue[parseMethod]('width', '10px'); - assert_style_value_equals(result, CSS.px(10)); - }, 'Calling CSSStyleValue.' + parseMethod + ' with a valid cssText for the given property returns a valid CSSStyleValue'); +const gValidNonListTests = [ + { property: 'width', value: '10px', expected: CSS.px(10), desc: 'a valid cssText for the given property' }, + { property: 'wIdTh', value: '10px', expected: CSS.px(10), desc: 'a mixed case cssText' }, + { property: '--foo', value: '10%', expected: CSS.percent(10), desc: 'a custom property' }, +]; +for (const {property, value, expected, desc} of gValidNonListTests) { test(() => { - const result = CSSStyleValue[parseMethod]('wIdTh', '10px'); - assert_style_value_equals(result, CSS.px(10)); - }, 'Calling CSSStyleValue.' + parseMethod + ' with a mixed case cssText returns a valid CSSStyleValue'); + const result = CSSStyleValue.parse(property, value); + assert_style_value_equals(result, expected); + }, 'Calling CSSStyleValue.parse with ' + desc + ' returns a valid CSSStyleValue'); +} +for (const {property, value, expected, desc} of gValidNonListTests) { test(() => { - const result = CSSStyleValue[parseMethod]('--foo', '10%'); - assert_style_value_equals(result, CSS.percent(10)); - }, 'Calling CSSStyleValue.' + parseMethod + ' with a custom property returns a valid CSSStyleValue'); + const result = CSSStyleValue.parseAll(property, value); + assert_style_value_array_equals(result, [expected]); + }, 'Calling CSSStyleValue.parseAll with ' + desc + ' returns a single-element list containing a valid CSSStyleValue'); } test(() => {
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 009196c..b88f7dc 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -794,6 +794,7 @@ method removeRule interface CSSStyleValue static method parse + static method parseAll attribute @@toStringTag method constructor method toString
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index 57ee773..1e44dc4 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1847,6 +1847,7 @@ "//third_party/WebKit/Source/platform:blink_fuzzer_test_support", "//third_party/libprotobuf-mutator", ] + dict = "//third_party/WebKit/Source/core/css/css.dict" } proto_library("css_proto") {
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp index c21de49..b878230 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
@@ -13,25 +13,23 @@ namespace blink { -ScriptValue CSSStyleValue::parse(ScriptState* script_state, - const String& property_name, - const String& value, - ExceptionState& exception_state) { - if (property_name.IsEmpty()) { - exception_state.ThrowTypeError("Property name cannot be empty"); - return ScriptValue::CreateNull(script_state); - } +namespace { - CSSPropertyID property_id = cssPropertyID(property_name); - // TODO(timloh): Handle custom properties +CSSStyleValueVector ParseCSSStyleValue(const String& property_name, + const String& value, + ExceptionState& exception_state) { + const CSSPropertyID property_id = cssPropertyID(property_name); + + // TODO(775804): Handle custom properties if (property_id == CSSPropertyInvalid || property_id == CSSPropertyVariable) { exception_state.ThrowTypeError("Invalid property name"); - return ScriptValue::CreateNull(script_state); + return CSSStyleValueVector(); } + if (isShorthandProperty(property_id)) { exception_state.ThrowTypeError( "Parsing shorthand properties is not supported"); - return ScriptValue::CreateNull(script_state); + return CSSStyleValueVector(); } const CSSValue* css_value = @@ -41,17 +39,38 @@ kSyntaxError, "The value provided ('" + value + "') could not be parsed as a '" + property_name + "'."); - return ScriptValue::CreateNull(script_state); + return CSSStyleValueVector(); } CSSStyleValueVector style_value_vector = StyleValueFactory::CssValueToStyleValueVector(property_id, *css_value); DCHECK(!style_value_vector.IsEmpty()); + return style_value_vector; +} - v8::Local<v8::Value> wrapped_value = - ToV8(style_value_vector[0], script_state->GetContext()->Global(), - script_state->GetIsolate()); - return ScriptValue(script_state, wrapped_value); +} // namespace + +CSSStyleValue* CSSStyleValue::parse(const String& property_name, + const String& value, + ExceptionState& exception_state) { + CSSStyleValueVector style_value_vector = + ParseCSSStyleValue(property_name, value, exception_state); + if (style_value_vector.IsEmpty()) + return nullptr; + + return style_value_vector[0]; +} + +Nullable<CSSStyleValueVector> CSSStyleValue::parseAll( + const String& property_name, + const String& value, + ExceptionState& exception_state) { + CSSStyleValueVector style_value_vector = + ParseCSSStyleValue(property_name, value, exception_state); + if (style_value_vector.IsEmpty()) + return nullptr; + + return style_value_vector; } String CSSStyleValue::StyleValueTypeToString(StyleValueType type) {
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h index 422dd9fa..7770b19 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h
@@ -5,6 +5,7 @@ #ifndef CSSStyleValue_h #define CSSStyleValue_h +#include "bindings/core/v8/Nullable.h" #include "core/CSSPropertyNames.h" #include "core/CoreExport.h" #include "core/css/CSSValue.h" @@ -14,8 +15,9 @@ namespace blink { class ExceptionState; -class ScriptState; -class ScriptValue; + +class CSSStyleValue; +using CSSStyleValueVector = HeapVector<Member<CSSStyleValue>>; // The base class for all CSS values returned by the Typed OM. // See CSSStyleValue.idl for additional documentation about this class. @@ -48,10 +50,12 @@ kInvalidType, }; - static ScriptValue parse(ScriptState*, - const String& property_name, - const String& value, - ExceptionState&); + static CSSStyleValue* parse(const String& property_name, + const String& value, + ExceptionState&); + static Nullable<CSSStyleValueVector> parseAll(const String& property_name, + const String& value, + ExceptionState&); virtual ~CSSStyleValue() {} @@ -75,8 +79,6 @@ CSSStyleValue() {} }; -typedef HeapVector<Member<CSSStyleValue>> CSSStyleValueVector; - } // namespace blink #endif
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl index cf09319..6eabaa9 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl +++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl
@@ -10,7 +10,7 @@ Exposed(Window CSSTypedOM, PaintWorklet CSSPaintAPI) ] interface CSSStyleValue { stringifier; - // TODO(meade): Should be (CSSStyleValue or sequence<CSSStyleValue>)? instead of object?. Fix when the code generator supports this. // Putting Exposed=Window in the next line makes |parse| not exposed to PaintWorklet. - [RaisesException, CallWith=ScriptState, Exposed=Window] static object? parse(DOMString property, DOMString cssText); + [RaisesException, Exposed=Window] static CSSStyleValue? parse(DOMString property, DOMString cssText); + [RaisesException, Exposed=Window] static sequence<CSSStyleValue>? parseAll(DOMString property, DOMString cssText); };
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp index 2a0065a..f12bc688 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -853,9 +853,12 @@ transformed_painting_info.ancestor_has_clip_path_clipping = painting_info.ancestor_has_clip_path_clipping; - // Remove skip root background flag when we're painting with a new root. - if (&paint_layer_ != painting_info.root_layer) + if (&paint_layer_ != painting_info.root_layer) { + // Remove skip root background flag when we're painting with a new root. paint_flags &= ~kPaintLayerPaintingSkipRootBackground; + // When painting a new root we are no longer painting overflow contents. + paint_flags &= ~kPaintLayerPaintingOverflowContents; + } return PaintLayerContentsCompositingAllPhases( context, transformed_painting_info, paint_flags, kForceSingleFragment);
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp index a6f70fda..ee79a78 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -58,7 +58,6 @@ #include "platform/wtf/PtrUtil.h" #include "platform/wtf/Threading.h" #include "platform/wtf/text/WTFString.h" -#include "public/platform/InterfaceProvider.h" #include "public/platform/Platform.h" namespace blink { @@ -70,12 +69,6 @@ // TODO(nhiroki): Adjust the delay based on UMA. constexpr TimeDelta kForcibleTerminationDelay = TimeDelta::FromSeconds(2); -void ForwardInterfaceRequest(const std::string& name, - mojo::ScopedMessagePipeHandle handle) { - Platform::Current()->GetInterfaceProvider()->GetInterface(name.c_str(), - std::move(handle)); -} - } // namespace static Mutex& ThreadSetMutex() { @@ -307,13 +300,6 @@ return exit_code_; } -service_manager::InterfaceProvider& WorkerThread::GetInterfaceProvider() { - // TODO(https://crbug.com/734210): Instead of forwarding to the process-wide - // interface provider a worker-specific interface provider pipe should be - // passed in as part of the WorkerThreadStartupData. - return interface_provider_; -} - WorkerThread::WorkerThread(ThreadableLoadingContext* loading_context, WorkerReportingProxy& worker_reporting_proxy) : time_origin_(MonotonicallyIncreasingTime()), @@ -329,8 +315,6 @@ DCHECK(IsMainThread()); MutexLocker lock(ThreadSetMutex()); WorkerThreads().insert(this); - interface_provider_.Forward( - ConvertToBaseCallback(WTF::Bind(&ForwardInterfaceRequest))); } void WorkerThread::ScheduleToTerminateScriptExecution() {
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.h b/third_party/WebKit/Source/core/workers/WorkerThread.h index 3c73e845..5c7ccd8 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThread.h +++ b/third_party/WebKit/Source/core/workers/WorkerThread.h
@@ -45,7 +45,6 @@ #include "platform/wtf/Optional.h" #include "platform/wtf/RefPtr.h" #include "public/platform/WebThread.h" -#include "services/service_manager/public/cpp/interface_provider.h" #include "v8/include/v8.h" namespace blink { @@ -171,8 +170,6 @@ return global_scope_scheduler_.get(); } - service_manager::InterfaceProvider& GetInterfaceProvider(); - // For ServiceWorkerScriptStreaming. Returns nullptr otherwise. virtual InstalledScriptsManager* GetInstalledScriptsManager() { return nullptr; @@ -284,10 +281,6 @@ CrossThreadPersistent<ParentFrameTaskRunners> parent_frame_task_runners_; - // Mojo interface provider serving interface requests scoped to this worker - // context. - service_manager::InterfaceProvider interface_provider_; - // Tasks managed by this scheduler are canceled when the global scope is // closed. std::unique_ptr<scheduler::WorkerGlobalScopeScheduler>
diff --git a/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.cpp b/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.cpp index 2aab272..fa1cd4a 100644 --- a/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.cpp +++ b/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.cpp
@@ -12,8 +12,8 @@ #include "modules/cookie_store/CookieStore.h" #include "platform/Supplementable.h" #include "platform/heap/Handle.h" -#include "public/platform/InterfaceProvider.h" #include "services/network/public/interfaces/restricted_cookie_manager.mojom-blink.h" +#include "services/service_manager/public/cpp/interface_provider.h" namespace blink {
diff --git a/third_party/WebKit/Source/modules/payments/PaymentManager.cpp b/third_party/WebKit/Source/modules/payments/PaymentManager.cpp index 2ebf80b5..0eaeb0f 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentManager.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentManager.cpp
@@ -6,15 +6,10 @@ #include "bindings/core/v8/ScriptPromise.h" #include "core/dom/DOMException.h" -#include "core/dom/Document.h" -#include "core/frame/LocalFrame.h" -#include "core/workers/WorkerGlobalScope.h" -#include "core/workers/WorkerThread.h" #include "modules/payments/PaymentInstruments.h" #include "modules/serviceworkers/ServiceWorkerRegistration.h" #include "platform/bindings/ScriptState.h" -#include "platform/mojo/MojoHelper.h" -#include "public/platform/Platform.h" +#include "services/service_manager/public/cpp/interface_provider.h" namespace blink { @@ -49,14 +44,10 @@ DCHECK(registration); auto request = mojo::MakeRequest(&manager_); - ExecutionContext* context = registration->GetExecutionContext(); - if (context && context->IsDocument()) { - LocalFrame* frame = ToDocument(context)->GetFrame(); - if (frame) - frame->GetInterfaceProvider().GetInterface(std::move(request)); - } else if (context && context->IsWorkerGlobalScope()) { - WorkerThread* thread = ToWorkerGlobalScope(context)->GetThread(); - thread->GetInterfaceProvider().GetInterface(std::move(request)); + if (ExecutionContext* context = registration->GetExecutionContext()) { + if (auto* interface_provider = context->GetInterfaceProvider()) { + interface_provider->GetInterface(std::move(request)); + } } manager_.set_connection_error_handler(ConvertToBaseCallback(WTF::Bind(
diff --git a/third_party/WebKit/Source/modules/permissions/PermissionUtils.cpp b/third_party/WebKit/Source/modules/permissions/PermissionUtils.cpp index b0c7094..bf61ed7 100644 --- a/third_party/WebKit/Source/modules/permissions/PermissionUtils.cpp +++ b/third_party/WebKit/Source/modules/permissions/PermissionUtils.cpp
@@ -21,21 +21,11 @@ using mojom::blink::PermissionDescriptorPtr; using mojom::blink::PermissionName; -bool ConnectToPermissionService( +void ConnectToPermissionService( ExecutionContext* execution_context, mojom::blink::PermissionServiceRequest request) { - if (execution_context->IsWorkerGlobalScope()) { - WorkerThread* thread = ToWorkerGlobalScope(execution_context)->GetThread(); - thread->GetInterfaceProvider().GetInterface(std::move(request)); - return true; - } - - LocalFrame* frame = ToDocument(execution_context)->GetFrame(); - if (!frame) - return false; - - frame->GetInterfaceProvider().GetInterface(std::move(request)); - return true; + if (auto* interface_provider = execution_context->GetInterfaceProvider()) + interface_provider->GetInterface(std::move(request)); } PermissionDescriptorPtr CreatePermissionDescriptor(PermissionName name) {
diff --git a/third_party/WebKit/Source/modules/permissions/PermissionUtils.h b/third_party/WebKit/Source/modules/permissions/PermissionUtils.h index 50379cd8..ec76be7 100644 --- a/third_party/WebKit/Source/modules/permissions/PermissionUtils.h +++ b/third_party/WebKit/Source/modules/permissions/PermissionUtils.h
@@ -11,7 +11,7 @@ class ExecutionContext; -bool ConnectToPermissionService(ExecutionContext*, +void ConnectToPermissionService(ExecutionContext*, mojom::blink::PermissionServiceRequest); mojom::blink::PermissionDescriptorPtr CreatePermissionDescriptor(
diff --git a/third_party/WebKit/Source/modules/permissions/Permissions.cpp b/third_party/WebKit/Source/modules/permissions/Permissions.cpp index 558c8dcc..d882ea4 100644 --- a/third_party/WebKit/Source/modules/permissions/Permissions.cpp +++ b/third_party/WebKit/Source/modules/permissions/Permissions.cpp
@@ -157,16 +157,6 @@ if (exception_state.HadException()) return exception_state.Reject(script_state); - // This must be called after `parsePermission` because the website might - // be able to run code. - PermissionService* service = GetService(ExecutionContext::From(script_state)); - if (!service) - return ScriptPromise::RejectWithDOMException( - script_state, - DOMException::Create( - kInvalidStateError, - "In its current state, the global scope can't query permissions.")); - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); @@ -175,12 +165,13 @@ // permission prompt will be shown even if the returned permission will most // likely be "prompt". PermissionDescriptorPtr descriptor_copy = descriptor->Clone(); - service->HasPermission( - std::move(descriptor), - ExecutionContext::From(script_state)->GetSecurityOrigin(), - ConvertToBaseCallback(WTF::Bind( - &Permissions::TaskComplete, WrapPersistent(this), - WrapPersistent(resolver), WTF::Passed(std::move(descriptor_copy))))); + GetService(ExecutionContext::From(script_state)) + .HasPermission(std::move(descriptor), + ExecutionContext::From(script_state)->GetSecurityOrigin(), + ConvertToBaseCallback(WTF::Bind( + &Permissions::TaskComplete, WrapPersistent(this), + WrapPersistent(resolver), + WTF::Passed(std::move(descriptor_copy))))); return promise; } @@ -196,27 +187,20 @@ ExecutionContext* context = ExecutionContext::From(script_state); - // This must be called after `parsePermission` because the website might - // be able to run code. - PermissionService* service = GetService(context); - if (!service) - return ScriptPromise::RejectWithDOMException( - script_state, DOMException::Create(kInvalidStateError, - "In its current state, the global " - "scope can't request permissions.")); - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); PermissionDescriptorPtr descriptor_copy = descriptor->Clone(); Document* doc = ToDocumentOrNull(context); Frame* frame = doc ? doc->GetFrame() : nullptr; - service->RequestPermission( - std::move(descriptor), context->GetSecurityOrigin(), - Frame::HasTransientUserActivation(frame, true /* checkIfMainThread */), - ConvertToBaseCallback(WTF::Bind( - &Permissions::TaskComplete, WrapPersistent(this), - WrapPersistent(resolver), WTF::Passed(std::move(descriptor_copy))))); + GetService(ExecutionContext::From(script_state)) + .RequestPermission(std::move(descriptor), context->GetSecurityOrigin(), + Frame::HasTransientUserActivation( + frame, true /* checkIfMainThread */), + ConvertToBaseCallback(WTF::Bind( + &Permissions::TaskComplete, WrapPersistent(this), + WrapPersistent(resolver), + WTF::Passed(std::move(descriptor_copy))))); return promise; } @@ -230,25 +214,18 @@ if (exception_state.HadException()) return exception_state.Reject(script_state); - // This must be called after `parsePermission` because the website might - // be able to run code. - PermissionService* service = GetService(ExecutionContext::From(script_state)); - if (!service) - return ScriptPromise::RejectWithDOMException( - script_state, DOMException::Create(kInvalidStateError, - "In its current state, the global " - "scope can't revoke permissions.")); - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); PermissionDescriptorPtr descriptor_copy = descriptor->Clone(); - service->RevokePermission( - std::move(descriptor), - ExecutionContext::From(script_state)->GetSecurityOrigin(), - ConvertToBaseCallback(WTF::Bind( - &Permissions::TaskComplete, WrapPersistent(this), - WrapPersistent(resolver), WTF::Passed(std::move(descriptor_copy))))); + GetService(ExecutionContext::From(script_state)) + .RevokePermission( + std::move(descriptor), + ExecutionContext::From(script_state)->GetSecurityOrigin(), + ConvertToBaseCallback( + WTF::Bind(&Permissions::TaskComplete, WrapPersistent(this), + WrapPersistent(resolver), + WTF::Passed(std::move(descriptor_copy))))); return promise; } @@ -286,15 +263,6 @@ ExecutionContext* context = ExecutionContext::From(script_state); - // This must be called after `parsePermission` because the website might - // be able to run code. - PermissionService* service = GetService(context); - if (!service) - return ScriptPromise::RejectWithDOMException( - script_state, DOMException::Create(kInvalidStateError, - "In its current state, the global " - "scope can't request permissions.")); - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); @@ -305,24 +273,27 @@ Document* doc = ToDocumentOrNull(context); Frame* frame = doc ? doc->GetFrame() : nullptr; - service->RequestPermissions( - std::move(internal_permissions), context->GetSecurityOrigin(), - Frame::HasTransientUserActivation(frame, true /* checkIfMainThread */), - ConvertToBaseCallback( - WTF::Bind(&Permissions::BatchTaskComplete, WrapPersistent(this), - WrapPersistent(resolver), - WTF::Passed(std::move(internal_permissions_copy)), - WTF::Passed(std::move(caller_index_to_internal_index))))); + GetService(ExecutionContext::From(script_state)) + .RequestPermissions( + std::move(internal_permissions), context->GetSecurityOrigin(), + Frame::HasTransientUserActivation(frame, + true /* checkIfMainThread */), + ConvertToBaseCallback(WTF::Bind( + &Permissions::BatchTaskComplete, WrapPersistent(this), + WrapPersistent(resolver), + WTF::Passed(std::move(internal_permissions_copy)), + WTF::Passed(std::move(caller_index_to_internal_index))))); return promise; } -PermissionService* Permissions::GetService( +PermissionService& Permissions::GetService( ExecutionContext* execution_context) { - if (!service_ && ConnectToPermissionService(execution_context, - mojo::MakeRequest(&service_))) + if (!service_) { + ConnectToPermissionService(execution_context, mojo::MakeRequest(&service_)); service_.set_connection_error_handler(ConvertToBaseCallback(WTF::Bind( &Permissions::ServiceConnectionError, WrapWeakPersistent(this)))); - return service_.get(); + } + return *service_; } void Permissions::ServiceConnectionError() {
diff --git a/third_party/WebKit/Source/modules/permissions/Permissions.h b/third_party/WebKit/Source/modules/permissions/Permissions.h index cf6022b8..69c966e 100644 --- a/third_party/WebKit/Source/modules/permissions/Permissions.h +++ b/third_party/WebKit/Source/modules/permissions/Permissions.h
@@ -27,7 +27,7 @@ ScriptPromise requestAll(ScriptState*, const Vector<Dictionary>&); private: - mojom::blink::PermissionService* GetService(ExecutionContext*); + mojom::blink::PermissionService& GetService(ExecutionContext*); void ServiceConnectionError(); void TaskComplete(ScriptPromiseResolver*, mojom::blink::PermissionDescriptorPtr,
diff --git a/third_party/WebKit/Source/modules/quota/StorageManager.cpp b/third_party/WebKit/Source/modules/quota/StorageManager.cpp index 4ac1ab6..ab56273d 100644 --- a/third_party/WebKit/Source/modules/quota/StorageManager.cpp +++ b/third_party/WebKit/Source/modules/quota/StorageManager.cpp
@@ -77,23 +77,15 @@ } DCHECK(execution_context->IsDocument()); - PermissionService* permission_service = - GetPermissionService(ExecutionContext::From(script_state)); - if (!permission_service) { - resolver->Reject(DOMException::Create( - kInvalidStateError, - "In its current state, the global scope can't request permissions.")); - return promise; - } - Document* doc = ToDocumentOrNull(execution_context); - permission_service->RequestPermission( - CreatePermissionDescriptor(PermissionName::DURABLE_STORAGE), - ExecutionContext::From(script_state)->GetSecurityOrigin(), - Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr), - ConvertToBaseCallback( - WTF::Bind(&StorageManager::PermissionRequestComplete, - WrapPersistent(this), WrapPersistent(resolver)))); + GetPermissionService(ExecutionContext::From(script_state)) + .RequestPermission( + CreatePermissionDescriptor(PermissionName::DURABLE_STORAGE), + ExecutionContext::From(script_state)->GetSecurityOrigin(), + Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr), + ConvertToBaseCallback( + WTF::Bind(&StorageManager::PermissionRequestComplete, + WrapPersistent(this), WrapPersistent(resolver)))); return promise; } @@ -110,20 +102,13 @@ return promise; } - PermissionService* permission_service = - GetPermissionService(ExecutionContext::From(script_state)); - if (!permission_service) { - resolver->Reject(DOMException::Create( - kInvalidStateError, - "In its current state, the global scope can't query permissions.")); - return promise; - } - permission_service->HasPermission( - CreatePermissionDescriptor(PermissionName::DURABLE_STORAGE), - ExecutionContext::From(script_state)->GetSecurityOrigin(), - ConvertToBaseCallback( - WTF::Bind(&StorageManager::PermissionRequestComplete, - WrapPersistent(this), WrapPersistent(resolver)))); + GetPermissionService(ExecutionContext::From(script_state)) + .HasPermission( + CreatePermissionDescriptor(PermissionName::DURABLE_STORAGE), + ExecutionContext::From(script_state)->GetSecurityOrigin(), + ConvertToBaseCallback( + WTF::Bind(&StorageManager::PermissionRequestComplete, + WrapPersistent(this), WrapPersistent(resolver)))); return promise; } @@ -146,15 +131,16 @@ return promise; } -PermissionService* StorageManager::GetPermissionService( +PermissionService& StorageManager::GetPermissionService( ExecutionContext* execution_context) { - if (!permission_service_ && - ConnectToPermissionService(execution_context, - mojo::MakeRequest(&permission_service_))) + if (!permission_service_) { + ConnectToPermissionService(execution_context, + mojo::MakeRequest(&permission_service_)); permission_service_.set_connection_error_handler(ConvertToBaseCallback( WTF::Bind(&StorageManager::PermissionServiceConnectionError, WrapWeakPersistent(this)))); - return permission_service_.get(); + } + return *permission_service_; } void StorageManager::PermissionServiceConnectionError() {
diff --git a/third_party/WebKit/Source/modules/quota/StorageManager.h b/third_party/WebKit/Source/modules/quota/StorageManager.h index 8c87c5f..db7e71f9 100644 --- a/third_party/WebKit/Source/modules/quota/StorageManager.h +++ b/third_party/WebKit/Source/modules/quota/StorageManager.h
@@ -26,7 +26,7 @@ ScriptPromise estimate(ScriptState*); private: - mojom::blink::PermissionService* GetPermissionService(ExecutionContext*); + mojom::blink::PermissionService& GetPermissionService(ExecutionContext*); void PermissionServiceConnectionError(); void PermissionRequestComplete(ScriptPromiseResolver*, mojom::blink::PermissionStatus);
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp index 414f22b9..d5bbb93c 100644 --- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp +++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
@@ -46,8 +46,8 @@ #include "platform/wtf/PtrUtil.h" #include "platform/wtf/text/CString.h" #include "platform/wtf/text/WTFString.h" -#include "public/platform/InterfaceProvider.h" #include "public/platform/TaskType.h" +#include "services/service_manager/public/cpp/interface_provider.h" namespace blink { @@ -414,7 +414,7 @@ // SSL interstitial decision to WebSocket connections from the worker. mojom::blink::WebSocketPtrInfo socket_ptr_info; if (!worker_global_scope_->IsDedicatedWorkerGlobalScope()) { - worker_thread->GetInterfaceProvider().GetInterface( + worker_global_scope_->GetInterfaceProvider()->GetInterface( mojo::MakeRequest(&socket_ptr_info)); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp index a72c0453..c09e80bb 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
@@ -90,6 +90,7 @@ DEBUG_STRING_CASE(PrintedContentPDFURLRect); DEBUG_STRING_CASE(Resizer); DEBUG_STRING_CASE(SVGClip); + DEBUG_STRING_CASE(SVGClipBoundsHack); DEBUG_STRING_CASE(SVGFilter); DEBUG_STRING_CASE(SVGMask); DEBUG_STRING_CASE(ScrollbarBackButtonEnd);
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 257c7d9..5ccabe5 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -352,7 +352,6 @@ 'TSAN Release': 'tsan_disable_nacl_release_bot', 'UBSan Release': 'ubsan_release_bot', 'UBSan vptr Release': 'ubsan_vptr_edge_release_bot', - 'Win ASan Release Coverage': 'asan_edge_fuzzer_v8_heap_release_bot_x86', 'Win ASan Release Media': 'asan_fuzzer_v8_heap_chrome_with_codecs_release_bot_x86', 'Win ASan Release': 'asan_fuzzer_v8_heap_release_bot_x86', 'Win SyzyASAN LKGR': 'syzyasan_no_pch_release_x86', @@ -1013,10 +1012,6 @@ 'asan', 'edge', 'fuzzer', 'v8_heap', 'release_bot', 'hybrid', ], - 'asan_edge_fuzzer_v8_heap_release_bot_x86': [ - 'clang', 'asan', 'edge', 'fuzzer', 'v8_heap', 'release_bot', 'x86', - ], - 'asan_edge_v8_heap_debug_bot_hybrid': [ 'asan', 'edge', 'v8_heap', 'debug_bot', 'hybrid', ],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a950f86..a722760 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -27793,32 +27793,22 @@ </enum> <enum name="NegativeSampleReason"> - <int value="0" - label="Persistent sparse histogram had logged value but no active - sample."/> - <int value="1" - label="Persistent sparse histogram active sample less than logged - value."/> - <int value="2" - label="Persistent sparse histogram added a negative count during - iteration."/> + <int value="0" label="Histogram had logged value but no active sample."/> + <int value="1" label="Histogram active sample less than logged value."/> + <int value="2" label="Histogram added a negative count during iteration."/> <int value="3" - label="Persistent sparse histogram added negative count that caused - negative value."/> + label="Histogram added negative count that caused negative value."/> <int value="4" - label="Persistent sparse histogram active sample overflowed and became - negative."/> - <int value="5" - label="Persistent sparse histogram accumulated a negative count."/> + label="Histogram active sample overflowed and became negative."/> + <int value="5" label="Histogram accumulated a negative count."/> <int value="6" - label="Persistent sparse histogram accumulated a negative count that - caused a negative value."/> + label="Histogram accumulated a negative count that caused a negative + value."/> <int value="7" - label="Persistent sparse histogram active sample was negative after - accumulation (deprecated)."/> + label="Histogram active sample was negative after accumulation + (deprecated)."/> <int value="8" - label="Persistent sparse histogram active sample wrapped 2^31 during - accumulation."/> + label="Histogram active sample wrapped 2^31 during accumulation."/> </enum> <enum name="NetCacheState">
diff --git a/ui/gfx/native_pixmap.h b/ui/gfx/native_pixmap.h index 1677dc0..c168001 100644 --- a/ui/gfx/native_pixmap.h +++ b/ui/gfx/native_pixmap.h
@@ -34,6 +34,14 @@ virtual gfx::BufferFormat GetBufferFormat() const = 0; virtual gfx::Size GetBufferSize() const = 0; + // Return an id that is guaranteed to be unique and equal for all instances + // of this NativePixmap backed by the same buffer, for the duration of its + // lifetime. If such id cannot be generated, 0 (an invalid id) is returned. + // + // TODO(posciak): crbug.com/771863, remove this once a different mechanism + // for protected shared memory buffers is implemented. + virtual uint32_t GetUniqueId() const = 0; + // Sets the overlay plane to switch to at the next page flip. // |widget| specifies the screen to display this overlay plane on. // |plane_z_order| specifies the stacking order of the plane relative to the
diff --git a/ui/gfx/native_pixmap_handle.h b/ui/gfx/native_pixmap_handle.h index 827a7fe..b4210dc 100644 --- a/ui/gfx/native_pixmap_handle.h +++ b/ui/gfx/native_pixmap_handle.h
@@ -57,7 +57,8 @@ // Returns an instance of |handle| which can be sent over IPC. This duplicates // the file-handles, so that the IPC code take ownership of them, without // invalidating |handle|. -NativePixmapHandle CloneHandleForIPC(const NativePixmapHandle& handle); +GFX_EXPORT NativePixmapHandle +CloneHandleForIPC(const NativePixmapHandle& handle); #endif } // namespace gfx
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc index 6cc5b50a..234c3f9 100644 --- a/ui/ozone/platform/cast/surface_factory_cast.cc +++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -63,6 +63,7 @@ return gfx::BufferFormat::BGRA_8888; } gfx::Size GetBufferSize() const override { return gfx::Size(); } + uint32_t GetUniqueId() const override { return 0; } bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int plane_z_order,
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc index e7b24aa..38ad6cb 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -261,11 +261,11 @@ // Try to use scanout if supported. int gbm_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING; - bool try_scanout = - gbm_device_is_format_supported(gbm->device(), format, gbm_flags); + if (!gbm_device_is_format_supported(gbm->device(), format, gbm_flags)) + gbm_flags &= ~GBM_BO_USE_SCANOUT; gbm_bo* bo = nullptr; - if (try_scanout) { + if (gbm_device_is_format_supported(gbm->device(), format, gbm_flags)) { struct gbm_import_fd_planar_data fd_data; fd_data.width = size.width(); fd_data.height = size.height(); @@ -287,8 +287,6 @@ LOG(ERROR) << "nullptr returned from gbm_bo_import"; return nullptr; } - } else { - gbm_flags &= ~GBM_BO_USE_SCANOUT; } scoped_refptr<GbmBuffer> buffer(new GbmBuffer(gbm, bo, format, gbm_flags, 0, @@ -365,6 +363,10 @@ return buffer_->GetSize(); } +uint32_t GbmPixmap::GetUniqueId() const { + return buffer_->GetHandle(); +} + bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int plane_z_order, gfx::OverlayTransform plane_transform,
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.h b/ui/ozone/platform/drm/gpu/gbm_buffer.h index 6715274..4891b8f 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.h +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -119,6 +119,7 @@ uint64_t GetDmaBufModifier(size_t plane) const override; gfx::BufferFormat GetBufferFormat() const override; gfx::Size GetBufferSize() const override; + uint32_t GetUniqueId() const override; bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int plane_z_order, gfx::OverlayTransform plane_transform,
diff --git a/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc b/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc index cbb3e077..ca8a520 100644 --- a/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc +++ b/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
@@ -160,7 +160,7 @@ } scoped_refptr<gfx::NativePixmap> -GbmSurfaceFactory::CreateNativePixmapFromHandle( +GbmSurfaceFactory::CreateNativePixmapFromHandleInternal( gfx::AcceleratedWidget widget, gfx::Size size, gfx::BufferFormat format, @@ -176,7 +176,6 @@ } std::vector<gfx::NativePixmapPlane> planes; - for (const auto& plane : handle.planes) { planes.push_back(plane); } @@ -185,7 +184,44 @@ widget, size, format, std::move(scoped_fds), planes); if (!buffer) return nullptr; + return base::MakeRefCounted<GbmPixmap>(this, buffer); } +scoped_refptr<gfx::NativePixmap> +GbmSurfaceFactory::CreateNativePixmapFromHandle( + gfx::AcceleratedWidget widget, + gfx::Size size, + gfx::BufferFormat format, + const gfx::NativePixmapHandle& handle) { + // Query the external service (if available), whether it recognizes this + // NativePixmapHandle, and whether it can provide a corresponding NativePixmap + // backing it. If so, the handle is consumed. Otherwise, the handle remains + // valid and can be further importer by standard means. + if (!get_protected_native_pixmap_callback_.is_null()) { + auto protected_pixmap = get_protected_native_pixmap_callback_.Run(handle); + if (protected_pixmap) + return protected_pixmap; + } + + return CreateNativePixmapFromHandleInternal(widget, size, format, handle); +} + +scoped_refptr<gfx::NativePixmap> +GbmSurfaceFactory::CreateNativePixmapForProtectedBufferHandle( + gfx::AcceleratedWidget widget, + gfx::Size size, + gfx::BufferFormat format, + const gfx::NativePixmapHandle& handle) { + // Create a new NativePixmap without querying the external service for any + // existing mappings. + return CreateNativePixmapFromHandleInternal(widget, size, format, handle); +} + +void GbmSurfaceFactory::SetGetProtectedNativePixmapDelegate( + const GetProtectedNativePixmapCallback& + get_protected_native_pixmap_callback) { + get_protected_native_pixmap_callback_ = get_protected_native_pixmap_callback; +} + } // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/gbm_surface_factory.h b/ui/ozone/platform/drm/gpu/gbm_surface_factory.h index ce1abfdc..3955c1c1 100644 --- a/ui/ozone/platform/drm/gpu/gbm_surface_factory.h +++ b/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
@@ -50,8 +50,22 @@ gfx::Size size, gfx::BufferFormat format, const gfx::NativePixmapHandle& handle) override; + void SetGetProtectedNativePixmapDelegate( + const GetProtectedNativePixmapCallback& + get_protected_native_pixmap_callback) override; + scoped_refptr<gfx::NativePixmap> CreateNativePixmapForProtectedBufferHandle( + gfx::AcceleratedWidget widget, + gfx::Size size, + gfx::BufferFormat format, + const gfx::NativePixmapHandle& handle) override; private: + scoped_refptr<gfx::NativePixmap> CreateNativePixmapFromHandleInternal( + gfx::AcceleratedWidget widget, + gfx::Size size, + gfx::BufferFormat format, + const gfx::NativePixmapHandle& handle); + std::unique_ptr<GLOzone> egl_implementation_; std::unique_ptr<GLOzone> osmesa_implementation_; @@ -61,6 +75,8 @@ std::map<gfx::AcceleratedWidget, GbmSurfaceless*> widget_to_surface_map_; + GetProtectedNativePixmapCallback get_protected_native_pixmap_callback_; + DISALLOW_COPY_AND_ASSIGN(GbmSurfaceFactory); };
diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc index dcfcf54..4ba3929 100644 --- a/ui/ozone/platform/headless/headless_surface_factory.cc +++ b/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -83,6 +83,7 @@ uint64_t GetDmaBufModifier(size_t plane) const override { return 0; } gfx::BufferFormat GetBufferFormat() const override { return format_; } gfx::Size GetBufferSize() const override { return gfx::Size(); } + uint32_t GetUniqueId() const override { return 0; } bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int plane_z_order, gfx::OverlayTransform plane_transform,
diff --git a/ui/ozone/public/surface_factory_ozone.cc b/ui/ozone/public/surface_factory_ozone.cc index 527aa29..c7c2dc3 100644 --- a/ui/ozone/public/surface_factory_ozone.cc +++ b/ui/ozone/public/surface_factory_ozone.cc
@@ -52,4 +52,17 @@ return nullptr; } +scoped_refptr<gfx::NativePixmap> +SurfaceFactoryOzone::CreateNativePixmapForProtectedBufferHandle( + gfx::AcceleratedWidget widget, + gfx::Size size, + gfx::BufferFormat format, + const gfx::NativePixmapHandle& handle) { + return nullptr; +} + +void SurfaceFactoryOzone::SetGetProtectedNativePixmapDelegate( + const GetProtectedNativePixmapCallback& + get_protected_native_pixmap_callback) {} + } // namespace ui
diff --git a/ui/ozone/public/surface_factory_ozone.h b/ui/ozone/public/surface_factory_ozone.h index 6e7726a..1b7ba91 100644 --- a/ui/ozone/public/surface_factory_ozone.h +++ b/ui/ozone/public/surface_factory_ozone.h
@@ -99,6 +99,38 @@ gfx::BufferFormat format, const gfx::NativePixmapHandle& handle); + // A temporary solution that allows protected NativePixmap management to be + // handled outside the Ozone platform (crbug.com/771863). + // The current implementation uses dummy NativePixmaps as transparent handles + // to separate NativePixmaps with actual contents. This method takes + // a NativePixmapHandle to such a dummy pixmap, and creates a NativePixmap + // instance for it. + virtual scoped_refptr<gfx::NativePixmap> + CreateNativePixmapForProtectedBufferHandle( + gfx::AcceleratedWidget widget, + gfx::Size size, + gfx::BufferFormat format, + const gfx::NativePixmapHandle& handle); + + // This callback can be used by implementations of this interface to query + // for a NativePixmap for the given NativePixmapHandle, instead of importing + // it via standard means. This happens if an external service is maintaining + // a separate mapping of NativePixmapHandles to NativePixmaps. + // If this callback returns non-nullptr, the returned NativePixmap should + // be used instead of the NativePixmap that would have been produced by the + // standard, implementation-specific NativePixmapHandle import mechanism. + using GetProtectedNativePixmapCallback = + base::Callback<scoped_refptr<gfx::NativePixmap>( + const gfx::NativePixmapHandle&)>; + // Called by an external service to set the GetProtectedNativePixmapCallback, + // to be used by the implementation when importing NativePixmapHandles. + // TODO(posciak): crbug.com/778555, move this to platform-specific + // implementation(s) and make protected pixmap handling transparent to the + // clients of this interface, removing the need for this callback. + virtual void SetGetProtectedNativePixmapDelegate( + const GetProtectedNativePixmapCallback& + get_protected_native_pixmap_callback); + protected: SurfaceFactoryOzone(); virtual ~SurfaceFactoryOzone();
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.h b/ui/views/controls/scrollbar/cocoa_scroll_bar.h index 91de43a2..a78bc84 100644 --- a/ui/views/controls/scrollbar/cocoa_scroll_bar.h +++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.h
@@ -51,6 +51,9 @@ // Returns the scroller style. NSScrollerStyle GetScrollerStyle() const { return scroller_style_; } + // Returns the thickness of the scrollbar. + int ScrollbarThickness() const; + // Returns true if the opacity is 0.0. bool IsScrollbarFullyHidden() const; @@ -85,9 +88,6 @@ // and is not in a hover/pressed state. void ResetOverlayScrollbar(); - // Returns the thickness of the scrollbar. - int ScrollbarThickness() const; - // Sets the scrolltrack's visibility and then repaints it. void SetScrolltrackVisible(bool visible);
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm index 6cab3ad..b5364da3 100644 --- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm +++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -31,16 +31,12 @@ const int kScrollbarThickness = 12; const int kExpandedScrollbarThickness = 16; -// The thickness of the scrollbar thumb. -const int kScrollbarThumbThickness = 8; - // The width of the scroller track border. const int kScrollerTrackBorderWidth = 1; -// The amount the thumb is inset from both the ends and the sides of the normal -// and expanded tracks. +// The amount the thumb is inset from the ends and the inside edge of track +// border. const int kScrollbarThumbInset = 2; -const int kExpandedScrollbarThumbInset = 3; // Scrollbar thumb colors. const SkColor kScrollerDefaultThumbColor = SkColorSetARGB(0x38, 0, 0, 0); @@ -82,16 +78,14 @@ void OnMouseExited(const ui::MouseEvent& event) override; private: - // Converts scroll_bar() into a CocoaScrollBar object and returns it. - CocoaScrollBar* cocoa_scroll_bar() { - return static_cast<CocoaScrollBar*>(scroll_bar()); - } + // The CocoaScrollBar that owns us. + CocoaScrollBar* cocoa_scroll_bar_; // weak. DISALLOW_COPY_AND_ASSIGN(CocoaScrollBarThumb); }; CocoaScrollBarThumb::CocoaScrollBarThumb(CocoaScrollBar* scroll_bar) - : BaseScrollBarThumb(scroll_bar) { + : BaseScrollBarThumb(scroll_bar), cocoa_scroll_bar_(scroll_bar) { DCHECK(scroll_bar); // This is necessary, otherwise the thumb will be rendered below the views if @@ -111,30 +105,37 @@ } gfx::Size CocoaScrollBarThumb::CalculatePreferredSize() const { - return gfx::Size(kScrollbarThumbThickness, kScrollbarThumbThickness); + int thickness = cocoa_scroll_bar_->ScrollbarThickness(); + return gfx::Size(thickness, thickness); } void CocoaScrollBarThumb::OnPaint(gfx::Canvas* canvas) { SkColor thumb_color = kScrollerDefaultThumbColor; - if (cocoa_scroll_bar()->GetScrollerStyle() == NSScrollerStyleOverlay || - IsStateHovered() || - IsStatePressed()) { + if (cocoa_scroll_bar_->GetScrollerStyle() == NSScrollerStyleOverlay || + IsStateHovered() || IsStatePressed()) { thumb_color = kScrollerHoverThumbColor; } - gfx::Rect local_bounds(GetLocalBounds()); + gfx::Rect bounds(GetLocalBounds()); + bounds.Inset(kScrollbarThumbInset, kScrollbarThumbInset); + if (IsHorizontal()) + bounds.Inset(0, kScrollerTrackBorderWidth, 0, 0); + else if (base::i18n::IsRTL()) + bounds.Inset(0, 0, kScrollerTrackBorderWidth, 0); + else + bounds.Inset(kScrollerTrackBorderWidth, 0, 0, 0); + cc::PaintFlags flags; flags.setAntiAlias(true); flags.setStyle(cc::PaintFlags::kFill_Style); flags.setColor(thumb_color); - const SkScalar radius = - std::min(local_bounds.width(), local_bounds.height()); - canvas->DrawRoundRect(local_bounds, radius, flags); + const SkScalar radius = std::min(bounds.width(), bounds.height()); + canvas->DrawRoundRect(bounds, radius, flags); } bool CocoaScrollBarThumb::OnMousePressed(const ui::MouseEvent& event) { // Ignore the mouse press if the scrollbar is hidden. - if (cocoa_scroll_bar()->IsScrollbarFullyHidden()) + if (cocoa_scroll_bar_->IsScrollbarFullyHidden()) return false; return BaseScrollBarThumb::OnMousePressed(event); @@ -191,19 +192,7 @@ // CocoaScrollBar, BaseScrollBar: gfx::Rect CocoaScrollBar::GetTrackBounds() const { - gfx::Rect local_bounds(GetLocalBounds()); - - int inset = kScrollbarThumbInset; - if (is_expanded_) { - inset = thickness_animation_.CurrentValueBetween( - kScrollbarThumbInset, kExpandedScrollbarThumbInset); - } - local_bounds.Inset(inset, inset); - - gfx::Size track_size = local_bounds.size(); - track_size.SetToMax(GetThumb()->GetPreferredSize()); - local_bounds.set_size(track_size); - return local_bounds; + return GetLocalBounds(); } ////////////////////////////////////////////////////////////////// @@ -448,6 +437,14 @@ ////////////////////////////////////////////////////////////////// // CocoaScrollBar, public: +int CocoaScrollBar::ScrollbarThickness() const { + if (scroller_style_ == NSScrollerStyleLegacy) + return kScrollbarThickness; + + return thickness_animation_.CurrentValueBetween(kScrollbarThickness, + kExpandedScrollbarThickness); +} + bool CocoaScrollBar::IsScrollbarFullyHidden() const { return layer()->opacity() == 0.0f; } @@ -521,14 +518,6 @@ } } -int CocoaScrollBar::ScrollbarThickness() const { - if (scroller_style_ == NSScrollerStyleLegacy) - return kScrollbarThickness; - - return thickness_animation_.CurrentValueBetween(kScrollbarThickness, - kExpandedScrollbarThickness); -} - void CocoaScrollBar::SetScrolltrackVisible(bool visible) { has_scrolltrack_ = visible; SchedulePaint();