diff --git a/DEPS b/DEPS index 8da860e..9f81754 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'b2cd1d7b442b689ff74409029defbf505c044b2c', + 'skia_revision': '98829b979119297bd9dbbe9313ba98ea0b3289af', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'b6bf2cf7592692af6f230e9fe6d4438bb26b6d55', + 'v8_revision': '1e96ba3f4ede6cceee6146f78d558c4b34f6b2ee', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '03de88464cc818ac4353de3e7ec49b98166bcdc5', + 'pdfium_revision': '5c1673db6deae2e1858c4ffc3b3a0b79901dd827', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -354,7 +354,7 @@ }, 'ios': { 'src/ios/third_party/earl_grey/src': - Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '625b2b7cdaf9371ae2b001d6cdc23b1790d41cd8', + Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'c5c89d810a8e76547ed0506e85c1a80f3a10bc48', 'src/ios/third_party/fishhook/src': Var('chromium_git') + '/external/github.com/facebook/fishhook.git' + '@' + 'd172d5247aa590c25d0b1885448bae76036ea22c',
diff --git a/ash/common/BUILD.gn b/ash/common/BUILD.gn index 94b8211..e5c535f1 100644 --- a/ash/common/BUILD.gn +++ b/ash/common/BUILD.gn
@@ -8,6 +8,7 @@ testonly = true sources = [ "accelerators/accelerator_table_unittest.cc", + "drag_drop/drag_image_view_unittest.cc", "system/chromeos/audio/tray_audio_unittest.cc", "system/chromeos/brightness/tray_brightness_unittest.cc", "system/chromeos/network/vpn_list_unittest.cc",
diff --git a/ash/common/drag_drop/drag_image_view.cc b/ash/common/drag_drop/drag_image_view.cc index 5c763c3..2f9a9ff 100644 --- a/ash/common/drag_drop/drag_image_view.cc +++ b/ash/common/drag_drop/drag_image_view.cc
@@ -58,12 +58,13 @@ } void DragImageView::SetBoundsInScreen(const gfx::Rect& bounds) { + drag_image_size_ = bounds.size(); widget_->SetBounds(bounds); - widget_size_ = bounds.size(); } void DragImageView::SetScreenPosition(const gfx::Point& position) { - widget_->SetBounds(gfx::Rect(position, widget_size_)); + widget_->SetBounds( + gfx::Rect(position, widget_->GetWindowBoundsInScreen().size())); } gfx::Rect DragImageView::GetBoundsInScreen() const { @@ -82,6 +83,12 @@ void DragImageView::SetTouchDragOperationHintOff() { // Simply set the drag type to non-touch so that no hint is drawn. drag_event_source_ = ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE; + + // This disables the drag hint image. This should reduce the widget size if + // the drag image is smaller than the drag hint image, so we set new bounds. + gfx::Rect new_bounds = GetBoundsInScreen(); + new_bounds.set_size(drag_image_size_); + SetBoundsInScreen(new_bounds); SchedulePaint(); } @@ -110,32 +117,30 @@ if (GetImage().isNull()) return; - // |widget_size_| is in DIP. ImageSkia::size() also returns the size in DIP. - if (GetImage().size() == widget_size_) { + // |drag_image_size_| is in DIP. + // ImageSkia::size() also returns the size in DIP. + if (GetImage().size() == drag_image_size_) { canvas->DrawImageInt(GetImage(), 0, 0); } else { WmWindow* window = WmLookup::Get()->GetWindowForWidget(widget_.get()); const float device_scale = window->GetDisplayNearestWindow().device_scale_factor(); // The drag image already has device scale factor applied. But - // |widget_size_| is in DIP units. - gfx::Size scaled_widget_size = - gfx::ScaleToRoundedSize(widget_size_, device_scale); + // |drag_image_size_| is in DIP units. + gfx::Size drag_image_size_pixels = + gfx::ScaleToRoundedSize(drag_image_size_, device_scale); gfx::ImageSkiaRep image_rep = GetImage().GetRepresentation(device_scale); if (image_rep.is_null()) return; SkBitmap scaled = skia::ImageOperations::Resize( image_rep.sk_bitmap(), skia::ImageOperations::RESIZE_LANCZOS3, - scaled_widget_size.width(), scaled_widget_size.height()); + drag_image_size_pixels.width(), drag_image_size_pixels.height()); gfx::ImageSkia image_skia(gfx::ImageSkiaRep(scaled, device_scale)); canvas->DrawImageInt(image_skia, 0, 0); } - if (drag_event_source_ != ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH) - return; - gfx::Image* drag_hint = DragHint(); - if (drag_hint->IsEmpty()) + if (!ShouldDrawDragHint() || drag_hint->IsEmpty()) return; // Make sure drag hint image is positioned within the widget. @@ -143,7 +148,9 @@ gfx::Point drag_hint_position = touch_drag_operation_indicator_position_; drag_hint_position.Offset(-drag_hint_size.width() / 2, 0); gfx::Rect drag_hint_bounds(drag_hint_position, drag_hint_size); - drag_hint_bounds.AdjustToFit(gfx::Rect(widget_size_)); + + gfx::Size widget_size = widget_->GetWindowBoundsInScreen().size(); + drag_hint_bounds.AdjustToFit(gfx::Rect(widget_size)); // Draw image. canvas->DrawImageInt(*(drag_hint->ToImageSkia()), drag_hint_bounds.x(), @@ -168,21 +175,34 @@ return drag_hint; } +bool DragImageView::ShouldDrawDragHint() const { + return drag_event_source_ == ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH; +} + +gfx::Size DragImageView::GetMinimumSize() const { + gfx::Size minimum_size = drag_image_size_; + if (ShouldDrawDragHint()) + minimum_size.SetToMax(DragHint()->Size()); + return minimum_size; +} + void DragImageView::Layout() { View::Layout(); + // Only consider resizing the widget for the drag hint image if we are in a + // touch initiated drag. gfx::Image* drag_hint = DragHint(); - if (drag_hint->IsEmpty()) + if (!ShouldDrawDragHint() || drag_hint->IsEmpty()) return; gfx::Size drag_hint_size = drag_hint->Size(); // Enlarge widget if required to fit the drag hint image. - if (drag_hint_size.width() > widget_size_.width() || - drag_hint_size.height() > widget_size_.height()) { - gfx::Size new_widget_size = widget_size_; - new_widget_size.SetToMax(drag_hint_size); - widget_->SetSize(new_widget_size); + gfx::Size widget_size = widget_->GetWindowBoundsInScreen().size(); + if (drag_hint_size.width() > widget_size.width() || + drag_hint_size.height() > widget_size.height()) { + widget_size.SetToMax(drag_hint_size); + widget_->SetSize(widget_size); } }
diff --git a/ash/common/drag_drop/drag_image_view.h b/ash/common/drag_drop/drag_image_view.h index 63b972e..de6e4d5 100644 --- a/ash/common/drag_drop/drag_image_view.h +++ b/ash/common/drag_drop/drag_image_view.h
@@ -7,6 +7,7 @@ #include <memory> +#include "ash/ash_export.h" #include "base/macros.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/gfx/geometry/point.h" @@ -29,7 +30,7 @@ // does this by creating a widget and setting the content as the given view. The // caller can then use this object to freely move / drag it around on the // desktop in screen coordinates. -class DragImageView : public views::ImageView { +class ASH_EXPORT DragImageView : public views::ImageView { public: // |root_window| is the root window on which to create the drag image widget. // |source| is the event source that started this drag drop operation (touch @@ -67,8 +68,12 @@ // Sets the |opacity| of the image view between 0.0 and 1.0. void SetOpacity(float opacity); + gfx::Size GetMinimumSize() const override; + private: gfx::Image* DragHint() const; + // Drag hint images are only drawn when the input source is touch. + bool ShouldDrawDragHint() const; // Overridden from views::ImageView. void OnPaint(gfx::Canvas* canvas) override; @@ -77,7 +82,12 @@ void Layout() override; std::unique_ptr<views::Widget> widget_; - gfx::Size widget_size_; + + // Save the requested drag image size. We may need to display a drag hint + // image, which potentially expands |widget_|'s size. That drag hint image + // may be disabled (e.g. during the drag cancel animation). In that case, + // we need to know the originally requested size to render the drag image. + gfx::Size drag_image_size_; ui::DragDropTypes::DragEventSource drag_event_source_;
diff --git a/ash/common/drag_drop/drag_image_view_unittest.cc b/ash/common/drag_drop/drag_image_view_unittest.cc new file mode 100644 index 0000000..e74d1bc --- /dev/null +++ b/ash/common/drag_drop/drag_image_view_unittest.cc
@@ -0,0 +1,77 @@ +// 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 "ash/common/drag_drop/drag_image_view.h" + +#include "ash/common/test/ash_test.h" +#include "ui/base/dragdrop/drag_drop_types.h" + +namespace ash { +namespace test { + +using DragDropImageTest = AshTest; + +TEST_F(DragDropImageTest, SetBoundsConsidersDragHintForTouch) { + std::unique_ptr<WindowOwner> window_owner(CreateTestWindow()); + DragImageView drag_image_view( + window_owner->window(), + ui::DragDropTypes::DragEventSource::DRAG_EVENT_SOURCE_TOUCH); + + gfx::Size minimum_size = drag_image_view.GetMinimumSize(); + gfx::Point new_pos(5, 5); + + if (!minimum_size.IsEmpty()) { + // Expect that the view is at least the size of the drag hint image. + gfx::Rect small_bounds(0, 0, 1, 1); + drag_image_view.SetBoundsInScreen(small_bounds); + EXPECT_EQ(gfx::Rect(minimum_size), drag_image_view.GetBoundsInScreen()); + + // Expect that we can change the position without affecting the bounds. + drag_image_view.SetScreenPosition(new_pos); + EXPECT_EQ(gfx::Rect(new_pos, minimum_size), + drag_image_view.GetBoundsInScreen()); + } + + // Expect that we can resize the view normally. + gfx::Rect large_bounds(0, 0, minimum_size.width() + 1, + minimum_size.height() + 1); + drag_image_view.SetBoundsInScreen(large_bounds); + EXPECT_EQ(large_bounds, drag_image_view.GetBoundsInScreen()); + // Expect that we can change the position without affecting the bounds. + drag_image_view.SetScreenPosition(new_pos); + EXPECT_EQ(gfx::Rect(new_pos, large_bounds.size()), + drag_image_view.GetBoundsInScreen()); +} + +TEST_F(DragDropImageTest, SetBoundsIgnoresDragHintForMouse) { + std::unique_ptr<WindowOwner> window_owner(CreateTestWindow()); + DragImageView drag_image_view( + window_owner->window(), + ui::DragDropTypes::DragEventSource::DRAG_EVENT_SOURCE_MOUSE); + + // Expect no drag hint image. + gfx::Rect small_bounds(0, 0, 1, 1); + drag_image_view.SetBoundsInScreen(small_bounds); + EXPECT_EQ(small_bounds, drag_image_view.GetBoundsInScreen()); + EXPECT_EQ(drag_image_view.GetMinimumSize(), + drag_image_view.GetBoundsInScreen().size()); + + gfx::Point new_pos(5, 5); + // Expect that we can change the position without affecting the bounds. + drag_image_view.SetScreenPosition(new_pos); + EXPECT_EQ(gfx::Rect(new_pos, small_bounds.size()), + drag_image_view.GetBoundsInScreen()); + + // Expect that we can resize the view. + gfx::Rect large_bounds(0, 0, 100, 100); + drag_image_view.SetBoundsInScreen(large_bounds); + EXPECT_EQ(large_bounds, drag_image_view.GetBoundsInScreen()); + // Expect that we can change the position without affecting the bounds. + drag_image_view.SetScreenPosition(new_pos); + EXPECT_EQ(gfx::Rect(new_pos, large_bounds.size()), + drag_image_view.GetBoundsInScreen()); +} + +} // namespace test +} // namespace ash
diff --git a/base/BUILD.gn b/base/BUILD.gn index fa5e369d..7f46e71 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -149,6 +149,8 @@ "allocator/allocator_check.h", "allocator/allocator_extension.cc", "allocator/allocator_extension.h", + "allocator/allocator_interception_mac.h", + "allocator/allocator_interception_mac.mm", "allocator/allocator_shim.h", "allocator/oom.h", "android/animation_frame_time_histogram.cc",
diff --git a/base/allocator/allocator_interception_mac.h b/base/allocator/allocator_interception_mac.h new file mode 100644 index 0000000..87cbf489 --- /dev/null +++ b/base/allocator/allocator_interception_mac.h
@@ -0,0 +1,55 @@ +// 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 BASE_ALLOCATOR_ALLOCATOR_INTERCEPTION_MAC_H_ +#define BASE_ALLOCATOR_ALLOCATOR_INTERCEPTION_MAC_H_ + +#include <malloc/malloc.h> +#include <stddef.h> + +#include "third_party/apple_apsl/malloc.h" + +namespace base { +namespace allocator { + +typedef void* (*malloc_type)(struct _malloc_zone_t* zone, size_t size); +typedef void* (*calloc_type)(struct _malloc_zone_t* zone, + size_t num_items, + size_t size); +typedef void* (*valloc_type)(struct _malloc_zone_t* zone, size_t size); +typedef void (*free_type)(struct _malloc_zone_t* zone, void* ptr); +typedef void* (*realloc_type)(struct _malloc_zone_t* zone, + void* ptr, + size_t size); +typedef void* (*memalign_type)(struct _malloc_zone_t* zone, + size_t alignment, + size_t size); + +struct MallocZoneFunctions { + malloc_type malloc = nullptr; + calloc_type calloc = nullptr; + valloc_type valloc = nullptr; + free_type free = nullptr; + realloc_type realloc = nullptr; + memalign_type memalign = nullptr; +}; + +// Saves the function pointers currently used by |zone| into |functions|. +void StoreZoneFunctions(ChromeMallocZone* zone, MallocZoneFunctions* functions); + +// Updates the malloc zone to use the functions specified by |functions|. +void ReplaceZoneFunctions(ChromeMallocZone* zone, + const MallocZoneFunctions* functions); + +// Calls the original implementation of malloc/calloc prior to interception. +bool UncheckedMallocMac(size_t size, void** result); +bool UncheckedCallocMac(size_t num_items, size_t size, void** result); + +// Intercepts calls to default and purgeable malloc zones. Intercepts Core +// Foundation and Objective-C allocations. +void InterceptAllocationsMac(); +} // namespace allocator +} // namespace base + +#endif // BASE_ALLOCATOR_ALLOCATOR_INTERCEPTION_MAC_H_
diff --git a/base/allocator/allocator_interception_mac.mm b/base/allocator/allocator_interception_mac.mm new file mode 100644 index 0000000..941c5b4a --- /dev/null +++ b/base/allocator/allocator_interception_mac.mm
@@ -0,0 +1,471 @@ +// 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. + +// This file contains all the logic necessary to intercept allocations on +// macOS. "malloc zones" are an abstraction that allows the process to intercept +// all malloc-related functions. There is no good mechanism [short of +// interposition] to determine new malloc zones are added, so there's no clean +// mechanism to intercept all malloc zones. This file contains logic to +// intercept the default and purgeable zones, which always exist. A cursory +// review of Chrome seems to imply that non-default zones are almost never used. +// +// This file also contains logic to intercept Core Foundation and Objective-C +// allocations. The implementations forward to the default malloc zone, so the +// only reason to intercept these calls is to re-label OOM crashes with slightly +// more details. + +#include "base/allocator/allocator_interception_mac.h" + +#include <CoreFoundation/CoreFoundation.h> +#import <Foundation/Foundation.h> +#include <errno.h> +#include <mach/mach.h> +#include <mach/mach_vm.h> +#import <objc/runtime.h> +#include <stddef.h> + +#include <new> + +#include "base/logging.h" +#include "base/mac/mac_util.h" +#include "base/mac/mach_logging.h" +#include "base/process/memory.h" +#include "base/scoped_clear_errno.h" +#include "build/build_config.h" +#include "third_party/apple_apsl/CFBase.h" + +namespace base { +namespace allocator { + +namespace { + +bool g_oom_killer_enabled; + +#if !defined(ADDRESS_SANITIZER) + +// Starting with Mac OS X 10.7, the zone allocators set up by the system are +// read-only, to prevent them from being overwritten in an attack. However, +// blindly unprotecting and reprotecting the zone allocators fails with +// GuardMalloc because GuardMalloc sets up its zone allocator using a block of +// memory in its bss. Explicit saving/restoring of the protection is required. +// +// This function takes a pointer to a malloc zone, de-protects it if necessary, +// and returns (in the out parameters) a region of memory (if any) to be +// re-protected when modifications are complete. This approach assumes that +// there is no contention for the protection of this memory. +void DeprotectMallocZone(ChromeMallocZone* default_zone, + mach_vm_address_t* reprotection_start, + mach_vm_size_t* reprotection_length, + vm_prot_t* reprotection_value) { + mach_port_t unused; + *reprotection_start = reinterpret_cast<mach_vm_address_t>(default_zone); + struct vm_region_basic_info_64 info; + mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; + kern_return_t result = mach_vm_region( + mach_task_self(), reprotection_start, reprotection_length, + VM_REGION_BASIC_INFO_64, reinterpret_cast<vm_region_info_t>(&info), + &count, &unused); + MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_region"; + + // The kernel always returns a null object for VM_REGION_BASIC_INFO_64, but + // balance it with a deallocate in case this ever changes. See 10.9.2 + // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region. + mach_port_deallocate(mach_task_self(), unused); + + // Does the region fully enclose the zone pointers? Possibly unwarranted + // simplification used: using the size of a full version 8 malloc zone rather + // than the actual smaller size if the passed-in zone is not version 8. + CHECK(*reprotection_start <= + reinterpret_cast<mach_vm_address_t>(default_zone)); + mach_vm_size_t zone_offset = + reinterpret_cast<mach_vm_size_t>(default_zone) - + reinterpret_cast<mach_vm_size_t>(*reprotection_start); + CHECK(zone_offset + sizeof(ChromeMallocZone) <= *reprotection_length); + + if (info.protection & VM_PROT_WRITE) { + // No change needed; the zone is already writable. + *reprotection_start = 0; + *reprotection_length = 0; + *reprotection_value = VM_PROT_NONE; + } else { + *reprotection_value = info.protection; + result = mach_vm_protect(mach_task_self(), *reprotection_start, + *reprotection_length, false, + info.protection | VM_PROT_WRITE); + MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_protect"; + } +} + +MallocZoneFunctions g_old_zone; +MallocZoneFunctions g_old_purgeable_zone; + +void* oom_killer_malloc(struct _malloc_zone_t* zone, size_t size) { + void* result = g_old_zone.malloc(zone, size); + if (!result && size) + TerminateBecauseOutOfMemory(size); + return result; +} + +void* oom_killer_calloc(struct _malloc_zone_t* zone, + size_t num_items, + size_t size) { + void* result = g_old_zone.calloc(zone, num_items, size); + if (!result && num_items && size) + TerminateBecauseOutOfMemory(num_items * size); + return result; +} + +void* oom_killer_valloc(struct _malloc_zone_t* zone, size_t size) { + void* result = g_old_zone.valloc(zone, size); + if (!result && size) + TerminateBecauseOutOfMemory(size); + return result; +} + +void oom_killer_free(struct _malloc_zone_t* zone, void* ptr) { + g_old_zone.free(zone, ptr); +} + +void* oom_killer_realloc(struct _malloc_zone_t* zone, void* ptr, size_t size) { + void* result = g_old_zone.realloc(zone, ptr, size); + if (!result && size) + TerminateBecauseOutOfMemory(size); + return result; +} + +void* oom_killer_memalign(struct _malloc_zone_t* zone, + size_t alignment, + size_t size) { + void* result = g_old_zone.memalign(zone, alignment, size); + // Only die if posix_memalign would have returned ENOMEM, since there are + // other reasons why NULL might be returned (see + // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). + if (!result && size && alignment >= sizeof(void*) && + (alignment & (alignment - 1)) == 0) { + TerminateBecauseOutOfMemory(size); + } + return result; +} + +void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, size_t size) { + void* result = g_old_purgeable_zone.malloc(zone, size); + if (!result && size) + TerminateBecauseOutOfMemory(size); + return result; +} + +void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, + size_t num_items, + size_t size) { + void* result = g_old_purgeable_zone.calloc(zone, num_items, size); + if (!result && num_items && size) + TerminateBecauseOutOfMemory(num_items * size); + return result; +} + +void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, size_t size) { + void* result = g_old_purgeable_zone.valloc(zone, size); + if (!result && size) + TerminateBecauseOutOfMemory(size); + return result; +} + +void oom_killer_free_purgeable(struct _malloc_zone_t* zone, void* ptr) { + g_old_purgeable_zone.free(zone, ptr); +} + +void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, + void* ptr, + size_t size) { + void* result = g_old_purgeable_zone.realloc(zone, ptr, size); + if (!result && size) + TerminateBecauseOutOfMemory(size); + return result; +} + +void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, + size_t alignment, + size_t size) { + void* result = g_old_purgeable_zone.memalign(zone, alignment, size); + // Only die if posix_memalign would have returned ENOMEM, since there are + // other reasons why NULL might be returned (see + // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). + if (!result && size && alignment >= sizeof(void*) && + (alignment & (alignment - 1)) == 0) { + TerminateBecauseOutOfMemory(size); + } + return result; +} + +#endif // !defined(ADDRESS_SANITIZER) + +// === C++ operator new === + +void oom_killer_new() { + TerminateBecauseOutOfMemory(0); +} + +#if !defined(ADDRESS_SANITIZER) + +// === Core Foundation CFAllocators === + +bool CanGetContextForCFAllocator() { + return !base::mac::IsOSLaterThan10_12_DontCallThis(); +} + +CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { + ChromeCFAllocatorLions* our_allocator = const_cast<ChromeCFAllocatorLions*>( + reinterpret_cast<const ChromeCFAllocatorLions*>(allocator)); + return &our_allocator->_context; +} + +CFAllocatorAllocateCallBack g_old_cfallocator_system_default; +CFAllocatorAllocateCallBack g_old_cfallocator_malloc; +CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; + +void* oom_killer_cfallocator_system_default(CFIndex alloc_size, + CFOptionFlags hint, + void* info) { + void* result = g_old_cfallocator_system_default(alloc_size, hint, info); + if (!result) + TerminateBecauseOutOfMemory(alloc_size); + return result; +} + +void* oom_killer_cfallocator_malloc(CFIndex alloc_size, + CFOptionFlags hint, + void* info) { + void* result = g_old_cfallocator_malloc(alloc_size, hint, info); + if (!result) + TerminateBecauseOutOfMemory(alloc_size); + return result; +} + +void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, + CFOptionFlags hint, + void* info) { + void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); + if (!result) + TerminateBecauseOutOfMemory(alloc_size); + return result; +} + +#endif // !defined(ADDRESS_SANITIZER) + +// === Cocoa NSObject allocation === + +typedef id (*allocWithZone_t)(id, SEL, NSZone*); +allocWithZone_t g_old_allocWithZone; + +id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) { + id result = g_old_allocWithZone(self, _cmd, zone); + if (!result) + TerminateBecauseOutOfMemory(0); + return result; +} + +} // namespace + +bool UncheckedMallocMac(size_t size, void** result) { +#if defined(ADDRESS_SANITIZER) + *result = malloc(size); +#else + if (g_old_zone.malloc) { + *result = g_old_zone.malloc(malloc_default_zone(), size); + } else { + *result = malloc(size); + } +#endif // defined(ADDRESS_SANITIZER) + + return *result != NULL; +} + +bool UncheckedCallocMac(size_t num_items, size_t size, void** result) { +#if defined(ADDRESS_SANITIZER) + *result = calloc(num_items, size); +#else + if (g_old_zone.calloc) { + *result = g_old_zone.calloc(malloc_default_zone(), num_items, size); + } else { + *result = calloc(num_items, size); + } +#endif // defined(ADDRESS_SANITIZER) + + return *result != NULL; +} + +void StoreZoneFunctions(ChromeMallocZone* zone, + MallocZoneFunctions* functions) { + functions->malloc = zone->malloc; + functions->calloc = zone->calloc; + functions->valloc = zone->valloc; + functions->free = zone->free; + functions->realloc = zone->realloc; + CHECK(functions->malloc && functions->calloc && functions->valloc && + functions->free && functions->realloc); + + if (zone->version >= 5) { + functions->memalign = zone->memalign; + CHECK(functions->memalign); + } +} + +void ReplaceZoneFunctions(ChromeMallocZone* zone, + const MallocZoneFunctions* functions) { + // Remove protection. + mach_vm_address_t reprotection_start = 0; + mach_vm_size_t reprotection_length = 0; + vm_prot_t reprotection_value = VM_PROT_NONE; + DeprotectMallocZone(zone, &reprotection_start, &reprotection_length, + &reprotection_value); + + zone->malloc = functions->malloc; + zone->calloc = functions->calloc; + zone->valloc = functions->valloc; + zone->free = functions->free; + zone->realloc = functions->realloc; + if (zone->version >= 5) { + zone->memalign = functions->memalign; + } + + // Restore protection if it was active. + if (reprotection_start) { + kern_return_t result = + mach_vm_protect(mach_task_self(), reprotection_start, + reprotection_length, false, reprotection_value); + MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_protect"; + } +} + +void InterceptAllocationsMac() { + if (g_oom_killer_enabled) + return; + + g_oom_killer_enabled = true; + +// === C malloc/calloc/valloc/realloc/posix_memalign === + +// This approach is not perfect, as requests for amounts of memory larger than +// MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will +// still fail with a NULL rather than dying (see +// http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). +// Unfortunately, it's the best we can do. Also note that this does not affect +// allocations from non-default zones. + +#if !defined(ADDRESS_SANITIZER) + // Don't do anything special on OOM for the malloc zones replaced by + // AddressSanitizer, as modifying or protecting them may not work correctly. + ChromeMallocZone* default_zone = + reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); + StoreZoneFunctions(default_zone, &g_old_zone); + MallocZoneFunctions new_functions; + new_functions.malloc = oom_killer_malloc; + new_functions.calloc = oom_killer_calloc; + new_functions.valloc = oom_killer_valloc; + new_functions.free = oom_killer_free; + new_functions.realloc = oom_killer_realloc; + new_functions.memalign = oom_killer_memalign; + ReplaceZoneFunctions(default_zone, &new_functions); + + ChromeMallocZone* purgeable_zone = + reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); + if (purgeable_zone) { + StoreZoneFunctions(purgeable_zone, &g_old_purgeable_zone); + MallocZoneFunctions new_functions; + new_functions.malloc = oom_killer_malloc_purgeable; + new_functions.calloc = oom_killer_calloc_purgeable; + new_functions.valloc = oom_killer_valloc_purgeable; + new_functions.free = oom_killer_free_purgeable; + new_functions.realloc = oom_killer_realloc_purgeable; + new_functions.memalign = oom_killer_memalign_purgeable; + ReplaceZoneFunctions(purgeable_zone, &new_functions); + } +#endif + + // === C malloc_zone_batch_malloc === + + // batch_malloc is omitted because the default malloc zone's implementation + // only supports batch_malloc for "tiny" allocations from the free list. It + // will fail for allocations larger than "tiny", and will only allocate as + // many blocks as it's able to from the free list. These factors mean that it + // can return less than the requested memory even in a non-out-of-memory + // situation. There's no good way to detect whether a batch_malloc failure is + // due to these other factors, or due to genuine memory or address space + // exhaustion. The fact that it only allocates space from the "tiny" free list + // means that it's likely that a failure will not be due to memory exhaustion. + // Similarly, these constraints on batch_malloc mean that callers must always + // be expecting to receive less memory than was requested, even in situations + // where memory pressure is not a concern. Finally, the only public interface + // to batch_malloc is malloc_zone_batch_malloc, which is specific to the + // system's malloc implementation. It's unlikely that anyone's even heard of + // it. + + // === C++ operator new === + + // Yes, operator new does call through to malloc, but this will catch failures + // that our imperfect handling of malloc cannot. + + std::set_new_handler(oom_killer_new); + +#ifndef ADDRESS_SANITIZER + // === Core Foundation CFAllocators === + + // This will not catch allocation done by custom allocators, but will catch + // all allocation done by system-provided ones. + + CHECK(!g_old_cfallocator_system_default && !g_old_cfallocator_malloc && + !g_old_cfallocator_malloc_zone) + << "Old allocators unexpectedly non-null"; + + bool cf_allocator_internals_known = CanGetContextForCFAllocator(); + + if (cf_allocator_internals_known) { + CFAllocatorContext* context = + ContextForCFAllocator(kCFAllocatorSystemDefault); + CHECK(context) << "Failed to get context for kCFAllocatorSystemDefault."; + g_old_cfallocator_system_default = context->allocate; + CHECK(g_old_cfallocator_system_default) + << "Failed to get kCFAllocatorSystemDefault allocation function."; + context->allocate = oom_killer_cfallocator_system_default; + + context = ContextForCFAllocator(kCFAllocatorMalloc); + CHECK(context) << "Failed to get context for kCFAllocatorMalloc."; + g_old_cfallocator_malloc = context->allocate; + CHECK(g_old_cfallocator_malloc) + << "Failed to get kCFAllocatorMalloc allocation function."; + context->allocate = oom_killer_cfallocator_malloc; + + context = ContextForCFAllocator(kCFAllocatorMallocZone); + CHECK(context) << "Failed to get context for kCFAllocatorMallocZone."; + g_old_cfallocator_malloc_zone = context->allocate; + CHECK(g_old_cfallocator_malloc_zone) + << "Failed to get kCFAllocatorMallocZone allocation function."; + context->allocate = oom_killer_cfallocator_malloc_zone; + } else { + DLOG(WARNING) << "Internals of CFAllocator not known; out-of-memory " + "failures via CFAllocator will not result in termination. " + "http://crbug.com/45650"; + } +#endif + + // === Cocoa NSObject allocation === + + // Note that both +[NSObject new] and +[NSObject alloc] call through to + // +[NSObject allocWithZone:]. + + CHECK(!g_old_allocWithZone) << "Old allocator unexpectedly non-null"; + + Class nsobject_class = [NSObject class]; + Method orig_method = + class_getClassMethod(nsobject_class, @selector(allocWithZone:)); + g_old_allocWithZone = + reinterpret_cast<allocWithZone_t>(method_getImplementation(orig_method)); + CHECK(g_old_allocWithZone) + << "Failed to get allocWithZone allocation function."; + method_setImplementation(orig_method, + reinterpret_cast<IMP>(oom_killer_allocWithZone)); +} + +} // namespace allocator +} // namespace base
diff --git a/base/process/memory_mac.mm b/base/process/memory_mac.mm index 4c1b120..155004dc 100644 --- a/base/process/memory_mac.mm +++ b/base/process/memory_mac.mm
@@ -4,25 +4,8 @@ #include "base/process/memory.h" -#include <CoreFoundation/CoreFoundation.h> -#import <Foundation/Foundation.h> -#include <errno.h> -#include <mach/mach.h> -#include <mach/mach_vm.h> -#include <malloc/malloc.h> -#import <objc/runtime.h> -#include <stddef.h> - -#include <new> - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/mac/mac_util.h" -#include "base/mac/mach_logging.h" -#include "base/scoped_clear_errno.h" +#include "base/allocator/allocator_interception_mac.h" #include "build/build_config.h" -#include "third_party/apple_apsl/CFBase.h" -#include "third_party/apple_apsl/malloc.h" namespace base { @@ -32,521 +15,16 @@ #endif } -// ------------------------------------------------------------------------ - -namespace { - -bool g_oom_killer_enabled; - -#if !defined(ADDRESS_SANITIZER) - -// Starting with Mac OS X 10.7, the zone allocators set up by the system are -// read-only, to prevent them from being overwritten in an attack. However, -// blindly unprotecting and reprotecting the zone allocators fails with -// GuardMalloc because GuardMalloc sets up its zone allocator using a block of -// memory in its bss. Explicit saving/restoring of the protection is required. -// -// This function takes a pointer to a malloc zone, de-protects it if necessary, -// and returns (in the out parameters) a region of memory (if any) to be -// re-protected when modifications are complete. This approach assumes that -// there is no contention for the protection of this memory. -void DeprotectMallocZone(ChromeMallocZone* default_zone, - mach_vm_address_t* reprotection_start, - mach_vm_size_t* reprotection_length, - vm_prot_t* reprotection_value) { - mach_port_t unused; - *reprotection_start = reinterpret_cast<mach_vm_address_t>(default_zone); - struct vm_region_basic_info_64 info; - mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; - kern_return_t result = - mach_vm_region(mach_task_self(), - reprotection_start, - reprotection_length, - VM_REGION_BASIC_INFO_64, - reinterpret_cast<vm_region_info_t>(&info), - &count, - &unused); - MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_region"; - - // The kernel always returns a null object for VM_REGION_BASIC_INFO_64, but - // balance it with a deallocate in case this ever changes. See 10.9.2 - // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region. - mach_port_deallocate(mach_task_self(), unused); - - // Does the region fully enclose the zone pointers? Possibly unwarranted - // simplification used: using the size of a full version 8 malloc zone rather - // than the actual smaller size if the passed-in zone is not version 8. - CHECK(*reprotection_start <= - reinterpret_cast<mach_vm_address_t>(default_zone)); - mach_vm_size_t zone_offset = reinterpret_cast<mach_vm_size_t>(default_zone) - - reinterpret_cast<mach_vm_size_t>(*reprotection_start); - CHECK(zone_offset + sizeof(ChromeMallocZone) <= *reprotection_length); - - if (info.protection & VM_PROT_WRITE) { - // No change needed; the zone is already writable. - *reprotection_start = 0; - *reprotection_length = 0; - *reprotection_value = VM_PROT_NONE; - } else { - *reprotection_value = info.protection; - result = mach_vm_protect(mach_task_self(), - *reprotection_start, - *reprotection_length, - false, - info.protection | VM_PROT_WRITE); - MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_protect"; - } -} - -// === C malloc/calloc/valloc/realloc/posix_memalign === - -typedef void* (*malloc_type)(struct _malloc_zone_t* zone, - size_t size); -typedef void* (*calloc_type)(struct _malloc_zone_t* zone, - size_t num_items, - size_t size); -typedef void* (*valloc_type)(struct _malloc_zone_t* zone, - size_t size); -typedef void (*free_type)(struct _malloc_zone_t* zone, - void* ptr); -typedef void* (*realloc_type)(struct _malloc_zone_t* zone, - void* ptr, - size_t size); -typedef void* (*memalign_type)(struct _malloc_zone_t* zone, - size_t alignment, - size_t size); - -malloc_type g_old_malloc; -calloc_type g_old_calloc; -valloc_type g_old_valloc; -free_type g_old_free; -realloc_type g_old_realloc; -memalign_type g_old_memalign; - -malloc_type g_old_malloc_purgeable; -calloc_type g_old_calloc_purgeable; -valloc_type g_old_valloc_purgeable; -free_type g_old_free_purgeable; -realloc_type g_old_realloc_purgeable; -memalign_type g_old_memalign_purgeable; - -void* oom_killer_malloc(struct _malloc_zone_t* zone, - size_t size) { - void* result = g_old_malloc(zone, size); - if (!result && size) - TerminateBecauseOutOfMemory(size); - return result; -} - -void* oom_killer_calloc(struct _malloc_zone_t* zone, - size_t num_items, - size_t size) { - void* result = g_old_calloc(zone, num_items, size); - if (!result && num_items && size) - TerminateBecauseOutOfMemory(num_items * size); - return result; -} - -void* oom_killer_valloc(struct _malloc_zone_t* zone, - size_t size) { - void* result = g_old_valloc(zone, size); - if (!result && size) - TerminateBecauseOutOfMemory(size); - return result; -} - -void oom_killer_free(struct _malloc_zone_t* zone, - void* ptr) { - g_old_free(zone, ptr); -} - -void* oom_killer_realloc(struct _malloc_zone_t* zone, - void* ptr, - size_t size) { - void* result = g_old_realloc(zone, ptr, size); - if (!result && size) - TerminateBecauseOutOfMemory(size); - return result; -} - -void* oom_killer_memalign(struct _malloc_zone_t* zone, - size_t alignment, - size_t size) { - void* result = g_old_memalign(zone, alignment, size); - // Only die if posix_memalign would have returned ENOMEM, since there are - // other reasons why NULL might be returned (see - // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). - if (!result && size && alignment >= sizeof(void*) && - (alignment & (alignment - 1)) == 0) { - TerminateBecauseOutOfMemory(size); - } - return result; -} - -void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, - size_t size) { - void* result = g_old_malloc_purgeable(zone, size); - if (!result && size) - TerminateBecauseOutOfMemory(size); - return result; -} - -void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, - size_t num_items, - size_t size) { - void* result = g_old_calloc_purgeable(zone, num_items, size); - if (!result && num_items && size) - TerminateBecauseOutOfMemory(num_items * size); - return result; -} - -void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, - size_t size) { - void* result = g_old_valloc_purgeable(zone, size); - if (!result && size) - TerminateBecauseOutOfMemory(size); - return result; -} - -void oom_killer_free_purgeable(struct _malloc_zone_t* zone, - void* ptr) { - g_old_free_purgeable(zone, ptr); -} - -void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, - void* ptr, - size_t size) { - void* result = g_old_realloc_purgeable(zone, ptr, size); - if (!result && size) - TerminateBecauseOutOfMemory(size); - return result; -} - -void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, - size_t alignment, - size_t size) { - void* result = g_old_memalign_purgeable(zone, alignment, size); - // Only die if posix_memalign would have returned ENOMEM, since there are - // other reasons why NULL might be returned (see - // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). - if (!result && size && alignment >= sizeof(void*) - && (alignment & (alignment - 1)) == 0) { - TerminateBecauseOutOfMemory(size); - } - return result; -} - -#endif // !defined(ADDRESS_SANITIZER) - -// === C++ operator new === - -void oom_killer_new() { - TerminateBecauseOutOfMemory(0); -} - -#if !defined(ADDRESS_SANITIZER) - -// === Core Foundation CFAllocators === - -bool CanGetContextForCFAllocator() { - return !base::mac::IsOSLaterThan10_12_DontCallThis(); -} - -CFAllocatorContext* ContextForCFAllocator(CFAllocatorRef allocator) { - ChromeCFAllocatorLions* our_allocator = - const_cast<ChromeCFAllocatorLions*>( - reinterpret_cast<const ChromeCFAllocatorLions*>(allocator)); - return &our_allocator->_context; -} - -CFAllocatorAllocateCallBack g_old_cfallocator_system_default; -CFAllocatorAllocateCallBack g_old_cfallocator_malloc; -CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; - -void* oom_killer_cfallocator_system_default(CFIndex alloc_size, - CFOptionFlags hint, - void* info) { - void* result = g_old_cfallocator_system_default(alloc_size, hint, info); - if (!result) - TerminateBecauseOutOfMemory(alloc_size); - return result; -} - -void* oom_killer_cfallocator_malloc(CFIndex alloc_size, - CFOptionFlags hint, - void* info) { - void* result = g_old_cfallocator_malloc(alloc_size, hint, info); - if (!result) - TerminateBecauseOutOfMemory(alloc_size); - return result; -} - -void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, - CFOptionFlags hint, - void* info) { - void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); - if (!result) - TerminateBecauseOutOfMemory(alloc_size); - return result; -} - -#endif // !defined(ADDRESS_SANITIZER) - -// === Cocoa NSObject allocation === - -typedef id (*allocWithZone_t)(id, SEL, NSZone*); -allocWithZone_t g_old_allocWithZone; - -id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) -{ - id result = g_old_allocWithZone(self, _cmd, zone); - if (!result) - TerminateBecauseOutOfMemory(0); - return result; -} - -} // namespace - bool UncheckedMalloc(size_t size, void** result) { -#if defined(ADDRESS_SANITIZER) - *result = malloc(size); -#else - if (g_old_malloc) { - *result = g_old_malloc(malloc_default_zone(), size); - } else { - *result = malloc(size); - } -#endif // defined(ADDRESS_SANITIZER) - - return *result != NULL; + return allocator::UncheckedMallocMac(size, result); } bool UncheckedCalloc(size_t num_items, size_t size, void** result) { -#if defined(ADDRESS_SANITIZER) - *result = calloc(num_items, size); -#else - if (g_old_calloc) { - *result = g_old_calloc(malloc_default_zone(), num_items, size); - } else { - *result = calloc(num_items, size); - } -#endif // defined(ADDRESS_SANITIZER) - - return *result != NULL; -} - -void* UncheckedMalloc(size_t size) { - void* address; - return UncheckedMalloc(size, &address) ? address : NULL; -} - -void* UncheckedCalloc(size_t num_items, size_t size) { - void* address; - return UncheckedCalloc(num_items, size, &address) ? address : NULL; + return allocator::UncheckedCallocMac(num_items, size, result); } void EnableTerminationOnOutOfMemory() { - if (g_oom_killer_enabled) - return; - - g_oom_killer_enabled = true; - - // === C malloc/calloc/valloc/realloc/posix_memalign === - - // This approach is not perfect, as requests for amounts of memory larger than - // MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will - // still fail with a NULL rather than dying (see - // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). - // Unfortunately, it's the best we can do. Also note that this does not affect - // allocations from non-default zones. - -#if !defined(ADDRESS_SANITIZER) - // Don't do anything special on OOM for the malloc zones replaced by - // AddressSanitizer, as modifying or protecting them may not work correctly. - - CHECK(!g_old_malloc && !g_old_calloc && !g_old_valloc && !g_old_realloc && - !g_old_memalign) << "Old allocators unexpectedly non-null"; - - CHECK(!g_old_malloc_purgeable && !g_old_calloc_purgeable && - !g_old_valloc_purgeable && !g_old_realloc_purgeable && - !g_old_memalign_purgeable) << "Old allocators unexpectedly non-null"; - - ChromeMallocZone* default_zone = - reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); - ChromeMallocZone* purgeable_zone = - reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); - - mach_vm_address_t default_reprotection_start = 0; - mach_vm_size_t default_reprotection_length = 0; - vm_prot_t default_reprotection_value = VM_PROT_NONE; - DeprotectMallocZone(default_zone, - &default_reprotection_start, - &default_reprotection_length, - &default_reprotection_value); - - mach_vm_address_t purgeable_reprotection_start = 0; - mach_vm_size_t purgeable_reprotection_length = 0; - vm_prot_t purgeable_reprotection_value = VM_PROT_NONE; - if (purgeable_zone) { - DeprotectMallocZone(purgeable_zone, - &purgeable_reprotection_start, - &purgeable_reprotection_length, - &purgeable_reprotection_value); - } - - // Default zone - - g_old_malloc = default_zone->malloc; - g_old_calloc = default_zone->calloc; - g_old_valloc = default_zone->valloc; - g_old_free = default_zone->free; - g_old_realloc = default_zone->realloc; - CHECK(g_old_malloc && g_old_calloc && g_old_valloc && g_old_free && - g_old_realloc) - << "Failed to get system allocation functions."; - - default_zone->malloc = oom_killer_malloc; - default_zone->calloc = oom_killer_calloc; - default_zone->valloc = oom_killer_valloc; - default_zone->free = oom_killer_free; - default_zone->realloc = oom_killer_realloc; - - if (default_zone->version >= 5) { - g_old_memalign = default_zone->memalign; - if (g_old_memalign) - default_zone->memalign = oom_killer_memalign; - } - - // Purgeable zone (if it exists) - - if (purgeable_zone) { - g_old_malloc_purgeable = purgeable_zone->malloc; - g_old_calloc_purgeable = purgeable_zone->calloc; - g_old_valloc_purgeable = purgeable_zone->valloc; - g_old_free_purgeable = purgeable_zone->free; - g_old_realloc_purgeable = purgeable_zone->realloc; - CHECK(g_old_malloc_purgeable && g_old_calloc_purgeable && - g_old_valloc_purgeable && g_old_free_purgeable && - g_old_realloc_purgeable) - << "Failed to get system allocation functions."; - - purgeable_zone->malloc = oom_killer_malloc_purgeable; - purgeable_zone->calloc = oom_killer_calloc_purgeable; - purgeable_zone->valloc = oom_killer_valloc_purgeable; - purgeable_zone->free = oom_killer_free_purgeable; - purgeable_zone->realloc = oom_killer_realloc_purgeable; - - if (purgeable_zone->version >= 5) { - g_old_memalign_purgeable = purgeable_zone->memalign; - if (g_old_memalign_purgeable) - purgeable_zone->memalign = oom_killer_memalign_purgeable; - } - } - - // Restore protection if it was active. - - if (default_reprotection_start) { - kern_return_t result = mach_vm_protect(mach_task_self(), - default_reprotection_start, - default_reprotection_length, - false, - default_reprotection_value); - MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_protect"; - } - - if (purgeable_reprotection_start) { - kern_return_t result = mach_vm_protect(mach_task_self(), - purgeable_reprotection_start, - purgeable_reprotection_length, - false, - purgeable_reprotection_value); - MACH_CHECK(result == KERN_SUCCESS, result) << "mach_vm_protect"; - } -#endif - - // === C malloc_zone_batch_malloc === - - // batch_malloc is omitted because the default malloc zone's implementation - // only supports batch_malloc for "tiny" allocations from the free list. It - // will fail for allocations larger than "tiny", and will only allocate as - // many blocks as it's able to from the free list. These factors mean that it - // can return less than the requested memory even in a non-out-of-memory - // situation. There's no good way to detect whether a batch_malloc failure is - // due to these other factors, or due to genuine memory or address space - // exhaustion. The fact that it only allocates space from the "tiny" free list - // means that it's likely that a failure will not be due to memory exhaustion. - // Similarly, these constraints on batch_malloc mean that callers must always - // be expecting to receive less memory than was requested, even in situations - // where memory pressure is not a concern. Finally, the only public interface - // to batch_malloc is malloc_zone_batch_malloc, which is specific to the - // system's malloc implementation. It's unlikely that anyone's even heard of - // it. - - // === C++ operator new === - - // Yes, operator new does call through to malloc, but this will catch failures - // that our imperfect handling of malloc cannot. - - std::set_new_handler(oom_killer_new); - -#ifndef ADDRESS_SANITIZER - // === Core Foundation CFAllocators === - - // This will not catch allocation done by custom allocators, but will catch - // all allocation done by system-provided ones. - - CHECK(!g_old_cfallocator_system_default && !g_old_cfallocator_malloc && - !g_old_cfallocator_malloc_zone) - << "Old allocators unexpectedly non-null"; - - bool cf_allocator_internals_known = CanGetContextForCFAllocator(); - - if (cf_allocator_internals_known) { - CFAllocatorContext* context = - ContextForCFAllocator(kCFAllocatorSystemDefault); - CHECK(context) << "Failed to get context for kCFAllocatorSystemDefault."; - g_old_cfallocator_system_default = context->allocate; - CHECK(g_old_cfallocator_system_default) - << "Failed to get kCFAllocatorSystemDefault allocation function."; - context->allocate = oom_killer_cfallocator_system_default; - - context = ContextForCFAllocator(kCFAllocatorMalloc); - CHECK(context) << "Failed to get context for kCFAllocatorMalloc."; - g_old_cfallocator_malloc = context->allocate; - CHECK(g_old_cfallocator_malloc) - << "Failed to get kCFAllocatorMalloc allocation function."; - context->allocate = oom_killer_cfallocator_malloc; - - context = ContextForCFAllocator(kCFAllocatorMallocZone); - CHECK(context) << "Failed to get context for kCFAllocatorMallocZone."; - g_old_cfallocator_malloc_zone = context->allocate; - CHECK(g_old_cfallocator_malloc_zone) - << "Failed to get kCFAllocatorMallocZone allocation function."; - context->allocate = oom_killer_cfallocator_malloc_zone; - } else { - DLOG(WARNING) << "Internals of CFAllocator not known; out-of-memory " - "failures via CFAllocator will not result in termination. " - "http://crbug.com/45650"; - } -#endif - - // === Cocoa NSObject allocation === - - // Note that both +[NSObject new] and +[NSObject alloc] call through to - // +[NSObject allocWithZone:]. - - CHECK(!g_old_allocWithZone) - << "Old allocator unexpectedly non-null"; - - Class nsobject_class = [NSObject class]; - Method orig_method = class_getClassMethod(nsobject_class, - @selector(allocWithZone:)); - g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( - method_getImplementation(orig_method)); - CHECK(g_old_allocWithZone) - << "Failed to get allocWithZone allocation function."; - method_setImplementation(orig_method, - reinterpret_cast<IMP>(oom_killer_allocWithZone)); + allocator::InterceptAllocationsMac(); } } // namespace base
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index d6e93d3..0ecc9f76 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -373,6 +373,12 @@ if (is_multi_dll_chrome) { defines += [ "CHROME_MULTIPLE_DLL_BROWSER" ] deps += [ "//content/public/app:browser" ] + assert_no_deps = [ + # The browser DLL may not depend on blink or v8. + "//third_party/WebKit/public:blink", + "//gin", + "//v8", + ] } else { deps += [ ":child_dependencies", @@ -1219,16 +1225,20 @@ if (!is_component_build) { assert_no_deps = [ - # Blink and V8 should not be used in the browser process. In component - # build this is OK because all of content is linked into one library. - # Note that the blink_headers target is OK, so we can't do a wildcard for - # all blink targets. + # Blink should not be used in the browser process. In component build this + # is OK because all of content is linked into one library. Note that the + # blink_headers target is OK, so we can't do a wildcard for all blink + # targets. "//third_party/WebKit/public:blink", - # TODO(brettw) bug 581766: V8 should not be linked into the browser - # process, and then we can enable this. When testing whether you can - # enable this, run with a non-component build. - #"//v8/*", ] + + if (is_win) { + assert_no_deps += [ + # V8/Gin should not be used in the browser DLL on Windows. + "//gin", + "//v8", + ] + } } }
diff --git a/chrome/VERSION b/chrome/VERSION index 16b3c719..3b0661d 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=58 MINOR=0 -BUILD=2993 +BUILD=2994 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java index 76aa1ef..a3cd928 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
@@ -230,7 +230,9 @@ // * Otherwise, if closing the last incognito tab, select the current normal tab. // * Otherwise, select nothing. Tab nextTab = null; - if (tabToClose != currentTab && currentTab != null && !currentTab.isClosing()) { + if (!isCurrentModel()) { + nextTab = TabModelUtils.getCurrentTab(mModelDelegate.getCurrentModel()); + } else if (tabToClose != currentTab && currentTab != null && !currentTab.isClosing()) { nextTab = currentTab; } else if (parentTab != null && !parentTab.isClosing() && !mModelDelegate.isInOverviewMode()) { @@ -239,10 +241,9 @@ nextTab = adjacentTab; } else if (isIncognito()) { nextTab = TabModelUtils.getCurrentTab(mModelDelegate.getModel(false)); - if (nextTab != null && nextTab.isClosing()) nextTab = null; } - return nextTab; + return nextTab != null && nextTab.isClosing() ? null : nextTab; } @Override @@ -292,7 +293,7 @@ WebContents webContents = tab.getWebContents(); if (webContents != null) webContents.setAudioMuted(false); - boolean activeModel = mModelDelegate.getCurrentModel() == this; + boolean activeModel = isCurrentModel(); if (mIndex == INVALID_TAB_INDEX) { // If we're the active model call setIndex to actually select this tab, otherwise just @@ -443,14 +444,16 @@ // Index of the given tab in the order of the tab stack. @Override public int indexOf(Tab tab) { - return mTabs.indexOf(tab); + if (tab == null) return INVALID_TAB_INDEX; + int retVal = mTabs.indexOf(tab); + return retVal == -1 ? INVALID_TAB_INDEX : retVal; } /** * @return true if this is the current model according to the model selector */ private boolean isCurrentModel() { - return mModelDelegate.getCurrentModel() == this; + return mModelDelegate.getCurrentModel().isIncognito() == isIncognito(); } // TODO(aurimas): Move this method to TabModelSelector when notifications move there. @@ -544,8 +547,8 @@ final int closingTabId = tab.getId(); final int closingTabIndex = indexOf(tab); - Tab currentTab = TabModelUtils.getCurrentTab(this); - Tab adjacentTab = getTabAt(closingTabIndex == 0 ? 1 : closingTabIndex - 1); + Tab currentTabInModel = TabModelUtils.getCurrentTab(this); + Tab adjacentTabInModel = getTabAt(closingTabIndex == 0 ? 1 : closingTabIndex - 1); Tab nextTab = getNextTabIfClosed(closingTabId); // TODO(dtrainor): Update the list of undoable tabs instead of committing it. @@ -567,8 +570,8 @@ int nextTabIndex = nextTab == null ? INVALID_TAB_INDEX : TabModelUtils.getTabIndexById( mModelDelegate.getModel(nextIsIncognito), nextTabId); - if (nextTab != currentTab) { - if (nextIsIncognito != isIncognito()) mIndex = indexOf(adjacentTab); + if (nextTab != currentTabInModel) { + if (nextIsIncognito != isIncognito()) mIndex = indexOf(adjacentTabInModel); TabModel nextModel = mModelDelegate.getModel(nextIsIncognito); nextModel.setIndex(nextTabIndex, selectionType);
diff --git a/chrome/app/mash/BUILD.gn b/chrome/app/mash/BUILD.gn index 76dc0c4..e78d037 100644 --- a/chrome/app/mash/BUILD.gn +++ b/chrome/app/mash/BUILD.gn
@@ -11,6 +11,7 @@ "mash_runner.h", ] deps = [ + ":catalog_cpp_source", "//base:i18n", "//components/tracing:startup_tracing", "//content/public/common", @@ -28,10 +29,6 @@ "//services/service_manager/standalone", "//url", ] - data_deps = [ - ":catalog_copy", - "//chrome/app:service_manifests", - ] if (is_chromeos) { sources += [ @@ -80,12 +77,7 @@ catalog_deps = [ "//chrome/app:catalog" ] } -copy("catalog_copy") { - sources = get_target_outputs(":catalog") - outputs = [ - "${root_out_dir}/chrome_mash_catalog.json", - ] - deps = [ - ":catalog", - ] +catalog_cpp_source("catalog_cpp_source") { + catalog = ":catalog" + output_symbol_name = "kChromeMashCatalogContents" }
diff --git a/chrome/app/mash/mash_runner.cc b/chrome/app/mash/mash_runner.cc index 72da1805..42c50057 100644 --- a/chrome/app/mash/mash_runner.cc +++ b/chrome/app/mash/mash_runner.cc
@@ -61,6 +61,9 @@ using service_manager::mojom::ServiceFactory; +// Defined externally by the ":catalog_cpp_source" target. +extern const char kChromeMashCatalogContents[]; + namespace { // kProcessType used to identify child processes. @@ -68,9 +71,6 @@ const char kChromeMashServiceName[] = "chrome_mash"; -const base::FilePath::CharType kChromeMashCatalogFilename[] = - FILE_PATH_LITERAL("chrome_mash_catalog.json"); - bool IsChild() { return base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kProcessType) && @@ -177,14 +177,8 @@ ipc_thread.task_runner(), mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); - std::string catalog_contents; - base::FilePath exe_path; - base::PathService::Get(base::DIR_EXE, &exe_path); - base::FilePath catalog_path = exe_path.Append(kChromeMashCatalogFilename); - bool result = base::ReadFileToString(catalog_path, &catalog_contents); - DCHECK(result); std::unique_ptr<base::Value> manifest_value = - base::JSONReader::Read(catalog_contents); + base::JSONReader::Read(kChromeMashCatalogContents); DCHECK(manifest_value); // TODO(sky): refactor BackgroundServiceManager so can supply own context, we
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f4006f4..da403fc 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1544,7 +1544,6 @@ "//mojo/public/cpp/bindings", "//mojo/public/js", "//net:extras", - "//net:net_with_v8", "//ppapi/features", "//printing/features", "//rlz/features", @@ -1589,9 +1588,19 @@ "//ui/strings", "//ui/surface", "//ui/web_dialogs", - "//v8", ] + # Android does in-process PAC, so must link against V8 directly. Other + # platforms use OOP Mojo resolution. + if (is_android) { + deps += [ + "//net:net_with_v8", + "//v8", + ] + } else { + deps += [ "//net:net" ] + } + if (is_chromeos && use_cras) { defines += [ "USE_CRAS" ] }
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc index 054f8fe..44b3116 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
@@ -40,7 +40,6 @@ #include "chromeos/cryptohome/async_method_caller.h" #include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/session_manager_client.h" #include "chromeos/settings/cros_settings_names.h" #include "components/ownership/owner_key_util.h" #include "components/prefs/pref_registry_simple.h" @@ -52,7 +51,6 @@ #include "content/public/browser/browser_thread.h" #include "extensions/common/extension_urls.h" #include "extensions/common/manifest_handlers/kiosk_mode_info.h" -#include "third_party/cros_system_api/switches/chrome_switches.h" namespace chromeos { @@ -149,14 +147,6 @@ minor_version, bugfix_version)); } -// Converts a flag constant to actual command line switch value. -std::string GetSwitchString(const std::string& flag_name) { - base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM); - cmd_line.AppendSwitch(flag_name); - DCHECK_EQ(2U, cmd_line.argv().size()); - return cmd_line.argv()[1]; -} - } // namespace // static @@ -251,70 +241,10 @@ const std::string& app_id) { LOG_IF(FATAL, app_session_) << "Kiosk session is already initialized."; - base::CommandLine session_flags(base::CommandLine::NO_PROGRAM); - if (GetSwitchesForSessionRestore(app_id, &session_flags)) { - base::CommandLine::StringVector flags; - // argv[0] is the program name |base::CommandLine::NO_PROGRAM|. - flags.assign(session_flags.argv().begin() + 1, session_flags.argv().end()); - - // Update user flags, but do not restart Chrome - the purpose of the flags - // set here is to be able to properly restore session if the session is - // restarted - e.g. due to crash. For example, this will ensure restarted - // app session restores auto-launched state. - DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser( - cryptohome::Identification( - user_manager::UserManager::Get()->GetActiveUser()->GetAccountId()), - flags); - } - app_session_.reset(new AppSession); app_session_->Init(profile, app_id); } -bool KioskAppManager::GetSwitchesForSessionRestore( - const std::string& app_id, - base::CommandLine* switches) { - bool auto_launched = app_id == currently_auto_launched_with_zero_delay_app_; - const base::CommandLine* current_command_line = - base::CommandLine::ForCurrentProcess(); - bool has_auto_launched_flag = - current_command_line->HasSwitch(switches::kAppAutoLaunched); - if (auto_launched == has_auto_launched_flag) - return false; - - // Collect current policy defined switches, so they can be passed on to the - // session manager as well - otherwise they would get lost on restart. - // This ignores 'flag-switches-begin' - 'flag-switches-end' flags, but those - // should not be present for kiosk sessions. - bool in_policy_switches_block = false; - const std::string policy_switches_begin = - GetSwitchString(switches::kPolicySwitchesBegin); - const std::string policy_switches_end = - GetSwitchString(switches::kPolicySwitchesEnd); - - for (const auto& it : current_command_line->argv()) { - if (it == policy_switches_begin) { - DCHECK(!in_policy_switches_block); - in_policy_switches_block = true; - } - - if (in_policy_switches_block) - switches->AppendSwitch(it); - - if (it == policy_switches_end) { - DCHECK(in_policy_switches_block); - in_policy_switches_block = false; - } - } - - DCHECK(!in_policy_switches_block); - - if (auto_launched) - switches->AppendSwitch(switches::kAppAutoLaunched); - - return true; -} - void KioskAppManager::AddAppForTest( const std::string& app_id, const AccountId& account_id,
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h index f057d11..7aac2e7 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
@@ -26,10 +26,6 @@ class PrefRegistrySimple; class Profile; -namespace base { -class CommandLine; -} - namespace extensions { class Extension; class ExternalLoader; @@ -321,15 +317,6 @@ // Returns the auto launch delay. base::TimeDelta GetAutoLaunchDelay() const; - // Gets list of user switches that should be passed to Chrome in case current - // session has to be restored, e.g. in case of a crash. The switches will be - // returned as |switches| command line arguments. - // Returns whether the set of switches would have to be changed in respect to - // the current set of switches - if that is not the case |switches| might not - // get populated. - bool GetSwitchesForSessionRestore(const std::string& app_id, - base::CommandLine* switches); - // True if machine ownership is already established. bool ownership_established_; std::vector<std::unique_ptr<KioskAppData>> apps_;
diff --git a/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc new file mode 100644 index 0000000..703a763 --- /dev/null +++ b/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc
@@ -0,0 +1,194 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <string> + +#include "apps/test/app_window_waiter.h" +#include "base/base64.h" +#include "base/command_line.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "chrome/browser/chromeos/app_mode/fake_cws.h" +#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" +#include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h" +#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h" +#include "chrome/browser/chromeos/policy/device_local_account.h" +#include "chrome/browser/chromeos/policy/device_policy_builder.h" +#include "chrome/browser/extensions/browsertest_util.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/chromeos_switches.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/fake_session_manager_client.h" +#include "chromeos/dbus/fake_shill_manager_client.h" +#include "components/ownership/mock_owner_key_util.h" +#include "extensions/browser/app_window/app_window.h" +#include "extensions/browser/app_window/app_window_registry.h" +#include "extensions/browser/app_window/native_app_window.h" +#include "extensions/common/value_builder.h" +#include "extensions/test/extension_test_message_listener.h" +#include "net/dns/mock_host_resolver.h" + +namespace em = enterprise_management; + +namespace chromeos { + +namespace { + +const char kTestKioskApp[] = "ggbflgnkafappblpkiflbgpmkfdpnhhe"; + +} // namespace + +class KioskCrashRestoreTest : public InProcessBrowserTest { + public: + KioskCrashRestoreTest() + : owner_key_util_(new ownership::MockOwnerKeyUtil()), + fake_cws_(new FakeCWS) {} + + // InProcessBrowserTest + void SetUp() override { + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + InProcessBrowserTest::SetUp(); + } + + bool SetUpUserDataDirectory() override { + SetUpExistingKioskApp(); + return true; + } + + void SetUpInProcessBrowserTestFixture() override { + host_resolver()->AddRule("*", "127.0.0.1"); + SimulateNetworkOnline(); + + OverrideDevicePolicy(); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + const AccountId account_id = AccountId::FromUserEmail(GetTestAppUserId()); + const cryptohome::Identification cryptohome_id(account_id); + + command_line->AppendSwitchASCII(switches::kLoginUser, cryptohome_id.id()); + command_line->AppendSwitchASCII( + switches::kLoginProfile, + CryptohomeClient::GetStubSanitizedUsername(cryptohome_id)); + + fake_cws_->Init(embedded_test_server()); + fake_cws_->SetUpdateCrx(test_app_id_, test_app_id_ + ".crx", "1.0.0"); + } + + void SetUpOnMainThread() override { + extensions::browsertest_util::CreateAndInitializeLocalCache(); + + embedded_test_server()->StartAcceptingConnections(); + } + + const std::string GetTestAppUserId() const { + return policy::GenerateDeviceLocalAccountUserId( + test_app_id_, policy::DeviceLocalAccount::TYPE_KIOSK_APP); + } + + const std::string& test_app_id() const { return test_app_id_; } + + private: + void SetUpExistingKioskApp() { + // Create policy data that contains the test app as an existing kiosk app. + em::DeviceLocalAccountsProto* const device_local_accounts = + device_policy_.payload().mutable_device_local_accounts(); + + em::DeviceLocalAccountInfoProto* const account = + device_local_accounts->add_account(); + account->set_account_id(test_app_id_); + account->set_type( + em::DeviceLocalAccountInfoProto_AccountType_ACCOUNT_TYPE_KIOSK_APP); + account->mutable_kiosk_app()->set_app_id(test_app_id_); + device_policy_.Build(); + + // Prepare the policy data to store in device policy cache. + em::PolicyData policy_data; + CHECK(device_policy_.payload().SerializeToString( + policy_data.mutable_policy_value())); + const std::string policy_data_string = policy_data.SerializeAsString(); + std::string encoded; + base::Base64Encode(policy_data_string, &encoded); + + // Store policy data and existing device local accounts in local state. + const std::string local_state_json = + extensions::DictionaryBuilder() + .Set(prefs::kDeviceSettingsCache, encoded) + .Set("PublicAccounts", + extensions::ListBuilder().Append(GetTestAppUserId()).Build()) + .ToJSON(); + + base::FilePath local_state_file; + CHECK(PathService::Get(chrome::DIR_USER_DATA, &local_state_file)); + local_state_file = local_state_file.Append(chrome::kLocalStateFilename); + base::WriteFile(local_state_file, local_state_json.data(), + local_state_json.size()); + } + + void SimulateNetworkOnline() { + NetworkPortalDetectorTestImpl* const network_portal_detector = + new NetworkPortalDetectorTestImpl(); + // Takes ownership of |network_portal_detector|. + network_portal_detector::InitializeForTesting(network_portal_detector); + network_portal_detector->SetDefaultNetworkForTesting( + FakeShillManagerClient::kFakeEthernetNetworkGuid); + + NetworkPortalDetector::CaptivePortalState online_state; + online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE; + online_state.response_code = 204; + network_portal_detector->SetDetectionResultsForTesting( + FakeShillManagerClient::kFakeEthernetNetworkGuid, online_state); + } + + void OverrideDevicePolicy() { + OwnerSettingsServiceChromeOSFactory::GetInstance() + ->SetOwnerKeyUtilForTesting(owner_key_util_); + owner_key_util_->SetPublicKeyFromPrivateKey( + *device_policy_.GetSigningKey()); + + session_manager_client_ = new FakeSessionManagerClient; + session_manager_client_->set_device_policy(device_policy_.GetBlob()); + + DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient( + std::unique_ptr<SessionManagerClient>(session_manager_client_)); + } + + std::string test_app_id_ = kTestKioskApp; + + policy::DevicePolicyBuilder device_policy_; + scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_; + FakeSessionManagerClient* session_manager_client_; + std::unique_ptr<FakeCWS> fake_cws_; + + DISALLOW_COPY_AND_ASSIGN(KioskCrashRestoreTest); +}; + +IN_PROC_BROWSER_TEST_F(KioskCrashRestoreTest, Basic) { + ExtensionTestMessageListener launch_data_check_listener( + "launchData.isKioskSession = true", false); + + Profile* const app_profile = ProfileManager::GetPrimaryUserProfile(); + ASSERT_TRUE(app_profile); + extensions::AppWindowRegistry* const app_window_registry = + extensions::AppWindowRegistry::Get(app_profile); + extensions::AppWindow* const window = + apps::AppWindowWaiter(app_window_registry, test_app_id()).Wait(); + ASSERT_TRUE(window); + + window->GetBaseWindow()->Close(); + + // Wait until the app terminates if it is still running. + if (!app_window_registry->GetAppWindowsForApp(test_app_id()).empty()) + base::RunLoop().Run(); + + EXPECT_TRUE(launch_data_check_listener.was_satisfied()); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc b/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc deleted file mode 100644 index 9b5f8c6..0000000 --- a/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc +++ /dev/null
@@ -1,470 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <memory> -#include <string> -#include <vector> - -#include "apps/test/app_window_waiter.h" -#include "base/base64.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/json/json_file_value_serializer.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/values.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/chromeos/app_mode/fake_cws.h" -#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" -#include "chrome/browser/chromeos/login/app_launch_controller.h" -#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h" -#include "chrome/browser/chromeos/policy/device_local_account.h" -#include "chrome/browser/chromeos/policy/device_policy_builder.h" -#include "chrome/browser/chromeos/settings/stub_install_attributes.h" -#include "chrome/browser/extensions/browsertest_util.h" -#include "chrome/browser/extensions/extension_apitest.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/pref_names.h" -#include "chromeos/dbus/cryptohome_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_session_manager_client.h" -#include "chromeos/dbus/shill_manager_client.h" -#include "components/ownership/mock_owner_key_util.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "content/public/browser/notification_service.h" -#include "extensions/browser/app_window/app_window.h" -#include "extensions/browser/app_window/app_window_registry.h" -#include "extensions/browser/app_window/native_app_window.h" -#include "extensions/common/value_builder.h" -#include "extensions/test/extension_test_message_listener.h" -#include "net/dns/mock_host_resolver.h" -#include "third_party/cros_system_api/switches/chrome_switches.h" - -namespace em = enterprise_management; - -namespace chromeos { - -namespace { - -// This is a simple test app that creates an app window and immediately closes -// it again. Webstore data json is in -// chrome/test/data/chromeos/app_mode/webstore/inlineinstall/ -// detail/ggbflgnkafappblpkiflbgpmkfdpnhhe -const char kTestKioskApp[] = "ggbflgnkafappblpkiflbgpmkfdpnhhe"; - -const char kTestAccountId[] = "enterprise-kiosk-app@localhost"; - -const char kSessionManagerStateCache[] = "test_session_manager_state.json"; - -// Keys for values in dictionary used to preserve session manager state. -const char kLoginArgsKey[] = "login_args"; -const char kExtraArgsKey[] = "extra_args"; -const char kArgNameKey[] = "name"; -const char kArgValueKey[] = "value"; - -// Default set policy switches. -const struct { - const char* name; - const char* value; -} kDefaultPolicySwitches[] = {{"test_switch_1", ""}, - {"test_switch_2", "test_switch_2_value"}}; - -// Fake session manager implementation that persists its state in local file. -// It can be used to preserve session state in PRE_ browser tests. -// Primarily used for testing user/login switches. -class PersistentSessionManagerClient : public FakeSessionManagerClient { - public: - PersistentSessionManagerClient() {} - - ~PersistentSessionManagerClient() override { - PersistFlagsToFile(backing_file_); - } - - // Initializes session state (primarily session flags)- if |backing_file| - // exists, the session state is restored from the file value. Otherwise it's - // set to the default session state. - void Initialize(const base::FilePath& backing_file) { - backing_file_ = backing_file; - - if (ExtractFlagsFromFile(backing_file_)) - return; - - // Failed to extract ached flags - set the default values. - login_args_ = {{"login-manager", ""}}; - - extra_args_ = {{switches::kPolicySwitchesBegin, ""}}; - for (size_t i = 0; i < arraysize(kDefaultPolicySwitches); ++i) { - extra_args_.push_back( - {kDefaultPolicySwitches[i].name, kDefaultPolicySwitches[i].value}); - } - extra_args_.push_back({switches::kPolicySwitchesEnd, ""}); - } - - void AppendSwitchesToCommandLine(base::CommandLine* command_line) { - for (const auto& flag : login_args_) - command_line->AppendSwitchASCII(flag.name, flag.value); - for (const auto& flag : extra_args_) - command_line->AppendSwitchASCII(flag.name, flag.value); - } - - void StartSession(const cryptohome::Identification& cryptohome_id) override { - FakeSessionManagerClient::StartSession(cryptohome_id); - - std::string user_id_hash = - CryptohomeClient::GetStubSanitizedUsername(cryptohome_id); - login_args_ = {{"login-user", cryptohome_id.id()}, - {"login-profile", user_id_hash}}; - } - - void StopSession() override { - FakeSessionManagerClient::StopSession(); - - login_args_ = {{"login-manager", ""}}; - } - - bool SupportsRestartToApplyUserFlags() const override { return true; } - - void SetFlagsForUser(const cryptohome::Identification& identification, - const std::vector<std::string>& flags) override { - extra_args_.clear(); - FakeSessionManagerClient::SetFlagsForUser(identification, flags); - - std::vector<std::string> argv = {"" /* Empty program */}; - argv.insert(argv.end(), flags.begin(), flags.end()); - - // Parse flag name-value pairs using command line initialization. - base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM); - cmd_line.InitFromArgv(argv); - - for (const auto& flag : cmd_line.GetSwitches()) - extra_args_.push_back({flag.first, flag.second}); - } - - private: - // Keeps information about a switch - its name and value. - struct Switch { - std::string name; - std::string value; - }; - - bool ExtractFlagsFromFile(const base::FilePath& backing_file) { - JSONFileValueDeserializer deserializer(backing_file); - - int error_code = 0; - std::unique_ptr<base::Value> value = - deserializer.Deserialize(&error_code, nullptr); - if (error_code != JSONFileValueDeserializer::JSON_NO_ERROR) - return false; - - std::unique_ptr<base::DictionaryValue> value_dict = - base::DictionaryValue::From(std::move(value)); - DCHECK(value_dict); - - CHECK(InitArgListFromCachedValue(*value_dict, kLoginArgsKey, &login_args_)); - CHECK(InitArgListFromCachedValue(*value_dict, kExtraArgsKey, &extra_args_)); - return true; - } - - bool PersistFlagsToFile(const base::FilePath& backing_file) { - base::DictionaryValue cached_state; - cached_state.Set(kLoginArgsKey, GetArgListValue(login_args_)); - cached_state.Set(kExtraArgsKey, GetArgListValue(extra_args_)); - - JSONFileValueSerializer serializer(backing_file); - return serializer.Serialize(cached_state); - } - - std::unique_ptr<base::ListValue> GetArgListValue( - const std::vector<Switch>& args) { - std::unique_ptr<base::ListValue> result(new base::ListValue()); - for (const auto& arg : args) { - result->Append(extensions::DictionaryBuilder() - .Set(kArgNameKey, arg.name) - .Set(kArgValueKey, arg.value) - .Build()); - } - return result; - } - - bool InitArgListFromCachedValue(const base::DictionaryValue& cache_value, - const std::string& list_key, - std::vector<Switch>* arg_list_out) { - arg_list_out->clear(); - const base::ListValue* arg_list_value; - if (!cache_value.GetList(list_key, &arg_list_value)) - return false; - for (size_t i = 0; i < arg_list_value->GetSize(); ++i) { - const base::DictionaryValue* arg_value; - if (!arg_list_value->GetDictionary(i, &arg_value)) - return false; - Switch arg; - if (!arg_value->GetStringASCII(kArgNameKey, &arg.name) || - !arg_value->GetStringASCII(kArgValueKey, &arg.value)) { - return false; - } - arg_list_out->push_back(arg); - } - return true; - } - - std::vector<Switch> login_args_; - std::vector<Switch> extra_args_; - - base::FilePath backing_file_; - - DISALLOW_COPY_AND_ASSIGN(PersistentSessionManagerClient); -}; - -// Used to listen for app termination notification. -class TerminationObserver : public content::NotificationObserver { - public: - TerminationObserver() { - registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, - content::NotificationService::AllSources()); - } - ~TerminationObserver() override = default; - - // Whether app has been terminated - i.e. whether app termination notification - // has been observed. - bool terminated() const { return notification_seen_; } - - private: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { - ASSERT_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); - notification_seen_ = true; - } - - bool notification_seen_ = false; - content::NotificationRegistrar registrar_; - - DISALLOW_COPY_AND_ASSIGN(TerminationObserver); -}; - -} // namespace - -class AutoLaunchedKioskTest : public ExtensionApiTest { - public: - AutoLaunchedKioskTest() - : install_attributes_( - chromeos::ScopedStubInstallAttributes::CreateEnterprise( - "domain.com", - "device_id")), - owner_key_util_(new ownership::MockOwnerKeyUtil()), - fake_session_manager_(new PersistentSessionManagerClient()), - fake_cws_(new FakeCWS) { - set_chromeos_user_ = false; - } - - ~AutoLaunchedKioskTest() override = default; - - void SetUp() override { - ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); - AppLaunchController::SkipSplashWaitForTesting(); - - ExtensionApiTest::SetUp(); - } - - void SetUpCommandLine(base::CommandLine* command_line) override { - fake_cws_->Init(embedded_test_server()); - fake_cws_->SetUpdateCrx(kTestKioskApp, std::string(kTestKioskApp) + ".crx", - "1.0.0"); - ExtensionApiTest::SetUpCommandLine(command_line); - } - - bool SetUpUserDataDirectory() override { - InitDevicePolicy(); - - base::FilePath user_data_path; - CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_path)); - CacheDevicePolicyToLocalState(user_data_path); - - // Restore session_manager state and ensure session manager flags are - // applied. - fake_session_manager_->Initialize( - user_data_path.Append(kSessionManagerStateCache)); - fake_session_manager_->AppendSwitchesToCommandLine( - base::CommandLine::ForCurrentProcess()); - - return true; - } - - void SetUpInProcessBrowserTestFixture() override { - host_resolver()->AddRule("*", "127.0.0.1"); - - OwnerSettingsServiceChromeOSFactory::GetInstance() - ->SetOwnerKeyUtilForTesting(owner_key_util_); - owner_key_util_->SetPublicKeyFromPrivateKey( - *device_policy_.GetSigningKey()); - - fake_session_manager_->set_device_policy(device_policy_.GetBlob()); - DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient( - std::move(fake_session_manager_)); - - ExtensionApiTest::SetUpInProcessBrowserTestFixture(); - } - - void SetUpOnMainThread() override { - extensions::browsertest_util::CreateAndInitializeLocalCache(); - - embedded_test_server()->StartAcceptingConnections(); - - ExtensionApiTest::SetUpOnMainThread(); - } - - void RunTestOnMainThreadLoop() override { - termination_observer_.reset(new TerminationObserver()); - - ExtensionApiTest::RunTestOnMainThreadLoop(); - } - - void TearDownOnMainThread() override { - termination_observer_.reset(); - - ExtensionApiTest::TearDownOnMainThread(); - } - - void InitDevicePolicy() { - // Create device policy, and cache it to local state. - em::DeviceLocalAccountsProto* const device_local_accounts = - device_policy_.payload().mutable_device_local_accounts(); - - em::DeviceLocalAccountInfoProto* const account = - device_local_accounts->add_account(); - account->set_account_id(kTestAccountId); - account->set_type(em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_KIOSK_APP); - account->mutable_kiosk_app()->set_app_id(kTestKioskApp); - - device_local_accounts->set_auto_login_id(kTestAccountId); - - device_policy_.Build(); - } - - void CacheDevicePolicyToLocalState(const base::FilePath& user_data_path) { - em::PolicyData policy_data; - DCHECK(device_policy_.payload().SerializeToString( - policy_data.mutable_policy_value())); - const std::string policy_data_str = policy_data.SerializeAsString(); - std::string policy_data_encoded; - base::Base64Encode(policy_data_str, &policy_data_encoded); - - std::unique_ptr<base::DictionaryValue> local_state = - extensions::DictionaryBuilder() - .Set(prefs::kDeviceSettingsCache, policy_data_encoded) - .Set("PublicAccounts", - extensions::ListBuilder().Append(GetTestAppUserId()).Build()) - .Build(); - - JSONFileValueSerializer serializer( - user_data_path.Append(chrome::kLocalStateFilename)); - CHECK(serializer.Serialize(*local_state)); - } - - const std::string GetTestAppUserId() const { - return policy::GenerateDeviceLocalAccountUserId( - kTestAccountId, policy::DeviceLocalAccount::TYPE_KIOSK_APP); - } - - bool CloseAppWindow(const std::string& app_id) { - Profile* const app_profile = ProfileManager::GetPrimaryUserProfile(); - if (!app_profile) { - ADD_FAILURE() << "No primary (app) profile."; - return false; - } - - extensions::AppWindowRegistry* const app_window_registry = - extensions::AppWindowRegistry::Get(app_profile); - extensions::AppWindow* const window = - apps::AppWindowWaiter(app_window_registry, app_id).Wait(); - if (!window) { - ADD_FAILURE() << "No app window found for " << app_id << "."; - return false; - } - - window->GetBaseWindow()->Close(); - - // Wait until the app terminates if it is still running. - if (!app_window_registry->GetAppWindowsForApp(app_id).empty()) - base::RunLoop().Run(); - return true; - } - - bool IsKioskAppAutoLaunched(const std::string& app_id) { - KioskAppManager::App app; - if (!KioskAppManager::Get()->GetApp(app_id, &app)) { - ADD_FAILURE() << "App " << app_id << " not found."; - return false; - } - return app.was_auto_launched_with_zero_delay; - } - - void ExpectCommandLineHasDefaultPolicySwitches( - const base::CommandLine& cmd_line) { - for (size_t i = 0u; i < arraysize(kDefaultPolicySwitches); ++i) { - EXPECT_TRUE(cmd_line.HasSwitch(kDefaultPolicySwitches[i].name)) - << "Missing flag " << kDefaultPolicySwitches[i].name; - EXPECT_EQ(kDefaultPolicySwitches[i].value, - cmd_line.GetSwitchValueASCII(kDefaultPolicySwitches[i].name)) - << "Invalid value for switch " << kDefaultPolicySwitches[i].name; - } - } - - protected: - std::unique_ptr<TerminationObserver> termination_observer_; - - private: - chromeos::ScopedStubInstallAttributes install_attributes_; - policy::DevicePolicyBuilder device_policy_; - scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_; - std::unique_ptr<PersistentSessionManagerClient> fake_session_manager_; - std::unique_ptr<FakeCWS> fake_cws_; - - DISALLOW_COPY_AND_ASSIGN(AutoLaunchedKioskTest); -}; - -IN_PROC_BROWSER_TEST_F(AutoLaunchedKioskTest, PRE_CrashRestore) { - // Verify that Chrome hasn't already exited, e.g. in order to apply user - // session flags. - ASSERT_FALSE(termination_observer_->terminated()); - - // Set up default network connections, so tests think the device is online. - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->SetupDefaultEnvironment(); - - // Check that policy flags have not been lost. - ExpectCommandLineHasDefaultPolicySwitches( - *base::CommandLine::ForCurrentProcess()); - - ExtensionTestMessageListener listener("appWindowLoaded", false); - EXPECT_TRUE(listener.WaitUntilSatisfied()); - - EXPECT_TRUE(IsKioskAppAutoLaunched(kTestKioskApp)); - - ASSERT_TRUE(CloseAppWindow(kTestKioskApp)); -} - -IN_PROC_BROWSER_TEST_F(AutoLaunchedKioskTest, CrashRestore) { - // Verify that Chrome hasn't already exited, e.g. in order to apply user - // session flags. - ASSERT_FALSE(termination_observer_->terminated()); - - ExpectCommandLineHasDefaultPolicySwitches( - *base::CommandLine::ForCurrentProcess()); - - ExtensionTestMessageListener listener("appWindowLoaded", false); - EXPECT_TRUE(listener.WaitUntilSatisfied()); - - EXPECT_TRUE(IsKioskAppAutoLaunched(kTestKioskApp)); - - ASSERT_TRUE(CloseAppWindow(kTestKioskApp)); -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 145a9ee..fe16fe3 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -581,18 +581,14 @@ // type has be set before kiosk app controller takes over, as at that point // kiosk app profile would already be initialized - feature session type // should be set before that. + // TODO(tbarzic): Note that this does not work well for auto-launched + // sessions, as information about whether session was auto-launched is not + // persisted over session restart - http://crbug.com/677340. if (user->GetType() == user_manager::USER_TYPE_KIOSK_APP) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kLoginUser)) { - // For kiosk session crash recovery, feature session type has be set - // before kiosk app controller takes over, as at that point iosk app - // profile would already be initialized - feature session type - // should be set before that. - bool auto_launched = base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAppAutoLaunched); extensions::SetCurrentFeatureSessionType( - auto_launched ? extensions::FeatureSessionType::AUTOLAUNCHED_KIOSK - : extensions::FeatureSessionType::KIOSK); + extensions::FeatureSessionType::KIOSK); } return; }
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc index f785b60..a3f7408 100644 --- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -30,7 +30,6 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h" #include "chrome/browser/chromeos/login/session/user_session_manager.h" #include "chrome/browser/chromeos/login/signin/auth_sync_observer.h" @@ -860,13 +859,6 @@ // Disable window animation since kiosk app runs in a single full screen // window and window animation causes start-up janks. command_line->AppendSwitch(wm::switches::kWindowAnimationsDisabled); - - // If restoring auto-launched kiosk session, make sure the app is marked - // as auto-launched. - if (command_line->HasSwitch(switches::kLoginUser) && - command_line->HasSwitch(switches::kAppAutoLaunched)) { - KioskAppManager::Get()->SetAppWasAutoLaunchedWithZeroDelay(kiosk_app_id); - } } void ChromeUserManagerImpl::ArcKioskAppLoggedIn(user_manager::User* user) {
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index b4ad845..cbc4ded 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -339,6 +339,9 @@ GetLocalState()->GetBoolean(prefs::kOobeMdMode)) SetShowMdOobe(true); + // Disable md oobe by default in m57. + SetShowMdOobe(false); + // TODO(drcrash): Remove this after testing (http://crbug.com/647411). if (IsRemoraPairingOobe() || IsSharkRequisition() || IsRemoraRequisition()) { SetShowMdOobe(false);
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc index 31896bc6..b4852c6 100644 --- a/chrome/browser/media/encrypted_media_browsertest.cc +++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -60,6 +60,8 @@ "org.chromium.externalclearkey.platformverificationtest"; const char kExternalClearKeyCrashKeySystem[] = "org.chromium.externalclearkey.crash"; +const char kExternalClearKeyVerifyCdmHostTestKeySystem[] = + "org.chromium.externalclearkey.verifycdmhosttest"; // Supported media types. const char kWebMVorbisAudioOnly[] = "audio/webm; codecs=\"vorbis\""; @@ -274,6 +276,8 @@ RegisterPepperCdm(command_line, kClearKeyCdmBaseDirectory, kClearKeyCdmAdapterFileName, kClearKeyCdmDisplayName, kClearKeyCdmPepperMimeType); + // Need to tell CdmHostFile(s) to ignore missing CDM host files in tests. + command_line->AppendSwitch(switches::kIgnoreMissingCdmHostFile); command_line->AppendSwitchASCII(switches::kEnableFeatures, media::kExternalClearKeyForTesting.name); } @@ -673,4 +677,9 @@ kEmeSessionNotFound); } +IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, VerifyCdmHostTest) { + TestNonPlaybackCases(kExternalClearKeyVerifyCdmHostTestKeySystem, + kUnitTestSuccess); +} + #endif // BUILDFLAG(ENABLE_PEPPER_CDMS)
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index f8dd499f..bb1ca3f 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -401,6 +401,9 @@ { key::kForceEphemeralProfiles, prefs::kForceEphemeralProfiles, base::Value::Type::BOOLEAN }, + { key::kDHEEnabled, + ssl_config::prefs::kDHEEnabled, + base::Value::Type::BOOLEAN }, { key::kNTPContentSuggestionsEnabled, ntp_snippets::prefs::kEnableSnippets, base::Value::Type::BOOLEAN },
diff --git a/chrome/browser/resources/md_downloads/item.html b/chrome/browser/resources/md_downloads/item.html index d1b4ec0..98d711f 100644 --- a/chrome/browser/resources/md_downloads/item.html +++ b/chrome/browser/resources/md_downloads/item.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> @@ -14,7 +15,7 @@ <dom-module id="downloads-item"> <template> - <style> + <style include="action-link"> :host { display: flex; flex-direction: column; @@ -316,6 +317,5 @@ </div> </template> - <link rel="import" type="css" href="chrome://resources/css/action_link.css"> <script src="chrome://downloads/item.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js index 29a6ca68..66db1a9 100644 --- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js +++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
@@ -587,7 +587,7 @@ * @return {boolean} * @private */ - dialogIsVisible_(dialogId, dialogToShow) { + dialogIsVisible_: function(dialogId, dialogToShow) { return dialogToShow == dialogId; },
diff --git a/chrome/browser/resources/settings/device_page/device_page.js b/chrome/browser/resources/settings/device_page/device_page.js index 5ec0105a..b3bb4acc 100644 --- a/chrome/browser/resources/settings/device_page/device_page.js +++ b/chrome/browser/resources/settings/device_page/device_page.js
@@ -219,7 +219,7 @@ * @return {string} Description of the power source. * @private */ - computePowerSourceName_(powerSources, lowPowerCharger) { + computePowerSourceName_: function (powerSources, lowPowerCharger) { if (lowPowerCharger) return this.i18n('powerSourceLowPowerCharger'); if (powerSources.length)
diff --git a/chrome/browser/resources/settings/device_page/display.js b/chrome/browser/resources/settings/device_page/display.js index 31e25c8..1a9a8c9 100644 --- a/chrome/browser/resources/settings/device_page/display.js +++ b/chrome/browser/resources/settings/device_page/display.js
@@ -118,7 +118,7 @@ * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays * @private */ - displayInfoFetched_(displays) { + displayInfoFetched_: function(displays) { if (!displays.length) return; settings.display.systemDisplayApi.getDisplayLayout( @@ -130,7 +130,7 @@ * @param {!Array<!chrome.system.display.DisplayLayout>} layouts * @private */ - displayLayoutFetched_(displays, layouts) { + displayLayoutFetched_: function(displays, layouts) { this.layouts = layouts; this.displays = displays; this.updateDisplayInfo_();
diff --git a/chrome/browser/resources/settings/device_page/stylus.html b/chrome/browser/resources/settings/device_page/stylus.html index 2d4a473..f6620b6 100644 --- a/chrome/browser/resources/settings/device_page/stylus.html +++ b/chrome/browser/resources/settings/device_page/stylus.html
@@ -22,11 +22,13 @@ </settings-toggle-button> </div> + <!-- TODO(scottchen): Make a proper a[href].settings-box with + icon-external (see: https://crbug.com/684005)--> <div class="settings-box"> <!-- TODO(jdufault): This should launch an intent (using the enable-intent-picker flag) that opens up the play store to a curated list of apps. --> - <a is="action-link" target="_blank" + <a target="_blank" href="https://play.google.com/store/apps/collection/promotion_30023cb_stylus_apps"> $i18n{stylusFindMoreApps} </a>
diff --git a/chrome/browser/resources/settings/internet_page/internet_page.js b/chrome/browser/resources/settings/internet_page/internet_page.js index cd63a51..342bab9 100644 --- a/chrome/browser/resources/settings/internet_page/internet_page.js +++ b/chrome/browser/resources/settings/internet_page/internet_page.js
@@ -236,7 +236,7 @@ * @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy * @return {boolean} */ - allowAddConnection_(globalPolicy) { + allowAddConnection_: function(globalPolicy) { return !globalPolicy.AllowOnlyPolicyNetworksToConnect; },
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.html b/chrome/browser/resources/settings/internet_page/network_summary_item.html index 40c730e..6940b89 100644 --- a/chrome/browser/resources/settings/internet_page/network_summary_item.html +++ b/chrome/browser/resources/settings/internet_page/network_summary_item.html
@@ -1,6 +1,8 @@ <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> <link rel="import" href="chrome://resources/cr_elements/network/cr_network_list.html"> <link rel="import" href="chrome://resources/cr_elements/network/cr_network_list_item.html"> +<link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> @@ -13,7 +15,7 @@ <dom-module name="network-summary-item"> <template> - <style include="settings-shared"> + <style include="settings-shared action-link"> paper-spinner { @apply(--cr-icon-height-width); margin: 0 var(--settings-box-row-padding); @@ -23,12 +25,6 @@ padding: 0 var(--settings-box-row-padding); } - .button-row { - align-items: center; - display: flex; - min-height: var(--settings-row-min-height); - } - .padded { @apply(--settings-list-frame-padding); } @@ -109,8 +105,11 @@ </cr-network-list> <template is="dom-if" if="[[knownNetworksIsVisible_(activeNetworkState)]]"> - <div class="button-row" actionable on-tap="onKnownNetworksTap_"> - <a is="action-link">$i18n{knownNetworksButton}</a> + <div class="list-item"> + <a is="action-link" class="list-button" + on-tap="onKnownNetworksTap_"> + $i18n{knownNetworksButton} + </a> </div> </template> </div>
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html index 8684f16..00635ba 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.html +++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -1,4 +1,5 @@ <link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/polymer.html"> @@ -29,7 +30,7 @@ <dom-module id="settings-languages-page"> <template> - <style include="settings-shared"> + <style include="settings-shared action-link"> #languagesCollapse .list-item.selected { min-height: var(--settings-row-two-line-min-height); } @@ -125,8 +126,11 @@ </paper-icon-button> </div> </template> - <div class="list-item list-button" on-tap="onAddLanguagesTap_"> - <a is="action-link">$i18n{addLanguages}</a> + <div class="list-item"> + <a is="action-link" class="list-button" + on-tap="onAddLanguagesTap_"> + $i18n{addLanguages} + </a> </div> </div> </iron-collapse> @@ -167,9 +171,11 @@ </paper-icon-button> </div> </template> - <div class="list-item list-button" - on-tap="onManageInputMethodsTap_"> - <a is="action-link">$i18n{manageInputMethods}</a> + <div class="list-item"> + <a is="action-link" class="list-button" + on-tap="onManageInputMethodsTap_"> + $i18n{manageInputMethods} + </a> </div> </div> </iron-collapse> @@ -199,8 +205,11 @@ </paper-checkbox> </label> </template> - <div class="list-item list-button" on-tap="onEditDictionaryTap_"> - <a is="action-link">$i18n{manageSpellCheck}</a> + <div class="list-item"> + <a is="action-link" class="list-button" + on-tap="onEditDictionaryTap_"> + $i18n{manageSpellCheck} + </a> </div> </div> </iron-collapse>
diff --git a/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js b/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js index ad3690d96..92d1223 100644 --- a/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js +++ b/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js
@@ -144,8 +144,8 @@ language: displayLanguage, inputMethods: combinedInputMethods, }); - for (var languageCode of languageFamilyCodes) - usedLanguages.add(languageCode); + for (var k = 0; k < languageFamilyCodes.length; k++) + usedLanguages.add(languageFamilyCodes[k]); } this.languageList_ = languageList; @@ -163,9 +163,9 @@ var /** !Set<string> */ usedInputMethods = new Set(); /** @type {!Array<chrome.languageSettingsPrivate.InputMethod>} */ var combinedInputMethods = []; - for (var languageCode of languageCodes) { + for (var i = 0; i < languageCodes.length; i++) { var inputMethods = this.languageHelper.getInputMethodsForLanguage( - languageCode); + languageCodes[i]); // Get the language's unused input methods and mark them as used. var newInputMethods = inputMethods.filter(function(inputMethod) { if (usedInputMethods.has(inputMethod.id))
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html index 8a4a1bf14..2627254 100644 --- a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html +++ b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html
@@ -1,4 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> @@ -11,7 +13,7 @@ <dom-module id="settings-startup-urls-page"> <template> - <style include="settings-shared"> + <style include="settings-shared action-link"> #outer { @apply(--settings-list-frame-padding); max-height: 395px; /** Enough height to show six entries. */ @@ -39,11 +41,17 @@ </div> <template is="dom-if" if="[[!prefs.session.startup_urls.controlledBy]]" restamp> - <div class="list-item list-button" id="addPage" on-tap="onAddPageTap_"> - $i18n{onStartupAddNewPage} + <div class="list-item" id="addPage"> + <a is="action-link" class="list-button" on-tap="onAddPageTap_"> + $i18n{onStartupAddNewPage} + </a> </div> - <div class="list-item list-button" id="useCurrentPages" - on-tap="onUseCurrentPagesTap_">$i18n{onStartupUseCurrent}</div> + <div class="list-item" id="useCurrentPages"> + <a is="action-link" class="list-button" + on-tap="onUseCurrentPagesTap_"> + $i18n{onStartupUseCurrent} + </a> + </div> </template> <template is="dom-if" if="[[prefs.session.startup_urls.extensionId]]" restamp>
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html index c11eec9..275186eb 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> <link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> <link rel="import" href="/i18n_setup.html"> @@ -9,9 +10,8 @@ <link rel="import" href="/settings_shared_css.html"> <dom-module id="settings-autofill-section"> - <link rel="import" type="css" href="chrome://resources/css/action_link.css"> <template> - <style include="settings-shared passwords-shared"> + <style include="settings-shared passwords-shared action-link"> .type-column { align-items: center; flex: 2; @@ -82,8 +82,10 @@ hidden$="[[hasSome_(addresses)]]"> $i18n{noAddressesFound} </div> - <div class="list-item list-button"> - <a is="action-link" on-tap="onAddAddressTap_">$i18n{addAddress}</a> + <div class="list-item"> + <a is="action-link" class="list-button" on-tap="onAddAddressTap_"> + $i18n{addAddress} + </a> </div> </div> <dialog is="cr-action-menu" id="addressSharedMenu"> @@ -136,8 +138,8 @@ hidden$="[[hasSome_(creditCards)]]"> $i18n{noCreditCardsFound} </div> - <div class="list-item list-button"> - <a is="action-link" on-tap="onAddCreditCardTap_"> + <div class="list-item"> + <a is="action-link" class="list-button" on-tap="onAddCreditCardTap_"> $i18n{addCreditCard} </a> </div>
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html index 7c9cfe4..befa6ed 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
@@ -12,8 +12,6 @@ <link rel="import" href="/settings_shared_css.html"> <dom-module id="passwords-section"> - <!-- action_link.css is needed for the |managePasswordsLabel| link --> - <link rel="import" type="css" href="chrome://resources/css/action_link.css"> <template> <style include="settings-shared passwords-shared"> #password {
diff --git a/chrome/browser/resources/settings/people_page/camera.js b/chrome/browser/resources/settings/people_page/camera.js index e31a25d..ce25918 100644 --- a/chrome/browser/resources/settings/people_page/camera.js +++ b/chrome/browser/resources/settings/people_page/camera.js
@@ -141,8 +141,8 @@ */ stopVideoTracks_: function(stream) { var tracks = stream.getVideoTracks(); - for (var t of tracks) - t.stop(); + for (var i = 0; i < tracks.length; i++) + tracks[i].stop(); }, /**
diff --git a/chrome/browser/resources/settings/people_page/lock_screen.html b/chrome/browser/resources/settings/people_page/lock_screen.html index cf290e9..017c2b7 100644 --- a/chrome/browser/resources/settings/people_page/lock_screen.html +++ b/chrome/browser/resources/settings/people_page/lock_screen.html
@@ -1,6 +1,7 @@ -<link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html"> <link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/people_page/lock_screen_constants.html"> @@ -13,14 +14,10 @@ <dom-module id="settings-lock-screen"> <template> - <style include="settings-shared"></style> + <style include="settings-shared action-link"></style> <style> .radio-indent { - margin-left: 28px; - } - - paper-button { - text-transform: none; + margin-left: 36px; } </style> @@ -33,15 +30,13 @@ <paper-radio-button name="pin+password"> $i18n{lockScreenPinOrPassword} </paper-radio-button> - <div class="settings-box continuation radio-indent" - hidden$="[[!showConfigurePinButton_(selectedUnlockType)]]"> - <!-- TODO(dbeam): I seriously doubt paper-button[is=action-link] is - a good idea. --> - <paper-button is="action-link" on-tap="onConfigurePin_"> - [[getSetupPinText_(hasPin)]] - </paper-button> - </div> </paper-radio-group> + <div class="list-item radio-indent" + hidden$="[[!showConfigurePinButton_(selectedUnlockType)]]"> + <a is="action-link" class="list-button" on-tap="onConfigurePin_"> + [[getSetupPinText_(hasPin)]] + </a> + </div> </div> <div class="settings-box">
diff --git a/chrome/browser/resources/settings/people_page/users_page.html b/chrome/browser/resources/settings/people_page/users_page.html index f0ddb52..36686f1 100644 --- a/chrome/browser/resources/settings/people_page/users_page.html +++ b/chrome/browser/resources/settings/people_page/users_page.html
@@ -1,3 +1,5 @@ +<link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> @@ -8,7 +10,7 @@ <dom-module id="settings-users-page"> <template> - <style include="settings-shared"> + <style include="settings-shared action-link"> .users { /* The users box must line up with the checkbox text. */ -webkit-margin-start: var(--settings-indent-width); @@ -59,11 +61,12 @@ disabled="[[isEditingUsersDisabled_(isOwner_, isWhitelistManaged_, prefs.cros.accounts.allowGuest.value)]]"> </settings-user-list> - <div id="add-user-button" class="list-item list-button" - on-tap="openAddUserDialog_" + <div id="add-user-button" class="list-item" hidden="[[isEditingUsersDisabled_(isOwner_, isWhitelistManaged_, prefs.cros.accounts.allowGuest.value)]]"> - $i18n{addUsers} + <a is="action-link" class="list-button" on-tap="openAddUserDialog_"> + $i18n{addUsers} + </a> </div> </div> </div>
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers.html b/chrome/browser/resources/settings/printing_page/cups_printers.html index be8dfb4..677f48c9 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printers.html +++ b/chrome/browser/resources/settings/printing_page/cups_printers.html
@@ -1,3 +1,5 @@ +<link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="/printing_page/cups_add_printer_dialog.html"> <link rel="import" href="/printing_page/cups_printers_list.html"> @@ -5,17 +7,7 @@ <dom-module id="settings-cups-printers"> <template> - <style include="settings-shared"> - a[is='action-link'] { - display: inline-block; - text-decoration: none; - } - - a[is='action-link']:hover { - color: blue; - text-decoration: underline; - } - + <style include="settings-shared action-link"> .settings-box .start { color: var(--paper-grey-500); } @@ -54,7 +46,7 @@ </style> <div class="settings-box first"> - <a is="action-link" on-tap="onAddPrinterTap_" actionable + <a is="action-link" on-tap="onAddPrinterTap_" hidden="[[!canAddPrinter_]]"> $i18n{addCupsPrinter} </a> @@ -79,7 +71,7 @@ </div> <div class="center" id="addPrinterErrorMessage" hidden> <span>$i18n{printerAddedFailedMessage}</span> - <a is="action-link" on-tap="onAddPrinterTap_" actionable> + <a is="action-link" on-tap="onAddPrinterTap_"> $i18n{printerAddedTryAgainMessage} </a> </div>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index c9a7031..f0f28d98 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -352,7 +352,10 @@ <if expr="chromeos"> <div actionable class="settings-box" on-tap="onAdobeFlashStorageClicked_"> - <div class="list-item list-button">$i18n{adobeFlashStorage}</div> + <div class="start"> + $i18n{adobeFlashStorage} + </div> + <button class="icon-external" is="paper-icon-button-light"></button> </div> </if> <category-setting-exceptions
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html index e5cb1c0..1dfd9a4 100644 --- a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html +++ b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> @@ -10,9 +11,8 @@ <link rel="import" href="/settings_shared_css.html"> <dom-module id="settings-reset-profile-dialog"> - <link rel="import" type="css" href="chrome://resources/css/action_link.css"> <template> - <style include="settings-shared"> + <style include="settings-shared action-link"> .footer a { vertical-align: middle; }
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_page.html b/chrome/browser/resources/settings/search_engines_page/search_engines_page.html index 35a512f..bae938a 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engines_page.html +++ b/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
@@ -1,6 +1,7 @@ -<link rel="import" href="chrome://resources/html/action_link.html"> -<link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> +<link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="/search_engines_page/search_engines_browser_proxy.html"> <link rel="import" href="/search_engines_page/search_engine_dialog.html"> @@ -9,9 +10,8 @@ <link rel="import" href="/settings_shared_css.html"> <dom-module id="settings-search-engines-page"> - <link rel="import" type="css" href="chrome://resources/css/action_link.css"> <template> - <style include="settings-shared"> + <style include="settings-shared action-link"> .extension-engines { @apply(--settings-list-frame-padding); } @@ -35,12 +35,12 @@ <div class="settings-box first"> <h2>$i18n{searchEnginesOther}</h2> </div> - <!-- TODO(dbeam): why does on-click work with keyboard but on-tap - doesn't? --> <settings-search-engines-list engines="[[otherEngines]]"> - <a class="list-item list-button" is="action-link" - on-tap="onAddSearchEngineTap_" id="addSearchEngine"> - $i18n{searchEnginesAddSearchEngine}</a> + <div class="list-item" id="addSearchEngine"> + <a is="action-link" class="list-button" on-tap="onAddSearchEngineTap_"> + $i18n{searchEnginesAddSearchEngine} + </a> + </div> </settings-search-engines-list> <template is="dom-if" if="[[showExtensionsList_]]">
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html index 9526560..22646f8 100644 --- a/chrome/browser/resources/settings/settings_shared_css.html +++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -78,10 +78,6 @@ -webkit-margin-start: 4px; } - [is='action-link'], - [is='action-link']:active, - [is='action-link']:hover, - [is='action-link']:visited, .primary-button, .tertiary-button, a[href] { @@ -95,8 +91,7 @@ }; } - a[href], - [is='action-link']:hover { + a[href] { text-decoration: none; } @@ -232,10 +227,11 @@ } /* This button has no ink ripple. */ - .list-item.list-button { - @apply(--settings-actionable); + .list-button[is='action-link'] { + min-height: inherit; + display: flex; align-items: center; - color: var(--google-blue-500); + flex: 1; font-weight: 500; }
diff --git a/chrome/browser/resources/settings/site_settings/site_details.html b/chrome/browser/resources/settings/site_settings/site_details.html index 0898ee3..767d5e3b 100644 --- a/chrome/browser/resources/settings/site_settings/site_details.html +++ b/chrome/browser/resources/settings/site_settings/site_details.html
@@ -1,4 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/html/action_link.html"> +<link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> @@ -12,7 +14,7 @@ <dom-module id="site-details"> <template> - <style include="settings-shared"> + <style include="settings-shared action-link"> .favicon-image { margin: 2px; } @@ -108,8 +110,10 @@ label="$i18n{siteSettingsUnsandboxedPlugins}" site="[[site]]"> </site-details-permission> - <div on-tap="onClearAndReset_" raised class="list-item list-button"> - $i18n{siteSettingsClearAndReset} + <div class="list-item"> + <a is="action-link" class="list-button" on-tap="onClearAndReset_" > + $i18n{siteSettingsClearAndReset} + </a> </div> </div> <website-usage-private-api id="usageApi"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 3a31875..4e8f3cbd 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -575,7 +575,7 @@ "//device/usb", "//extensions/features", "//media", - "//net:net_with_v8", + "//net:net", "//ppapi/features", "//printing/features", "//rlz/features",
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index acc2361..fb23d30 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -530,6 +530,14 @@ "//sandbox/linux:sandbox_services", ] } + + if (enable_pepper_cdms) { + sources += [ + "media/cdm_host_file_path.cc", + "media/cdm_host_file_path.h", + ] + public_deps += [ "//chrome/common:version_header" ] + } } process_version("version_header") {
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index 29930ce..d480ff03 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc
@@ -116,6 +116,8 @@ #if defined(OS_MACOSX) const base::FilePath::CharType kFrameworkName[] = FPL(PRODUCT_STRING " Framework.framework"); +const base::FilePath::CharType kFrameworkExecutableName[] = + FPL(PRODUCT_STRING " Framework"); #endif // OS_MACOSX #if defined(OS_WIN)
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h index 53a3b71..d738b8e 100644 --- a/chrome/common/chrome_constants.h +++ b/chrome/common/chrome_constants.h
@@ -29,6 +29,7 @@ // TODO(tfarina): Remove the comment above, when you fix components to use plist // on Mac. extern const base::FilePath::CharType kFrameworkName[]; +extern const base::FilePath::CharType kFrameworkExecutableName[]; #endif // OS_MACOSX #if defined(OS_WIN) extern const base::FilePath::CharType kBrowserResourcesDll[];
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc index 2e67b3b..be0eb7e6 100644 --- a/chrome/common/chrome_content_client.cc +++ b/chrome/common/chrome_content_client.cc
@@ -86,6 +86,10 @@ #include "chrome/common/widevine_cdm_constants.h" #endif +#if BUILDFLAG(ENABLE_PEPPER_CDMS) +#include "chrome/common/media/cdm_host_file_path.h" +#endif + #if defined(OS_ANDROID) #include "chrome/common/chrome_media_client_android.h" #endif @@ -540,26 +544,35 @@ } void ChromeContentClient::AddContentDecryptionModules( - std::vector<content::CdmInfo>* cdms) { + std::vector<content::CdmInfo>* cdms, + std::vector<content::CdmHostFilePath>* cdm_host_file_paths) { + if (cdms) { // TODO(jrummell): Need to have a better flag to indicate systems Widevine // is available on. For now we continue to use ENABLE_PEPPER_CDMS so that // we can experiment between pepper and mojo. #if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT) - base::FilePath adapter_path; - base::FilePath cdm_path; - std::vector<std::string> codecs_supported; - if (IsWidevineAvailable(&adapter_path, &cdm_path, &codecs_supported)) { - // CdmInfo needs |path| to be the actual Widevine library, - // not the adapter, so adjust as necessary. It will be in the - // same directory as the installed adapter. - const base::Version version(WIDEVINE_CDM_VERSION_STRING); - DCHECK(version.IsValid()); - cdms->push_back(content::CdmInfo(kWidevineCdmType, version, cdm_path, - codecs_supported)); - } + base::FilePath adapter_path; + base::FilePath cdm_path; + std::vector<std::string> codecs_supported; + if (IsWidevineAvailable(&adapter_path, &cdm_path, &codecs_supported)) { + // CdmInfo needs |path| to be the actual Widevine library, + // not the adapter, so adjust as necessary. It will be in the + // same directory as the installed adapter. + const base::Version version(WIDEVINE_CDM_VERSION_STRING); + DCHECK(version.IsValid()); + cdms->push_back(content::CdmInfo(kWidevineCdmType, version, cdm_path, + codecs_supported)); + } #endif // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT) - // TODO(jrummell): Add External Clear Key CDM for testing, if it's available. + // TODO(jrummell): Add External Clear Key CDM for testing, if it's + // available. + } + +#if BUILDFLAG(ENABLE_PEPPER_CDMS) + if (cdm_host_file_paths) + chrome::AddCdmHostFilePaths(cdm_host_file_paths); +#endif } static const char* const kChromeStandardURLSchemes[] = {
diff --git a/chrome/common/chrome_content_client.h b/chrome/common/chrome_content_client.h index 15f2628a..2eff7f7 100644 --- a/chrome/common/chrome_content_client.h +++ b/chrome/common/chrome_content_client.h
@@ -73,7 +73,9 @@ void AddPepperPlugins( std::vector<content::PepperPluginInfo>* plugins) override; void AddContentDecryptionModules( - std::vector<content::CdmInfo>* cdms) override; + std::vector<content::CdmInfo>* cdms, + std::vector<content::CdmHostFilePath>* cdm_host_file_paths) override; + void AddAdditionalSchemes(Schemes* schemes) override; std::string GetProduct() const override; std::string GetUserAgent() const override;
diff --git a/chrome/common/media/cdm_host_file_path.cc b/chrome/common/media/cdm_host_file_path.cc new file mode 100644 index 0000000..421f4db --- /dev/null +++ b/chrome/common/media/cdm_host_file_path.cc
@@ -0,0 +1,103 @@ +// 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/common/media/cdm_host_file_path.h" + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/path_service.h" +#include "build/build_config.h" +#include "chrome/common/chrome_version.h" + +#if defined(OS_MACOSX) +#include "base/mac/bundle_locations.h" +#include "chrome/common/chrome_constants.h" +#endif + +namespace chrome { + +namespace { + +using content::CdmHostFilePath; + +// TODO(xhwang): Move this to a common place if needed. +const base::FilePath::CharType kSignatureFileExtension[] = + FILE_PATH_LITERAL(".sig"); + +// Returns the signature file path given the |file_path|. This function should +// only be used when the signature file and the file are located in the same +// directory. +base::FilePath GetSigFilePath(const base::FilePath& file_path) { + return file_path.AddExtension(kSignatureFileExtension); +} + +} // namespace + +void AddCdmHostFilePaths( + std::vector<content::CdmHostFilePath>* cdm_host_file_paths) { + DVLOG(1) << __func__; + DCHECK(cdm_host_file_paths); + DCHECK(cdm_host_file_paths->empty()); + +#if defined(OS_WIN) + + static const base::FilePath::CharType* const kUnversionedFiles[] = { + FILE_PATH_LITERAL("chrome.exe")}; + static const base::FilePath::CharType* const kVersionedFiles[] = { + FILE_PATH_LITERAL("chrome.dll"), FILE_PATH_LITERAL("chrome_child.dll")}; + + // Find where chrome.exe is installed. + base::FilePath chrome_exe_dir; + if (!PathService::Get(base::DIR_EXE, &chrome_exe_dir)) + NOTREACHED(); + + cdm_host_file_paths->reserve(arraysize(kUnversionedFiles) + + arraysize(kVersionedFiles)); + + for (size_t i = 0; i < arraysize(kUnversionedFiles); ++i) { + base::FilePath file_path = chrome_exe_dir.Append(kUnversionedFiles[i]); + DVLOG(2) << __func__ << ": unversioned file " << i << " at " + << file_path.value(); + cdm_host_file_paths->push_back( + CdmHostFilePath(file_path, GetSigFilePath(file_path))); + } + + base::FilePath version_dir(chrome_exe_dir.AppendASCII(CHROME_VERSION_STRING)); + for (size_t i = 0; i < arraysize(kVersionedFiles); ++i) { + base::FilePath file_path = version_dir.Append(kVersionedFiles[i]); + DVLOG(2) << __func__ << ": versioned file " << i << " at " + << file_path.value(); + cdm_host_file_paths->push_back( + CdmHostFilePath(file_path, GetSigFilePath(file_path))); + } + +#elif defined(OS_MACOSX) + + base::FilePath chrome_framework_path = + base::mac::FrameworkBundlePath().Append(chrome::kFrameworkExecutableName); + + DVLOG(2) << __func__ + << ": chrome_framework_path=" << chrome_framework_path.value(); + cdm_host_file_paths->push_back(CdmHostFilePath( + chrome_framework_path, GetSigFilePath(chrome_framework_path))); + +#elif defined(OS_LINUX) + + base::FilePath chrome_exe_dir; + if (!PathService::Get(base::DIR_EXE, &chrome_exe_dir)) + NOTREACHED(); + + base::FilePath chrome_path = + chrome_exe_dir.Append(FILE_PATH_LITERAL("chrome")); + DVLOG(2) << __func__ << ": chrome_path=" << chrome_path.value(); + cdm_host_file_paths->push_back( + CdmHostFilePath(chrome_path, GetSigFilePath(chrome_path))); + +#endif // defined(OS_WIN) +} + +} // namespace chrome
diff --git a/chrome/common/media/cdm_host_file_path.h b/chrome/common/media/cdm_host_file_path.h new file mode 100644 index 0000000..3495536a --- /dev/null +++ b/chrome/common/media/cdm_host_file_path.h
@@ -0,0 +1,20 @@ +// 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_COMMON_MEDIA_CDM_HOST_FILE_PATH_H_ +#define CHROME_COMMON_MEDIA_CDM_HOST_FILE_PATH_H_ + +#include <vector> + +#include "content/public/common/cdm_info.h" + +namespace chrome { + +// Gets a list of CDM host file paths and put them in |cdm_host_file_paths|. +void AddCdmHostFilePaths( + std::vector<content::CdmHostFilePath>* cdm_host_file_paths); + +} // namespace chrome + +#endif // CHROME_COMMON_MEDIA_CDM_HOST_FILE_PATH_H_
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc index 9375555..de68108 100644 --- a/chrome/renderer/media/chrome_key_systems.cc +++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -63,6 +63,8 @@ // External Clear Key (used for testing). static void AddExternalClearKey( std::vector<std::unique_ptr<KeySystemProperties>>* concrete_key_systems) { + // TODO(xhwang): Move these into an array so we can use a for loop to add + // supported key systems below. static const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; static const char kExternalClearKeyDecryptOnlyKeySystem[] = @@ -79,6 +81,8 @@ "org.chromium.externalclearkey.initializefail"; static const char kExternalClearKeyCrashKeySystem[] = "org.chromium.externalclearkey.crash"; + static const char kExternalClearKeyVerifyCdmHostTestKeySystem[] = + "org.chromium.externalclearkey.verifycdmhosttest"; std::vector<base::string16> additional_param_names; std::vector<base::string16> additional_param_values; @@ -120,6 +124,10 @@ // A key system that triggers a crash in ClearKeyCdm. concrete_key_systems->emplace_back( new cdm::ExternalClearKeyProperties(kExternalClearKeyCrashKeySystem)); + + // A key system that triggers the verify host files test in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyVerifyCdmHostTestKeySystem)); } #if defined(WIDEVINE_CDM_AVAILABLE)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index e16115f..7179c43 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2186,6 +2186,7 @@ "../browser/chromeos/app_mode/arc/arc_kiosk_app_manager_browsertest.cc", "../browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc", "../browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc", + "../browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc", "../browser/chromeos/arc/arc_session_manager_browsertest.cc", "../browser/chromeos/arc/auth/arc_robot_auth_code_fetcher_browsertest.cc", "../browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc", @@ -2230,7 +2231,6 @@ "../browser/chromeos/first_run/goodies_displayer_browsertest.cc", "../browser/chromeos/input_method/input_method_engine_browsertests.cc", "../browser/chromeos/input_method/mode_indicator_browsertest.cc", - "../browser/chromeos/login/auto_launched_kiosk_browsertest.cc", "../browser/chromeos/login/bluetooth_host_pairing_browsertest.cc", "../browser/chromeos/login/crash_restore_browsertest.cc", "../browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc",
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 46150a0..2e1d91b 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -1944,11 +1944,9 @@ }, "SSLVersionMin": { - "note": "This policy is retired, see https://crbug.com/487730." }, "SSLVersionFallbackMin": { - "note": "This policy is retired, see https://crbug.com/621780." }, "CertificateTransparencyEnforcementDisabledForUrls": { @@ -1960,11 +1958,16 @@ }, "RC4Enabled": { - "note": "This policy is retired, see https://crbug.com/375342." }, "DHEEnabled": { - "note": "This policy is retired, see https://crbug.com/619194." + "os": ["win", "linux", "mac", "chromeos"], + "test_policy": { "DHEEnabled": true }, + "pref_mappings": [ + { "pref": "ssl.dhe_enabled", + "local_state": true + } + ] }, "WelcomePageOnOSUpgradeEnabled": {
diff --git a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js index aad0d078..418edb82 100644 --- a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js +++ b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
@@ -237,7 +237,7 @@ getFromElement('paper-radio-button[name="password"]'); pinPasswordRadioButton = getFromElement('paper-radio-button[name="pin+password"]'); - configureButton = getFromElement('paper-button'); + configureButton = getFromElement('a[is="action-link"]'); done(); });
diff --git a/chrome/test/data/webui/settings/search_engines_page_test.js b/chrome/test/data/webui/settings/search_engines_page_test.js index 6f26ef0..07456114 100644 --- a/chrome/test/data/webui/settings/search_engines_page_test.js +++ b/chrome/test/data/webui/settings/search_engines_page_test.js
@@ -328,7 +328,7 @@ // button is tapped. test('AddSearchEngineDialog', function() { assertFalse(!!page.$$('settings-search-engine-dialog')); - var addSearchEngineButton = page.$.addSearchEngine; + var addSearchEngineButton = page.$$('#addSearchEngine > a'); assertTrue(!!addSearchEngineButton); MockInteractions.tap(addSearchEngineButton);
diff --git a/chrome/test/data/webui/settings/startup_urls_page_test.js b/chrome/test/data/webui/settings/startup_urls_page_test.js index a0fa115..8028da3 100644 --- a/chrome/test/data/webui/settings/startup_urls_page_test.js +++ b/chrome/test/data/webui/settings/startup_urls_page_test.js
@@ -216,14 +216,14 @@ }); test('UseCurrentPages', function() { - var useCurrentPagesButton = page.$$('#useCurrentPages'); + var useCurrentPagesButton = page.$$('#useCurrentPages > a'); assertTrue(!!useCurrentPagesButton); MockInteractions.tap(useCurrentPagesButton); return browserProxy.whenCalled('useCurrentPages'); }); test('AddPage_OpensDialog', function() { - var addPageButton = page.$$('#addPage'); + var addPageButton = page.$$('#addPage > a'); assertTrue(!!addPageButton); assertFalse(!!page.$$('settings-startup-url-dialog'));
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index 48caceec..9e04b6d 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc
@@ -55,11 +55,6 @@ // mode. This can be enabled by this flag. const char kAllowRAInDevMode[] = "allow-ra-in-dev-mode"; -// Specifies whether an app launched in kiosk mode was auto launched with zero -// delay. Used in order to properly restore auto-launched state during session -// restore flow. -const char kAppAutoLaunched[] = "app-auto-launched"; - // Path for app's OEM manifest file. const char kAppOemManifestFile[] = "app-mode-oem-manifest";
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index 86d216a..90e0850 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h
@@ -27,7 +27,6 @@ CHROMEOS_EXPORT extern const char kAllowDataRoamingByDefault[]; CHROMEOS_EXPORT extern const char kAllowFailedPolicyFetchForTest[]; CHROMEOS_EXPORT extern const char kAllowRAInDevMode[]; -CHROMEOS_EXPORT extern const char kAppAutoLaunched[]; CHROMEOS_EXPORT extern const char kAppOemManifestFile[]; CHROMEOS_EXPORT extern const char kArcAvailable[]; CHROMEOS_EXPORT extern const char kArtifactsDir[];
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index f6bcad3..d4c757a9 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -8199,7 +8199,6 @@ 'dynamic_refresh': True, 'per_profile': False, }, - 'deprecated': True, 'example_value': 'ssl3', 'id': 279, 'caption': '''Minimum SSL version enabled''', @@ -8301,7 +8300,6 @@ 'dynamic_refresh': True, 'per_profile': False, }, - 'deprecated': True, 'example_value': False, 'id': 310, 'caption': '''Whether RC4 cipher suites in TLS are enabled''', @@ -8326,7 +8324,6 @@ 'dynamic_refresh': True, 'per_profile': False, }, - 'deprecated': True, 'example_value': False, 'id': 334, 'caption': '''Whether DHE cipher suites in TLS are enabled''',
diff --git a/components/ssl_config/ssl_config_prefs.cc b/components/ssl_config/ssl_config_prefs.cc index 7a515124..540be23a 100644 --- a/components/ssl_config/ssl_config_prefs.cc +++ b/components/ssl_config/ssl_config_prefs.cc
@@ -15,6 +15,7 @@ const char kSSLVersionMin[] = "ssl.version_min"; const char kSSLVersionMax[] = "ssl.version_max"; const char kCipherSuiteBlacklist[] = "ssl.cipher_suites.blacklist"; +const char kDHEEnabled[] = "ssl.dhe_enabled"; } // namespace prefs } // namespace ssl_config
diff --git a/components/ssl_config/ssl_config_prefs.h b/components/ssl_config/ssl_config_prefs.h index c10ed21..7f19e1e 100644 --- a/components/ssl_config/ssl_config_prefs.h +++ b/components/ssl_config/ssl_config_prefs.h
@@ -14,6 +14,7 @@ extern const char kSSLVersionMin[]; extern const char kSSLVersionMax[]; extern const char kCipherSuiteBlacklist[]; +extern const char kDHEEnabled[]; } // namespace prefs } // namespace ssl_config
diff --git a/components/ssl_config/ssl_config_service_manager_pref.cc b/components/ssl_config/ssl_config_service_manager_pref.cc index 9437237..0dab204 100644 --- a/components/ssl_config/ssl_config_service_manager_pref.cc +++ b/components/ssl_config/ssl_config_service_manager_pref.cc
@@ -175,6 +175,7 @@ BooleanPrefMember sha1_local_anchors_enabled_; StringPrefMember ssl_version_min_; StringPrefMember ssl_version_max_; + BooleanPrefMember dhe_enabled_; // The cached list of disabled SSL cipher suites. std::vector<uint16_t> disabled_cipher_suites_; @@ -215,6 +216,8 @@ local_state_callback); ssl_version_max_.Init(ssl_config::prefs::kSSLVersionMax, local_state, local_state_callback); + dhe_enabled_.Init(ssl_config::prefs::kDHEEnabled, local_state, + local_state_callback); local_state_change_registrar_.Init(local_state); local_state_change_registrar_.Add(ssl_config::prefs::kCipherSuiteBlacklist, @@ -243,6 +246,8 @@ registry->RegisterStringPref(ssl_config::prefs::kSSLVersionMax, std::string()); registry->RegisterListPref(ssl_config::prefs::kCipherSuiteBlacklist); + registry->RegisterBooleanPref(ssl_config::prefs::kDHEEnabled, + default_config.dhe_enabled); } net::SSLConfigService* SSLConfigServiceManagerPref::Get() { @@ -290,6 +295,7 @@ config->version_max = version_max; } config->disabled_cipher_suites = disabled_cipher_suites_; + config->dhe_enabled = dhe_enabled_.GetValue(); } void SSLConfigServiceManagerPref::OnDisabledCipherSuitesChange(
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc index 1c9183a..33d3c51 100644 --- a/components/translate/core/browser/translate_manager.cc +++ b/components/translate/core/browser/translate_manager.cc
@@ -4,7 +4,6 @@ #include "components/translate/core/browser/translate_manager.h" -#include <iostream> #include <map> #include "base/bind.h" @@ -225,14 +224,12 @@ InitTranslateEvent(language_code, target_lang, *translate_prefs); // Don't translate similar languages (ex: en-US to en). - // Also do not offer to translate between Simplified and Traditional Chinese. - if (language_code == target_lang || - (language_code == "zh-CN" && target_lang == "zh-TW") || - (language_code == "zh-TW" && target_lang == "zh-CN")) { + if (language_code == target_lang) { TranslateBrowserMetrics::ReportInitiationStatus( TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES); return; } + // Nothing to do if either the language Chrome is in or the language of the // page is not supported by the translation server. if (target_lang.empty() ||
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc index dfe0696..fda38d7 100644 --- a/components/translate/core/browser/translate_manager_unittest.cc +++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -307,64 +307,6 @@ 1); } -// The test measures that Translate is not triggered for a zh-TW page for a -// zh-CN user. -TEST_F(TranslateManagerTest, - DontTranslateZhTraditionalPageForZhSimplifiedLocale) { - TranslateManager::SetIgnoreMissingKeyForTesting(true); - translate_manager_.reset(new translate::TranslateManager( - &mock_translate_client_, kAcceptLanguages)); - - const char kMetricName[] = "Translate.InitiationStatus.v2"; - base::HistogramTester histogram_tester; - - const std::string locale = "zh-TW"; - const std::string page_lang = "zh-CN"; - - network_notifier_.SimulateOnline(); - manager_->set_application_locale(locale); - ON_CALL(mock_translate_client_, IsTranslatableURL(_)) - .WillByDefault(Return(true)); - - EXPECT_EQ("zh-TW", translate_manager_->GetTargetLanguage(&translate_prefs_)); - translate_manager_->GetLanguageState().LanguageDetermined(page_lang, true); - translate_manager_->InitiateTranslation(page_lang); - - histogram_tester.ExpectUniqueSample( - kMetricName, - translate::TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES, - 1); -} - -// The test measures that Translate is not triggered for a zh-CN page for a -// zh-TW user. -TEST_F(TranslateManagerTest, - DontTranslateZhSimplifiedPageForZhTraditionalLocale) { - TranslateManager::SetIgnoreMissingKeyForTesting(true); - translate_manager_.reset(new translate::TranslateManager( - &mock_translate_client_, kAcceptLanguages)); - - const char kMetricName[] = "Translate.InitiationStatus.v2"; - base::HistogramTester histogram_tester; - - const std::string locale = "zh-CN"; - const std::string page_lang = "zh-TW"; - - network_notifier_.SimulateOnline(); - manager_->set_application_locale(locale); - ON_CALL(mock_translate_client_, IsTranslatableURL(_)) - .WillByDefault(Return(true)); - - EXPECT_EQ("zh-CN", translate_manager_->GetTargetLanguage(&translate_prefs_)); - translate_manager_->GetLanguageState().LanguageDetermined(page_lang, true); - translate_manager_->InitiateTranslation(page_lang); - - histogram_tester.ExpectUniqueSample( - kMetricName, - translate::TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES, - 1); -} - // Utility function to set the threshold params void ChangeThresholdInParams( const char* initiate_translation_confidence_threshold,
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc index 0994d24..a48d5b6d 100644 --- a/content/app/content_main_runner.cc +++ b/content/app/content_main_runner.cc
@@ -112,6 +112,10 @@ #include "crypto/nss_util.h" #endif +#if BUILDFLAG(ENABLE_PEPPER_CDMS) +#include "content/common/media/cdm_host_files.h" +#endif + namespace content { extern int GpuMain(const content::MainFunctionParams&); #if BUILDFLAG(ENABLE_PLUGINS) @@ -334,6 +338,15 @@ command_line.GetSwitchValueASCII(switches::kProcessType); ContentClientInitializer::Set(process_type, delegate); +#if BUILDFLAG(ENABLE_PEPPER_CDMS) + if (process_type != switches::kPpapiPluginProcess) { + DVLOG(1) << "Closing CDM files for non-ppapi process."; + CdmHostFiles::TakeGlobalInstance().reset(); + } else { + DVLOG(1) << "Not closing CDM files for ppapi process."; + } +#endif + MainFunctionParams main_params(command_line); main_params.zygote_child = true;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index e4e9bb0..587428e 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -79,7 +79,6 @@ "//device/sensors/public/cpp", "//device/vibration", "//device/wake_lock", - "//gin", "//google_apis", "//gpu", "//gpu/command_buffer/client:gles2_implementation", @@ -1458,6 +1457,9 @@ "file_descriptor_info_impl.cc", "file_descriptor_info_impl.h", ] + + # On Windows, the browser cannot depend on gin/V8. + deps += [ "//gin" ] } if (enable_basic_printing || enable_print_preview) {
diff --git a/content/browser/DEPS b/content/browser/DEPS index 06eee06..375720da 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -27,6 +27,8 @@ "+device/vibration", # For Vibration API "+device/vr", # For WebVR API "+device/wake_lock", + # This can only be used on POSIX, in particular it mustn't be used on Windows + # in the browser DLL. "+gin/v8_initializer.h", "+mojo", "+services",
diff --git a/content/browser/media/cdm_registry_impl.cc b/content/browser/media/cdm_registry_impl.cc index fba9689..1f38fe0 100644 --- a/content/browser/media/cdm_registry_impl.cc +++ b/content/browser/media/cdm_registry_impl.cc
@@ -30,7 +30,7 @@ void CdmRegistryImpl::Init() { // Let embedders register CDMs. - GetContentClient()->AddContentDecryptionModules(&cdms_); + GetContentClient()->AddContentDecryptionModules(&cdms_, nullptr); } void CdmRegistryImpl::RegisterCdm(const CdmInfo& info) {
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc index 7b541e7..56d2023 100644 --- a/content/browser/ppapi_plugin_process_host.cc +++ b/content/browser/ppapi_plugin_process_host.cc
@@ -33,6 +33,7 @@ #include "content/public/common/sandbox_type.h" #include "content/public/common/sandboxed_process_launcher_delegate.h" #include "content/public/common/service_names.mojom.h" +#include "media/base/media_switches.h" #include "mojo/edk/embedder/embedder.h" #include "net/base/network_change_notifier.h" #include "ppapi/proxy/ppapi_messages.h" @@ -399,6 +400,8 @@ #if defined(OS_MACOSX) switches::kEnableSandboxLogging, #endif + // Need to tell CdmHostFile(s) to ignore missing CDM host files. + switches::kIgnoreMissingCdmHostFile, switches::kNoSandbox, switches::kPpapiStartupDialog, };
diff --git a/content/browser/zygote_host/zygote_communication_linux.cc b/content/browser/zygote_host/zygote_communication_linux.cc index 47554825..76548d22 100644 --- a/content/browser/zygote_host/zygote_communication_linux.cc +++ b/content/browser/zygote_host/zygote_communication_linux.cc
@@ -22,6 +22,7 @@ #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" #include "content/public/common/result_codes.h" +#include "media/base/media_switches.h" #include "ui/display/display_switches.h" #include "ui/gfx/switches.h" @@ -250,8 +251,7 @@ // Should this list be obtained from browser_render_process_host.cc? static const char* const kForwardSwitches[] = { switches::kAllowSandboxDebugging, switches::kAndroidFontsPath, - switches::kDisableSeccompFilterSandbox, - switches::kEnableHeapProfiling, + switches::kDisableSeccompFilterSandbox, switches::kEnableHeapProfiling, switches::kEnableLogging, // Support, e.g., --enable-logging=stderr. // Need to tell the zygote that it is headless so that we don't try to use // the wrong type of main delegate. @@ -261,6 +261,8 @@ switches::kForceDeviceScaleFactor, switches::kLoggingLevel, switches::kNoSandbox, switches::kPpapiInProcess, switches::kRegisterPepperPlugins, switches::kV, switches::kVModule, + // Need to tell CdmHostFile(s) to ignore missing CDM host files. + switches::kIgnoreMissingCdmHostFile, }; cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches, arraysize(kForwardSwitches));
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 46b56be6..c2efa7c 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -531,6 +531,23 @@ "external_ipc_dumper.h", ] } + + if (enable_pepper_cdms) { + sources += [ + "media/cdm_host_file.cc", + "media/cdm_host_file.h", + "media/cdm_host_files.cc", + "media/cdm_host_files.h", + ] + deps += [ + "//media:cdm_paths", + + # Needed for finding CDM path from CDM adapter path. + # TODO(xhwang): Remove this dependency when CDM adapter is deprecated. + # See http://crbug.com/403462 + "//third_party/widevine/cdm:headers", + ] + } } # See comment at the top of //content/BUILD.gn for how this works.
diff --git a/content/common/media/cdm_host_file.cc b/content/common/media/cdm_host_file.cc new file mode 100644 index 0000000..99d5cca2 --- /dev/null +++ b/content/common/media/cdm_host_file.cc
@@ -0,0 +1,72 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/media/cdm_host_file.h" + +#include <memory> + +#include "base/command_line.h" +#include "base/feature_list.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "media/base/media_switches.h" +#include "media/cdm/api/content_decryption_module_ext.h" + +namespace content { + +namespace { + +bool IgnoreMissingCdmHostFile() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kIgnoreMissingCdmHostFile); +} + +} // namespace + +// static +std::unique_ptr<CdmHostFile> CdmHostFile::Create( + const base::FilePath& file_path, + const base::FilePath& sig_file_path) { + // Open file at |file_path|. + base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!file.IsValid()) { + DVLOG(1) << "Failed to open file at " << file_path.MaybeAsASCII(); + return nullptr; + } + + // Also open the sig file at |sig_file_path|. + base::File sig_file(sig_file_path, + base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!sig_file.IsValid()) { + DVLOG(1) << "Failed to open sig file at " << sig_file_path.MaybeAsASCII(); + if (!IgnoreMissingCdmHostFile()) + return nullptr; + + DVLOG(1) << "Ignoring sig file failure at " << sig_file_path.MaybeAsASCII(); + } + + return std::unique_ptr<CdmHostFile>( + new CdmHostFile(file_path, std::move(file), std::move(sig_file))); +} + +cdm::HostFile CdmHostFile::TakePlatformFile() { + return cdm::HostFile(file_path_.value().c_str(), file_.TakePlatformFile(), + sig_file_.TakePlatformFile()); +} + +CdmHostFile::CdmHostFile(const base::FilePath& file_path, + base::File file, + base::File sig_file) + : file_path_(file_path), + file_(std::move(file)), + sig_file_(std::move(sig_file)) { + DVLOG(1) << __func__ << ": " << file_path_.value(); + DCHECK(!file_path_.empty()) << "File path is empty."; + DCHECK(file_.IsValid()) << "Invalid file."; + + if (!IgnoreMissingCdmHostFile()) + DCHECK(sig_file_.IsValid()) << "Invalid signature file."; +} + +} // namespace content
diff --git a/content/common/media/cdm_host_file.h b/content/common/media/cdm_host_file.h new file mode 100644 index 0000000..ade3a27 --- /dev/null +++ b/content/common/media/cdm_host_file.h
@@ -0,0 +1,53 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_COMMON_MEDIA_CDM_HOST_FILE_H_ +#define CONTENT_COMMON_MEDIA_CDM_HOST_FILE_H_ + +#include <memory> + +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/macros.h" + +namespace cdm { +struct HostFile; +} + +namespace content { + +// Represents a file that participated in hosting the CDM. +class CdmHostFile { + public: + // Opens the file at |file_path| and the corresponding signature file at + // |sig_file_path|. Upon success, constructs and returns a CdmHostFile object. + // Otherwise returns nullptr. The opened files are closed when |this| is + // destructed unless TakePlatformFile() was called, in which case the caller + // must make sure the files are closed properly. + static std::unique_ptr<CdmHostFile> Create( + const base::FilePath& file_path, + const base::FilePath& sig_file_path); + + // Takes the PlatformFile of the |file_| and |sig_file_| and put them in the + // returned cdm::HostFile. The caller must make sure the PlatformFiles are + // properly closed after use. + cdm::HostFile TakePlatformFile(); + + private: + CdmHostFile(const base::FilePath& file_path, + base::File file, + base::File sig_file); + + base::FilePath file_path_; + base::File file_; + + // The signature file associated with |file_|. + base::File sig_file_; + + DISALLOW_COPY_AND_ASSIGN(CdmHostFile); +}; + +} // namespace content + +#endif // CONTENT_COMMON_MEDIA_CDM_HOST_FILE_H_
diff --git a/content/common/media/cdm_host_files.cc b/content/common/media/cdm_host_files.cc new file mode 100644 index 0000000..637891e --- /dev/null +++ b/content/common/media/cdm_host_files.cc
@@ -0,0 +1,338 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/media/cdm_host_files.h" + +#include <map> +#include <memory> +#include <vector> + +#include "base/command_line.h" +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/native_library.h" +#include "base/path_service.h" +#include "base/scoped_native_library.h" +#include "build/build_config.h" +#include "content/common/media/cdm_host_file.h" +#include "content/public/common/cdm_info.h" +#include "content/public/common/content_client.h" +#include "media/base/media_switches.h" +#include "media/cdm/api/content_decryption_module_ext.h" +#include "media/cdm/cdm_paths.h" + +#if defined(POSIX_WITH_ZYGOTE) +#include "content/common/pepper_plugin_list.h" +#include "content/public/common/pepper_plugin_info.h" +#endif + +#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. + +namespace content { + +namespace { + +bool IgnoreMissingCdmHostFile() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kIgnoreMissingCdmHostFile); +} + +// TODO(xhwang): Move this to a common place if needed. +const base::FilePath::CharType kSignatureFileExtension[] = + FILE_PATH_LITERAL(".sig"); + +// Returns the signature file path given the |file_path|. This function should +// only be used when the signature file and the file are located in the same +// directory, which is the case for the CDM and CDM adapter. +base::FilePath GetSigFilePath(const base::FilePath& file_path) { + return file_path.AddExtension(kSignatureFileExtension); +} + +// Returns the CDM library file name given the |cdm_adapter_file_name|. Returns +// nullptr if |cdm_adapter_file_name| does not correspond to a known CDM. +const char* GetCdmFileName(const base::FilePath& cdm_adapter_file_name) { +#if defined(WIDEVINE_CDM_AVAILABLE) + if (cdm_adapter_file_name == + base::FilePath::FromUTF8Unsafe(kWidevineCdmAdapterFileName)) + return kWidevineCdmLibraryName; +#endif + + // Clear Key CDM. For test only. + if (cdm_adapter_file_name == + base::FilePath::FromUTF8Unsafe(media::kClearKeyCdmAdapterFileName)) + return media::kClearKeyCdmLibraryName; + + return nullptr; +} + +// Returns the path to the CDM binary given the |cdm_adapter_path|. Returns an +// empty path if |cdm_adapter_path| does not correspond to a known CDM. +base::FilePath GetCdmPath(const base::FilePath& cdm_adapter_path) { + const char* cdm_file_name = GetCdmFileName(cdm_adapter_path.BaseName()); + if (!cdm_file_name) + return base::FilePath(); + + return cdm_adapter_path.DirName().AppendASCII( + base::GetNativeLibraryName(cdm_file_name)); +} + +#if defined(POSIX_WITH_ZYGOTE) +// From the list of registered plugins, finds all registered CDMs and fills +// |cdm_adapter_paths| with found CDM adapters paths. +void GetRegisteredCdms(std::vector<base::FilePath>* cdm_adapter_paths) { + std::vector<PepperPluginInfo> plugins; + ComputePepperPluginList(&plugins); + for (const auto& plugin : plugins) { + // CDM is not an internal plugin. + if (plugin.is_internal) + continue; + + if (IsCdm(plugin.path)) + cdm_adapter_paths->push_back(plugin.path); + } +} + +// A global instance used on platforms where we have to open the files in the +// Zygote process. +base::LazyInstance<std::unique_ptr<CdmHostFiles>> g_cdm_host_files = + LAZY_INSTANCE_INITIALIZER; +#endif + +} // namespace + +CdmHostFiles::CdmHostFiles() { + DVLOG(1) << __func__; +} + +CdmHostFiles::~CdmHostFiles() { + DVLOG(1) << __func__; +} + +#if defined(POSIX_WITH_ZYGOTE) +// static +void CdmHostFiles::CreateGlobalInstance() { + DVLOG(1) << __func__; + DCHECK(!g_cdm_host_files.Get().get()); + + std::unique_ptr<CdmHostFiles> cdm_host_files = + base::MakeUnique<CdmHostFiles>(); + if (!cdm_host_files->OpenFilesForAllRegisteredCdms()) { + DVLOG(1) << __func__ << " failed."; + cdm_host_files.reset(); + return; + } + + g_cdm_host_files.Get().reset(cdm_host_files.release()); +} + +// static +std::unique_ptr<CdmHostFiles> CdmHostFiles::TakeGlobalInstance() { + return std::move(g_cdm_host_files.Get()); +} +#endif + +// static +std::unique_ptr<CdmHostFiles> CdmHostFiles::Create( + const base::FilePath& cdm_adapter_path) { + DVLOG(1) << __func__; + std::unique_ptr<CdmHostFiles> cdm_host_files = + base::MakeUnique<CdmHostFiles>(); + if (!cdm_host_files->OpenFiles(cdm_adapter_path)) { + cdm_host_files.reset(); + return nullptr; + } + + return cdm_host_files; +} + +bool CdmHostFiles::VerifyFiles(base::NativeLibrary cdm_adapter_library, + const base::FilePath& cdm_adapter_path) { + DVLOG(1) << __func__; + DCHECK(cdm_adapter_library); + + // Get function pointer exported by the CDM. + // See media/cdm/api/content_decryption_module_ext.h. + using VerifyCdmHostFunc = + bool (*)(const cdm::HostFile* cdm_host_files, uint32_t num_files); + static const char kVerifyCdmHostFuncName[] = "VerifyCdmHost_0"; + + base::NativeLibrary cdm_library; +#if defined(OS_LINUX) || defined(OS_MACOSX) + // On POSIX, "the dlsym() function shall search for the named symbol in all + // objects loaded automatically as a result of loading the object referenced + // by handle". Since the CDM is loaded automatically as a result of loading + // the CDM adapter, we can just use the adapter to look for CDM symbols. + cdm_library = cdm_adapter_library; +#elif defined(OS_WIN) + // On Windows, we have manually load the CDM. + base::ScopedNativeLibrary scoped_cdm_library; + base::NativeLibraryLoadError error; + scoped_cdm_library.Reset( + base::LoadNativeLibrary(GetCdmPath(cdm_adapter_path), &error)); + if (!scoped_cdm_library.is_valid()) { + LOG(ERROR) << "Failed to load CDM (error: " << error.ToString() << ")"; + CloseAllFiles(); + return true; + } + cdm_library = scoped_cdm_library.get(); +#endif + + VerifyCdmHostFunc verify_cdm_host_func = reinterpret_cast<VerifyCdmHostFunc>( + base::GetFunctionPointerFromNativeLibrary(cdm_library, + kVerifyCdmHostFuncName)); + if (!verify_cdm_host_func) { + LOG(ERROR) << "Function " << kVerifyCdmHostFuncName << " not found."; + CloseAllFiles(); + return true; + } + + // Fills |cdm_host_files| with common and CDM specific files for + // |cdm_adapter_path|. + std::vector<cdm::HostFile> cdm_host_files; + if (!TakePlatformFiles(cdm_adapter_path, &cdm_host_files)) { + DVLOG(1) << "Failed to take platform files."; + CloseAllFiles(); + return true; + } + + // Call |verify_cdm_host_func| on the CDM with |cdm_host_files|. Note that + // the ownership of these files are transferred to the CDM, which will close + // the files immediately after use. + DVLOG(1) << __func__ << ": Calling " << kVerifyCdmHostFuncName << "()."; + if (!verify_cdm_host_func(cdm_host_files.data(), cdm_host_files.size())) { + DVLOG(1) << "Failed to verify CDM host."; + CloseAllFiles(); + return false; + } + + // Close all files not passed to the CDM. + CloseAllFiles(); + return true; +} + +#if defined(POSIX_WITH_ZYGOTE) +bool CdmHostFiles::OpenFilesForAllRegisteredCdms() { + std::vector<base::FilePath> cdm_adapter_paths; + GetRegisteredCdms(&cdm_adapter_paths); + if (cdm_adapter_paths.empty()) { + DVLOG(1) << "No CDM registered."; + return false; + } + + // Ignore + for (auto& cdm_adapter_path : cdm_adapter_paths) { + bool result = OpenCdmFiles(cdm_adapter_path); + if (!result) + DVLOG(1) << "CDM files cannot be opened for " << cdm_adapter_path.value(); + // Ignore the failure and try other registered CDM. + } + + if (cdm_specific_files_map_.empty()) { + DVLOG(1) << "CDM specific files cannot be opened for any registered CDM."; + return false; + } + + return OpenCommonFiles(); +} +#endif + +bool CdmHostFiles::OpenFiles(const base::FilePath& cdm_adapter_path) { + if (!OpenCdmFiles(cdm_adapter_path)) + return false; + + return OpenCommonFiles(); +} + +bool CdmHostFiles::OpenCommonFiles() { + DCHECK(common_files_.empty()); + + std::vector<CdmHostFilePath> cdm_host_file_paths; + GetContentClient()->AddContentDecryptionModules(nullptr, + &cdm_host_file_paths); + + for (const CdmHostFilePath& value : cdm_host_file_paths) { + std::unique_ptr<CdmHostFile> cdm_host_file = + CdmHostFile::Create(value.file_path, value.sig_file_path); + if (cdm_host_file) { + common_files_.push_back(std::move(cdm_host_file)); + continue; + } + + if (!IgnoreMissingCdmHostFile()) + return false; + } + + return true; +} + +bool CdmHostFiles::OpenCdmFiles(const base::FilePath& cdm_adapter_path) { + DCHECK(!cdm_adapter_path.empty()); + DCHECK(!cdm_specific_files_map_.count(cdm_adapter_path)); + + std::unique_ptr<CdmHostFile> cdm_adapter_file = + CdmHostFile::Create(cdm_adapter_path, GetSigFilePath(cdm_adapter_path)); + if (!cdm_adapter_file) + return false; + + base::FilePath cdm_path = GetCdmPath(cdm_adapter_path); + std::unique_ptr<CdmHostFile> cdm_file = + CdmHostFile::Create(cdm_path, GetSigFilePath(cdm_path)); + if (!cdm_file) + return false; + + ScopedFileVector cdm_specific_files; + cdm_specific_files.reserve(2); + cdm_specific_files.push_back(std::move(cdm_adapter_file)); + cdm_specific_files.push_back(std::move(cdm_file)); + + cdm_specific_files_map_[cdm_adapter_path] = std::move(cdm_specific_files); + return true; +} + +bool CdmHostFiles::TakePlatformFiles( + const base::FilePath& cdm_adapter_path, + std::vector<cdm::HostFile>* cdm_host_files) { + DCHECK(cdm_host_files->empty()); + + if (!IgnoreMissingCdmHostFile()) + DCHECK(!common_files_.empty()); + + // Check whether CDM specific files exist. + const auto& iter = cdm_specific_files_map_.find(cdm_adapter_path); + if (iter == cdm_specific_files_map_.end()) { + // This could happen on Linux where CDM files fail to open for Foo CDM, but + // now we hit Bar CDM. + DVLOG(1) << "No CDM specific files for " << cdm_adapter_path.value(); + return false; + } + + const ScopedFileVector& cdm_specific_files = iter->second; + + cdm_host_files->reserve(common_files_.size() + cdm_specific_files.size()); + + // Populate an array of cdm::HostFile. + for (const auto& file : common_files_) + cdm_host_files->push_back(file->TakePlatformFile()); + + for (const auto& file : cdm_specific_files) + cdm_host_files->push_back(file->TakePlatformFile()); + + return true; +} + +void CdmHostFiles::CloseAllFiles() { + common_files_.clear(); + cdm_specific_files_map_.clear(); +} + +// Question(xhwang): Any better way to check whether a plugin is a CDM? Maybe +// when we register the plugin we can set some flag explicitly? +bool IsCdm(const base::FilePath& cdm_adapter_path) { + return !GetCdmPath(cdm_adapter_path).empty(); +} + +} // namespace content
diff --git a/content/common/media/cdm_host_files.h b/content/common/media/cdm_host_files.h new file mode 100644 index 0000000..5ec1daf --- /dev/null +++ b/content/common/media/cdm_host_files.h
@@ -0,0 +1,110 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_COMMON_MEDIA_CDM_HOST_FILES_H_ +#define CONTENT_COMMON_MEDIA_CDM_HOST_FILES_H_ + +#include <map> +#include <memory> +#include <vector> + +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/native_library.h" +#include "base/path_service.h" +#include "build/build_config.h" +#include "content/common/media/cdm_host_file.h" +#include "content/common/pepper_plugin_list.h" +#include "content/public/common/pepper_plugin_info.h" +#include "media/cdm/api/content_decryption_module_ext.h" +#include "media/cdm/cdm_paths.h" + +// On systems that use the zygote process to spawn child processes, we must +// open files in the zygote process. +#if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MACOSX) && \ + !defined(OS_ANDROID) +#define POSIX_WITH_ZYGOTE 1 +#endif + +namespace base { +class FilePath; +} + +namespace content { + +// Manages all CDM host files. +class CdmHostFiles { + public: + CdmHostFiles(); + ~CdmHostFiles(); + +#if defined(POSIX_WITH_ZYGOTE) + // Opens CDM host files for all registered CDMs and set the global + // CdmHostFiles instance. On any failure, the global instance will not be + // set and no file will be left open. + static void CreateGlobalInstance(); + + // Takes and returns the global CdmHostFiles instance. The return value could + // be nullptr if CreateGlobalInstance() failed. + static std::unique_ptr<CdmHostFiles> TakeGlobalInstance(); +#endif + + // Opens CDM host files for the CDM adapter at |cdm_adapter_path| and returns + // the created CdmHostFiles instance. Returns nullptr if any of the files + // cannot be opened, in which case no file will be left open. + static std::unique_ptr<CdmHostFiles> Create( + const base::FilePath& cdm_adapter_path); + + // Verifies |cdm_adapter_path| CDM files by calling the function exported + // by the CDM. If unexpected error happens, all files will be closed. + // Otherwise, the PlatformFiles are passed to the CDM which will close the + // files later. + // Only returns false if the CDM returns false (when there's an immediate + // failure). Otherwise always returns true for backward compatibility, e.g. + // when using an old CDM which doesn't implement the verification API. + bool VerifyFiles(base::NativeLibrary cdm_adapter_library, + const base::FilePath& cdm_adapter_path); + + private: +#if defined(POSIX_WITH_ZYGOTE) + // Opens all common files and CDM specific files for all registered CDMs. + bool OpenFilesForAllRegisteredCdms(); +#endif + + // Opens all common files and CDM specific files for the CDM adapter + // registered at |cdm_adapter_path|. + bool OpenFiles(const base::FilePath& cdm_adapter_path); + + // Opens common CDM host files shared by all CDMs. Upon failure, close all + // files opened. + bool OpenCommonFiles(); + + // Opens CDM specific files for the CDM adapter registered at + // |cdm_adapter_path|. Returns whether all CDM specific files are opened. + // Upon failure, close all files opened. + bool OpenCdmFiles(const base::FilePath& cdm_adapter_path); + + // Fills |cdm_host_files| with common and CDM specific files for + // |cdm_adapter_path|. The ownership of those files are also transferred. + // Returns true upon success where the remaining files will be closed. + // Returns false upon any failure and all files will be closed. + bool TakePlatformFiles(const base::FilePath& cdm_adapter_path, + std::vector<cdm::HostFile>* cdm_host_files); + + void CloseAllFiles(); + + using ScopedFileVector = std::vector<std::unique_ptr<CdmHostFile>>; + ScopedFileVector common_files_; + std::map<base::FilePath, ScopedFileVector> cdm_specific_files_map_; +}; + +// Returns whether the |cdm_adapter_path| corresponds to a known CDM. +bool IsCdm(const base::FilePath& cdm_adapter_path); + +} // namespace content + +#endif // CONTENT_COMMON_MEDIA_CDM_HOST_FILES_H_
diff --git a/content/common/media/cdm_info.cc b/content/common/media/cdm_info.cc index 0a3a7b1..3dbdcdab 100644 --- a/content/common/media/cdm_info.cc +++ b/content/common/media/cdm_info.cc
@@ -19,4 +19,10 @@ CdmInfo::~CdmInfo() {} +CdmHostFilePath::CdmHostFilePath(const base::FilePath& file_path, + const base::FilePath& sig_file_path) + : file_path(file_path), sig_file_path(sig_file_path) {} + +CdmHostFilePath::~CdmHostFilePath() {} + } // namespace content
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc index 7aa89dd..6743e954 100644 --- a/content/ppapi_plugin/ppapi_thread.cc +++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -65,6 +65,10 @@ #include "content/common/sandbox_init_mac.h" #endif +#if BUILDFLAG(ENABLE_PEPPER_CDMS) +#include "content/common/media/cdm_host_files.h" +#endif + #if defined(OS_WIN) const char kWidevineCdmAdapterFileName[] = "widevinecdmadapter.dll"; @@ -372,6 +376,22 @@ } } +#if BUILDFLAG(ENABLE_PEPPER_CDMS) + // Use a local instance of CdmHostFiles so that if we return early for any + // error, all files will closed automatically. + std::unique_ptr<CdmHostFiles> cdm_host_files; + +#if defined(OS_WIN) || defined(OS_MACOSX) + // Open CDM host files before the process is sandboxed. + if (!is_broker_ && IsCdm(path)) + cdm_host_files = CdmHostFiles::Create(path); +#elif defined(OS_LINUX) + cdm_host_files = CdmHostFiles::TakeGlobalInstance(); + if (is_broker_ || !IsCdm(path)) + cdm_host_files.reset(); // Close all opened files. +#endif // defined(OS_WIN) || defined(OS_MACOSX) +#endif // BUILDFLAG(ENABLE_PEPPER_CDMS) + #if defined(OS_WIN) // If code subsequently tries to exit using abort(), force a crash (since // otherwise these would be silent terminations and fly under the radar). @@ -458,6 +478,18 @@ ReportLoadResult(path, INIT_FAILED); return; } +#if BUILDFLAG(ENABLE_PEPPER_CDMS) + // Now the process is sandboxed. Verify CDM host. + if (cdm_host_files) { + DCHECK(IsCdm(path)); + if (!cdm_host_files->VerifyFiles(library.get(), path)) { + LOG(WARNING) << "CDM host verification failed."; + // TODO(xhwang): Add a new load result if needed. + ReportLoadResult(path, INIT_FAILED); + return; + } + } +#endif // BUILDFLAG(ENABLE_PEPPER_CDMS) } // Initialization succeeded, so keep the plugin DLL loaded.
diff --git a/content/public/common/cdm_info.h b/content/public/common/cdm_info.h index ee6780b2..ca66734 100644 --- a/content/public/common/cdm_info.h +++ b/content/public/common/cdm_info.h
@@ -39,6 +39,18 @@ std::vector<std::string> supported_codecs; }; +struct CONTENT_EXPORT CdmHostFilePath { + CdmHostFilePath(const base::FilePath& file_path, + const base::FilePath& sig_file_path); + ~CdmHostFilePath(); + + // Path to a file that takes part in hosting the CDM. + base::FilePath file_path; + + // Path to a signature file of the file at |file_path|. + base::FilePath sig_file_path; +}; + } // namespace content #endif // CONTENT_PUBLIC_COMMON_CDM_INFO_H_
diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h index 57a52fa..ea0bb0d 100644 --- a/content/public/common/content_client.h +++ b/content/public/common/content_client.h
@@ -45,6 +45,7 @@ class ContentRendererClient; class ContentUtilityClient; class OriginTrialPolicy; +struct CdmHostFilePath; struct CdmInfo; struct PepperPluginInfo; @@ -87,10 +88,13 @@ virtual void AddPepperPlugins( std::vector<content::PepperPluginInfo>* plugins) {} - // Gives the embedder a chance to register the content decryption - // modules it supports. + // Gives the embedder a chance to register the Content Decryption Modules + // (CDM) it supports, as well as the CDM host file paths to verify CDM host. + // |cdms| or |cdm_host_file_paths| can be null which means that specific list + // is not needed. virtual void AddContentDecryptionModules( - std::vector<content::CdmInfo>* cdms) {} + std::vector<content::CdmInfo>* cdms, + std::vector<content::CdmHostFilePath>* cdm_host_file_paths) {} // Gives the embedder a chance to register its own schemes early in the // startup sequence.
diff --git a/content/renderer/mus/BUILD.gn b/content/renderer/mus/BUILD.gn index 9f9daac6..5409466 100644 --- a/content/renderer/mus/BUILD.gn +++ b/content/renderer/mus/BUILD.gn
@@ -7,10 +7,10 @@ visibility = [ "//content/renderer/*" ] sources = [ - "render_widget_mus_connection.cc", - "render_widget_mus_connection.h", "render_widget_window_tree_client_factory.cc", "render_widget_window_tree_client_factory.h", + "renderer_window_tree_client.cc", + "renderer_window_tree_client.h", ] configs += [ "//content:content_implementation" ]
diff --git a/content/renderer/mus/render_widget_mus_connection.cc b/content/renderer/mus/render_widget_mus_connection.cc deleted file mode 100644 index 0d473b1..0000000 --- a/content/renderer/mus/render_widget_mus_connection.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/mus/render_widget_mus_connection.h" - -#include <map> - -#include "base/lazy_instance.h" -#include "base/macros.h" -#include "content/renderer/render_thread_impl.h" -#include "content/renderer/render_view_impl.h" -#include "services/ui/public/cpp/window_compositor_frame_sink.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" - -namespace content { - -namespace { - -typedef std::map<int, RenderWidgetMusConnection*> ConnectionMap; -base::LazyInstance<ConnectionMap>::Leaky g_connections = - LAZY_INSTANCE_INITIALIZER; -} - -void RenderWidgetMusConnection::Bind( - mojo::InterfaceRequest<ui::mojom::WindowTreeClient> request) { - // TODO(sad): crbug.com/672913 -} - -std::unique_ptr<cc::CompositorFrameSink> -RenderWidgetMusConnection::CreateCompositorFrameSink( - const cc::FrameSinkId& frame_sink_id, - scoped_refptr<cc::ContextProvider> context_provider, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { - // TODO(sad): crbug.com/672913 - return nullptr; -} - -// static -RenderWidgetMusConnection* RenderWidgetMusConnection::Get(int routing_id) { - auto it = g_connections.Get().find(routing_id); - if (it != g_connections.Get().end()) - return it->second; - return nullptr; -} - -// static -RenderWidgetMusConnection* RenderWidgetMusConnection::GetOrCreate( - int routing_id) { - RenderWidgetMusConnection* connection = Get(routing_id); - if (!connection) { - connection = new RenderWidgetMusConnection(routing_id); - g_connections.Get().insert(std::make_pair(routing_id, connection)); - } - return connection; -} - -RenderWidgetMusConnection::RenderWidgetMusConnection(int routing_id) - : routing_id_(routing_id) { - DCHECK(routing_id); -} - -RenderWidgetMusConnection::~RenderWidgetMusConnection() {} - -} // namespace content
diff --git a/content/renderer/mus/render_widget_mus_connection.h b/content/renderer/mus/render_widget_mus_connection.h deleted file mode 100644 index edf6697..0000000 --- a/content/renderer/mus/render_widget_mus_connection.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MUS_RENDER_WIDGET_MUS_CONNECTION_H_ -#define CONTENT_RENDERER_MUS_RENDER_WIDGET_MUS_CONNECTION_H_ - -#include "base/macros.h" -#include "base/threading/thread_checker.h" -#include "cc/output/compositor_frame_sink.h" -#include "cc/output/context_provider.h" -#include "content/common/content_export.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" - -namespace gpu { -class GpuMemoryBufferManager; -} - -namespace ui { -class WindowCompositorFrameSinkBinding; -} - -namespace content { - -// This lives in the main-thread, and manages the connection to the mus window -// server for a RenderWidget. -class CONTENT_EXPORT RenderWidgetMusConnection { - public: - // Bind to a WindowTreeClient request. - void Bind(mojo::InterfaceRequest<ui::mojom::WindowTreeClient> request); - - // Create a cc output surface. - std::unique_ptr<cc::CompositorFrameSink> CreateCompositorFrameSink( - const cc::FrameSinkId& frame_sink_id, - scoped_refptr<cc::ContextProvider> context_provider, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); - - static RenderWidgetMusConnection* Get(int routing_id); - - // Get the connection from a routing_id, if the connection doesn't exist, - // a new connection will be created. - static RenderWidgetMusConnection* GetOrCreate(int routing_id); - - private: - friend class CompositorMusConnection; - friend class CompositorMusConnectionTest; - - explicit RenderWidgetMusConnection(int routing_id); - ~RenderWidgetMusConnection(); - - const int routing_id_; - std::unique_ptr<ui::WindowCompositorFrameSinkBinding> - window_compositor_frame_sink_binding_; - - DISALLOW_COPY_AND_ASSIGN(RenderWidgetMusConnection); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MUS_RENDER_WIDGET_MUS_CONNECTION_H_
diff --git a/content/renderer/mus/render_widget_window_tree_client_factory.cc b/content/renderer/mus/render_widget_window_tree_client_factory.cc index 642a0e7a..e2a1998 100644 --- a/content/renderer/mus/render_widget_window_tree_client_factory.cc +++ b/content/renderer/mus/render_widget_window_tree_client_factory.cc
@@ -16,7 +16,7 @@ #include "content/common/render_widget_window_tree_client_factory.mojom.h" #include "content/public/common/connection_filter.h" #include "content/public/common/service_manager_connection.h" -#include "content/renderer/mus/render_widget_mus_connection.h" +#include "content/renderer/mus/renderer_window_tree_client.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/service_manager/public/cpp/interface_factory.h" #include "services/service_manager/public/cpp/interface_registry.h" @@ -31,9 +31,7 @@ void BindMusConnectionOnMainThread( uint32_t routing_id, ui::mojom::WindowTreeClientRequest request) { - RenderWidgetMusConnection* connection = - RenderWidgetMusConnection::GetOrCreate(routing_id); - connection->Bind(std::move(request)); + RendererWindowTreeClient::Get(routing_id)->Bind(std::move(request)); } // This object's lifetime is managed by ServiceManagerConnection because it's a
diff --git a/content/renderer/mus/renderer_window_tree_client.cc b/content/renderer/mus/renderer_window_tree_client.cc new file mode 100644 index 0000000..2be8bcf --- /dev/null +++ b/content/renderer/mus/renderer_window_tree_client.cc
@@ -0,0 +1,225 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/mus/renderer_window_tree_client.h" + +#include <map> + +#include "base/lazy_instance.h" +#include "services/ui/public/cpp/window_compositor_frame_sink.h" + +namespace content { + +namespace { +typedef std::map<int, RendererWindowTreeClient*> ConnectionMap; +base::LazyInstance<ConnectionMap>::Leaky g_connections = + LAZY_INSTANCE_INITIALIZER; +} // namespace + +// static +RendererWindowTreeClient* RendererWindowTreeClient::Get(int routing_id) { + auto it = g_connections.Get().find(routing_id); + if (it != g_connections.Get().end()) + return it->second; + return nullptr; +} + +// static +void RendererWindowTreeClient::Create(int routing_id) { + DCHECK(g_connections.Get().find(routing_id) == g_connections.Get().end()); + RendererWindowTreeClient* connection = + new RendererWindowTreeClient(routing_id); + g_connections.Get().insert(std::make_pair(routing_id, connection)); +} + +RendererWindowTreeClient::RendererWindowTreeClient(int routing_id) + : routing_id_(routing_id), binding_(this) {} + +RendererWindowTreeClient::~RendererWindowTreeClient() { + g_connections.Get().erase(routing_id_); +} + +void RendererWindowTreeClient::Bind( + ui::mojom::WindowTreeClientRequest request) { + binding_.Bind(std::move(request)); +} + +std::unique_ptr<cc::CompositorFrameSink> +RendererWindowTreeClient::CreateCompositorFrameSink( + const cc::FrameSinkId& frame_sink_id, + scoped_refptr<cc::ContextProvider> context_provider, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { + std::unique_ptr<ui::WindowCompositorFrameSinkBinding> frame_sink_binding; + auto frame_sink = ui::WindowCompositorFrameSink::Create( + frame_sink_id, std::move(context_provider), gpu_memory_buffer_manager, + &frame_sink_binding); + if (tree_) { + tree_->AttachCompositorFrameSink( + root_window_id_, frame_sink_binding->TakeFrameSinkRequest(), + mojo::MakeProxy(frame_sink_binding->TakeFrameSinkClient())); + } else { + pending_frame_sink_ = std::move(frame_sink_binding); + } + return std::move(frame_sink); +} + +void RendererWindowTreeClient::DestroySelf() { + delete this; +} + +void RendererWindowTreeClient::OnEmbed(ui::ClientSpecificId client_id, + ui::mojom::WindowDataPtr root, + ui::mojom::WindowTreePtr tree, + int64_t display_id, + ui::Id focused_window_id, + bool drawn) { + root_window_id_ = root->window_id; + tree_ = std::move(tree); + if (pending_frame_sink_) { + tree_->AttachCompositorFrameSink( + root_window_id_, pending_frame_sink_->TakeFrameSinkRequest(), + mojo::MakeProxy(pending_frame_sink_->TakeFrameSinkClient())); + pending_frame_sink_ = nullptr; + } +} + +void RendererWindowTreeClient::OnEmbeddedAppDisconnected(ui::Id window_id) { + // TODO(sad): Embedded mus-client (oopif) is gone. Figure out what to do. +} + +void RendererWindowTreeClient::OnUnembed(ui::Id window_id) { + CHECK_EQ(window_id, root_window_id_); + DestroySelf(); +} + +void RendererWindowTreeClient::OnCaptureChanged(ui::Id new_capture_window_id, + ui::Id old_capture_window_id) {} + +void RendererWindowTreeClient::OnTopLevelCreated(uint32_t change_id, + ui::mojom::WindowDataPtr data, + int64_t display_id, + bool drawn) { + NOTREACHED(); +} + +void RendererWindowTreeClient::OnWindowBoundsChanged( + ui::Id window_id, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) {} + +void RendererWindowTreeClient::OnClientAreaChanged( + uint32_t window_id, + const gfx::Insets& new_client_area, + const std::vector<gfx::Rect>& new_additional_client_areas) {} + +void RendererWindowTreeClient::OnTransientWindowAdded( + uint32_t window_id, + uint32_t transient_window_id) {} + +void RendererWindowTreeClient::OnTransientWindowRemoved( + uint32_t window_id, + uint32_t transient_window_id) {} + +void RendererWindowTreeClient::OnWindowHierarchyChanged( + ui::Id window_id, + ui::Id old_parent_id, + ui::Id new_parent_id, + std::vector<ui::mojom::WindowDataPtr> windows) {} + +void RendererWindowTreeClient::OnWindowReordered( + ui::Id window_id, + ui::Id relative_window_id, + ui::mojom::OrderDirection direction) {} + +void RendererWindowTreeClient::OnWindowDeleted(ui::Id window_id) { + // TODO(sad): With OOPIF, |window_id| may not be |root_window_id_|. We need to + // make sure that works correctly. + CHECK_EQ(window_id, root_window_id_); + DestroySelf(); +} + +void RendererWindowTreeClient::OnWindowVisibilityChanged(ui::Id window_id, + bool visible) {} + +void RendererWindowTreeClient::OnWindowOpacityChanged(ui::Id window_id, + float old_opacity, + float new_opacity) {} + +void RendererWindowTreeClient::OnWindowParentDrawnStateChanged(ui::Id window_id, + bool drawn) {} + +void RendererWindowTreeClient::OnWindowSharedPropertyChanged( + ui::Id window_id, + const std::string& name, + const base::Optional<std::vector<uint8_t>>& new_data) {} + +void RendererWindowTreeClient::OnWindowInputEvent( + uint32_t event_id, + ui::Id window_id, + std::unique_ptr<ui::Event> event, + bool matches_pointer_watcher) { + NOTREACHED(); +} + +void RendererWindowTreeClient::OnPointerEventObserved( + std::unique_ptr<ui::Event> event, + uint32_t window_id) { + NOTREACHED(); +} + +void RendererWindowTreeClient::OnWindowFocused(ui::Id focused_window_id) {} + +void RendererWindowTreeClient::OnWindowPredefinedCursorChanged( + ui::Id window_id, + ui::mojom::Cursor cursor) {} + +void RendererWindowTreeClient::OnWindowSurfaceChanged( + ui::Id window_id, + const cc::SurfaceInfo& surface_info) { + NOTIMPLEMENTED(); +} + +void RendererWindowTreeClient::OnDragDropStart( + const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data) {} + +void RendererWindowTreeClient::OnDragEnter( + ui::Id window_id, + uint32_t event_flags, + const gfx::Point& position, + uint32_t effect_bitmask, + const OnDragEnterCallback& callback) {} + +void RendererWindowTreeClient::OnDragOver(ui::Id window_id, + uint32_t event_flags, + const gfx::Point& position, + uint32_t effect_bitmask, + const OnDragOverCallback& callback) {} + +void RendererWindowTreeClient::OnDragLeave(ui::Id window_id) {} + +void RendererWindowTreeClient::OnCompleteDrop( + ui::Id window_id, + uint32_t event_flags, + const gfx::Point& position, + uint32_t effect_bitmask, + const OnCompleteDropCallback& callback) {} + +void RendererWindowTreeClient::OnPerformDragDropCompleted( + uint32_t window, + bool success, + uint32_t action_taken) {} + +void RendererWindowTreeClient::OnDragDropDone() {} + +void RendererWindowTreeClient::OnChangeCompleted(uint32_t change_id, + bool success) {} + +void RendererWindowTreeClient::RequestClose(uint32_t window_id) {} + +void RendererWindowTreeClient::GetWindowManager( + mojo::AssociatedInterfaceRequest<ui::mojom::WindowManager> internal) { + NOTREACHED(); +} + +} // namespace content
diff --git a/content/renderer/mus/renderer_window_tree_client.h b/content/renderer/mus/renderer_window_tree_client.h new file mode 100644 index 0000000..81662e5 --- /dev/null +++ b/content/renderer/mus/renderer_window_tree_client.h
@@ -0,0 +1,153 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MUS_RENDERER_WINDOW_TREE_CLIENT_H_ +#define CONTENT_RENDERER_MUS_RENDERER_WINDOW_TREE_CLIENT_H_ + +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/ui/common/types.h" +#include "services/ui/public/interfaces/window_tree.mojom.h" + +namespace cc { +class CompositorFrameSink; +class ContextProvider; +} + +namespace gpu { +class GpuMemoryBufferManager; +} + +namespace ui { +class WindowCompositorFrameSinkBinding; +} + +namespace content { + +// ui.mojom.WindowTreeClient implementation for RenderWidget. This lives and +// operates on the renderer's main thread. +class RendererWindowTreeClient : public ui::mojom::WindowTreeClient { + public: + // Creates a RendererWindowTreeClient instance for the RenderWidget instance + // associated with |routing_id|. The instance self-destructs when the + // connection to mus is lost, or when the window is closed. + static void Create(int routing_id); + + // Returns the RendererWindowTreeClient associated with |routing_id|. Returns + // nullptr if none exists. + static RendererWindowTreeClient* Get(int routing_id); + + void Bind(ui::mojom::WindowTreeClientRequest request); + + std::unique_ptr<cc::CompositorFrameSink> CreateCompositorFrameSink( + const cc::FrameSinkId& frame_sink_id, + scoped_refptr<cc::ContextProvider> context_provider, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); + + private: + explicit RendererWindowTreeClient(int routing_id); + ~RendererWindowTreeClient() override; + + void DestroySelf(); + + // ui::mojom::WindowTreeClient: + // Note: A number of the following are currently not-implemented. Some of + // these will remain unimplemented in the long-term. Some of the + // implementations would require some amount of refactoring out of + // RenderWidget and related classes (e.g. resize, input, ime etc.). + void OnEmbed(ui::ClientSpecificId client_id, + ui::mojom::WindowDataPtr root, + ui::mojom::WindowTreePtr tree, + int64_t display_id, + ui::Id focused_window_id, + bool drawn) override; + void OnEmbeddedAppDisconnected(ui::Id window_id) override; + void OnUnembed(ui::Id window_id) override; + void OnCaptureChanged(ui::Id new_capture_window_id, + ui::Id old_capture_window_id) override; + void OnTopLevelCreated(uint32_t change_id, + ui::mojom::WindowDataPtr data, + int64_t display_id, + bool drawn) override; + void OnWindowBoundsChanged(ui::Id window_id, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) override; + void OnClientAreaChanged( + uint32_t window_id, + const gfx::Insets& new_client_area, + const std::vector<gfx::Rect>& new_additional_client_areas) override; + void OnTransientWindowAdded(uint32_t window_id, + uint32_t transient_window_id) override; + void OnTransientWindowRemoved(uint32_t window_id, + uint32_t transient_window_id) override; + void OnWindowHierarchyChanged( + ui::Id window_id, + ui::Id old_parent_id, + ui::Id new_parent_id, + std::vector<ui::mojom::WindowDataPtr> windows) override; + void OnWindowReordered(ui::Id window_id, + ui::Id relative_window_id, + ui::mojom::OrderDirection direction) override; + void OnWindowDeleted(ui::Id window_id) override; + void OnWindowVisibilityChanged(ui::Id window_id, bool visible) override; + void OnWindowOpacityChanged(ui::Id window_id, + float old_opacity, + float new_opacity) override; + void OnWindowParentDrawnStateChanged(ui::Id window_id, bool drawn) override; + void OnWindowSharedPropertyChanged( + ui::Id window_id, + const std::string& name, + const base::Optional<std::vector<uint8_t>>& new_data) override; + void OnWindowInputEvent(uint32_t event_id, + ui::Id window_id, + std::unique_ptr<ui::Event> event, + bool matches_pointer_watcher) override; + void OnPointerEventObserved(std::unique_ptr<ui::Event> event, + uint32_t window_id) override; + void OnWindowFocused(ui::Id focused_window_id) override; + void OnWindowPredefinedCursorChanged(ui::Id window_id, + ui::mojom::Cursor cursor) override; + void OnWindowSurfaceChanged(ui::Id window_id, + const cc::SurfaceInfo& surface_info) override; + void OnDragDropStart( + const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data) + override; + void OnDragEnter(ui::Id window_id, + uint32_t event_flags, + const gfx::Point& position, + uint32_t effect_bitmask, + const OnDragEnterCallback& callback) override; + void OnDragOver(ui::Id window_id, + uint32_t event_flags, + const gfx::Point& position, + uint32_t effect_bitmask, + const OnDragOverCallback& callback) override; + void OnDragLeave(ui::Id window_id) override; + void OnCompleteDrop(ui::Id window_id, + uint32_t event_flags, + const gfx::Point& position, + uint32_t effect_bitmask, + const OnCompleteDropCallback& callback) override; + void OnPerformDragDropCompleted(uint32_t window, + bool success, + uint32_t action_taken) override; + void OnDragDropDone() override; + void OnChangeCompleted(uint32_t change_id, bool success) override; + void RequestClose(uint32_t window_id) override; + void GetWindowManager( + mojo::AssociatedInterfaceRequest<ui::mojom::WindowManager> internal) + override; + + const int routing_id_; + ui::Id root_window_id_; + ui::mojom::WindowTreePtr tree_; + std::unique_ptr<ui::WindowCompositorFrameSinkBinding> pending_frame_sink_; + mojo::Binding<ui::mojom::WindowTreeClient> binding_; + + DISALLOW_COPY_AND_ASSIGN(RendererWindowTreeClient); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MUS_RENDERER_WINDOW_TREE_CLIENT_H_
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index e374de41..791b768e 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -199,8 +199,8 @@ #endif #include "content/public/common/service_manager_connection.h" -#include "content/renderer/mus/render_widget_mus_connection.h" #include "content/renderer/mus/render_widget_window_tree_client_factory.h" +#include "content/renderer/mus/renderer_window_tree_client.h" #include "services/ui/public/cpp/gpu/gpu.h" #if defined(ENABLE_IPC_FUZZER) @@ -1894,13 +1894,12 @@ use_software = true; #if defined(USE_AURA) - if (GetServiceManagerConnection() && !use_software && - command_line.HasSwitch(switches::kUseMusInRenderer)) { - RenderWidgetMusConnection* connection = - RenderWidgetMusConnection::GetOrCreate(routing_id); - return connection->CreateCompositorFrameSink( - frame_sink_id, gpu_->CreateContextProvider(EstablishGpuChannelSync()), - GetGpuMemoryBufferManager()); + if (!use_software && command_line.HasSwitch(switches::kUseMusInRenderer)) { + return RendererWindowTreeClient::Get(routing_id) + ->CreateCompositorFrameSink( + frame_sink_id, + gpu_->CreateContextProvider(EstablishGpuChannelSync()), + GetGpuMemoryBufferManager()); } #endif
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 90a1550..3d64c0d 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -106,8 +106,7 @@ #endif // defined(OS_POSIX) #if defined(USE_AURA) -#include "content/public/common/service_manager_connection.h" -#include "content/renderer/mus/render_widget_mus_connection.h" +#include "content/renderer/mus/renderer_window_tree_client.h" #endif #if defined(OS_MACOSX) @@ -385,6 +384,12 @@ ->NewRenderWidgetSchedulingState(); render_widget_scheduling_state_->SetHidden(is_hidden_); } +#if defined(USE_AURA) + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUseMusInRenderer)) { + RendererWindowTreeClient::Create(routing_id_); + } +#endif } RenderWidget::~RenderWidget() {
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 8a57b370..77a2c78 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -222,6 +222,9 @@ self.Flaky('conformance2/textures/image_bitmap_from_video/' + 'tex-2d-rgba16f-rgba-half_float.html', ['mac', ('nvidia', 0xfe9)], bug=682834) + self.Fail('conformance/uniforms/' + + 'no-over-optimization-on-uniform-array-12.html', + ['mac', ('nvidia', 0xfe9)], bug=684903) self.Fail('deqp/functional/gles3/framebufferblit/conversion_04.html', ['mac', ('nvidia', 0xfe9)], bug=483282)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 4b00720..fcb0434 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -379,9 +379,6 @@ ['mac', ('nvidia', 0xfe9)], bug=635081) self.Fail('conformance/textures/misc/tex-input-validation.html', ['mac', ('nvidia', 0xfe9)], bug=635081) - self.Fail('conformance/uniforms/' + - 'no-over-optimization-on-uniform-array-12.html', - ['mac', ('nvidia', 0xfe9)], bug=684903) # Mac ASAN only self.Fail(
diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc index 02beffa..e1b5489 100644 --- a/content/zygote/zygote_main_linux.cc +++ b/content/zygote/zygote_main_linux.cc
@@ -76,6 +76,10 @@ #include <sanitizer/coverage_interface.h> #endif +#if BUILDFLAG(ENABLE_PEPPER_CDMS) +#include "content/common/media/cdm_host_files.h" +#endif + namespace content { namespace { @@ -367,6 +371,10 @@ InitializeWebRtcModule(); #endif +#if BUILDFLAG(ENABLE_PEPPER_CDMS) + CdmHostFiles::CreateGlobalInstance(); +#endif + SkFontConfigInterface::SetGlobal( new FontConfigIPC(GetSandboxFD()))->unref();
diff --git a/docs/updating_clang_format_binaries.md b/docs/updating_clang_format_binaries.md index 1915152..c030518d 100644 --- a/docs/updating_clang_format_binaries.md +++ b/docs/updating_clang_format_binaries.md
@@ -28,7 +28,7 @@ # [double check you have the tools you need] where cmake.exe # You need to install this. where svn.exe # Maybe fix with: set PATH=%PATH%;D:\src\depot_tools\svn_bin -"c:\Program Files (x86)\Microsoft Visual Studio 12.0\vc\vcvarsall.bat" amd64_x86 +"c:\Program Files (x86)\Microsoft Visual Studio 14.0\vc\vcvarsall.bat" amd64_x86 set CLANG_REV=198831 # You must change this value (see above) @@ -43,8 +43,8 @@ cd ..\..\llvm-build set CC=cl set CXX=cl -cmake -G Ninja ..\llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_USE_CRT_RELEASE=MT \ - -DLLVM_ENABLE_ASSERTIONS=NO -DLLVM_ENABLE_THREADS=NO \ +cmake -G Ninja ..\llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_USE_CRT_RELEASE=MT ^ + -DLLVM_ENABLE_ASSERTIONS=NO -DLLVM_ENABLE_THREADS=NO ^ -DPYTHON_EXECUTABLE=d:\src\depot_tools\python276_bin\python.exe ninja clang-format bin\clang-format.exe --version @@ -65,7 +65,7 @@ cd ../../llvm-build # Option 1: with cmake -MACOSX_DEPLOYMENT_TARGET=10.9 cmake -G Ninja -DCMAKE_BUILD_TYPE=Release \ +MACOSX_DEPLOYMENT_TARGET=10.9 cmake -G Ninja -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_ASSERTIONS=NO -DLLVM_ENABLE_THREADS=NO ../llvm/ time caffeinate ninja clang-format strip bin/clang-format
diff --git a/ios/chrome/browser/context_menu/context_menu_egtest.mm b/ios/chrome/browser/context_menu/context_menu_egtest.mm index 7afbc4c..398e057 100644 --- a/ios/chrome/browser/context_menu/context_menu_egtest.mm +++ b/ios/chrome/browser/context_menu/context_menu_egtest.mm
@@ -70,8 +70,7 @@ }; GREYAssert(testing::WaitUntilConditionOrTimeout( testing::kWaitForUIElementTimeout, condition), - [NSString stringWithFormat:@"Waiting for matcher %@ failed.", - contextMenuItemButton]); + @"Waiting for matcher %@ failed.", contextMenuItemButton); } // Long press on |elementId| to trigger context menu and then tap on
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm index 266f54d5..4412291 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
@@ -71,7 +71,7 @@ }; GREYAssert( testing::WaitUntilConditionOrTimeout(kWaitElementTimeout, condition), - [NSString stringWithFormat:@"Waiting for matcher %@ failed.", name]); + @"Waiting for matcher %@ failed.", name); } // Wait until |matcher| is accessible (not nil) and tap on it. @@ -373,10 +373,9 @@ histogramTester.GetHistogramSamplesSinceCreation( kPageLoadsBeforeEvictedTabSelected); int sampleSum = samples ? samples->sum() : 0; - GREYAssertEqual( - sampleSum, numberOfTabs * 2, - [NSString stringWithFormat:@"Expected page loads is %d, actual %d.", - numberOfTabs * 2, sampleSum]); + GREYAssertEqual(sampleSum, numberOfTabs * 2, + @"Expected page loads is %d, actual %d.", numberOfTabs * 2, + sampleSum); } // Tests that tabs reloaded on cold start are reported as @@ -779,10 +778,8 @@ histogramTester.GetHistogramSamplesSinceCreation( kPageLoadsBeforeEvictedTabSelected); int sampleSum = samples->sum(); - GREYAssertEqual( - sampleSum, 1, - [NSString stringWithFormat:@"Expected page loads is %d, actual is %d.", 1, - sampleSum]); + GREYAssertEqual(sampleSum, 1, @"Expected page loads is %d, actual is %d.", 1, + sampleSum); } // Tests that navigations are correctly reported in @@ -826,10 +823,8 @@ histogramTester.GetHistogramSamplesSinceCreation( kPageLoadsBeforeEvictedTabSelected); int sampleSum = samples->sum(); - GREYAssertEqual( - sampleSum, 2, - [NSString stringWithFormat:@"Expected page loads is %d, actual %d.", 2, - sampleSum]); + GREYAssertEqual(sampleSum, 2, @"Expected page loads is %d, actual %d.", 2, + sampleSum); FailureBlock failureBlock = ^(NSString* error) { GREYFail(error);
diff --git a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm index 6617b7d..d827393 100644 --- a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm +++ b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm
@@ -104,10 +104,9 @@ error:&error]; return error == nil; }; - GREYAssert( - testing::WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, - condition), - [NSString stringWithFormat:@"Waiting for matcher %@ failed.", matcher]); + GREYAssert(testing::WaitUntilConditionOrTimeout( + testing::kWaitForUIElementTimeout, condition), + @"Waiting for matcher %@ failed.", matcher); } // Asserts that |identity| is actually signed in to the active profile.
diff --git a/ios/chrome/browser/web/browsing_prevent_default_egtest.mm b/ios/chrome/browser/web/browsing_prevent_default_egtest.mm index cd6e955..87a96c66 100644 --- a/ios/chrome/browser/web/browsing_prevent_default_egtest.mm +++ b/ios/chrome/browser/web/browsing_prevent_default_egtest.mm
@@ -109,9 +109,8 @@ chrome_test_util::AssertMainTabCount(1U); const GURL& currentURL = chrome_test_util::GetCurrentWebState()->GetVisibleURL(); - GREYAssert(currentURL == testURL, - [NSString stringWithFormat:@"Page navigated unexpectedly %s", - currentURL.spec().c_str()]); + GREYAssert(currentURL == testURL, @"Page navigated unexpectedly %s", + currentURL.spec().c_str()); } // Taps a link with onclick="event.preventDefault()" and target="_blank" and
diff --git a/ios/chrome/test/earl_grey/chrome_assertions.mm b/ios/chrome/test/earl_grey/chrome_assertions.mm index 1088f2f..947d09ac 100644 --- a/ios/chrome/test/earl_grey/chrome_assertions.mm +++ b/ios/chrome/test/earl_grey/chrome_assertions.mm
@@ -20,8 +20,7 @@ ^{ return GetMainTabCount() == expected_tab_count; }), - [NSString stringWithFormat:@"Did not receive %" PRIuNS " tabs", - expected_tab_count]); + @"Did not receive %" PRIuNS " tabs", expected_tab_count); } void AssertIncognitoTabCount(NSUInteger expected_tab_count) { @@ -30,11 +29,9 @@ ConditionBlock condition = ^{ return GetIncognitoTabCount() == expected_tab_count; }; - GREYAssert( - testing::WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, - condition), - [NSString stringWithFormat:@"Did not receive %" PRIuNS " incognito tabs", - expected_tab_count]); + GREYAssert(testing::WaitUntilConditionOrTimeout( + testing::kWaitForUIElementTimeout, condition), + @"Did not receive %" PRIuNS " incognito tabs", expected_tab_count); } } // namespace chrome_test_util
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index c29a73f..16ec1cf0 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -87,10 +87,8 @@ BOOL success = web::test::TapWebViewElementWithId(chrome_test_util::GetCurrentWebState(), base::SysNSStringToUTF8(elementID)); - GREYAssertTrue( - success, - [NSString stringWithFormat:@"Failed to tap web view element with ID: %@", - elementID]); + GREYAssertTrue(success, @"Failed to tap web view element with ID: %@", + elementID); } @end
diff --git a/ios/third_party/earl_grey/BUILD.gn b/ios/third_party/earl_grey/BUILD.gn index be7a6f68..90314bb 100644 --- a/ios/third_party/earl_grey/BUILD.gn +++ b/ios/third_party/earl_grey/BUILD.gn
@@ -28,6 +28,8 @@ "src/EarlGrey/Action/GREYPathGestureUtils.m", "src/EarlGrey/Action/GREYPickerAction.h", "src/EarlGrey/Action/GREYPickerAction.m", + "src/EarlGrey/Action/GREYPinchAction.h", + "src/EarlGrey/Action/GREYPinchAction.m", "src/EarlGrey/Action/GREYScrollAction.h", "src/EarlGrey/Action/GREYScrollAction.m", "src/EarlGrey/Action/GREYScrollActionError.h", @@ -97,6 +99,7 @@ "src/EarlGrey/Assertion/GREYAssertions.m", "src/EarlGrey/Common/GREYAnalytics.h", "src/EarlGrey/Common/GREYAnalytics.m", + "src/EarlGrey/Common/GREYAnalyticsDelegate.h", "src/EarlGrey/Common/GREYConfiguration.h", "src/EarlGrey/Common/GREYConfiguration.m", "src/EarlGrey/Common/GREYConstants.h", @@ -104,16 +107,36 @@ "src/EarlGrey/Common/GREYDefines.h", "src/EarlGrey/Common/GREYElementHierarchy.h", "src/EarlGrey/Common/GREYElementHierarchy.m", + "src/EarlGrey/Common/GREYError+Internal.h", + "src/EarlGrey/Common/GREYError.h", + "src/EarlGrey/Common/GREYError.m", "src/EarlGrey/Common/GREYExposed.h", - "src/EarlGrey/Common/GREYPrivate.h", + "src/EarlGrey/Common/GREYFailureFormatter.h", + "src/EarlGrey/Common/GREYFailureFormatter.m", + "src/EarlGrey/Common/GREYFailureScreenshotter+Internal.h", + "src/EarlGrey/Common/GREYFailureScreenshotter.h", + "src/EarlGrey/Common/GREYFailureScreenshotter.m", + "src/EarlGrey/Common/GREYLogger.h", + "src/EarlGrey/Common/GREYLogger.m", + "src/EarlGrey/Common/GREYObjectFormatter+Internal.h", + "src/EarlGrey/Common/GREYObjectFormatter.h", + "src/EarlGrey/Common/GREYObjectFormatter.m", + "src/EarlGrey/Common/GREYScreenshotUtil+Internal.h", "src/EarlGrey/Common/GREYScreenshotUtil.h", "src/EarlGrey/Common/GREYScreenshotUtil.m", + "src/EarlGrey/Common/GREYStopwatch.h", + "src/EarlGrey/Common/GREYStopwatch.m", "src/EarlGrey/Common/GREYSwizzler.h", "src/EarlGrey/Common/GREYSwizzler.m", + "src/EarlGrey/Common/GREYTestCaseInvocation.h", + "src/EarlGrey/Common/GREYTestCaseInvocation.m", "src/EarlGrey/Common/GREYTestHelper.h", "src/EarlGrey/Common/GREYTestHelper.m", + "src/EarlGrey/Common/GREYVisibilityChecker+Internal.h", "src/EarlGrey/Common/GREYVisibilityChecker.h", "src/EarlGrey/Common/GREYVisibilityChecker.m", + "src/EarlGrey/Common/GREYWeakObjectContainer.h", + "src/EarlGrey/Common/GREYWeakObjectContainer.m", "src/EarlGrey/Core/GREYAutomationSetup.h", "src/EarlGrey/Core/GREYAutomationSetup.m", "src/EarlGrey/Core/GREYElementFinder.h", @@ -134,10 +157,14 @@ "src/EarlGrey/Delegate/GREYUIWebViewDelegate.m", "src/EarlGrey/EarlGrey.h", "src/EarlGrey/EarlGrey.m", - "src/EarlGrey/Event/GREYSingleSequenceTouchInjector.h", - "src/EarlGrey/Event/GREYSingleSequenceTouchInjector.m", "src/EarlGrey/Event/GREYSyntheticEvents.h", "src/EarlGrey/Event/GREYSyntheticEvents.m", + "src/EarlGrey/Event/GREYTouchInfo.h", + "src/EarlGrey/Event/GREYTouchInfo.m", + "src/EarlGrey/Event/GREYTouchInjector.h", + "src/EarlGrey/Event/GREYTouchInjector.m", + "src/EarlGrey/Event/GREYZeroToleranceTimer.h", + "src/EarlGrey/Event/GREYZeroToleranceTimer.m", "src/EarlGrey/Exception/GREYDefaultFailureHandler.h", "src/EarlGrey/Exception/GREYDefaultFailureHandler.m", "src/EarlGrey/Exception/GREYFailureHandler.h", @@ -176,6 +203,10 @@ "src/EarlGrey/Synchronization/GREYCondition.m", "src/EarlGrey/Synchronization/GREYDispatchQueueIdlingResource.h", "src/EarlGrey/Synchronization/GREYDispatchQueueIdlingResource.m", + "src/EarlGrey/Synchronization/GREYDispatchQueueTracker.h", + "src/EarlGrey/Synchronization/GREYDispatchQueueTracker.m", + "src/EarlGrey/Synchronization/GREYManagedObjectContextIdlingResource.h", + "src/EarlGrey/Synchronization/GREYManagedObjectContextIdlingResource.m", "src/EarlGrey/Synchronization/GREYNSTimerIdlingResource.h", "src/EarlGrey/Synchronization/GREYNSTimerIdlingResource.m", "src/EarlGrey/Synchronization/GREYOperationQueueIdlingResource.h", @@ -197,6 +228,7 @@ "src/EarlGrey/Action/GREYActionBlock.h", "src/EarlGrey/Action/GREYActions.h", "src/EarlGrey/Action/GREYBaseAction.h", + "src/EarlGrey/Action/GREYPinchAction.h", "src/EarlGrey/Action/GREYScrollActionError.h", "src/EarlGrey/AppSupport/GREYIdlingResource.h", "src/EarlGrey/Assertion/GREYAssertion.h", @@ -208,6 +240,7 @@ "src/EarlGrey/Common/GREYDefines.h", "src/EarlGrey/Common/GREYElementHierarchy.h", "src/EarlGrey/Common/GREYScreenshotUtil.h", + "src/EarlGrey/Common/GREYStopwatch.h", "src/EarlGrey/Common/GREYTestHelper.h", "src/EarlGrey/Core/GREYElementFinder.h", "src/EarlGrey/Core/GREYElementInteraction.h", @@ -225,6 +258,7 @@ "src/EarlGrey/Matcher/GREYNot.h", "src/EarlGrey/Provider/GREYDataEnumerator.h", "src/EarlGrey/Provider/GREYProvider.h", + "src/EarlGrey/Synchronization/GREYManagedObjectContextIdlingResource.h", "src/EarlGrey/Synchronization/GREYNSTimerIdlingResource.h", "src/EarlGrey/Synchronization/GREYOperationQueueIdlingResource.h", "src/EarlGrey/Synchronization/GREYDispatchQueueIdlingResource.h", @@ -240,10 +274,9 @@ public_deps = [ "//ios/third_party/ochamcrest:ochamcrest+link", ] - precompiled_header = "src/EarlGrey.pch" - precompiled_source = "src/EarlGrey.pch" libs = [ + "CoreData.framework", "CoreGraphics.framework", "Foundation.framework", "IOKit.framework",
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 5299efe7..30431d7 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -126,6 +126,11 @@ const char kMSEAudioBufferSizeLimit[] = "mse-audio-buffer-size-limit"; const char kMSEVideoBufferSizeLimit[] = "mse-video-buffer-size-limit"; +// By default, if any CDM host (including signature) file is missing, the CDM +// will not be called to verify the host. Enable this switch to ignore missing +// CDM host files. This can be used in tests. +const char kIgnoreMissingCdmHostFile[] = "ignore-missing-cdm-host-file"; + } // namespace switches namespace media {
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 781e927..7964461 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -71,6 +71,8 @@ MEDIA_EXPORT extern const char kMSEAudioBufferSizeLimit[]; MEDIA_EXPORT extern const char kMSEVideoBufferSizeLimit[]; +MEDIA_EXPORT extern const char kIgnoreMissingCdmHostFile[]; + } // namespace switches namespace media {
diff --git a/media/blink/webcontentdecryptionmodulesession_impl.cc b/media/blink/webcontentdecryptionmodulesession_impl.cc index bfb089e..e7546ffa 100644 --- a/media/blink/webcontentdecryptionmodulesession_impl.cc +++ b/media/blink/webcontentdecryptionmodulesession_impl.cc
@@ -495,7 +495,11 @@ void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate( base::Time new_expiry_time) { DCHECK(thread_checker_.CalledOnValidThread()); - client_->expirationChanged(new_expiry_time.ToJsTime()); + // The check works around an issue in base::Time that converts null base::Time + // to |1601-01-01 00:00:00 UTC| in ToJsTime(). See http://crbug.com/679079 + client_->expirationChanged(new_expiry_time.is_null() + ? std::numeric_limits<double>::quiet_NaN() + : new_expiry_time.ToJsTime()); } void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
diff --git a/media/cdm/cdm_paths.cc b/media/cdm/cdm_paths.cc index 7caeff1..b72daea 100644 --- a/media/cdm/cdm_paths.cc +++ b/media/cdm/cdm_paths.cc
@@ -13,6 +13,15 @@ // Name of the ClearKey CDM library. const char kClearKeyCdmLibraryName[] = "clearkeycdm"; +const char kClearKeyCdmAdapterFileName[] = +#if defined(OS_MACOSX) + "clearkeycdmadapter.plugin"; +#elif defined(OS_WIN) + "clearkeycdmadapter.dll"; +#elif defined(OS_POSIX) + "libclearkeycdmadapter.so"; +#endif + // Note: This file must be in sync with cdm_paths.gni. // TODO(xhwang): Improve how we enable platform specific path. See // http://crbug.com/468584
diff --git a/media/cdm/cdm_paths.h b/media/cdm/cdm_paths.h index 8ae6fe05..6060729 100644 --- a/media/cdm/cdm_paths.h +++ b/media/cdm/cdm_paths.h
@@ -14,6 +14,9 @@ // Name of the ClearKey CDM library. extern const char kClearKeyCdmLibraryName[]; +// Platform-specific filename relative to kClearKeyCdmBaseDirectory. +extern const char kClearKeyCdmAdapterFileName[]; + // Returns the path of a CDM relative to DIR_COMPONENTS. // On platforms where a platform specific path is used, returns // |cdm_base_path|/_platform_specific/<platform>_<arch>
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc index 4820555..54efa56 100644 --- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc +++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
@@ -10,6 +10,7 @@ #include <utility> #include "base/bind.h" +#include "base/files/file.h" #include "base/logging.h" #include "base/macros.h" #include "base/time/time.h" @@ -18,6 +19,7 @@ #include "media/base/cdm_key_information.h" #include "media/base/decoder_buffer.h" #include "media/base/decrypt_config.h" +#include "media/cdm/api/content_decryption_module_ext.h" #include "media/cdm/json_web_key.h" #include "media/cdm/ppapi/cdm_file_io_test.h" #include "media/cdm/ppapi/external_clear_key/cdm_video_decoder.h" @@ -64,6 +66,8 @@ "org.chromium.externalclearkey.platformverificationtest"; const char kExternalClearKeyCrashKeySystem[] = "org.chromium.externalclearkey.crash"; +const char kExternalClearKeyVerifyCdmHostTestKeySystem[] = + "org.chromium.externalclearkey.verifycdmhosttest"; // Constants for the enumalted session that can be loaded by LoadSession(). // These constants need to be in sync with @@ -234,7 +238,8 @@ key_system_string != kExternalClearKeyFileIOTestKeySystem && key_system_string != kExternalClearKeyOutputProtectionTestKeySystem && key_system_string != kExternalClearKeyPlatformVerificationTestKeySystem && - key_system_string != kExternalClearKeyCrashKeySystem) { + key_system_string != kExternalClearKeyCrashKeySystem && + key_system_string != kExternalClearKeyVerifyCdmHostTestKeySystem) { DVLOG(1) << "Unsupported key system:" << key_system_string; return NULL; } @@ -256,6 +261,42 @@ return kClearKeyCdmVersion; } +static bool g_verify_host_files_result = false; + +// Makes sure files and corresponding signature files are readable but not +// writable. +bool VerifyCdmHost_0(const cdm::HostFile* host_files, uint32_t num_files) { + DVLOG(1) << __func__; + + // We should always have the CDM and CDM adapter. + // We might not have any common CDM host file (e.g. chrome) since we are + // running in browser_tests. + if (num_files < 2) { + LOG(ERROR) << "Too few host files: " << num_files; + g_verify_host_files_result = false; + return true; + } + + for (uint32_t i = 0; i < num_files; ++i) { + const int kBytesToRead = 10; + std::vector<char> buffer(kBytesToRead); + + base::File file(static_cast<base::PlatformFile>(host_files[i].file)); + int bytes_read = file.Read(0, buffer.data(), buffer.size()); + if (bytes_read != kBytesToRead) { + LOG(ERROR) << "File bytes read: " << bytes_read; + g_verify_host_files_result = false; + return true; + } + + // TODO(xhwang): Check that the files are not writable. + // TODO(xhwang): Also verify the signature file when it's available. + } + + g_verify_host_files_result = true; + return true; +} + namespace media { ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, @@ -317,6 +358,8 @@ } else if (key_system_ == kExternalClearKeyPlatformVerificationTestKeySystem) { StartPlatformVerificationTest(); + } else if (key_system_ == kExternalClearKeyVerifyCdmHostTestKeySystem) { + VerifyCdmHostTest(); } } @@ -982,4 +1025,10 @@ challenge.data(), challenge.size()); } +void ClearKeyCdm::VerifyCdmHostTest() { + // VerifyCdmHost() should have already been called and test result stored + // in |g_verify_host_files_result|. + OnUnitTestComplete(g_verify_host_files_result); +} + } // namespace media
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.h b/media/cdm/ppapi/external_clear_key/clear_key_cdm.h index a16559d..a410aee 100644 --- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.h +++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.h
@@ -153,6 +153,8 @@ // Keep track of the last session created. void SetSessionId(const std::string& session_id); + void VerifyCdmHostTest(); + scoped_refptr<AesDecryptor> decryptor_; ClearKeyCdmHost* host_;
diff --git a/media/test/data/eme_player_js/globals.js b/media/test/data/eme_player_js/globals.js index 2d80031..81e344e1 100644 --- a/media/test/data/eme_player_js/globals.js +++ b/media/test/data/eme_player_js/globals.js
@@ -45,6 +45,8 @@ var PLATFORM_VERIFICATION_TEST_KEYSYSTEM = 'org.chromium.externalclearkey.platformverificationtest'; var CRASH_TEST_KEYSYSTEM = 'org.chromium.externalclearkey.crash'; +var VERIFY_HOST_FILES_TEST_KEYSYSTEM = + 'org.chromium.externalclearkey.verifycdmhosttest'; // Key system name:value map to show on the document page. var KEY_SYSTEMS = {
diff --git a/media/test/data/eme_player_js/player_utils.js b/media/test/data/eme_player_js/player_utils.js index f1dfb4e5..d5897364 100644 --- a/media/test/data/eme_player_js/player_utils.js +++ b/media/test/data/eme_player_js/player_utils.js
@@ -213,6 +213,7 @@ case FILE_IO_TEST_KEYSYSTEM: case OUTPUT_PROTECTION_TEST_KEYSYSTEM: case PLATFORM_VERIFICATION_TEST_KEYSYSTEM: + case VERIFY_HOST_FILES_TEST_KEYSYSTEM: return UnitTestPlayer; default: Utils.timeLog(keySystem + ' is not a known key system');
diff --git a/net/BUILD.gn b/net/BUILD.gn index 2df02d38..218d34b 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -2514,7 +2514,7 @@ } } -if (use_v8_in_net && !is_android) { +if (!is_ios && !is_android) { source_set("net_browser_services") { sources = [ "dns/mojo_host_resolver_impl.cc", @@ -2527,7 +2527,7 @@ ] public_deps = [ - ":net_with_v8", + ":net", "//base", "//mojo/public/cpp/bindings", "//net/interfaces",
diff --git a/net/proxy/proxy_resolver_v8.h b/net/proxy/proxy_resolver_v8.h index ce22407..bebfa15 100644 --- a/net/proxy/proxy_resolver_v8.h +++ b/net/proxy/proxy_resolver_v8.h
@@ -65,7 +65,7 @@ int GetProxyForURL(const GURL& url, ProxyInfo* results, JSBindings* bindings); - // Get total/ued heap memory usage of all v8 instances used by the proxy + // Get total/used heap memory usage of all v8 instances used by the proxy // resolver. static size_t GetTotalHeapSize(); static size_t GetUsedHeapSize();
diff --git a/net/proxy/proxy_service_mojo.cc b/net/proxy/proxy_service_mojo.cc index 4c8d41e4..394bcf7 100644 --- a/net/proxy/proxy_service_mojo.cc +++ b/net/proxy/proxy_service_mojo.cc
@@ -16,7 +16,6 @@ #include "net/proxy/network_delegate_error_observer.h" #include "net/proxy/proxy_resolver_factory.h" #include "net/proxy/proxy_resolver_factory_mojo.h" -#include "net/proxy/proxy_resolver_v8_tracing.h" #include "net/proxy/proxy_service.h" namespace net {
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index c993fa8f..4be80d7 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -993,12 +993,24 @@ SSL_clear_mode(ssl_.get(), mode.clear_mask); // Use BoringSSL defaults, but disable HMAC-SHA256 and HMAC-SHA384 ciphers - // (note that SHA256 and SHA384 only select legacy CBC ciphers). - std::string command("ALL:!SHA256:!SHA384:!kDHE:!aPSK:!RC4"); + // (note that SHA256 and SHA384 only select legacy CBC ciphers). Also disable + // DHE_RSA_WITH_AES_256_GCM_SHA384. Historically, AES_256_GCM was not + // supported. As DHE is being deprecated, don't add a cipher only to remove + // it immediately. + // + // TODO(davidben): Remove the DHE_RSA_WITH_AES_256_GCM_SHA384 exclusion when + // the DHEEnabled administrative policy expires. + std::string command( + "ALL:!SHA256:!SHA384:!DHE-RSA-AES256-GCM-SHA384:!aPSK:!RC4"); if (ssl_config_.require_ecdhe) command.append(":!kRSA:!kDHE"); + if (!ssl_config_.deprecated_cipher_suites_enabled) { + // Only offer DHE on the second handshake. https://crbug.com/538690 + command.append(":!kDHE"); + } + // Additionally disable HMAC-SHA1 ciphers in ECDSA. These are the remaining // CBC-mode ECDSA ciphers. if (!AreLegacyECDSACiphersEnabled()) @@ -1149,6 +1161,16 @@ ssl_session_cache_lookup_count_, 20); } + // DHE is offered on the deprecated cipher fallback and then rejected + // afterwards. This is to aid in diagnosing connection failures because a + // server requires DHE ciphers. + // + // TODO(davidben): A few releases after DHE's removal, remove this logic. + if (!ssl_config_.dhe_enabled && + SSL_CIPHER_is_DHE(SSL_get_current_cipher(ssl_.get()))) { + return ERR_SSL_OBSOLETE_CIPHER; + } + // Check that if token binding was negotiated, then extended master secret // and renegotiation indication must also be negotiated. if (tb_was_negotiated_ &&
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index ec24dcb..58c7fa8 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -2596,17 +2596,34 @@ EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); } -// Test that DHE is removed. -TEST_F(SSLClientSocketTest, NoDHE) { +// Test that DHE is removed but gives a dedicated error. Also test that the +// dhe_enabled option can restore it. +TEST_F(SSLClientSocketTest, DHE) { SpawnedTestServer::SSLOptions ssl_options; ssl_options.key_exchanges = SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; ASSERT_TRUE(StartTestServer(ssl_options)); + // Normal handshakes with DHE do not work, with or without DHE enabled. SSLConfig ssl_config; int rv; ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH)); + + ssl_config.dhe_enabled = true; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); + EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH)); + + // Enabling deprecated ciphers gives DHE a dedicated error code. + ssl_config.dhe_enabled = false; + ssl_config.deprecated_cipher_suites_enabled = true; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); + EXPECT_THAT(rv, IsError(ERR_SSL_OBSOLETE_CIPHER)); + + // Enabling both deprecated ciphers and DHE restores it. + ssl_config.dhe_enabled = true; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); + EXPECT_THAT(rv, IsOk()); } // Tests that enabling deprecated ciphers shards the session cache. @@ -2759,6 +2776,21 @@ TestFalseStart(server_options, client_config, false)); } +// Test that False Start is disabled with DHE_RSA ciphers. +TEST_F(SSLClientSocketFalseStartTest, DHE_RSA) { + SpawnedTestServer::SSLOptions server_options; + server_options.key_exchanges = + SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; + server_options.bulk_ciphers = + SpawnedTestServer::SSLOptions::BULK_CIPHER_AES128GCM; + server_options.alpn_protocols.push_back("http/1.1"); + SSLConfig client_config; + client_config.alpn_protos.push_back(kProtoHTTP11); + // DHE is only advertised when deprecated ciphers are enabled. + client_config.deprecated_cipher_suites_enabled = true; + ASSERT_NO_FATAL_FAILURE(TestFalseStart(server_options, client_config, false)); +} + // Test that False Start is disabled without an AEAD. TEST_F(SSLClientSocketFalseStartTest, NoAEAD) { SpawnedTestServer::SSLOptions server_options;
diff --git a/net/ssl/ssl_config.cc b/net/ssl/ssl_config.cc index 62e192e1..3275ac4 100644 --- a/net/ssl/ssl_config.cc +++ b/net/ssl/ssl_config.cc
@@ -27,6 +27,7 @@ version_min(kDefaultSSLVersionMin), version_max(kDefaultSSLVersionMax), deprecated_cipher_suites_enabled(false), + dhe_enabled(false), channel_id_enabled(true), false_start_enabled(true), signed_cert_timestamps_enabled(true),
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h index 1188a0d..0cc7f552 100644 --- a/net/ssl/ssl_config.h +++ b/net/ssl/ssl_config.h
@@ -103,11 +103,11 @@ // to them as far as downgrades are concerned, so this should only be used for // measurement of ciphers not to be carried long-term. It is no fix for // servers with bad configurations without full removal. - // - // TODO(davidben): This is no longer used. Remove - // it. https://crbug.com/684730. bool deprecated_cipher_suites_enabled; + // Enables DHE cipher suites. + bool dhe_enabled; + bool channel_id_enabled; // True if TLS channel ID extension is enabled. // List of Token Binding key parameters supported by the client. If empty,
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index ebebfac..58076877 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -8875,6 +8875,31 @@ EXPECT_EQ(kOriginHeaderValue, received_cors_header); } +// Test that DHE-only servers fail with the expected dedicated error code. +TEST_F(HTTPSRequestTest, DHE) { + SpawnedTestServer::SSLOptions ssl_options; + ssl_options.key_exchanges = + SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; + SpawnedTestServer test_server( + SpawnedTestServer::TYPE_HTTPS, ssl_options, + base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + ASSERT_TRUE(test_server.Start()); + + TestDelegate d; + { + std::unique_ptr<URLRequest> r(default_context_.CreateRequest( + test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); + + r->Start(); + EXPECT_TRUE(r->is_pending()); + + base::RunLoop().Run(); + + EXPECT_EQ(1, d.response_started_count()); + EXPECT_EQ(ERR_SSL_OBSOLETE_CIPHER, d.request_status()); + } +} + namespace { class SSLClientAuthTestDelegate : public TestDelegate {
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index aa796a76..89ee890 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -761,6 +761,8 @@ crbug.com/636239 [ Win7 ] media/video-zoom-controls.html [ Failure ] +crbug.com/684923 inspector/sources/debugger-async/async-callstack-promises.html [ NeedsManualRebaseline ] + crbug.com/432129 fast/html/marquee-scroll.html [ Failure Pass ] crbug.com/326139 crbug.com/390125 media/video-frame-accurate-seek.html [ Failure Pass ] crbug.com/248938 virtual/threaded/animations/animation-iteration-event-destroy-renderer.html [ Pass Timeout ] @@ -1914,7 +1916,6 @@ crbug.com/626703 external/wpt/workers/opaque-origin.html [ Failure Crash ] # Other untriaged test failures, timeouts and crashes from newly-imported WPT tests. -crbug.com/626703 external/wpt/dom/events/Event-dispatch-click.html [ Timeout Crash ] crbug.com/666703 external/wpt/html/browsers/sandboxing/sandbox-disallow-same-origin.html [ Timeout ] crbug.com/626703 external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.html [ Timeout ] crbug.com/626703 external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/compositing/iframes/floating-self-painting-frame-complex-expected.html b/third_party/WebKit/LayoutTests/compositing/iframes/floating-self-painting-frame-complex-expected.html new file mode 100644 index 0000000..5ab2433 --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/iframes/floating-self-painting-frame-complex-expected.html
@@ -0,0 +1,3 @@ +<!DOCTYPE html> +<iframe style="width: 400px; height: 500px" + srcdoc="<div style='width: 300px; height:400px; background: blue'></div>"></iframe>
diff --git a/third_party/WebKit/LayoutTests/compositing/iframes/floating-self-painting-frame-complex.html b/third_party/WebKit/LayoutTests/compositing/iframes/floating-self-painting-frame-complex.html new file mode 100644 index 0000000..2a32bc7c --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/iframes/floating-self-painting-frame-complex.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<script src="../../resources/run-after-layout-and-paint.js"></script> +<!-- This is similar to floating-self-painting-frame.html, but contains multiple +containing blocks and sibling blocks in which the floating objects overhangs +and intrudes. Tests shouldPaint flag is set on at most one ancestor containing +block. Passes if no crash (on display items with duplicated ids because the +iframe would be painted multiple times). --> +<style>div {height: 100px; background-color: white;}</style> +<div> + <div> + <div> + <iframe id="target" style="float: left; width: 400px; height: 100px" + srcdoc="<div style='width: 300px; height:400px; background: blue'></div>"></iframe> + <div></div> + <div></div> + </div> + </div> +</div> +<script> +if (window.internals) + window.internals.settings.setPreferCompositingToLCDTextEnabled(true); +runAfterLayoutAndPaint(function() { + target.style.height = "500px"; +}, true); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-click-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-click-expected.txt new file mode 100644 index 0000000..5928c6a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-click-expected.txt
@@ -0,0 +1,17 @@ +This is a testharness.js-based test. +PASS basic with click() +PASS basic with dispatchEvent() +PASS basic with wrong event class +PASS look at parents only when event bubbles +FAIL look at parents when event bubbles assert_true: expected true got false +FAIL pick the first with activation behavior <input type=checkbox> assert_true: child pre-click must be triggered expected true got false +PASS pick the first with activation behavior <a href> +PASS event state during post-click handling +PASS redispatch during post-click handling +PASS disabled checkbox still has activation behavior +PASS disabled checkbox still has activation behavior, part 2 +PASS disconnected checkbox should be checked +PASS disconnected radio should be checked +FAIL disconnected form should not submit assert_false: expected false got true +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js index 51857652..5765c5d 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
@@ -104,12 +104,14 @@ InspectorTest.runAsyncCallStacksTest = function(totalDebuggerStatements, maxAsyncCallStackDepth) { + var defaultMaxAsyncCallStackDepth = 8; + InspectorTest.setQuiet(true); InspectorTest.startDebuggerTest(step1); function step1() { - InspectorTest.DebuggerAgent.setAsyncCallStackDepth(maxAsyncCallStackDepth, step2); + InspectorTest.DebuggerAgent.setAsyncCallStackDepth(maxAsyncCallStackDepth || defaultMaxAsyncCallStackDepth, step2); } function step2()
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-fetch.html b/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-fetch.html index 5482979..b0247c5 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-fetch.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-fetch.html
@@ -23,8 +23,7 @@ var test = function() { var totalDebuggerStatements = 2; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator.html b/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator.html index e7bd3abca..227ea8c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator.html
@@ -31,7 +31,7 @@ var test = function() { - var maxAsyncCallStackDepth = 4; + var maxAsyncCallStackDepth = 8; var numberOfConsoleMessages = 2; InspectorTest.setQuiet(true);
diff --git a/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt b/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt index bdb496b..ae83a282 100644 --- a/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
@@ -13,7 +13,7 @@ frontend: {"id":<number>,"method":"Page.configureOverlay","params":{"suspended":false}} frontend: {"id":<number>,"method":"Debugger.enable"} frontend: {"id":<number>,"method":"Debugger.setPauseOnExceptions","params":{"state":"none"}} -frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"maxDepth":4}} +frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"maxDepth":8}} frontend: {"id":<number>,"method":"DOM.enable"} frontend: {"id":<number>,"method":"CSS.enable"} frontend: {"id":<number>,"method":"Target.setAutoAttach","params":{"autoAttach":true,"waitForDebuggerOnStart":true}}
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await1.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await1.html index e6b33037..a51fd15 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await1.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await1.html
@@ -96,8 +96,7 @@ var test = function() { var totalDebuggerStatements = 4; - var maxAsyncCallStackDepth = 5; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await2.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await2.html index d87dd494..25a5011c 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await2.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await2.html
@@ -92,8 +92,7 @@ var test = function() { var totalDebuggerStatements = 6; - var maxAsyncCallStackDepth = 5; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await3.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await3.html index 77b73e4..8988715 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await3.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-await/async-callstack-async-await3.html
@@ -133,8 +133,7 @@ var test = function() { var totalDebuggerStatements = 5; - var maxAsyncCallStackDepth = 5; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-events.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-events.html index 05b1d1d..a67ab99 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-events.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-events.html
@@ -74,8 +74,7 @@ var test = function() { var totalDebuggerStatements = 4; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-expected.txt index adb5d402..a5e235c0 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-expected.txt
@@ -71,5 +71,13 @@ 0) longTail3 (:3) [setTimeout] 0) longTail4 (:4) + [setTimeout] + 0) longTail5 (:5) + [setTimeout] + 0) longTail6 (:6) + [setTimeout] + 0) longTail7 (:7) + [setTimeout] + 0) longTail8 (:8)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-get-as-string.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-get-as-string.html index 80bf70b2..c2afce9 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-get-as-string.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-get-as-string.html
@@ -41,8 +41,7 @@ function test() { var totalDebuggerStatements = 2; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-in-console.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-in-console.html index 70acff1..42841ad 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-in-console.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-in-console.html
@@ -42,7 +42,7 @@ var test = function() { - var maxAsyncCallStackDepth = 4; + var maxAsyncCallStackDepth = 8; var numberOfConsoleMessages = 5; InspectorTest.setQuiet(true);
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db-expected.txt index d433bb0..7186848 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db-expected.txt
@@ -15,6 +15,9 @@ 0) openDB (async-callstack-indexed-db.html:23) [setTimeout] 0) testFunction (async-callstack-indexed-db.html:12) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Call stack: 0) onSuccessDeleteDatabase (async-callstack-indexed-db.html:104) @@ -30,6 +33,13 @@ [IndexedDB] 0) populateDB (async-callstack-indexed-db.html:52) 1) onSuccessOpenDB (async-callstack-indexed-db.html:45) + [IndexedDB] + 0) openDB (async-callstack-indexed-db.html:23) + [setTimeout] + 0) testFunction (async-callstack-indexed-db.html:12) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Call stack: 0) onSuccessDeleteItem (async-callstack-indexed-db.html:90) @@ -44,6 +54,11 @@ 1) onSuccessOpenDB (async-callstack-indexed-db.html:45) [IndexedDB] 0) openDB (async-callstack-indexed-db.html:23) + [setTimeout] + 0) testFunction (async-callstack-indexed-db.html:12) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Call stack: 0) onSuccessOpenDB (async-callstack-indexed-db.html:43)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db.html index d6aceadd..6bd9cfe8 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db.html
@@ -107,8 +107,7 @@ function test() { var totalDebuggerStatements = 6; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-middle-run.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-middle-run.html index 257b114f..a974c9b8 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-middle-run.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-middle-run.html
@@ -29,7 +29,7 @@ var test = function() { var totalDebuggerStatements = 3; - var maxAsyncCallStackDepth = 4; + var maxAsyncCallStackDepth = 8; InspectorTest.setQuiet(true); InspectorTest.startDebuggerTest(step1);
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer-expected.txt index bc2f27c..784212e 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer-expected.txt
@@ -53,6 +53,11 @@ [attributes] 0) doMutations1 (async-callstack-mutation-observer.html:50) 1) timeout1 (async-callstack-mutation-observer.html:44) + [setTimeout] + 0) testFunction (async-callstack-mutation-observer.html:35) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Call stack: 0) timeoutFromMutation (async-callstack-mutation-observer.html:70) @@ -79,5 +84,8 @@ 1) timeout1 (async-callstack-mutation-observer.html:44) [setTimeout] 0) testFunction (async-callstack-mutation-observer.html:35) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer.html index e74b27d..4b0a23c 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer.html
@@ -79,8 +79,7 @@ var test = function() { var totalDebuggerStatements = 6; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message-expected.txt index e0d340c9..e4c36eab 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message-expected.txt
@@ -16,6 +16,9 @@ 1) timeout (async-callstack-post-message.html:16) [setTimeout] 0) testFunction (async-callstack-post-message.html:9) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Call stack: 0) onMessageReceivedInFrame (post-message-listener.html:7) @@ -42,6 +45,11 @@ [postMessage] 0) postMessageToFrame (async-callstack-post-message.html:35) 1) timeout (async-callstack-post-message.html:16) + [setTimeout] + 0) testFunction (async-callstack-post-message.html:9) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Call stack: 0) onMessageReceivedInParent (async-callstack-post-message.html:21)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message.html index a372623..6a9d073 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message.html
@@ -38,8 +38,7 @@ var test = function() { var totalDebuggerStatements = 5; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises-expected.txt index d979d19..d6fc299 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises-expected.txt
@@ -31,6 +31,13 @@ 2) chained1 (async-callstack-promises.html:110) [Promise.resolve] 0) resolvePromise (async-callstack-promises.html:12) + [setTimeout] + 0) promiseCallback (async-callstack-promises.html:21) + 1) timeoutPromise (async-callstack-promises.html:9) + 2) doTestThrowFromChain (async-callstack-promises.html:109) + 3) testFunctionTimeout (async-callstack-promises.html:50) + [setTimeout] + 0) testFunction (async-callstack-promises.html:43) Call stack: 0) catchCallback (async-callstack-promises.html:130) @@ -46,6 +53,14 @@ 0) promiseCallback (async-callstack-promises.html:21) 1) timeoutPromise (async-callstack-promises.html:9) 2) chained2 (async-callstack-promises.html:124) + [Promise.resolve] + 0) resolvePromise (async-callstack-promises.html:12) + [setTimeout] + 0) promiseCallback (async-callstack-promises.html:21) + 1) timeoutPromise (async-callstack-promises.html:9) + 2) chained1 (async-callstack-promises.html:122) + [Promise.resolve] + 0) resolvePromise (async-callstack-promises.html:12) Call stack: 0) chained1 (async-callstack-promises.html:80) @@ -77,6 +92,11 @@ 1) timeoutPromise (async-callstack-promises.html:9) 2) doTestChainedPromises (async-callstack-promises.html:79) 3) testFunctionTimeout (async-callstack-promises.html:50) + [setTimeout] + 0) testFunction (async-callstack-promises.html:43) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Call stack: 0) chained3 (async-callstack-promises.html:86) @@ -93,6 +113,11 @@ 1) timeoutPromise (async-callstack-promises.html:9) 2) doTestChainedPromises (async-callstack-promises.html:79) 3) testFunctionTimeout (async-callstack-promises.html:50) + [setTimeout] + 0) testFunction (async-callstack-promises.html:43) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Call stack: 0) chained4 (async-callstack-promises.html:89) @@ -108,6 +133,16 @@ 2) chained1 (async-callstack-promises.html:81) [Promise.resolve] 0) resolvePromise (async-callstack-promises.html:12) + [setTimeout] + 0) promiseCallback (async-callstack-promises.html:21) + 1) timeoutPromise (async-callstack-promises.html:9) + 2) doTestChainedPromises (async-callstack-promises.html:79) + 3) testFunctionTimeout (async-callstack-promises.html:50) + [setTimeout] + 0) testFunction (async-callstack-promises.html:43) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Call stack: 0) errorCallback (async-callstack-promises.html:60) @@ -181,6 +216,17 @@ 2) chained3 (async-callstack-promises.html:87) [Promise.resolve] 0) resolvePromise (async-callstack-promises.html:12) + [setTimeout] + 0) promiseCallback (async-callstack-promises.html:21) + 1) timeoutPromise (async-callstack-promises.html:9) + 2) chained1 (async-callstack-promises.html:81) + [Promise.resolve] + 0) resolvePromise (async-callstack-promises.html:12) + [setTimeout] + 0) promiseCallback (async-callstack-promises.html:21) + 1) timeoutPromise (async-callstack-promises.html:9) + 2) doTestChainedPromises (async-callstack-promises.html:79) + 3) testFunctionTimeout (async-callstack-promises.html:50) Call stack: 0) thenCallback (async-callstack-promises.html:55)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises.html index cc0120bd..e6ccf64 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises.html
@@ -140,8 +140,7 @@ var test = function() { var totalDebuggerStatements = 14; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-reload-no-crash.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-reload-no-crash.html index 16068a07..9e22c73d 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-reload-no-crash.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-reload-no-crash.html
@@ -17,7 +17,7 @@ function test() { - var maxAsyncCallStackDepth = 4; + var maxAsyncCallStackDepth = 8; InspectorTest.startDebuggerTest(step1, true); function step1()
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-scripted-scroll.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-scripted-scroll.html index e011c61f..c7961ec 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-scripted-scroll.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-scripted-scroll.html
@@ -36,8 +36,7 @@ var test = function() { var totalDebuggerStatements = 2; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-set-interval.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-set-interval.html index bca5e64..9f0cbe5 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-set-interval.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-set-interval.html
@@ -27,8 +27,7 @@ function test() { var totalDebuggerStatements = 3; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-web-sql.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-web-sql.html index 2b282e3..69a319b 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-web-sql.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-web-sql.html
@@ -50,8 +50,7 @@ function test() { var totalDebuggerStatements = 5; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-xhrs.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-xhrs.html index 34e2baf2..5efe39d 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-xhrs.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-xhrs.html
@@ -23,7 +23,7 @@ function sendXHR(async) { var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function() + xhr.onreadystatechange = function() { if (xhr.readyState == 4) { xhr.onreadystatechange = null; @@ -69,8 +69,7 @@ var test = function() { var totalDebuggerStatements = 9; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack.html index bfbdeb6..05308e27 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack.html
@@ -64,8 +64,7 @@ var test = function() { var totalDebuggerStatements = 6; - var maxAsyncCallStackDepth = 4; - InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements, maxAsyncCallStackDepth); + InspectorTest.runAsyncCallStacksTest(totalDebuggerStatements); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-with-async-callstack-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-with-async-callstack-expected.txt index a2c49c48..5980b95 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-with-async-callstack-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-with-async-callstack-expected.txt
@@ -22,6 +22,9 @@ 5) timeout1 (frameworks-with-async-callstack.html:20) [setTimeout] 0) testFunction (frameworks-with-async-callstack.html:15) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...> Printing visible call stack: Call stack: @@ -33,4 +36,7 @@ 1) timeout1 (frameworks-with-async-callstack.html:20) [setTimeout] 0) testFunction (frameworks-with-async-callstack.html:15) + [setTimeout] + 0) scheduleTestFunction (debugger-test.js:3) + <... skipped remaining frames ...>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-with-async-callstack.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-with-async-callstack.html index aca7f6bf..54f5403 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-with-async-callstack.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-with-async-callstack.html
@@ -33,7 +33,7 @@ function test() { var frameworkRegexString = "/framework\\.js$"; - var maxAsyncCallStackDepth = 4; + var maxAsyncCallStackDepth = 8; Common.settingForTest("skipStackFramesPattern").set(frameworkRegexString);
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp index 19c6471a..0b634d1 100644 --- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp +++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -81,7 +81,7 @@ } // namespace -bool needsLayoutTreeUpdate(const Node& node) { +static bool needsLayoutTreeUpdate(const Node& node) { const Document& document = node.document(); if (document.needsLayoutTreeUpdate()) return true;
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.h b/third_party/WebKit/Source/core/editing/EditingUtilities.h index 563e02d..4958da65 100644 --- a/third_party/WebKit/Source/core/editing/EditingUtilities.h +++ b/third_party/WebKit/Source/core/editing/EditingUtilities.h
@@ -67,7 +67,6 @@ // This file contains a set of helper functions used by the editing commands -CORE_EXPORT bool needsLayoutTreeUpdate(const Node&); CORE_EXPORT bool needsLayoutTreeUpdate(const Position&); CORE_EXPORT bool needsLayoutTreeUpdate(const PositionInFlatTree&);
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp b/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp index d3652e7..0b9056a2 100644 --- a/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp
@@ -285,6 +285,13 @@ return *this; } +template <typename Strategy> +typename SelectionTemplate<Strategy>::Builder& +SelectionTemplate<Strategy>::Builder::setIsHandleVisible(bool isHandleVisible) { + m_selection.m_isHandleVisible = isHandleVisible; + return *this; +} + template class CORE_TEMPLATE_EXPORT SelectionTemplate<EditingStrategy>; template class CORE_TEMPLATE_EXPORT SelectionTemplate<EditingInFlatTreeStrategy>;
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplate.h b/third_party/WebKit/Source/core/editing/SelectionTemplate.h index 1d48c2d..78dd1843a 100644 --- a/third_party/WebKit/Source/core/editing/SelectionTemplate.h +++ b/third_party/WebKit/Source/core/editing/SelectionTemplate.h
@@ -66,6 +66,7 @@ Builder& setGranularity(TextGranularity); Builder& setHasTrailingWhitespace(bool); Builder& setIsDirectional(bool); + Builder& setIsHandleVisible(bool); private: SelectionTemplate m_selection; @@ -87,6 +88,7 @@ TextGranularity granularity() const { return m_granularity; } bool hasTrailingWhitespace() const { return m_hasTrailingWhitespace; } bool isDirectional() const { return m_isDirectional; } + bool isHandleVisible() const { return m_isHandleVisible; } bool isNone() const { return m_base.isNull(); } // Returns true if |this| selection holds valid values otherwise it causes @@ -115,6 +117,7 @@ TextGranularity m_granularity = CharacterGranularity; bool m_hasTrailingWhitespace = false; bool m_isDirectional = false; + bool m_isHandleVisible = false; #if DCHECK_IS_ON() uint64_t m_domTreeVersion; #endif
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplateTest.cpp b/third_party/WebKit/Source/core/editing/SelectionTemplateTest.cpp index e1f9864..63abb12 100644 --- a/third_party/WebKit/Source/core/editing/SelectionTemplateTest.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionTemplateTest.cpp
@@ -18,6 +18,7 @@ EXPECT_EQ(CharacterGranularity, selection.granularity()); EXPECT_FALSE(selection.hasTrailingWhitespace()); EXPECT_FALSE(selection.isDirectional()); + EXPECT_FALSE(selection.isHandleVisible()); EXPECT_TRUE(selection.isNone()); EXPECT_EQ(Position(), selection.base()); EXPECT_EQ(Position(), selection.extent()); @@ -36,6 +37,7 @@ EXPECT_EQ(CharacterGranularity, selection.granularity()); EXPECT_FALSE(selection.hasTrailingWhitespace()); EXPECT_FALSE(selection.isDirectional()); + EXPECT_FALSE(selection.isHandleVisible()); EXPECT_FALSE(selection.isNone()); EXPECT_EQ(position, selection.base()); EXPECT_EQ(position, selection.extent()); @@ -56,6 +58,7 @@ EXPECT_EQ(CharacterGranularity, selection.granularity()); EXPECT_FALSE(selection.hasTrailingWhitespace()); EXPECT_FALSE(selection.isDirectional()); + EXPECT_FALSE(selection.isHandleVisible()); EXPECT_FALSE(selection.isNone()); EXPECT_EQ(base, selection.base()); EXPECT_EQ(extent, selection.extent());
diff --git a/third_party/WebKit/Source/core/events/EventDispatcher.cpp b/third_party/WebKit/Source/core/events/EventDispatcher.cpp index b2c2126..6b6592a 100644 --- a/third_party/WebKit/Source/core/events/EventDispatcher.cpp +++ b/third_party/WebKit/Source/core/events/EventDispatcher.cpp
@@ -243,11 +243,6 @@ // 16. Set event’s currentTarget attribute to null. m_event->setCurrentTarget(nullptr); - // Pass the data from the preDispatchEventHandler to the - // postDispatchEventHandler. - m_node->postDispatchEventHandler(m_event.get(), - preDispatchEventHandlerResult); - bool isClick = m_event->isMouseEvent() && toMouseEvent(*m_event).type() == EventTypeNames::click; if (isClick) { @@ -257,6 +252,14 @@ cache->handleClicked(m_event->target()->toNode()); } + // Pass the data from the preDispatchEventHandler to the + // postDispatchEventHandler. + // This may dispatch an event, and m_node and m_event might be altered. + m_node->postDispatchEventHandler(m_event.get(), + preDispatchEventHandlerResult); + // TODO(tkent): Is it safe to kick defaultEventHandler() with such altered + // m_event? + // The DOM Events spec says that events dispatched by JS (other than "click") // should not have their default handlers invoked. bool isTrustedOrClick =
diff --git a/third_party/WebKit/Source/core/layout/FloatingObjects.cpp b/third_party/WebKit/Source/core/layout/FloatingObjects.cpp index 27b7106..f443714 100644 --- a/third_party/WebKit/Source/core/layout/FloatingObjects.cpp +++ b/third_party/WebKit/Source/core/layout/FloatingObjects.cpp
@@ -29,8 +29,6 @@ #include "core/layout/LayoutView.h" #include "core/layout/api/LineLayoutBlockFlow.h" #include "core/layout/shapes/ShapeOutsideInfo.h" -#include "core/paint/PaintLayer.h" -#include "platform/RuntimeEnabledFeatures.h" #include "wtf/PtrUtil.h" #include <algorithm> #include <memory> @@ -78,6 +76,7 @@ m_originatingLine(nullptr), m_frameRect(frameRect), m_type(type), + m_shouldPaint(shouldPaint), m_isDescendant(isDescendant), m_isPlaced(true), m_isLowestNonOverhangingFloatInChild(isLowestNonOverhangingFloatInChild) @@ -86,22 +85,6 @@ m_isInPlacedTree(false) #endif { - m_shouldPaint = shouldPaint || shouldPaintForCompositedLayoutPart(); -} - -bool FloatingObject::shouldPaintForCompositedLayoutPart() { - // HACK: only non-self-painting floats should paint. However, due to the - // fundamental compositing bug, some LayoutPart objects may become - // self-painting due to being composited. This leads to a chicken-egg issue - // because layout may not depend on compositing. - // If this is the case, set shouldPaint() to true even if the layer is - // technically self-painting. This lets the float which contains a LayoutPart - // start painting as soon as it stops being composited, without having to - // re-layout the float. - // This hack can be removed after SPv2. - return m_layoutObject->layer() && - m_layoutObject->layer()->isSelfPaintingOnlyBecauseIsCompositedPart() && - !RuntimeEnabledFeatures::slimmingPaintV2Enabled(); } std::unique_ptr<FloatingObject> FloatingObject::create( @@ -111,18 +94,13 @@ // If a layer exists, the float will paint itself. Otherwise someone else // will. - newObj->setShouldPaint(!layoutObject->hasSelfPaintingLayer() || - newObj->shouldPaintForCompositedLayoutPart()); + newObj->setShouldPaint(!layoutObject->hasSelfPaintingLayer()); newObj->setIsDescendant(true); return newObj; } -bool FloatingObject::shouldPaint() const { - return m_shouldPaint && !m_layoutObject->hasSelfPaintingLayer(); -} - std::unique_ptr<FloatingObject> FloatingObject::copyToNewContainer( LayoutSize offset, bool shouldPaint,
diff --git a/third_party/WebKit/Source/core/layout/FloatingObjects.h b/third_party/WebKit/Source/core/layout/FloatingObjects.h index c838dd1..fb83563 100644 --- a/third_party/WebKit/Source/core/layout/FloatingObjects.h +++ b/third_party/WebKit/Source/core/layout/FloatingObjects.h
@@ -113,7 +113,7 @@ void setIsInPlacedTree(bool value) { m_isInPlacedTree = value; } #endif - bool shouldPaint() const; + bool shouldPaint() const { return m_shouldPaint; } void setShouldPaint(bool shouldPaint) { m_shouldPaint = shouldPaint; } bool isDescendant() const { return m_isDescendant; } void setIsDescendant(bool isDescendant) { m_isDescendant = isDescendant; } @@ -139,8 +139,6 @@ bool isDescendant, bool isLowestNonOverhangingFloatInChild); - bool shouldPaintForCompositedLayoutPart(); - LayoutBox* m_layoutObject; RootInlineBox* m_originatingLine; LayoutRect m_frameRect;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp index f2f945d..359acb05 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -3998,7 +3998,9 @@ for (FloatingObjectSetIterator it = floatingObjectSet.end(); it != begin;) { --it; const FloatingObject& floatingObject = *it->get(); - if (floatingObject.shouldPaint()) { + if (floatingObject.shouldPaint() && + // TODO(wangxianzhu): Should this be a DCHECK? + !floatingObject.layoutObject()->hasSelfPaintingLayer()) { LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject.layoutObject()->location().x(); LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - @@ -4051,7 +4053,7 @@ return fixedOffset; } -void LayoutBlockFlow::setAncestorShouldPaintFloatingObject( +void LayoutBlockFlow::updateAncestorShouldPaintFloatingObject( const LayoutBox& floatBox) { ASSERT(floatBox.isFloating()); bool floatBoxIsSelfPaintingLayer =
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h index d45ad3a0..0267305 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
@@ -718,7 +718,8 @@ return m_floatingObjects.get(); } - static void setAncestorShouldPaintFloatingObject(const LayoutBox& floatBox); + static void updateAncestorShouldPaintFloatingObject( + const LayoutBox& floatBox); protected: LayoutUnit maxPositiveMarginBefore() const {
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp index 2c1b53b..dbfd4cf 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp
@@ -247,6 +247,17 @@ layer->didUpdateCompositingInputs(); m_geometryMap.popMappingsToAncestor(layer->parent()); + + if (layer->selfPaintingStatusChanged()) { + layer->clearSelfPaintingStatusChanged(); + // If the floating object becomes non-self-painting, so some ancestor should + // paint it; if it becomes self-painting, it should paint itself and no + // ancestor should paint it. + if (layer->layoutObject()->isFloating()) { + LayoutBlockFlow::updateAncestorShouldPaintFloatingObject( + *layer->layoutBox()); + } + } } #if DCHECK_IS_ON()
diff --git a/third_party/WebKit/Source/core/paint/BlockFlowPainter.cpp b/third_party/WebKit/Source/core/paint/BlockFlowPainter.cpp index 816eaf5..0ac6dd65 100644 --- a/third_party/WebKit/Source/core/paint/BlockFlowPainter.cpp +++ b/third_party/WebKit/Source/core/paint/BlockFlowPainter.cpp
@@ -53,6 +53,10 @@ continue; const LayoutBox* floatingLayoutObject = floatingObject->layoutObject(); + // TODO(wangxianzhu): Should this be a DCHECK? + if (floatingLayoutObject->hasSelfPaintingLayer()) + continue; + // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make // this much cleaner. LayoutPoint childPoint = m_layoutBlockFlow.flipFloatForWritingModeForChild(
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp index 168383e4..8ee0faf 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -157,6 +157,7 @@ m_hasNonIsolatedDescendantWithBlendMode(false), m_hasAncestorWithClipPath(false), m_hasRootScrollerAsDescendant(false), + m_selfPaintingStatusChanged(false), m_layoutObject(layoutObject), m_parent(0), m_previous(0), @@ -1516,15 +1517,7 @@ } void PaintLayer::didUpdateNeedsCompositedScrolling() { - bool wasSelfPaintingLayer = isSelfPaintingLayer(); updateSelfPaintingLayer(); - - // If the floating object becomes non-self-painting, so some ancestor should - // paint it; if it becomes self-painting, it should paint itself and no - // ancestor should paint it. - if (wasSelfPaintingLayer != isSelfPaintingLayer() && - m_layoutObject->isFloating()) - LayoutBlockFlow::setAncestorShouldPaintFloatingObject(*layoutBox()); } void PaintLayer::updateStackingNode() { @@ -2793,22 +2786,14 @@ return false; } -bool PaintLayer::isSelfPaintingLayerForIntrinsicOrScrollingReasons() const { - return layoutObject()->layerTypeRequired() == NormalPaintLayer || - (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars()) || - needsCompositedScrolling(); -} - bool PaintLayer::shouldBeSelfPaintingLayer() const { if (layoutObject()->isLayoutPart() && toLayoutPart(layoutObject())->requiresAcceleratedCompositing()) return true; - return isSelfPaintingLayerForIntrinsicOrScrollingReasons(); -} -bool PaintLayer::isSelfPaintingOnlyBecauseIsCompositedPart() const { - return shouldBeSelfPaintingLayer() && - !isSelfPaintingLayerForIntrinsicOrScrollingReasons(); + return layoutObject()->layerTypeRequired() == NormalPaintLayer || + (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars()) || + needsCompositedScrolling(); } void PaintLayer::updateSelfPaintingLayer() { @@ -2817,6 +2802,7 @@ return; m_isSelfPaintingLayer = isSelfPaintingLayer; + m_selfPaintingStatusChanged = true; if (PaintLayer* parent = this->parent()) { parent->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.h b/third_party/WebKit/Source/core/paint/PaintLayer.h index f57327c..75eb3c31 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.h +++ b/third_party/WebKit/Source/core/paint/PaintLayer.h
@@ -250,10 +250,6 @@ // FIXME: Many people call this function while it has out-of-date information. bool isSelfPaintingLayer() const { return m_isSelfPaintingLayer; } - // PaintLayers which represent LayoutParts may become self-painting due to - // being composited. If this is the case, this method returns true. - bool isSelfPaintingOnlyBecauseIsCompositedPart() const; - bool isTransparent() const { return layoutObject()->isTransparent() || layoutObject()->style()->hasBlendMode() || layoutObject()->hasMask(); @@ -988,6 +984,17 @@ return m_has3DTransformedDescendant; } + // Whether the value of isSelfPaintingLayer() changed since the last clearing + // (which happens after the flag is chedked during compositing update). + bool selfPaintingStatusChanged() const { + DCHECK(!RuntimeEnabledFeatures::slimmingPaintV2Enabled()); + return m_selfPaintingStatusChanged; + } + void clearSelfPaintingStatusChanged() { + DCHECK(!RuntimeEnabledFeatures::slimmingPaintV2Enabled()); + m_selfPaintingStatusChanged = false; + } + #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS void endShouldKeepAliveAllClientsRecursive(); #endif @@ -1115,8 +1122,6 @@ layer.m_needsPaintPhaseDescendantBlockBackgrounds; } - bool isSelfPaintingLayerForIntrinsicOrScrollingReasons() const; - bool shouldFragmentCompositedBounds(const PaintLayer* compositingLayer) const; void expandRectForStackingChildren(const PaintLayer& compositedLayer, @@ -1199,6 +1204,8 @@ unsigned m_hasAncestorWithClipPath : 1; unsigned m_hasRootScrollerAsDescendant : 1; + unsigned m_selfPaintingStatusChanged : 1; + LayoutBoxModelObject* m_layoutObject; PaintLayer* m_parent;
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/FlameChart.js b/third_party/WebKit/Source/devtools/front_end/perf_ui/FlameChart.js index 2aa6691..b432803 100644 --- a/third_party/WebKit/Source/devtools/front_end/perf_ui/FlameChart.js +++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/FlameChart.js
@@ -249,11 +249,11 @@ } _updateHighlight() { - const inDividersBar = this._lastMouseOffsetY < PerfUI.FlameChart.HeaderHeight; + var inDividersBar = this._lastMouseOffsetY < PerfUI.FlameChart.HeaderHeight; this._highlightedMarkerIndex = inDividersBar ? this._markerIndexAtPosition(this._lastMouseOffsetX) : -1; this._updateMarkerHighlight(); - const entryIndex = this._highlightedMarkerIndex === -1 ? + var entryIndex = this._highlightedMarkerIndex === -1 ? this._coordinatesToEntryIndex(this._lastMouseOffsetX, this._lastMouseOffsetY) : -1; if (entryIndex === -1) { @@ -320,7 +320,7 @@ // onClick comes after dragStart and dragEnd events. // So if there was drag (mouse move) in the middle of that events // we skip the click. Otherwise we jump to the sources. - const clickThreshold = 5; + var /** @const */ clickThreshold = 5; if (this.maxDragOffset() > clickThreshold) return; var groupIndex = this._coordinatesToGroupIndex(event.offsetX, event.offsetY); @@ -534,18 +534,18 @@ * @return {number} */ _markerIndexAtPosition(x) { - const markers = this._timelineData().markers; + var markers = this._timelineData().markers; if (!markers) return -1; - const accurracyOffsetPx = 4; - const time = this._cursorTime(x); - const leftTime = this._cursorTime(x - accurracyOffsetPx); - const rightTime = this._cursorTime(x + accurracyOffsetPx); - const left = this._markerIndexBeforeTime(leftTime); + var /** @const */ accurracyOffsetPx = 4; + var time = this._cursorTime(x); + var leftTime = this._cursorTime(x - accurracyOffsetPx); + var rightTime = this._cursorTime(x + accurracyOffsetPx); + var left = this._markerIndexBeforeTime(leftTime); var markerIndex = -1; var distance = Infinity; for (var i = left; i < markers.length && markers[i].startTime() < rightTime; i++) { - const nextDistance = Math.abs(markers[i].startTime() - time); + var nextDistance = Math.abs(markers[i].startTime() - time); if (nextDistance < distance) { markerIndex = i; distance = nextDistance; @@ -701,7 +701,7 @@ this._drawGroupHeaders(width, height); this._drawMarkers(); - const headerHeight = this._rulerEnabled ? PerfUI.FlameChart.HeaderHeight : 0; + var headerHeight = this._rulerEnabled ? PerfUI.FlameChart.HeaderHeight : 0; PerfUI.TimelineGrid.drawCanvasGrid(context, this._calculator, 3, headerHeight); this._updateElementPosition(this._highlightElement, this._highlightedEntryIndex); @@ -774,7 +774,7 @@ forEachGroup.call(this, (offset, index, group) => { context.font = group.style.font; if (this._isGroupCollapsible(index) && !group.expanded || group.style.shareHeaderLine) { - const width = this._labelWidthForGroup(context, group) + 2; + var width = this._labelWidthForGroup(context, group) + 2; context.fillStyle = Common.Color.parse(group.style.backgroundColor).setAlpha(0.8).asString(null); context.fillRect( this._headerLeftPadding - this._headerLabelXPadding, offset + this._headerLabelYPadding, width, @@ -888,20 +888,20 @@ var lastDrawOffset = Infinity; for (var entryIndexOnLevel = rightIndexOnLevel; entryIndexOnLevel >= 0; --entryIndexOnLevel) { - const entryIndex = levelIndexes[entryIndexOnLevel]; - const entryStartTime = entryStartTimes[entryIndex]; - const barX = this._timeToPositionClipped(entryStartTime); - const entryEndTime = entryStartTime + entryTotalTimes[entryIndex]; + var entryIndex = levelIndexes[entryIndexOnLevel]; + var entryStartTime = entryStartTimes[entryIndex]; + var barX = this._timeToPositionClipped(entryStartTime); + var entryEndTime = entryStartTime + entryTotalTimes[entryIndex]; if (isNaN(entryEndTime) || barX >= lastDrawOffset) continue; if (entryEndTime <= timeWindowLeft) break; lastDrawOffset = barX; - const color = this._dataProvider.entryColor(entryIndex); - const endBarX = this._timeToPositionClipped(entryEndTime); + var color = this._dataProvider.entryColor(entryIndex); + var endBarX = this._timeToPositionClipped(entryEndTime); if (group.style.useDecoratorsForOverview && this._dataProvider.forceDecoration(entryIndex)) { - const unclippedBarX = this._timeToPosition(entryStartTime); - const barWidth = endBarX - barX; + var unclippedBarX = this._timeToPosition(entryStartTime); + var barWidth = endBarX - barX; context.beginPath(); context.fillStyle = color; context.fillRect(barX, y, barWidth, barHeight); @@ -1095,7 +1095,7 @@ * @param {number} entryIndex */ _updateElementPosition(element, entryIndex) { - const elementMinWidthPx = 2; + var /** @const */ elementMinWidthPx = 2; if (element.parentElement) element.remove(); if (entryIndex === -1)
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js index 512b6f8..dd7b378 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -165,7 +165,7 @@ } asyncStackTracesStateChanged() { - const maxAsyncStackChainDepth = 4; + const maxAsyncStackChainDepth = 8; var enabled = Common.moduleSetting('enableAsyncStackTraces').get() && this._debuggerEnabled; this._agent.setAsyncCallStackDepth(enabled ? maxAsyncStackChainDepth : 0); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/AdvancedSearchView.js b/third_party/WebKit/Source/devtools/front_end/sources/AdvancedSearchView.js index 1bc8b2fc..bfc38df 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/AdvancedSearchView.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/AdvancedSearchView.js
@@ -29,10 +29,14 @@ this._search.setAttribute('results', '0'); this._search.setAttribute('size', 42); - this._searchPanelElement.createChild('div', 'search-icon'); - this._searchInputClearElement = this._searchPanelElement.createChild('div', 'search-cancel-button'); - this._searchInputClearElement.hidden = true; + var searchIcon = UI.Icon.create('smallicon-search', 'search-icon'); + this._searchPanelElement.appendChild(searchIcon); + + this._searchInputClearElement = UI.Icon.create('smallicon-clear-input', 'search-cancel-button'); + this._searchInputClearElement.classList.add('hidden'); this._searchInputClearElement.addEventListener('click', this._onSearchInputClear.bind(this), false); + var cancelButtonContainer = this._searchPanelElement.createChild('div', 'search-cancel-button-container'); + cancelButtonContainer.appendChild(this._searchInputClearElement); this._ignoreCaseLabel = UI.createCheckboxLabel(Common.UIString('Ignore case')); this._ignoreCaseLabel.classList.add('search-config-label'); @@ -132,7 +136,7 @@ _onSearchInputClear() { this._search.value = ''; this.focus(); - this._searchInputClearElement.hidden = true; + this._searchInputClearElement.classList.add('hidden'); } /** @@ -319,10 +323,8 @@ } _onInput() { - if (this._search.value && this._search.value.length) - this._searchInputClearElement.hidden = false; - else - this._searchInputClearElement.hidden = true; + var hasText = this._search.value && this._search.value.length; + this._searchInputClearElement.classList.toggle('hidden', !hasText); } _save() { @@ -335,7 +337,7 @@ this._ignoreCaseCheckbox.checked = searchConfig.ignoreCase(); this._regexCheckbox.checked = searchConfig.isRegex(); if (this._search.value && this._search.value.length) - this._searchInputClearElement.hidden = false; + this._searchInputClearElement.classList.remove('hidden'); } _onAction() {
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/FilePathScoreFunction.js b/third_party/WebKit/Source/devtools/front_end/sources/FilePathScoreFunction.js index 7d674651..defb82e1 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/FilePathScoreFunction.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/FilePathScoreFunction.js
@@ -79,7 +79,7 @@ } if (matchIndexes) this._restoreMatchIndexes(sequence, n, m, matchIndexes); - const maxDataLength = 256; + var maxDataLength = 256; return score[n * m - 1] * maxDataLength + (maxDataLength - data.length); } @@ -89,8 +89,11 @@ * @return {boolean} */ _testWordStart(data, j) { + if (j === 0) + return true; + var prevChar = data.charAt(j - 1); - return j === 0 || prevChar === '_' || prevChar === '-' || prevChar === '/' || + return prevChar === '_' || prevChar === '-' || prevChar === '/' || (data[j - 1] !== this._dataUpperCase[j - 1] && data[j] === this._dataUpperCase[j]); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/FilteredUISourceCodeListDelegate.js b/third_party/WebKit/Source/devtools/front_end/sources/FilteredUISourceCodeListDelegate.js index 8286ee1..c8f9474 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/FilteredUISourceCodeListDelegate.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/FilteredUISourceCodeListDelegate.js
@@ -106,8 +106,8 @@ this._scorer = new Sources.FilePathScoreFunction(query); } - var url = uiSourceCode.url(); - return score + 10 * this._scorer.score(url, null); + var fullDisplayName = uiSourceCode.fullDisplayName(); + return score + 10 * this._scorer.score(fullDisplayName, null); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/sourcesSearch.css b/third_party/WebKit/Source/devtools/front_end/sources/sourcesSearch.css index 35eaca7b..17aad8e0 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/sourcesSearch.css +++ b/third_party/WebKit/Source/devtools/front_end/sources/sourcesSearch.css
@@ -23,13 +23,8 @@ } .search-drawer-header .search-icon { - background-image: url(Images/toolbarButtonGlyphs.png); - background-size: 352px 168px; - background-position: -234px 138px; left: 10px; top: 10px; - width: 12px; - height: 12px; position: absolute; } @@ -37,22 +32,14 @@ -webkit-appearance: none; } -.search-drawer-header .search-cancel-button { +.search-drawer-header .search-cancel-button-container { position: relative; - left: -22px; - top: 9px; } -.search-drawer-header .search-cancel-button::before { - content: ''; - background-image: url(Images/toolbarButtonGlyphs.png); - background-size: 352px 168px; - left: 0; - top: 0; - width: 13px; - height: 13px; - background-position: -143px -96px; +.search-drawer-header .search-cancel-button { position: absolute; + right: 9px; + top: 9px; } :host-context(.platform-mac) .search-drawer-header input.search-config-search { @@ -89,16 +76,6 @@ overflow: hidden; } -@media (-webkit-min-device-pixel-ratio: 1.1) { -.search-drawer-header .search-icon { - background-image: url(Images/toolbarButtonGlyphs_2x.png); -} - -.search-drawer-header .search-cancel-button::before { - background-image: url(Images/toolbarButtonGlyphs_2x.png); -} -} /* media */ - .search-view .search-results { overflow-y: auto; display: flex;
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js index 756c2b5..3b1cc91 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
@@ -54,7 +54,7 @@ this._extensionColorGenerator = new PerfUI.FlameChart.ColorGenerator({min: 210, max: 300}, {min: 70, max: 100, count: 6}, 70, 0.7); - const defaultGroupStyle = { + var defaultGroupStyle = { padding: 4, height: 17, collapsible: true, @@ -85,7 +85,7 @@ entryTitle(entryIndex) { var entryType = this._entryType(entryIndex); if (entryType === Timeline.TimelineFlameChartEntryType.Event) { - const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]); + var event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]); if (event.phase === SDK.TracingModel.Phase.AsyncStepInto || event.phase === SDK.TracingModel.Phase.AsyncStepPast) return event.name + ':' + event.args['step']; if (event._blackboxRoot) @@ -98,7 +98,7 @@ return detailsText ? Common.UIString('%s (%s)', name, detailsText) : name; } if (entryType === Timeline.TimelineFlameChartEntryType.ExtensionEvent) { - const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]); + var event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]); return event.name; } var title = this._entryIndexToTitle[entryIndex]; @@ -401,8 +401,8 @@ } _appendGPUEvents() { - const eventType = Timeline.TimelineFlameChartEntryType.Event; - const gpuEvents = this._model.gpuEvents(); + var eventType = Timeline.TimelineFlameChartEntryType.Event; + var gpuEvents = this._model.gpuEvents(); if (this._appendSyncEvents(gpuEvents, Common.UIString('GPU'), this._headerLevel1, eventType, false)) ++this._currentLevel; }
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js index 4d79488..edc7062 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js
@@ -153,8 +153,8 @@ * @return {?string} */ entryTitle(index) { - const request = /** @type {!TimelineModel.TimelineModel.NetworkRequest} */ (this._requests[index]); - const parsedURL = new Common.ParsedURL(request.url || ''); + var request = /** @type {!TimelineModel.TimelineModel.NetworkRequest} */ (this._requests[index]); + var parsedURL = new Common.ParsedURL(request.url || ''); return parsedURL.isValid ? `${parsedURL.displayName} (${parsedURL.host})` : request.url || null; } @@ -181,7 +181,7 @@ * @return {boolean} */ decorateEntry(index, context, text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixelRatio) { - const request = /** @type {!TimelineModel.TimelineModel.NetworkRequest} */ (this._requests[index]); + var request = /** @type {!TimelineModel.TimelineModel.NetworkRequest} */ (this._requests[index]); if (!request.timing) return false; @@ -193,14 +193,14 @@ return Math.floor(unclippedBarX + (time - startTime) * timeToPixelRatio); } - const minBarWidthPx = 2; - const startTime = request.startTime; - const endTime = request.endTime; - const requestTime = request.timing.requestTime * 1000; - const sendStart = Math.max(timeToPixel(requestTime + request.timing.sendStart), unclippedBarX); - const headersEnd = Math.max(timeToPixel(requestTime + request.timing.receiveHeadersEnd), sendStart); - const finish = Math.max(timeToPixel(request.finishTime || endTime), headersEnd + minBarWidthPx); - const end = Math.max(timeToPixel(endTime), finish); + var /** @const */ minBarWidthPx = 2; + var startTime = request.startTime; + var endTime = request.endTime; + var requestTime = request.timing.requestTime * 1000; + var sendStart = Math.max(timeToPixel(requestTime + request.timing.sendStart), unclippedBarX); + var headersEnd = Math.max(timeToPixel(requestTime + request.timing.receiveHeadersEnd), sendStart); + var finish = Math.max(timeToPixel(request.finishTime || endTime), headersEnd + minBarWidthPx); + var end = Math.max(timeToPixel(endTime), finish); context.fillStyle = 'hsla(0, 100%, 100%, 0.8)'; context.fillRect(sendStart + 0.5, barY + 0.5, headersEnd - sendStart - 0.5, barHeight - 2); @@ -214,7 +214,7 @@ * @param {number} y */ function drawTick(begin, end, y) { - const tickHeightPx = 6; + var /** @const */ tickHeightPx = 6; context.moveTo(begin, y - tickHeightPx / 2); context.lineTo(begin, y + tickHeightPx / 2); context.moveTo(begin, y); @@ -223,33 +223,33 @@ context.lineWidth = 1; context.strokeStyle = '#ccc'; - const lineY = Math.floor(barY + barHeight / 2) + 0.5; - const leftTick = Math.floor(unclippedBarX) + 0.5; - const rightTick = end - 0.5; + var lineY = Math.floor(barY + barHeight / 2) + 0.5; + var leftTick = Math.floor(unclippedBarX) + 0.5; + var rightTick = end - 0.5; drawTick(leftTick, sendStart, lineY); drawTick(rightTick, finish, lineY); context.stroke(); if (typeof request.priority === 'string') { - const color = this._colorForPriority(request.priority); + var color = this._colorForPriority(request.priority); if (color) { context.fillStyle = color; context.fillRect(sendStart + 0.5, barY + 0.5, 3.5, 3.5); } } - const textStart = Math.max(sendStart, 0); - const textWidth = finish - textStart; - const minTextWidthPx = 20; + var textStart = Math.max(sendStart, 0); + var textWidth = finish - textStart; + var /** @const */ minTextWidthPx = 20; if (textWidth >= minTextWidthPx) { text = this.entryTitle(index) || ''; if (request.fromServiceWorker) text = 'âš™ ' + text; if (text) { - const textPadding = 4; - const textBaseline = 5; - const textBaseHeight = barHeight - textBaseline; - const trimmedText = UI.trimTextEnd(context, text, textWidth - 2 * textPadding); + var /** @const */ textPadding = 4; + var /** @const */ textBaseline = 5; + var textBaseHeight = barHeight - textBaseline; + var trimmedText = UI.trimTextEnd(context, text, textWidth - 2 * textPadding); context.fillStyle = '#333'; context.fillText(trimmedText, textStart + textPadding, barY + textBaseHeight); } @@ -330,8 +330,8 @@ var lastTimeByLevel = []; var maxLevel = 0; for (var i = 0; i < this._requests.length; ++i) { - const r = this._requests[i]; - const visible = r.startTime < this._endTime && r.endTime > this._startTime; + var r = this._requests[i]; + var visible = r.startTime < this._endTime && r.endTime > this._startTime; if (!visible) { this._timelineData.entryLevels[i] = -1; continue;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js index ed9fda13..3d5098c 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js
@@ -116,6 +116,8 @@ 'smallicon-inline-breakpoint-conditional': {x: -160, y: -20, width: 10, height: 10, spritesheet: 'smallicons'}, 'smallicon-file': {x: -64, y: -24, width: 12, height: 14, spritesheet: 'largeicons'}, 'smallicon-file-sync': {x: -76, y: -24, width: 12, height: 14, spritesheet: 'largeicons'}, + 'smallicon-search': {x: -234, y: -30, width: 12, height: 12, spritesheet: 'largeicons'}, + 'smallicon-clear-input': {x: -143, y: -96, width: 13, height: 13, spritesheet: 'largeicons'}, 'largeicon-longclick-triangle': {x: -290, y: -46, width: 28, height: 24, spritesheet: 'largeicons', isMask: true}, 'largeicon-menu': {x: -192, y: -24, width: 28, height: 24, spritesheet: 'largeicons', isMask: true}, @@ -218,4 +220,6 @@ 'largeicon-navigator-frame': {x: -256, y: -144, width: 32, height: 24, spritesheet: 'largeicons', isMask: true}, 'largeicon-navigator-worker': {x: -320, y: -144, width: 32, height: 24, spritesheet: 'largeicons', isMask: true}, 'largeicon-navigator-snippet': {x: -224, y: -96, width: 32, height: 24, spritesheet: 'largeicons', isMask: true}, + 'largeicon-edit': {x: -160, y: -0, width: 28, height: 24, spritesheet: 'largeicons'}, + };
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ListWidget.js b/third_party/WebKit/Source/devtools/front_end/ui/ListWidget.js index 0832723..8593e998 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ListWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ListWidget.js
@@ -117,11 +117,13 @@ controls.createChild('div', 'controls-gradient'); var buttons = controls.createChild('div', 'controls-buttons'); - var editButton = buttons.createChild('div', 'edit-button'); + var editButton = UI.Icon.create('largeicon-edit', 'edit-button'); + buttons.appendChild(editButton); editButton.title = Common.UIString('Edit'); editButton.addEventListener('click', onEditClicked.bind(this), false); - var removeButton = buttons.createChild('div', 'remove-button'); + var removeButton = UI.Icon.create('largeicon-trash-bin', 'remove-button'); + buttons.appendChild(removeButton); removeButton.title = Common.UIString('Remove'); removeButton.addEventListener('click', onRemoveClicked.bind(this), false);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/listWidget.css b/third_party/WebKit/Source/devtools/front_end/ui/listWidget.css index 6062ab7..5051019 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/listWidget.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/listWidget.css
@@ -58,23 +58,12 @@ .remove-button, .edit-button { - background-image: url(Images/toolbarButtonGlyphs.png); - background-size: 352px 168px; - width: 32px; - height: 24px; opacity: 0.5; cursor: pointer; flex: none; visibility: hidden; } -@media (-webkit-min-device-pixel-ratio: 1.1) { -.remove-button, -.edit-button { - background-image: url(Images/toolbarButtonGlyphs_2x.png); -} -} /* media */ - .list-item:hover .remove-button, .list-item:hover .edit-button { visibility: visible;
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp index 46f28d6..e992b4b 100644 --- a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp +++ b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp
@@ -959,9 +959,7 @@ // 3. If the new expiration time is not NaN, let expiration time be the // new expiration time in milliseconds since 01 January 1970 UTC. - // (Note that Chromium actually passes 0 to indicate no expiry.) - // FIXME: Get Chromium to pass NaN. - if (!std::isnan(updatedExpiryTimeInMS) && updatedExpiryTimeInMS != 0.0) + if (!std::isnan(updatedExpiryTimeInMS)) expirationTime = updatedExpiryTimeInMS; // 4. Set the session's expiration attribute to expiration time.
diff --git a/third_party/WebKit/Tools/Scripts/update-w3c-test-expectations b/third_party/WebKit/Tools/Scripts/update-w3c-test-expectations deleted file mode 100755 index 4977505..0000000 --- a/third_party/WebKit/Tools/Scripts/update-w3c-test-expectations +++ /dev/null
@@ -1,13 +0,0 @@ -#!/usr/bin/env python -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import sys - -from webkitpy.common import host -from webkitpy.w3c.update_w3c_test_expectations import W3CExpectationsLineAdder - -if __name__ == "__main__": - line_adder = W3CExpectationsLineAdder(host.Host()) - sys.exit(line_adder.run(sys.argv[1:]))
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl.py index e4da1f0..8a1401aa 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl.py
@@ -58,11 +58,11 @@ _log.error('Aborting: there are unstaged baselines:') for path in unstaged_baselines: _log.error(' %s', path) - return + return 1 issue_number = self._get_issue_number(options) if not issue_number: - return + return 1 # TODO(qyearsley): Replace this with git cl try-results to remove # dependency on Rietveld. See crbug.com/671684. @@ -71,14 +71,14 @@ if options.trigger_jobs: if self.trigger_jobs_for_missing_builds(builds): _log.info('Please re-run webkit-patch rebaseline-cl once all pending try jobs have finished.') - return + return 1 if not builds: _log.info('No builds to download baselines from.') _log.debug('Getting results for Rietveld issue %d.', issue_number) builds_to_results = self._fetch_results(builds) if builds_to_results is None: - return + return 1 test_prefix_list = {} if args: @@ -92,9 +92,10 @@ self._log_test_prefix_list(test_prefix_list) - if options.dry_run: - return - self.rebaseline(options, test_prefix_list) + if not options.dry_run: + self.rebaseline(options, test_prefix_list) + return 0 + def _get_issue_number(self, options): """Gets the Rietveld CL number from either |options| or from the current local branch."""
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl_unittest.py index bba5489..e31cb07 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl_unittest.py
@@ -156,7 +156,8 @@ return optparse.Values(dict(**options)) def test_execute_with_issue_number_given(self): - self.command.execute(self.command_options(issue=11112222), [], self.tool) + return_code = self.command.execute(self.command_options(issue=11112222), [], self.tool) + self.assertEqual(return_code, 0) self.assertLog([ 'INFO: Rebaselining fast/dom/prototype-inheritance.html\n', 'INFO: Rebaselining fast/dom/prototype-newtest.html\n', @@ -166,7 +167,8 @@ ]) def test_execute_with_no_issue_number(self): - self.command.execute(self.command_options(), [], self.tool) + return_code = self.command.execute(self.command_options(), [], self.tool) + self.assertEqual(return_code, 1) self.assertLog(['ERROR: No issue number given and no issue for current branch. This tool requires a CL\n' 'to operate on; please run `git cl upload` on this branch first, or use the --issue\n' 'option to download baselines for another existing CL.\n']) @@ -175,7 +177,8 @@ git_cl = GitCL(self.tool) git_cl.get_issue_number = lambda: '11112222' self.command.git_cl = lambda: git_cl - self.command.execute(self.command_options(), [], self.tool) + return_code = self.command.execute(self.command_options(), [], self.tool) + self.assertEqual(return_code, 0) self.assertLog([ 'INFO: Rebaselining fast/dom/prototype-inheritance.html\n', 'INFO: Rebaselining fast/dom/prototype-newtest.html\n', @@ -185,7 +188,8 @@ ]) def test_execute_with_only_changed_tests_option(self): - self.command.execute(self.command_options(issue=11112222, only_changed_tests=True), [], self.tool) + return_code = self.command.execute(self.command_options(issue=11112222, only_changed_tests=True), [], self.tool) + self.assertEqual(return_code, 0) # svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html # is in the list of failed tests, but not in the list of files modified # in the given CL; it should be included because all_tests is set to True. @@ -206,7 +210,8 @@ ], 'ignored': ['svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html'], })) - self.command.execute(self.command_options(issue=11112222), [], self.tool) + return_code = self.command.execute(self.command_options(issue=11112222), [], self.tool) + self.assertEqual(return_code, 0) self.assertLog([ 'INFO: Rebaselining fast/dom/prototype-inheritance.html\n', 'INFO: Rebaselining fast/dom/prototype-taco.html\n', @@ -219,7 +224,8 @@ # rebaselined. self.tool.buildbot.set_retry_sumary_json( Build('MOCK Try Win', 5000), None) - self.command.execute(self.command_options(issue=11112222), [], self.tool) + return_code = self.command.execute(self.command_options(issue=11112222), [], self.tool) + self.assertEqual(return_code, 0) self.assertLog([ 'WARNING: No retry summary available for build Build(builder_name=u\'MOCK Try Win\', build_number=5000).\n', 'INFO: Rebaselining fast/dom/prototype-inheritance.html\n', @@ -230,7 +236,8 @@ ]) def test_execute_with_trigger_jobs_option(self): - self.command.execute(self.command_options(issue=11112222, trigger_jobs=True), [], self.tool) + return_code = self.command.execute(self.command_options(issue=11112222, trigger_jobs=True), [], self.tool) + self.assertEqual(return_code, 1) self.assertLog([ 'INFO: Triggering try jobs for:\n', 'INFO: MOCK Try Linux\n', @@ -301,7 +308,8 @@ def test_bails_when_one_build_is_missing_results(self): self.tool.buildbot.set_results(Build("MOCK Try Win", 5000), None) - self.command.execute(self.command_options(issue=11112222), [], self.tool) + return_code = self.command.execute(self.command_options(issue=11112222), [], self.tool) + self.assertEqual(return_code, 1) self.assertLog([ 'ERROR: Failed to fetch results from ' '"https://storage.googleapis.com/chromium-layout-test-archives/MOCK_Try_Win/5000/layout-test-results".\n' @@ -312,7 +320,8 @@ def test_bails_when_there_are_unstaged_baselines(self): scm = self.tool.scm() scm.unstaged_changes = lambda: {'third_party/WebKit/LayoutTests/my-test-expected.txt': '?'} - self.command.execute(self.command_options(issue=11112222), [], self.tool) + return_code = self.command.execute(self.command_options(issue=11112222), [], self.tool) + self.assertEqual(return_code, 1) self.assertLog([ 'ERROR: Aborting: there are unstaged baselines:\n', 'ERROR: /mock-checkout/third_party/WebKit/LayoutTests/my-test-expected.txt\n',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py index 1011896..b7cbe26 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -23,9 +23,10 @@ from webkitpy.common.net.git_cl import GitCL from webkitpy.common.webkit_finder import WebKitFinder from webkitpy.layout_tests.models.test_expectations import TestExpectations, TestExpectationParser -from webkitpy.w3c.update_w3c_test_expectations import W3CExpectationsLineAdder -from webkitpy.w3c.test_copier import TestCopier from webkitpy.w3c.common import WPT_REPO_URL, CSS_REPO_URL, WPT_DEST_NAME, CSS_DEST_NAME +from webkitpy.w3c.directory_owners_extractor import DirectoryOwnersExtractor +from webkitpy.w3c.test_copier import TestCopier +from webkitpy.w3c.wpt_expectations_updater import WPTExpectationsUpdater # Settings for how often to check try job results and how long to wait. POLL_DELAY_SECONDS = 2 * 60 @@ -324,7 +325,7 @@ def _upload_cl(self): _log.info('Uploading change list.') - cc_list = self.get_directory_owners_to_cc() + cc_list = self.get_directory_owners() description = self._cl_description() self.git_cl.run([ 'upload', @@ -334,6 +335,14 @@ description, ] + ['--cc=' + email for email in cc_list]) + def get_directory_owners(self): + """Returns a list of email addresses of owners of changed tests.""" + _log.info('Gathering directory owners emails to CC.') + changed_files = self.host.cwd().changed_files() + extractor = DirectoryOwnersExtractor(self.fs) + extractor.read_owner_map() + return extractor.list_owners(changed_files) + def _cl_description(self): description = self.check_run(['git', 'log', '-1', '--format=%B']) build_link = self._build_link() @@ -355,54 +364,10 @@ return None return 'https://build.chromium.org/p/%s/builders/%s/builds/%s' % (master_name, builder_name, build_number) - def get_directory_owners_to_cc(self): - """Returns a list of email addresses to CC for the current import.""" - _log.info('Gathering directory owners emails to CC.') - directory_owners_file_path = self.finder.path_from_webkit_base( - 'Tools', 'Scripts', 'webkitpy', 'w3c', 'directory_owners.json') - with open(directory_owners_file_path) as data_file: - directory_to_owner = self.parse_directory_owners(json.load(data_file)) - out = self.check_run(['git', 'diff', 'origin/master', '--name-only']) - changed_files = out.splitlines() - return self.generate_email_list(changed_files, directory_to_owner) - - @staticmethod - def parse_directory_owners(decoded_data_file): - directory_dict = {} - for dict_set in decoded_data_file: - if dict_set['notification-email']: - directory_dict[dict_set['directory']] = dict_set['notification-email'] - return directory_dict - - def generate_email_list(self, changed_files, directory_to_owner): - """Returns a list of email addresses based on the given file list and - directory-to-owner mapping. - - Args: - changed_files: A list of file paths relative to the repository root. - directory_to_owner: A dict mapping layout test directories to emails. - - Returns: - A list of the email addresses to be notified for the current import. - """ - email_addresses = set() - for file_path in changed_files: - test_path = self.finder.layout_test_name(file_path) - if test_path is None: - continue - test_dir = self.fs.dirname(test_path) - if test_dir in directory_to_owner: - address = directory_to_owner[test_dir] - if not re.match(r'\S+@\S+', address): - _log.warning('%s appears not be an email address, skipping.', address) - continue - email_addresses.add(address) - return sorted(email_addresses) - def fetch_new_expectations_and_baselines(self): """Adds new expectations and downloads baselines based on try job results, then commits and uploads the change.""" _log.info('Adding test expectations lines to LayoutTests/TestExpectations.') - line_adder = W3CExpectationsLineAdder(self.host) + line_adder = WPTExpectationsUpdater(self.host) line_adder.run() message = 'Update test expectations and baselines.' self.check_run(['git', 'commit', '-a', '-m', message])
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py index 9e5fc35..f567ad98 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py
@@ -11,34 +11,6 @@ class TestImporterTest(unittest.TestCase): - def test_generate_email_list(self): - importer = TestImporter(MockHost()) - changed_files = [ - 'third_party/WebKit/LayoutTests/foo/bar/file.html', - 'third_party/WebKit/LayoutTests/foo/bar/otherfile.html', - 'third_party/WebKit/LayoutTests/foo/baz/files.html', - 'some/non-test.file', - ] - directory_to_owner = { - 'foo/bar': 'someone@gmail.com', - 'foo/baz': 'not an email address', - 'foo/bat': 'noone@gmail.com', - } - self.assertEqual( - importer.generate_email_list(changed_files, directory_to_owner), - ['someone@gmail.com']) - - def test_parse_directory_owners(self): - importer = TestImporter(MockHost()) - data_file = [ - {'notification-email': 'charizard@gmail.com', 'directory': 'foo/bar'}, - {'notification-email': 'blastoise@gmail.com', 'directory': 'foo/baz'}, - {'notification-email': '', 'directory': 'gol/bat'}, - ] - self.assertEqual( - importer.parse_directory_owners(data_file), - {'foo/bar': 'charizard@gmail.com', 'foo/baz': 'blastoise@gmail.com'}) - def test_update_test_expectations(self): host = MockHost() host.filesystem.files['/mock-checkout/third_party/WebKit/LayoutTests/TestExpectations'] = (
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py similarity index 97% rename from third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py rename to third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py index f3ba461..3444b17 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
@@ -2,13 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""A class for updating layout test expectations when updating w3c tests. +"""Updates layout test expectations and baselines when updating w3c tests. -Specifically, this class fetches results from try bots for the current CL, and: - 1. Downloads new baseline files for any tests that can be rebaselined. - 2. Updates the generic TestExpectations file for any other failing tests. - -This is used as part of the w3c test auto-import process. +Specifically, this class fetches results from try bots for the current CL, then +(1) downloads new baseline files for any tests that can be rebaselined, and +(2) updates the generic TestExpectations file for any other failing tests. """ import argparse @@ -26,7 +24,7 @@ MARKER_COMMENT = '# ====== New tests from w3c-test-autoroller added here ======' -class W3CExpectationsLineAdder(object): +class WPTExpectationsUpdater(object): def __init__(self, host): self.host = host
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py similarity index 77% rename from third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py rename to third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py index e3c1409..72cd63a 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py
@@ -10,16 +10,15 @@ from webkitpy.common.net.buildbot_mock import MockBuildBot from webkitpy.common.net.layout_test_results import LayoutTestResult, LayoutTestResults from webkitpy.common.net.web_mock import MockWeb -from webkitpy.common.system.executive_mock import MockExecutive from webkitpy.common.system.log_testing import LoggingTestCase from webkitpy.layout_tests.builder_list import BuilderList -from webkitpy.w3c.update_w3c_test_expectations import W3CExpectationsLineAdder, MARKER_COMMENT +from webkitpy.w3c.wpt_expectations_updater import WPTExpectationsUpdater, MARKER_COMMENT -class UpdateW3CTestExpectationsTest(LoggingTestCase): +class WPTExpectationsUpdaterTest(LoggingTestCase): def setUp(self): - super(UpdateW3CTestExpectationsTest, self).setUp() + super(WPTExpectationsUpdaterTest, self).setUp() self.host = MockHost() self.host.builders = BuilderList({ 'mac': {'port_name': 'test-mac'}, @@ -36,14 +35,14 @@ }, }, })) - line_adder = W3CExpectationsLineAdder(self.host) - self.assertEqual(line_adder.get_failing_results_dict(Build('mac', 123)), {}) + updater = WPTExpectationsUpdater(self.host) + self.assertEqual(updater.get_failing_results_dict(Build('mac', 123)), {}) def test_get_failing_results_dict_no_results(self): self.host.buildbot = MockBuildBot() self.host.buildbot.set_results(Build('mac', 123), None) - line_adder = W3CExpectationsLineAdder(self.host) - self.assertEqual(line_adder.get_failing_results_dict(Build('mac', 123)), {}) + updater = WPTExpectationsUpdater(self.host) + self.assertEqual(updater.get_failing_results_dict(Build('mac', 123)), {}) def test_get_failing_results_dict_some_failing_results(self): self.host.buildbot.set_results(Build('mac', 123), LayoutTestResults({ @@ -57,8 +56,8 @@ }, }, })) - line_adder = W3CExpectationsLineAdder(self.host) - self.assertEqual(line_adder.get_failing_results_dict(Build('mac', 123)), { + updater = WPTExpectationsUpdater(self.host) + self.assertEqual(updater.get_failing_results_dict(Build('mac', 123)), { 'x/failing-test.html': { 'Mac': { 'actual': 'IMAGE', @@ -69,18 +68,18 @@ }) def test_merge_same_valued_keys_all_match(self): - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) self.assertEqual( - line_adder.merge_same_valued_keys({ + updater.merge_same_valued_keys({ 'one': {'expected': 'FAIL', 'actual': 'PASS'}, 'two': {'expected': 'FAIL', 'actual': 'PASS'}, }), {('two', 'one'): {'expected': 'FAIL', 'actual': 'PASS'}}) def test_merge_same_valued_keys_one_mismatch(self): - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) self.assertEqual( - line_adder.merge_same_valued_keys({ + updater.merge_same_valued_keys({ 'one': {'expected': 'FAIL', 'actual': 'PASS'}, 'two': {'expected': 'FAIL', 'actual': 'TIMEOUT'}, 'three': {'expected': 'FAIL', 'actual': 'PASS'}, @@ -91,37 +90,37 @@ }) def test_get_expectations(self): - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) self.assertEqual( - line_adder.get_expectations({'expected': 'FAIL', 'actual': 'PASS'}), + updater.get_expectations({'expected': 'FAIL', 'actual': 'PASS'}), {'Pass'}) self.assertEqual( - line_adder.get_expectations({'expected': 'FAIL', 'actual': 'TIMEOUT'}), + updater.get_expectations({'expected': 'FAIL', 'actual': 'TIMEOUT'}), {'Timeout'}) self.assertEqual( - line_adder.get_expectations({'expected': 'TIMEOUT', 'actual': 'PASS'}), + updater.get_expectations({'expected': 'TIMEOUT', 'actual': 'PASS'}), {'Pass'}) self.assertEqual( - line_adder.get_expectations({'expected': 'PASS', 'actual': 'TIMEOUT CRASH FAIL'}), + updater.get_expectations({'expected': 'PASS', 'actual': 'TIMEOUT CRASH FAIL'}), {'Crash', 'Failure', 'Timeout'}) self.assertEqual( - line_adder.get_expectations({'expected': 'SLOW CRASH FAIL TIMEOUT', 'actual': 'PASS'}), + updater.get_expectations({'expected': 'SLOW CRASH FAIL TIMEOUT', 'actual': 'PASS'}), {'Pass'}) def test_create_line_list_old_tests(self): # In this example, there are two failures that are not in w3c tests. - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) results = { 'fake/test/path.html': { 'one': {'expected': 'FAIL', 'actual': 'PASS', 'bug': 'crbug.com/test'}, 'two': {'expected': 'FAIL', 'actual': 'PASS', 'bug': 'crbug.com/test'}, } } - self.assertEqual(line_adder.create_line_list(results), []) + self.assertEqual(updater.create_line_list(results), []) def test_create_line_list_new_tests(self): # In this example, there are unexpected non-fail results in w3c tests. - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) results = { 'external/fake/test/path.html': { 'one': {'expected': 'FAIL', 'actual': 'PASS', 'bug': 'crbug.com/test'}, @@ -130,7 +129,7 @@ } } self.assertEqual( - line_adder.create_line_list(results), + updater.create_line_list(results), [ 'crbug.com/test [ three ] external/fake/test/path.html [ Pass ]', 'crbug.com/test [ two ] external/fake/test/path.html [ Timeout ]', @@ -138,10 +137,10 @@ ]) def test_merge_dicts_with_conflict_raise_exception(self): - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) # Both dicts here have the key "one", and the value is not equal. with self.assertRaises(ValueError): - line_adder.merge_dicts( + updater.merge_dicts( { 'external/fake/test/path.html': { 'one': {'expected': 'FAIL', 'actual': 'PASS'}, @@ -156,7 +155,7 @@ }) def test_merge_dicts_merges_second_dict_into_first(self): - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) one = { 'fake/test/path.html': { 'one': {'expected': 'FAIL', 'actual': 'PASS'}, @@ -176,13 +175,13 @@ } } - output = line_adder.merge_dicts(one, three) + output = updater.merge_dicts(one, three) self.assertEqual(output, one) - output = line_adder.merge_dicts(two, three) + output = updater.merge_dicts(two, three) self.assertEqual(output, two) def test_generate_results_dict(self): - line_adder = W3CExpectationsLineAdder(MockHost()) + updater = WPTExpectationsUpdater(MockHost()) layout_test_list = [ LayoutTestResult( 'test/name.html', { @@ -192,7 +191,7 @@ 'has_stderr': True, } )] - self.assertEqual(line_adder.generate_results_dict('dummy_platform', layout_test_list), { + self.assertEqual(updater.generate_results_dict('dummy_platform', layout_test_list), { 'test/name.html': { 'dummy_platform': { 'expected': 'bar', @@ -205,10 +204,10 @@ def test_write_to_test_expectations_with_marker_comment(self): expectations_path = '/mock-checkout/third_party/WebKit/LayoutTests/TestExpectations' self.host.filesystem.files[expectations_path] = MARKER_COMMENT + '\n' - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) line_list = ['crbug.com/123 [ FakePlatform ] fake/file/path.html [ Pass ]'] - line_adder.write_to_test_expectations(line_list) - value = line_adder.host.filesystem.read_text_file(expectations_path) + updater.write_to_test_expectations(line_list) + value = updater.host.filesystem.read_text_file(expectations_path) self.assertMultiLineEqual( value, (MARKER_COMMENT + '\n' @@ -217,9 +216,9 @@ def test_write_to_test_expectations_with_no_marker_comment(self): expectations_path = '/mock-checkout/third_party/WebKit/LayoutTests/TestExpectations' self.host.filesystem.files[expectations_path] = 'crbug.com/111 [ FakePlatform ]\n' - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) line_list = ['crbug.com/123 [ FakePlatform ] fake/file/path.html [ Pass ]'] - line_adder.write_to_test_expectations(line_list) + updater.write_to_test_expectations(line_list) value = self.host.filesystem.read_text_file(expectations_path) self.assertMultiLineEqual( value, @@ -230,12 +229,12 @@ def test_write_to_test_expectations_skips_existing_lines(self): expectations_path = '/mock-checkout/third_party/WebKit/LayoutTests/TestExpectations' self.host.filesystem.files[expectations_path] = 'crbug.com/111 dont/copy/me.html [ Failure ]\n' - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) line_list = [ 'crbug.com/111 dont/copy/me.html [ Failure ]', 'crbug.com/222 do/copy/me.html [ Failure ]' ] - line_adder.write_to_test_expectations(line_list) + updater.write_to_test_expectations(line_list) value = self.host.filesystem.read_text_file(expectations_path) self.assertEqual( value, @@ -248,9 +247,9 @@ self.host.filesystem.files[expectations_path] = ( MARKER_COMMENT + '\n' 'crbug.com/123 [ FakePlatform ] fake/file/path.html [ Pass ]\n') - line_adder = W3CExpectationsLineAdder(self.host) - line_adder.write_to_test_expectations([]) - value = line_adder.host.filesystem.read_text_file(expectations_path) + updater = WPTExpectationsUpdater(self.host) + updater.write_to_test_expectations([]) + value = updater.host.filesystem.read_text_file(expectations_path) self.assertMultiLineEqual( value, (MARKER_COMMENT + '\n' @@ -259,25 +258,25 @@ def test_is_js_test_true(self): self.host.filesystem.files['/mock-checkout/third_party/WebKit/LayoutTests/foo/bar.html'] = ( '<script src="/resources/testharness.js"></script>') - line_adder = W3CExpectationsLineAdder(self.host) - self.assertTrue(line_adder.is_js_test('foo/bar.html')) + updater = WPTExpectationsUpdater(self.host) + self.assertTrue(updater.is_js_test('foo/bar.html')) def test_is_js_test_false(self): self.host.filesystem.files['/mock-checkout/third_party/WebKit/LayoutTests/foo/bar.html'] = ( '<script src="ref-test.html"></script>') - line_adder = W3CExpectationsLineAdder(self.host) - self.assertFalse(line_adder.is_js_test('foo/bar.html')) + updater = WPTExpectationsUpdater(self.host) + self.assertFalse(updater.is_js_test('foo/bar.html')) def test_is_js_test_non_existent_file(self): - line_adder = W3CExpectationsLineAdder(self.host) - self.assertFalse(line_adder.is_js_test('foo/bar.html')) + updater = WPTExpectationsUpdater(self.host) + self.assertFalse(updater.is_js_test('foo/bar.html')) def test_get_test_to_rebaseline_returns_only_tests_with_failures(self): self.host.filesystem.files['/mock-checkout/third_party/WebKit/LayoutTests/external/fake/test/path.html'] = ( '<script src="/resources/testharness.js"></script>') self.host.filesystem.files['/mock-checkout/third_party/WebKit/LayoutTests/external/other/test/path.html'] = ( '<script src="/resources/testharness.js"></script>') - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) two = { 'external/fake/test/path.html': { 'one': {'expected': 'FAIL', 'actual': 'PASS'}, @@ -285,14 +284,14 @@ 'three': {'expected': 'FAIL', 'actual': 'PASS'}, } } - tests_to_rebaseline, _ = line_adder.get_tests_to_rebaseline(two) + tests_to_rebaseline, _ = updater.get_tests_to_rebaseline(two) # The other test doesn't have an entry in the test results dict, so it is not listed as a test to rebaseline. self.assertEqual(tests_to_rebaseline, ['external/fake/test/path.html']) def test_get_test_to_rebaseline_returns_only_js_tests(self): self.host.filesystem.files['/mock-checkout/third_party/WebKit/LayoutTests/external/fake/test/path.html'] = ( 'this file does not look like a testharness JS test.') - line_adder = W3CExpectationsLineAdder(self.host) + updater = WPTExpectationsUpdater(self.host) two = { 'external/fake/test/path.html': { 'one': {'expected': 'FAIL', 'actual': 'PASS', 'bug': 'crbug.com/test'}, @@ -300,7 +299,7 @@ 'three': {'expected': 'FAIL', 'actual': 'PASS', 'bug': 'crbug.com/test'}, } } - tests_to_rebaseline, _ = line_adder.get_tests_to_rebaseline(two) + tests_to_rebaseline, _ = updater.get_tests_to_rebaseline(two) self.assertEqual(tests_to_rebaseline, []) def test_get_tests_to_rebaseline_returns_updated_dict(self): @@ -313,8 +312,8 @@ test_results_dict_copy = copy.deepcopy(test_results_dict) self.host.filesystem.files['/mock-checkout/third_party/WebKit/LayoutTests/external/fake/test/path.html'] = ( '<script src="/resources/testharness.js"></script>') - line_adder = W3CExpectationsLineAdder(self.host) - tests_to_rebaseline, modified_test_results = line_adder.get_tests_to_rebaseline( + updater = WPTExpectationsUpdater(self.host) + tests_to_rebaseline, modified_test_results = updater.get_tests_to_rebaseline( test_results_dict) self.assertEqual(tests_to_rebaseline, ['external/fake/test/path.html']) # The record for the builder with a timeout is kept, but not with a text mismatch, @@ -337,8 +336,8 @@ test_results_dict_copy = copy.deepcopy(test_results_dict) self.host.filesystem.files['/mock-checkout/third_party/WebKit/LayoutTests/external/fake/test/path.html'] = ( '<script src="/resources/testharness.js"></script>') - line_adder = W3CExpectationsLineAdder(self.host) - tests_to_rebaseline, modified_test_results = line_adder.get_tests_to_rebaseline( + updater = WPTExpectationsUpdater(self.host) + tests_to_rebaseline, modified_test_results = updater.get_tests_to_rebaseline( test_results_dict) self.assertEqual(tests_to_rebaseline, ['external/fake/test/path.html']) # The record for the builder with a timeout is kept, but not with a text mismatch, @@ -352,9 +351,9 @@ self.assertEqual(test_results_dict, test_results_dict_copy) def test_run_no_issue_number(self): - line_adder = W3CExpectationsLineAdder(self.host) - line_adder.get_issue_number = lambda: 'None' - self.assertEqual(1, line_adder.run(args=[])) + updater = WPTExpectationsUpdater(self.host) + updater.get_issue_number = lambda: 'None' + self.assertEqual(1, updater.run(args=[])) self.assertLog(['ERROR: No issue on current branch.\n']) def test_run_no_try_results(self): @@ -366,10 +365,10 @@ 'try_job_results': [] }) }) - line_adder = W3CExpectationsLineAdder(self.host) - line_adder.get_issue_number = lambda: '11112222' - line_adder.get_try_bots = lambda: ['test-builder-name'] - self.assertEqual(1, line_adder.run(args=[])) + updater = WPTExpectationsUpdater(self.host) + updater.get_issue_number = lambda: '11112222' + updater.get_try_bots = lambda: ['test-builder-name'] + self.assertEqual(1, updater.run(args=[])) self.assertEqual( self.host.web.urls_fetched, [
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py index 4cc6fb8..0f6d715 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py
@@ -87,7 +87,9 @@ def merge_pull_request(self, pull_request_number): path = '/repos/w3c/web-platform-tests/pulls/%d/merge' % pull_request_number - body = {} + body = { + 'merge_method': 'rebase', + } data, status_code = self.request(path, method='PUT', body=body) if status_code == 200:
diff --git a/third_party/WebKit/Tools/Scripts/wpt-update-expectations b/third_party/WebKit/Tools/Scripts/wpt-update-expectations new file mode 100755 index 0000000..82c0548 --- /dev/null +++ b/third_party/WebKit/Tools/Scripts/wpt-update-expectations
@@ -0,0 +1,14 @@ +#!/usr/bin/env python +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import sys + +from webkitpy.common import host +from webkitpy.w3c.wpt_expectations_updater import WPTExpectationsUpdater + + +if __name__ == "__main__": + updater = WPTExpectationsUpdater(host.Host()) + sys.exit(updater.run(sys.argv[1:]))
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index c976db80..9b24ca7 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -108,6 +108,7 @@ 'CFI Linux Full': 'cfi_full_release_static', 'Chromium Linux Goma Canary': 'release_bot', 'Chromium Linux Goma Canary (clobber)': 'release_bot', + 'Chromium Linux Goma Canary LocalOutputCache': 'release_bot', 'Chromium Linux Precise Goma LinkTest': 'release_bot', 'Chromium Linux32 Goma Canary (clobber)': 'release_bot_x86', 'Chromium Mac 10.10 MacViews': 'mac_views_browser_release_bot',
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py index 943f3f7c..8cc2d3f 100644 --- a/tools/perf/benchmarks/blink_perf.py +++ b/tools/perf/benchmarks/blink_perf.py
@@ -164,7 +164,8 @@ subdir = 'CSS' -@benchmark.Disabled('android-webview', # http://crbug.com/593200 +@benchmark.Disabled('android', # http://crbug.com/685320 + 'android-webview', # http://crbug.com/593200 'reference') # http://crbug.com/576779 class BlinkPerfCanvas(_BlinkPerfBenchmark): tag = 'canvas'
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py index aaa7463..faec5d8a 100644 --- a/tools/perf/benchmarks/smoothness.py +++ b/tools/perf/benchmarks/smoothness.py
@@ -451,6 +451,13 @@ def Name(cls): return 'smoothness.pathological_mobile_sites' + @classmethod + def ShouldDisable(cls, possible_browser): + # http://crbug.com/685342 + if possible_browser.platform.GetDeviceTypeName() == 'Nexus 7': + return True + return False + class SmoothnessToughTextureUploadCases(_Smoothness): page_set = page_sets.ToughTextureUploadCasesPageSet
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn index 4720a32..c568ec3 100644 --- a/ui/views/mus/BUILD.gn +++ b/ui/views/mus/BUILD.gn
@@ -120,7 +120,6 @@ deps = [ ":mus", - ":views_mus_tests_catalog_source", "//base", "//base/test:test_support", "//mojo/edk/system", @@ -139,6 +138,7 @@ ] data_deps = [ + ":views_mus_tests_catalog", "//ui/resources:ui_test_pak_data", ] } @@ -191,6 +191,7 @@ ] data_deps = [ + ":views_mus_tests_catalog_copy", "//services/ui/ime/test_ime_driver", "//services/ui/test_wm", ] @@ -251,6 +252,7 @@ ] data_deps = [ + ":views_mus_tests_catalog_copy", "//services/ui/test_wm", ] @@ -291,8 +293,13 @@ catalog_deps = [ "//mash:catalog" ] } -catalog_cpp_source("views_mus_tests_catalog_source") { +copy("views_mus_tests_catalog_copy") { testonly = true - catalog = ":views_mus_tests_catalog" - output_symbol_name = "kViewsMusTestCatalog" + sources = get_target_outputs(":views_mus_tests_catalog") + outputs = [ + "${root_out_dir}/views_mus_tests_catalog.json", + ] + deps = [ + ":views_mus_tests_catalog", + ] }
diff --git a/ui/views/mus/views_mus_test_suite.cc b/ui/views/mus/views_mus_test_suite.cc index 50c0c92..57776440 100644 --- a/ui/views/mus/views_mus_test_suite.cc +++ b/ui/views/mus/views_mus_test_suite.cc
@@ -9,7 +9,6 @@ #include "base/command_line.h" #include "base/files/file_path.h" -#include "base/json/json_reader.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" @@ -36,12 +35,12 @@ #include "ui/views/views_delegate.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" -// Generated within the ":views_mus_tests_catalog_source" target. -extern const char kViewsMusTestCatalog[]; - namespace views { namespace { +const base::FilePath::CharType kCatalogFilename[] = + FILE_PATH_LITERAL("views_mus_tests_catalog.json"); + void EnsureCommandLineSwitch(const std::string& name) { base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); if (!cmd_line->HasSwitch(name)) @@ -108,8 +107,8 @@ ServiceManagerConnection() : thread_("Persistent service_manager connections"), ipc_thread_("IPC thread") { - catalog::Catalog::SetDefaultCatalogManifest( - base::JSONReader::Read(kViewsMusTestCatalog)); + catalog::Catalog::LoadDefaultCatalogManifest( + base::FilePath(kCatalogFilename)); mojo::edk::Init(); ipc_thread_.StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
diff --git a/ui/webui/resources/html/action_link_css.html b/ui/webui/resources/html/action_link_css.html new file mode 100644 index 0000000..94ba00e --- /dev/null +++ b/ui/webui/resources/html/action_link_css.html
@@ -0,0 +1,28 @@ +<!-- "action_link_css.html" replaces "action_link.css" for MD pages. --> +<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> + +<dom-module id="action-link"> + <template> + <style> + [is='action-link'] { + @apply(--cr-actionable); + text-decoration: none; + } + + [is='action-link'], + [is='action-link']:active, + [is='action-link']:hover, + [is='action-link']:visited { + color: var(--google-blue-700); + } + + [is='action-link'][disabled] { + color: var(--paper-grey-600); + cursor: default; + opacity: 0.65; + pointer-events: none; + } + </style> + </template> +</dom-module>
diff --git a/ui/webui/resources/webui_resources.grd b/ui/webui/resources/webui_resources.grd index 642e5af..9a6617c 100644 --- a/ui/webui/resources/webui_resources.grd +++ b/ui/webui/resources/webui_resources.grd
@@ -265,6 +265,8 @@ <structure name="IDR_WEBUI_HTML_ACTION_LINK" file="html/action_link.html" type="chrome_html" /> + <structure name="IDR_WEBUI_HTML_ACTION_LINK_CSS" + file="html/action_link_css.html" type="chrome_html" /> <structure name="IDR_WEBUI_HTML_ASSERT" file="html/assert.html" type="chrome_html" /> <structure name="IDR_WEBUI_HTML_PROMISE_RESOLVER"