diff --git a/DEPS b/DEPS index bc63e37..4464bb9 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # 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': '03707bbe71e93513636b7887590823abbe66f221', + 'v8_revision': 'b7ac09574e4274c8e7a923e59a6cfbdb153e4ed6', # 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. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'c50cbdedf9a36a08ef7f2bb584625332f1a9592f', + 'catapult_revision': 'df42e552c40e046862a87aee40aac52565bb3425', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 47ee97d..7bafd482 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -7,7 +7,6 @@ #include "ash/common/accelerators/accelerator_controller.h" #include "ash/common/accelerators/accelerator_table.h" #include "ash/common/focus_cycler.h" -#include "ash/common/material_design/material_design_controller.h" #include "ash/common/session/session_controller.h" #include "ash/common/shelf/shelf_constants.h" #include "ash/common/shelf/shelf_layout_manager_observer.h" @@ -170,15 +169,6 @@ EXPECT_EQ(shelf_widget_bounds_.x(), shelf_bounds.x()); } - // Auto hidden shelf has a visible height of 0 in MD (where this inequality - // does not apply); whereas auto hidden shelf has a visible height of 3 in - // non-MD. - if (!ash::MaterialDesignController::IsImmersiveModeMaterial() || - shelf->GetAutoHideState() != ash::SHELF_AUTO_HIDE_HIDDEN) { - EXPECT_GE(shelf_bounds.height(), - auto_hidden_shelf_widget_bounds_.height()); - } - float scroll_delta = GetShelfLayoutManager()->PrimaryAxisValue(scroll_.y(), scroll_.x()); bool increasing_drag = @@ -510,12 +500,7 @@ gfx::Rect bounds_fullscreen = window->bounds(); EXPECT_TRUE(widget->IsFullscreen()); - // Shelf hints are removed in immersive full screen mode in MD; and some shelf - // hints are shown in non-MD mode. - if (ash::MaterialDesignController::IsImmersiveModeMaterial()) - EXPECT_EQ(bounds_noshelf.ToString(), bounds_fullscreen.ToString()); - else - EXPECT_NE(bounds_noshelf.ToString(), bounds_fullscreen.ToString()); + EXPECT_EQ(bounds_noshelf.ToString(), bounds_fullscreen.ToString()); // Swipe up. This should show the shelf. end = below_start - delta;
diff --git a/base/allocator/allocator_check.cc b/base/allocator/allocator_check.cc index 5a0564d..87d0e7e 100644 --- a/base/allocator/allocator_check.cc +++ b/base/allocator/allocator_check.cc
@@ -14,6 +14,10 @@ #include <malloc.h> #endif +#if defined(OS_MACOSX) +#include "base/allocator/allocator_interception_mac.h" +#endif + namespace base { namespace allocator { @@ -28,6 +32,9 @@ #define TC_MALLOPT_IS_OVERRIDDEN_BY_TCMALLOC 0xbeef42 return (mallopt(TC_MALLOPT_IS_OVERRIDDEN_BY_TCMALLOC, 0) == TC_MALLOPT_IS_OVERRIDDEN_BY_TCMALLOC); +#elif defined(OS_MACOSX) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + // From allocator_interception_mac.mm. + return base::allocator::g_replaced_default_zone; #else return true; #endif
diff --git a/base/allocator/allocator_interception_mac.h b/base/allocator/allocator_interception_mac.h index 694d66b3..ff9b0b1 100644 --- a/base/allocator/allocator_interception_mac.h +++ b/base/allocator/allocator_interception_mac.h
@@ -8,6 +8,7 @@ #include <malloc/malloc.h> #include <stddef.h> +#include "base/base_export.h" #include "third_party/apple_apsl/malloc.h" namespace base { @@ -58,6 +59,8 @@ // |functions|. void ReplaceFunctionsForDefaultZone(const MallocZoneFunctions* functions); +extern bool g_replaced_default_zone; + // 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); @@ -66,7 +69,7 @@ // Foundation and Objective-C allocations. // Has no effect on the default malloc zone if the allocator shim already // performs that interception. -void InterceptAllocationsMac(); +BASE_EXPORT void InterceptAllocationsMac(); } // namespace allocator } // namespace base
diff --git a/base/allocator/allocator_interception_mac.mm b/base/allocator/allocator_interception_mac.mm index be6c0fa..e945a29 100644 --- a/base/allocator/allocator_interception_mac.mm +++ b/base/allocator/allocator_interception_mac.mm
@@ -27,6 +27,8 @@ #include <new> +#include "base/allocator/allocator_shim.h" +#include "base/allocator/features.h" #include "base/logging.h" #include "base/mac/mac_util.h" #include "base/mac/mach_logging.h" @@ -38,12 +40,13 @@ namespace base { namespace allocator { +bool g_replaced_default_zone = false; + MallocZoneFunctions::MallocZoneFunctions() {} namespace { bool g_oom_killer_enabled; -bool g_replaced_default_zone = false; // 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, @@ -203,12 +206,6 @@ #endif // !defined(ADDRESS_SANITIZER) -// === C++ operator new === - -void oom_killer_new() { - TerminateBecauseOutOfMemory(0); -} - #if !defined(ADDRESS_SANITIZER) // === Core Foundation CFAllocators === @@ -441,13 +438,6 @@ // 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 ===
diff --git a/base/process/memory_mac.mm b/base/process/memory_mac.mm index 155004dc..4b5a3ce 100644 --- a/base/process/memory_mac.mm +++ b/base/process/memory_mac.mm
@@ -5,10 +5,18 @@ #include "base/process/memory.h" #include "base/allocator/allocator_interception_mac.h" +#include "base/allocator/allocator_shim.h" +#include "base/allocator/features.h" #include "build/build_config.h" namespace base { +namespace { +void oom_killer_new() { + TerminateBecauseOutOfMemory(0); +} +} // namespace + void EnableTerminationOnHeapCorruption() { #if !ARCH_CPU_64_BITS DLOG(WARNING) << "EnableTerminationOnHeapCorruption only works on 64-bit"; @@ -24,6 +32,17 @@ } void EnableTerminationOnOutOfMemory() { + // Step 1: Enable OOM killer on C++ failures. + std::set_new_handler(oom_killer_new); + +// Step 2: Enable OOM killer on C-malloc failures for the default zone (if we +// have a shim). +#if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) + allocator::SetCallNewHandlerOnMallocFailure(true); +#endif + + // Step 3: Enable OOM killer on all other malloc zones (or just "all" without + // "other" if shim is disabled). allocator::InterceptAllocationsMac(); }
diff --git a/base/process/memory_unittest.cc b/base/process/memory_unittest.cc index ce28225..ecf0b87 100644 --- a/base/process/memory_unittest.cc +++ b/base/process/memory_unittest.cc
@@ -27,6 +27,8 @@ #endif #if defined(OS_MACOSX) #include <malloc/malloc.h> +#include "base/allocator/allocator_interception_mac.h" +#include "base/allocator/allocator_shim.h" #include "base/process/memory_unittest_mac.h" #endif #if defined(OS_LINUX) @@ -59,6 +61,9 @@ // will fail. TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) { +#if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) + base::allocator::InitializeAllocatorShim(); +#endif // Assert that freeing an unallocated pointer will crash the process. char buf[9]; asm("" : "=r" (buf)); // Prevent clang from being too smart. @@ -79,6 +84,12 @@ #endif // defined(OS_MACOSX) TEST(MemoryTest, AllocatorShimWorking) { +#if defined(OS_MACOSX) +#if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) + base::allocator::InitializeAllocatorShim(); +#endif + base::allocator::InterceptAllocationsMac(); +#endif ASSERT_TRUE(base::allocator::IsAllocatorInitialized()); } @@ -124,6 +135,10 @@ class OutOfMemoryDeathTest : public OutOfMemoryTest { public: void SetUpInDeathAssert() { +#if defined(OS_MACOSX) && BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) + base::allocator::InitializeAllocatorShim(); +#endif + // Must call EnableTerminationOnOutOfMemory() because that is called from // chrome's main function and therefore hasn't been called yet. // Since this call may result in another thread being created and death
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni index f2118103c..2bcd6caa 100644 --- a/build/config/sysroot.gni +++ b/build/config/sysroot.gni
@@ -16,6 +16,10 @@ target_sysroot_dir = "" use_sysroot = true + + # TODO(tonikitoo): Remove this arg when wheezy is finally dropped and we + # can just use debian/jessie everywhere by default. crbug.com/564904. + use_jessie_sysroot = false } if (is_linux && target_sysroot_dir != "") { @@ -58,15 +62,8 @@ if (current_cpu == "x64") { sysroot = "//build/linux/debian_wheezy_amd64-sysroot" - # TODO(tonikitoo): Remove the whole if clause below when debian/wheezy - # sysroots are switched to debian/jessie, crbug.com/564904. - import("//build_overrides/build.gni") - if (build_with_chromium) { - import("//ui/ozone/ozone.gni") - import("//ui/base/ui_features.gni") - if (use_ozone && use_xkbcommon) { - sysroot = "//build/linux/debian_jessie_amd64-sysroot" - } + if (use_jessie_sysroot) { + sysroot = "//build/linux/debian_jessie_amd64-sysroot" } } else if (current_cpu == "x86") { sysroot = "//build/linux/debian_wheezy_i386-sysroot"
diff --git a/cc/surfaces/compositor_frame_sink_support.cc b/cc/surfaces/compositor_frame_sink_support.cc index e7848f80..f79f22c 100644 --- a/cc/surfaces/compositor_frame_sink_support.cc +++ b/cc/surfaces/compositor_frame_sink_support.cc
@@ -76,25 +76,34 @@ ++ack_pending_count_; float device_scale_factor = frame.metadata.device_scale_factor; + surface_factory_.SubmitCompositorFrame( + local_surface_id, std::move(frame), + base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck, + weak_factory_.GetWeakPtr())); + if (surface_manager_->using_surface_references()) { SurfaceId last_surface_id = reference_tracker_.current_surface_id(); // Populate list of surface references to add and remove based on reference - // surfaces in current frame compared with the last frame. - reference_tracker_.UpdateReferences(local_surface_id, - frame.metadata.referenced_surfaces); + // surfaces in current frame compared with the last frame. The list of + // surface references includes references from both the pending and active + // frame if any. + SurfaceId current_surface_id(frame_sink_id_, local_surface_id); + Surface* surface = surface_manager_->GetSurfaceForId(current_surface_id); + // TODO(fsamuel): This is pretty inefficent. We copy over referenced + // surfaces. Then we pass them into the ReferencedSurfaceTracker to copy + // them again into a set. ReferencedSurfaceTracker should just take in two + // vectors, one for pending referenced surfaces and one for active + // referenced surfaces. + std::vector<SurfaceId> referenced_surfaces = + surface->active_referenced_surfaces(); - surface_factory_.SubmitCompositorFrame( - local_surface_id, std::move(frame), - base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck, - weak_factory_.GetWeakPtr())); + referenced_surfaces.insert(referenced_surfaces.end(), + surface->pending_referenced_surfaces().begin(), + surface->pending_referenced_surfaces().end()); + reference_tracker_.UpdateReferences(local_surface_id, referenced_surfaces); UpdateSurfaceReferences(last_surface_id, local_surface_id); - } else { - surface_factory_.SubmitCompositorFrame( - local_surface_id, std::move(frame), - base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck, - weak_factory_.GetWeakPtr())); } if (display_)
diff --git a/cc/surfaces/compositor_frame_sink_support.h b/cc/surfaces/compositor_frame_sink_support.h index cfdd0a2..6bf64d14 100644 --- a/cc/surfaces/compositor_frame_sink_support.h +++ b/cc/surfaces/compositor_frame_sink_support.h
@@ -46,6 +46,10 @@ return surface_factory_.current_surface_for_testing(); } + const ReferencedSurfaceTracker& ReferenceTrackerForTesting() const { + return reference_tracker_; + } + void EvictFrame(); void SetNeedsBeginFrame(bool needs_begin_frame); void SubmitCompositorFrame(const LocalSurfaceId& local_surface_id,
diff --git a/cc/surfaces/compositor_frame_sink_support_unittest.cc b/cc/surfaces/compositor_frame_sink_support_unittest.cc index 6a49fce..67d08fa3 100644 --- a/cc/surfaces/compositor_frame_sink_support_unittest.cc +++ b/cc/surfaces/compositor_frame_sink_support_unittest.cc
@@ -50,13 +50,17 @@ class CompositorFrameSinkSupportTest : public testing::Test, public CompositorFrameSinkSupportClient { public: - CompositorFrameSinkSupportTest() {} + CompositorFrameSinkSupportTest() + : surface_manager_(SurfaceManager::LifetimeType::REFERENCES) {} ~CompositorFrameSinkSupportTest() override {} CompositorFrameSinkSupport& parent_support() { return *supports_[0]; } Surface* parent_surface() { return parent_support().current_surface_for_testing(); } + const ReferencedSurfaceTracker& parent_reference_tracker() { + return parent_support().ReferenceTrackerForTesting(); + } CompositorFrameSinkSupport& child_support1() { return *supports_[1]; } Surface* child_surface1() { @@ -105,7 +109,11 @@ void TearDown() override { surface_manager_.SetDependencyTracker(nullptr); + + // SurfaceDependencyTracker depends on this BeginFrameSource and so it must + // be destroyed AFTER the dependency tracker is destroyed. begin_frame_source_.reset(); + supports_.clear(); } @@ -387,5 +395,53 @@ EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); } +// This test verifies that the set of references from a Surface includes both +// the pending and active CompositorFrames. +TEST_F(CompositorFrameSinkSupportTest, + DisplayCompositorLockingReferencesFromPendingAndActiveFrames) { + const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); + const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1); + const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1); + const SurfaceReference parent_child_reference(parent_id, child_id); + const SurfaceReference parent_arbitrary_reference(parent_id, arbitrary_id); + + // child_support1 submits a CompositorFrame without any dependencies. + child_support1().SubmitCompositorFrame( + child_id.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); + + // Verify that the child surface is not blocked. + EXPECT_TRUE(child_surface1()->HasActiveFrame()); + EXPECT_FALSE(child_surface1()->HasPendingFrame()); + EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), IsEmpty()); + + // parent_support submits a CompositorFrame that depends on |child_id1| + // which is already active. Thus, this CompositorFrame should activate + // immediately. + parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), + MakeCompositorFrame({child_id})); + EXPECT_TRUE(parent_surface()->HasActiveFrame()); + EXPECT_FALSE(parent_surface()->HasPendingFrame()); + EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + // Verify that the parent will add a reference to the |child_id|. + EXPECT_THAT(parent_reference_tracker().references_to_add(), + UnorderedElementsAre(parent_child_reference)); + EXPECT_THAT(parent_reference_tracker().references_to_remove(), IsEmpty()); + + // parent_support now submits another CompositorFrame to the same surface + // but depends on arbitrary_id. The parent surface should now have both + // a pending and active CompositorFrame. + parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), + MakeCompositorFrame({arbitrary_id})); + EXPECT_TRUE(parent_surface()->HasActiveFrame()); + EXPECT_TRUE(parent_surface()->HasPendingFrame()); + EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + UnorderedElementsAre(arbitrary_id)); + // Verify that the parent will add a reference to |arbitrary_id| and will not + // remove a reference to |child_id|. + EXPECT_THAT(parent_reference_tracker().references_to_add(), + UnorderedElementsAre(parent_arbitrary_reference)); + EXPECT_THAT(parent_reference_tracker().references_to_remove(), IsEmpty()); +} + } // namespace test } // namespace cc
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc index 57e3a3c9..c2ab354 100644 --- a/cc/surfaces/surface.cc +++ b/cc/surfaces/surface.cc
@@ -63,6 +63,8 @@ pending_frame_ = std::move(frame); if (pending_frame_) { factory_->ReceiveFromChild(pending_frame_->resource_list); + pending_referenced_surfaces_ = + pending_frame_->metadata.referenced_surfaces; // Ask the surface manager to inform |this| when its dependencies are // resolved. factory_->manager()->RequestSurfaceResolution(this); @@ -149,6 +151,7 @@ DCHECK(pending_frame_); ActivateFrame(std::move(pending_frame_.value())); pending_frame_.reset(); + pending_referenced_surfaces_.clear(); // ActiveFrame resources are now double ref-ed. Unref. UnrefFrameResources(*active_frame_); } @@ -177,7 +180,7 @@ if (previous_frame) UnrefFrameResources(*previous_frame); - referenced_surfaces_ = active_frame_->metadata.referenced_surfaces; + active_referenced_surfaces_ = active_frame_->metadata.referenced_surfaces; for (auto& observer : observers_) observer.OnSurfaceActivated(this);
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h index a427a822..e8fbccf 100644 --- a/cc/surfaces/surface.h +++ b/cc/surfaces/surface.h
@@ -101,8 +101,12 @@ return destruction_dependencies_.size(); } - const std::vector<SurfaceId>& referenced_surfaces() const { - return referenced_surfaces_; + const std::vector<SurfaceId>& active_referenced_surfaces() const { + return active_referenced_surfaces_; + } + + const std::vector<SurfaceId>& pending_referenced_surfaces() const { + return pending_referenced_surfaces_; } const SurfaceDependencies& blocking_surfaces_for_testing() const { @@ -140,8 +144,19 @@ // on multiple Displays. std::set<BeginFrameSource*> begin_frame_sources_; - // The total set of CompositorFrames referenced by the active CompositorFrame. - std::vector<SurfaceId> referenced_surfaces_; + // The set of SurfaceIds referenced by the active CompositorFrame. + // TODO(fsamuel): It seems unnecessary to copy this vector over + // from CompostiorFrameMetadata to store locally here. We can simply + // provide an accessor to the referenced surfaces directly from + // CompositorFrameMetadata. + std::vector<SurfaceId> active_referenced_surfaces_; + + // The set of SurfaceIds referenced by the pending CompositorFrame. + // TODO(fsamuel): It seems unnecessary to copy this vector over + // from CompostiorFrameMetadata to store locally here. We can simply + // provide an accessor to the referenced surfaces directly from + // CompositorFrameMetadata. + std::vector<SurfaceId> pending_referenced_surfaces_; SurfaceDependencies blocking_surfaces_; base::ObserverList<PendingFrameObserver, true> observers_;
diff --git a/cc/surfaces/surface_dependency_tracker.cc b/cc/surfaces/surface_dependency_tracker.cc index 934586b..df20152 100644 --- a/cc/surfaces/surface_dependency_tracker.cc +++ b/cc/surfaces/surface_dependency_tracker.cc
@@ -26,6 +26,9 @@ SurfaceDependencyTracker::~SurfaceDependencyTracker() { surface_manager_->RemoveObserver(this); begin_frame_source_->RemoveObserver(this); + for (Surface* pending_surface : pending_surfaces_) + pending_surface->RemoveObserver(this); + pending_surfaces_.clear(); } void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc index c91bf2c..f7e3119 100644 --- a/cc/surfaces/surface_manager.cc +++ b/cc/surfaces/surface_manager.cc
@@ -327,7 +327,9 @@ Surface* surf = surface_map_[live_surfaces[i]]; DCHECK(surf); - for (const SurfaceId& id : surf->referenced_surfaces()) { + // TODO(fsamuel): We should probably keep alive pending referenced surfaces + // too. + for (const SurfaceId& id : surf->active_referenced_surfaces()) { if (live_surfaces_set.count(id)) continue;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java index 6c986de..e09cf97 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
@@ -200,7 +200,7 @@ // Check if we should launch an Instant App to handle the intent. if (InstantAppsHandler.getInstance().handleIncomingIntent( - this, intent, mIsCustomTabIntent && !mIsHerbIntent)) { + this, intent, mIsCustomTabIntent && !mIsHerbIntent, false)) { finish(); return; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java index c33e7ac..5c50882 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -642,15 +642,15 @@ return; } } else if (ACTION_DOWNLOAD_RESUME.equals(intent.getAction())) { - boolean metered = DownloadManagerService.isActiveNetworkMetered(mContext); - if (!entry.canDownloadWhileMetered) { - // If user manually resumes a download, update the network type if it - // is not metered previously. - entry.canDownloadWhileMetered = metered; - } - entry.isAutoResumable = true; + // If user manually resumes a download, update the network type if it + // is not metered previously. + boolean canDownloadWhileMetered = entry.canDownloadWhileMetered + || DownloadManagerService.isActiveNetworkMetered(mContext); // Update the SharedPreference entry. - mDownloadSharedPreferenceHelper.addOrReplaceSharedPreferenceEntry(entry); + mDownloadSharedPreferenceHelper.addOrReplaceSharedPreferenceEntry( + new DownloadSharedPreferenceEntry(entry.notificationId, entry.isOffTheRecord, + canDownloadWhileMetered, entry.downloadGuid, entry.fileName, + entry.itemType, true)); } else if (ACTION_DOWNLOAD_RESUME_ALL.equals(intent.getAction()) && (mDownloadSharedPreferenceHelper.getEntries().isEmpty() || DownloadManagerService.hasDownloadManagerService())) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java index ac75223..4ae33fa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java
@@ -27,13 +27,13 @@ public final int notificationId; public final boolean isOffTheRecord; // Whether the download is public (non incognito). - public boolean canDownloadWhileMetered; + public final boolean canDownloadWhileMetered; public final String fileName; public final String downloadGuid; public final int itemType; // This can only be false for paused downloads. For downloads that are pending or in progress, // isAutoResumable should always be true. - public boolean isAutoResumable; + public final boolean isAutoResumable; static final DownloadSharedPreferenceEntry INVALID_ENTRY = new DownloadSharedPreferenceEntry(-1, false, false, null, "", ITEM_TYPE_DOWNLOAD,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java index fa9c7a6..c954ec50 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -586,7 +586,7 @@ Intent resolvedIntent = new Intent(intent); resolvedIntent.setData(Uri.parse(url)); return handler.handleIncomingIntent(getAvailableContext(), resolvedIntent, - ChromeLauncherActivity.isCustomTabIntent(resolvedIntent)); + ChromeLauncherActivity.isCustomTabIntent(resolvedIntent), true); } else if (!isIncomingRedirect) { // Check if the navigation is coming from SERP and skip instant app handling. if (isSerpReferrer(tab)) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java index 8470bfd..4b7beb7b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java
@@ -11,6 +11,7 @@ import android.os.SystemClock; import android.provider.Browser; +import org.chromium.base.BuildInfo; import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample; @@ -159,18 +160,32 @@ } } - /** Handle incoming intent. */ + /** + * Handle incoming intent. + * @param context Context. + * @param intent The incoming intent being handled. + * @param isCustomTabsIntent Whether we are in custom tabs. + * @param isRedirect Whether this is the redirect resolve case where incoming intent was + * resolved to another URL. + * @return Whether Instant Apps is handling the URL request. + */ public boolean handleIncomingIntent(Context context, Intent intent, - boolean isCustomTabsIntent) { + boolean isCustomTabsIntent, boolean isRedirect) { long startTimeStamp = SystemClock.elapsedRealtime(); boolean result = handleIncomingIntentInternal(context, intent, isCustomTabsIntent, - startTimeStamp); + startTimeStamp, isRedirect); recordHandleIntentDuration(startTimeStamp); return result; } private boolean handleIncomingIntentInternal( - Context context, Intent intent, boolean isCustomTabsIntent, long startTime) { + Context context, Intent intent, boolean isCustomTabsIntent, long startTime, + boolean isRedirect) { + if (!isRedirect && !isCustomTabsIntent && BuildInfo.isAtLeastO()) { + Log.i(TAG, "Disabled for Android O+"); + return false; + } + if (isCustomTabsIntent && !IntentUtils.safeGetBooleanExtra( intent, CUSTOM_APPS_INSTANT_APP_EXTRA, false)) { Log.i(TAG, "Not handling with Instant Apps (missing CUSTOM_APPS_INSTANT_APP_EXTRA)");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/media/router/OWNERS index dc2593f..7816a76 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/OWNERS
@@ -1,2 +1,4 @@ avayvod@chromium.org mlamouri@chromium.org + +# COMPONENT: Blink>PresentationAPI
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/OWNERS index dc2593f..68dc47e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/OWNERS
@@ -1,2 +1,4 @@ avayvod@chromium.org mlamouri@chromium.org + +# COMPONENT: Internals>Media>UI
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java index fed38043..6757ff15 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java
@@ -11,7 +11,6 @@ import org.chromium.base.Callback; import org.chromium.base.Log; import org.chromium.base.SysUtils; -import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.ChromeBackgroundServiceWaiter; import org.chromium.chrome.browser.offlinepages.interfaces.BackgroundSchedulerProcessor; @@ -37,8 +36,26 @@ * * @returns true for success */ - public boolean startBackgroundRequests(Context context, Bundle bundle, - ChromeBackgroundServiceWaiter waiter) { + public void startBackgroundRequests( + Context context, Bundle bundle, final ChromeBackgroundServiceWaiter waiter) { + // Complete the wait if background request processing was not started. + // If background processing was started, completion is going to be handled by callback. + if (!startBackgroundRequestsImpl(context, bundle, waiter)) { + waiter.onWaitDone(); + } + } + + /** + * Triggers processing of background offlining requests. This is called when + * system conditions are appropriate for background offlining, typically from the + * GcmTaskService onRunTask() method. In response, we will start the + * task processing by passing the call along to the C++ RequestCoordinator. + * Also starts UMA collection. + * + * @returns true for success + */ + private boolean startBackgroundRequestsImpl( + Context context, Bundle bundle, final ChromeBackgroundServiceWaiter waiter) { // Set up backup scheduled task in case processing is killed before RequestCoordinator // has a chance to reschedule base on remaining work. TriggerConditions previousTriggerConditions = @@ -58,51 +75,23 @@ return false; } - // Now initiate processing. - processBackgroundRequests(bundle, currentConditions, waiter); - // Gather UMA data to measure how often the user's machine is amenable to background // loading when we wake to do a task. long taskScheduledTimeMillis = TaskExtrasPacker.unpackTimeFromBundle(bundle); OfflinePageUtils.recordWakeupUMA(context, taskScheduledTimeMillis); - return true; + return mBridge.startScheduledProcessing(currentConditions, createCallback(waiter)); } - /** - * Triggers processing of background offlining requests. - */ - // TODO(petewil): Change back to private when UMA works in the test, and test - // startBackgroundRequests instead of this method. - @VisibleForTesting - public void processBackgroundRequests( - Bundle bundle, DeviceConditions deviceConditions, - final ChromeBackgroundServiceWaiter waiter) { - // TODO(petewil): Nothing is holding the Wake Lock. We need some solution to - // keep hold of it. Options discussed so far are having a fresh set of functions - // to grab and release a countdown latch, or holding onto the wake lock ourselves, - // or grabbing the wake lock and then starting chrome and running - // startScheduledProcessing on the UI thread. - - // TODO(petewil): Decode the TriggerConditions from the bundle. - - Callback<Boolean> callback = new Callback<Boolean>() { - /** - * Callback function which indicates completion of background work. - * @param result - true if work was actually done (used for UMA). - */ + private Callback<Boolean> createCallback(final ChromeBackgroundServiceWaiter waiter) { + return new Callback<Boolean>() { + /** Callback releasing the wakelock once background work concludes. */ @Override public void onResult(Boolean result) { - // Release the wake lock. Log.d(TAG, "onProcessingDone"); + // Release the wake lock. waiter.onWaitDone(); } }; - - // Pass the activation on to the bridge to the C++ RequestCoordinator. - if (!mBridge.startScheduledProcessing(deviceConditions, callback)) { - // Processing not started currently. Let callback know. - callback.onResult(false); - } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS index 2ee557cd..fe55c0f2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -2,3 +2,5 @@ dominickn@chromium.org mlamouri@chromium.org changwan@chromium.org + +# COMPONENT: Content>WebApps
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java index a140742..756b9d73 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
@@ -66,7 +66,7 @@ Intent i = createViewIntent(); i.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true); - assertFalse(mHandler.handleIncomingIntent(mContext, i, false)); + assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true)); } @@ -75,13 +75,13 @@ Intent i = createViewIntent(); i.putExtra("com.google.android.gms.instantapps.DO_NOT_LAUNCH_INSTANT_APP", true); - assertFalse(mHandler.handleIncomingIntent(mContext, i, false)); + assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true)); } @SmallTest public void testInstantAppsDisabled_mainIntent() { Intent i = new Intent(Intent.ACTION_MAIN); - assertFalse(mHandler.handleIncomingIntent(mContext, i, false)); + assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true)); } @SmallTest @@ -89,20 +89,20 @@ Intent i = createViewIntent(); i.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName()); - assertFalse(mHandler.handleIncomingIntent(mContext, i, false)); + assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true)); Intent signedIntent = createViewIntent(); signedIntent.setPackage(mContext.getPackageName()); IntentHandler.addTrustedIntentExtras(signedIntent); - assertFalse(mHandler.handleIncomingIntent(mContext, signedIntent, false)); + assertFalse(mHandler.handleIncomingIntent(mContext, signedIntent, false, true)); } @SmallTest public void testInstantAppsDisabled_launchFromShortcut() { Intent i = createViewIntent(); i.putExtra(ShortcutHelper.EXTRA_SOURCE, 1); - assertFalse(mHandler.handleIncomingIntent(mContext, i, false)); + assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true)); } @SmallTest @@ -112,33 +112,37 @@ editor.putBoolean("applink.chrome_default_browser", false); editor.apply(); - assertFalse(mHandler.handleIncomingIntent(mContext, createViewIntent(), false)); + assertFalse(mHandler.handleIncomingIntent(mContext, createViewIntent(), false, true)); // Even if Chrome is not default, launch Instant Apps for CustomTabs since those never // show disambiguation dialogs. Intent cti = createViewIntent() .putExtra("android.support.customtabs.extra.EXTRA_ENABLE_INSTANT_APPS", true); - assertTrue(mHandler.handleIncomingIntent(mContext, cti, true)); + assertTrue(mHandler.handleIncomingIntent(mContext, cti, true, true)); } @SmallTest public void testInstantAppsEnabled() { Intent i = createViewIntent(); - assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, false)); + assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, false, + true)); // Check that identical intent wouldn't be enabled for CustomTab flow. - assertFalse(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, true)); + assertFalse(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, true, + true)); // Add CustomTab specific extra and check it's now enabled. i.putExtra("android.support.customtabs.extra.EXTRA_ENABLE_INSTANT_APPS", true); - assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, true)); + assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, true, + true)); } @SmallTest public void testNfcIntent() { Intent i = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED); i.setData(Uri.parse("http://instantapp.com/")); - assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, false)); + assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, false, + true)); } @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/media/OWNERS index f4a9d9c..c8e9dde 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/OWNERS +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/OWNERS
@@ -1,3 +1,5 @@ aberent@chromium.org avayvod@chromium.org mlamouri@chromium.org + +# COMPONENT: Internals>Media>UI
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS index 73145cc..bd7774a8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -2,3 +2,5 @@ dominickn@chromium.org changwan@chromium.org mlamouri@chromium.org + +# COMPONENT: Content>WebApps
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/router/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/media/router/OWNERS index dc2593f..7816a76 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/router/OWNERS +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/router/OWNERS
@@ -1,2 +1,4 @@ avayvod@chromium.org mlamouri@chromium.org + +# COMPONENT: Blink>PresentationAPI
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/OWNERS index f1deab2..a276f281 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/OWNERS +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/OWNERS
@@ -1,3 +1,5 @@ avayvod@chromium.org mlamouri@chromium.org zqzhang@chromium.org + +# COMPONENT: Internals>Media>UI
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java index f589465..21e214a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java
@@ -113,44 +113,12 @@ @Test @Feature({"OfflinePages"}) - public void testIncomingTask() { - BackgroundOfflinerTask task = - new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor); - ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1000); - task.processBackgroundRequests(mTaskExtras, mDeviceConditions, waiter); - - // Check with BackgroundSchedulerProcessor that it started processing. - assertTrue(mStubBackgroundSchedulerProcessor.getDidStartProcessing()); - assertSame(mDeviceConditions, mStubBackgroundSchedulerProcessor.getDeviceConditions()); - - // Call the callback and then waiter should not block. - mStubBackgroundSchedulerProcessor.callback(); - waiter.startWaiting(); - } - - @Test - @Feature({"OfflinePages"}) - public void testIncomingTaskNotStarted() { - mStubBackgroundSchedulerProcessor.setFailToStart(true); - BackgroundOfflinerTask task = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor); - ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1000); - task.processBackgroundRequests(mTaskExtras, mDeviceConditions, waiter); - - // Check with BackgroundSchedulerProcessor that it did not start. - assertFalse(mStubBackgroundSchedulerProcessor.getDidStartProcessing()); - - // The waiter should not block if startScheduledProcessing returned false. - waiter.startWaiting(); - } - - @Test - @Feature({"OfflinePages"}) public void testStartBackgroundRequests() { BackgroundOfflinerTask task = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor); ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1); assertNull("Nothing scheduled", mGcmNetworkManager.getScheduledTask()); - assertTrue(task.startBackgroundRequests( - RuntimeEnvironment.application, mTaskExtras, waiter)); + + task.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter); // Check that the backup task was scheduled. Task gcmTask = mGcmNetworkManager.getScheduledTask(); @@ -158,23 +126,50 @@ assertEquals(mTriggerConditions, TaskExtrasPacker.unpackTriggerConditionsFromBundle(gcmTask.getExtras())); - // Check with BackgroundSchedulerProcessor that startScheduledProcessing got called. + // Check with BackgroundSchedulerProcessor that processing stated. assertTrue(mStubBackgroundSchedulerProcessor.getDidStartProcessing()); assertSame(mDeviceConditions, mStubBackgroundSchedulerProcessor.getDeviceConditions()); + + // Waiter is only released at the end of the test, when the processing concludes. + mStubBackgroundSchedulerProcessor.callback(); + waiter.startWaiting(); + } + + @Test + @Feature({"OfflinePages"}) + public void testStartBackgroundRequestsNotStarted() { + mStubBackgroundSchedulerProcessor.setFailToStart(true); + BackgroundOfflinerTask task = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor); + ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1); + assertNull("Nothing scheduled", mGcmNetworkManager.getScheduledTask()); + + task.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter); + waiter.startWaiting(); + + // Check that the backup task was scheduled. + Task gcmTask = mGcmNetworkManager.getScheduledTask(); + assertNotNull("Backup task scheduled", gcmTask); + assertEquals(mTriggerConditions, + TaskExtrasPacker.unpackTriggerConditionsFromBundle(gcmTask.getExtras())); + + // Check with BackgroundSchedulerProcessor that it did not start. + assertFalse(mStubBackgroundSchedulerProcessor.getDidStartProcessing()); } @Test @Feature({"OfflinePages"}) public void testStartBackgroundRequestsForLowBatteryLevel() { + // Setup low battery conditions. DeviceConditions deviceConditionsLowBattery = new DeviceConditions( !POWER_CONNECTED, MINIMUM_BATTERY_LEVEL - 1, ConnectionType.CONNECTION_WIFI); when(mOfflinePageUtils.getDeviceConditionsImpl(any(Context.class))) .thenReturn(deviceConditionsLowBattery); + BackgroundOfflinerTask task = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor); ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1); assertNull("Nothing scheduled", mGcmNetworkManager.getScheduledTask()); - assertFalse(task.startBackgroundRequests( - RuntimeEnvironment.application, mTaskExtras, waiter)); + task.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter); + waiter.startWaiting(); // Check that the backup task was scheduled. Task gcmTask = mGcmNetworkManager.getScheduledTask(); @@ -190,11 +185,16 @@ POWER_CONNECTED, MINIMUM_BATTERY_LEVEL - 1, ConnectionType.CONNECTION_WIFI); when(mOfflinePageUtils.getDeviceConditionsImpl(any(Context.class))) .thenReturn(deviceConditionsPowerConnected); + BackgroundOfflinerTask task2 = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor); ChromeBackgroundServiceWaiter waiter2 = new ChromeBackgroundServiceWaiter(1); - assertTrue(task2.startBackgroundRequests( - RuntimeEnvironment.application, mTaskExtras, waiter2)); + task2.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter2); + + assertTrue(mStubBackgroundSchedulerProcessor.getDidStartProcessing()); + + mStubBackgroundSchedulerProcessor.callback(); + waiter2.startWaiting(); } @Test @@ -207,8 +207,8 @@ // Transition the test Activity to a running state. ApplicationStatus.onStateChangeForTesting(mTestActivity, ActivityState.STARTED); - assertFalse(task.startBackgroundRequests( - RuntimeEnvironment.application, mTaskExtras, waiter)); + task.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter); + waiter.startWaiting(); // Check that the backup task was scheduled. Task gcmTask = mGcmNetworkManager.getScheduledTask(); @@ -224,7 +224,11 @@ BackgroundOfflinerTask task2 = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor); ChromeBackgroundServiceWaiter waiter2 = new ChromeBackgroundServiceWaiter(1); - assertTrue(task2.startBackgroundRequests( - RuntimeEnvironment.application, mTaskExtras, waiter2)); + task2.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter2); + + assertTrue(mStubBackgroundSchedulerProcessor.getDidStartProcessing()); + + mStubBackgroundSchedulerProcessor.callback(); + waiter2.startWaiting(); } }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 2bdd423..77a1be94 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -6352,9 +6352,6 @@ <message name="IDS_FLAGS_DATASAVER_PROMPT_DEMO_MODE" desc="The value of the Data Saver prompt flag which always shows prompt on network properties change."> Demo mode </message> - <message name="IDS_FLAGS_DISABLE_UNIFIED_MEDIA_PIPELINE_NAME" desc="Title for the flag to disable the unified media pipeline on Android."> - Disables the unified media pipeline on Android. - </message> <message name="IDS_FLAGS_DISABLE_UNIFIED_MEDIA_PIPELINE_DESCRIPTION" desc="Description for the flag to disable the unified media pipeline on Android."> Disables the unified (Android and desktop) media pipeline on Android. </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 6c414b5..ea494c1 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2432,6 +2432,8 @@ "captive_portal/captive_portal_tab_helper.h", "captive_portal/captive_portal_tab_reloader.cc", "captive_portal/captive_portal_tab_reloader.h", + "component_updater/ssl_error_assistant_component_installer.cc", + "component_updater/ssl_error_assistant_component_installer.h", "ssl/captive_portal_blocking_page.cc", "ssl/captive_portal_blocking_page.h", "ssl/captive_portal_metrics_recorder.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 63fac04..1679909 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1766,12 +1766,6 @@ IDS_FLAGS_ENABLE_WEB_USB_DESCRIPTION, kOsAll, FEATURE_VALUE_TYPE(features::kWebUsb)}, #if defined(OS_ANDROID) - {"disable-unified-media-pipeline", - IDS_FLAGS_DISABLE_UNIFIED_MEDIA_PIPELINE_NAME, - IDS_FLAGS_DISABLE_UNIFIED_MEDIA_PIPELINE_DESCRIPTION, kOsAndroid, - SINGLE_VALUE_TYPE(switches::kDisableUnifiedMediaPipeline)}, -#endif // OS_ANDROID -#if defined(OS_ANDROID) {"force-show-update-menu-item", IDS_FLAGS_UPDATE_MENU_ITEM_NAME, IDS_FLAGS_UPDATE_MENU_ITEM_DESCRIPTION, kOsAndroid, SINGLE_VALUE_TYPE(switches::kForceShowUpdateMenuItem)},
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 98690ba..0cbbdd0 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -239,6 +239,10 @@ #include "chrome/browser/background/background_mode_manager.h" #endif // BUILDFLAG(ENABLE_BACKGROUND) +#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) +#include "chrome/browser/component_updater/ssl_error_assistant_component_installer.h" +#endif // BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) + #if BUILDFLAG(ENABLE_EXTENSIONS) #include "chrome/browser/extensions/startup_helper.h" #include "extensions/browser/extension_protocols.h" @@ -468,14 +472,19 @@ #endif // defined(OS_MACOSX) void RegisterComponentsForUpdate() { - const auto cus = g_browser_process->component_updater(); + component_updater::ComponentUpdateService* cus = + g_browser_process->component_updater(); + // Registration can be before or after cus->Start() so it is ok to post + // a task to the UI thread to do registration once you done the necessary + // file IO to know you existing component version. +#if !defined(OS_ANDROID) +#if !defined(OS_CHROMEOS) if (base::FeatureList::IsEnabled(features::kImprovedRecoveryComponent)) RegisterRecoveryImprovedComponent(cus, g_browser_process->local_state()); else RegisterRecoveryComponent(cus, g_browser_process->local_state()); - -#if !defined(OS_ANDROID) +#endif // !defined(OS_CHROMEOS) RegisterPepperFlashComponent(cus); #if !defined(OS_CHROMEOS) RegisterSwiftShaderComponent(cus); @@ -523,6 +532,10 @@ RegisterOriginTrialsComponent(cus, path); RegisterFileTypePoliciesComponent(cus, path); + +#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) + RegisterSSLErrorAssistantComponent(cus, path); +#endif } #if defined(OS_WIN)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index c9242bc1..cba43cd 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1146,8 +1146,6 @@ "policy/user_network_configuration_updater.h", "policy/user_network_configuration_updater_factory.cc", "policy/user_network_configuration_updater_factory.h", - "policy/user_policy_disk_cache.cc", - "policy/user_policy_disk_cache.h", "policy/user_policy_manager_factory_chromeos.cc", "policy/user_policy_manager_factory_chromeos.h", "policy/user_policy_token_loader.cc",
diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc index 4cdb6ec..a5fd09d 100644 --- a/chrome/browser/chromeos/options/network_config_view.cc +++ b/chrome/browser/chromeos/options/network_config_view.cc
@@ -200,10 +200,6 @@ return child_config_view_->GetInitiallyFocusedView(); } -int NetworkConfigView::GetDefaultDialogButton() const { - return ui::DIALOG_BUTTON_CANCEL; -} - base::string16 NetworkConfigView::GetWindowTitle() const { DCHECK(!child_config_view_->GetTitle().empty()); return child_config_view_->GetTitle();
diff --git a/chrome/browser/chromeos/options/network_config_view.h b/chrome/browser/chromeos/options/network_config_view.h index 250e3d1..d1f6cb0c 100644 --- a/chrome/browser/chromeos/options/network_config_view.h +++ b/chrome/browser/chromeos/options/network_config_view.h
@@ -62,7 +62,6 @@ bool Accept() override; views::View* CreateExtraView() override; views::View* GetInitiallyFocusedView() override; - int GetDefaultDialogButton() const override; // views::WidgetDelegate methods. base::string16 GetWindowTitle() const override;
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc index 0f4b4911..f73ec0c 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
@@ -18,7 +18,6 @@ #include "base/sequenced_task_runner.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" -#include "chrome/browser/chromeos/policy/user_policy_disk_cache.h" #include "chrome/browser/chromeos/policy/user_policy_token_loader.h" #include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/dbus/cryptohome_client.h"
diff --git a/chrome/browser/chromeos/policy/user_policy_disk_cache.cc b/chrome/browser/chromeos/policy/user_policy_disk_cache.cc deleted file mode 100644 index 5a97941..0000000 --- a/chrome/browser/chromeos/policy/user_policy_disk_cache.cc +++ /dev/null
@@ -1,148 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/policy/user_policy_disk_cache.h" - -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/metrics/histogram_macros.h" -#include "base/sequenced_task_runner.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/policy/core/common/cloud/enterprise_metrics.h" -#include "components/policy/proto/device_management_local.pb.h" - -namespace em = enterprise_management; - -namespace policy { - -UserPolicyDiskCache::Delegate::~Delegate() {} - -UserPolicyDiskCache::UserPolicyDiskCache( - const base::WeakPtr<Delegate>& delegate, - const base::FilePath& backing_file_path, - scoped_refptr<base::SequencedTaskRunner> background_task_runner) - : delegate_(delegate), - backing_file_path_(backing_file_path), - origin_task_runner_(base::ThreadTaskRunnerHandle::Get()), - background_task_runner_(background_task_runner) { -} - -void UserPolicyDiskCache::Load() { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - bool ret = background_task_runner_->PostTask( - FROM_HERE, base::Bind(&UserPolicyDiskCache::LoadOnFileThread, this)); - DCHECK(ret); -} - -void UserPolicyDiskCache::Store( - const em::CachedCloudPolicyResponse& policy) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - background_task_runner_->PostTask( - FROM_HERE, - base::Bind(&UserPolicyDiskCache::StoreOnFileThread, this, policy)); -} - -UserPolicyDiskCache::~UserPolicyDiskCache() {} - -void UserPolicyDiskCache::LoadOnFileThread() { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - - em::CachedCloudPolicyResponse cached_response; - if (!base::PathExists(backing_file_path_)) { - LoadDone(LOAD_RESULT_NOT_FOUND, cached_response); - return; - } - - // Read the protobuf from the file. - std::string data; - if (!base::ReadFileToString(backing_file_path_, &data)) { - LOG(WARNING) << "Failed to read policy data from " - << backing_file_path_.value(); - LoadDone(LOAD_RESULT_READ_ERROR, cached_response); - return; - } - - // Decode it. - if (!cached_response.ParseFromArray(data.c_str(), data.size())) { - LOG(WARNING) << "Failed to parse policy data read from " - << backing_file_path_.value(); - LoadDone(LOAD_RESULT_PARSE_ERROR, cached_response); - return; - } - - LoadDone(LOAD_RESULT_SUCCESS, cached_response); -} - -void UserPolicyDiskCache::LoadDone( - LoadResult result, - const em::CachedCloudPolicyResponse& policy) { - origin_task_runner_->PostTask( - FROM_HERE, - base::Bind( - &UserPolicyDiskCache::ReportResultOnUIThread, this, result, policy)); -} - -void UserPolicyDiskCache::ReportResultOnUIThread( - LoadResult result, - const em::CachedCloudPolicyResponse& policy) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - - switch (result) { - case LOAD_RESULT_NOT_FOUND: - break; - case LOAD_RESULT_READ_ERROR: - case LOAD_RESULT_PARSE_ERROR: - UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy, - kMetricPolicyLoadFailed, - policy::kMetricPolicySize); - break; - case LOAD_RESULT_SUCCESS: - UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy, - kMetricPolicyLoadSucceeded, - policy::kMetricPolicySize); - break; - } - - if (delegate_.get()) - delegate_->OnDiskCacheLoaded(result, policy); -} - -void UserPolicyDiskCache::StoreOnFileThread( - const em::CachedCloudPolicyResponse& policy) { - DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - std::string data; - if (!policy.SerializeToString(&data)) { - LOG(WARNING) << "Failed to serialize policy data"; - UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy, - kMetricPolicyStoreFailed, - policy::kMetricPolicySize); - return; - } - - if (!base::CreateDirectory(backing_file_path_.DirName())) { - LOG(WARNING) << "Failed to create directory " - << backing_file_path_.DirName().value(); - UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy, - kMetricPolicyStoreFailed, - policy::kMetricPolicySize); - return; - } - - int size = data.size(); - if (base::WriteFile(backing_file_path_, data.c_str(), size) != size) { - LOG(WARNING) << "Failed to write " << backing_file_path_.value(); - UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy, - kMetricPolicyStoreFailed, - policy::kMetricPolicySize); - return; - } - UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy, - kMetricPolicyStoreSucceeded, - policy::kMetricPolicySize); -} - -} // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_policy_disk_cache.h b/chrome/browser/chromeos/policy/user_policy_disk_cache.h deleted file mode 100644 index 6588ea5..0000000 --- a/chrome/browser/chromeos/policy/user_policy_disk_cache.h +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_POLICY_USER_POLICY_DISK_CACHE_H_ -#define CHROME_BROWSER_CHROMEOS_POLICY_USER_POLICY_DISK_CACHE_H_ - -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace enterprise_management { -class CachedCloudPolicyResponse; -} - -namespace policy { - -// Handles the on-disk cache file used by UserPolicyCache. This class handles -// the necessary thread switching and may outlive the associated UserPolicyCache -// instance. -class UserPolicyDiskCache - : public base::RefCountedThreadSafe<UserPolicyDiskCache> { - public: - // Indicates the status of a completed load operation. - enum LoadResult { - // Policy was loaded successfully. - LOAD_RESULT_SUCCESS, - // Cache file missing. - LOAD_RESULT_NOT_FOUND, - // Failed to read cache file. - LOAD_RESULT_READ_ERROR, - // Failed to parse cache file. - LOAD_RESULT_PARSE_ERROR, - }; - - // Delegate interface for observing loads operations. - class Delegate { - public: - virtual ~Delegate(); - virtual void OnDiskCacheLoaded( - LoadResult result, - const enterprise_management::CachedCloudPolicyResponse& policy) = 0; - }; - - UserPolicyDiskCache( - const base::WeakPtr<Delegate>& delegate, - const base::FilePath& backing_file_path, - scoped_refptr<base::SequencedTaskRunner> background_task_runner); - - // Starts reading the policy cache from disk. Passes the read policy - // information back to the hosting UserPolicyCache after a successful cache - // load through UserPolicyCache::OnDiskCacheLoaded(). - void Load(); - - // Triggers a write operation to the disk cache on the FILE thread. - void Store(const enterprise_management::CachedCloudPolicyResponse& policy); - - private: - friend class base::RefCountedThreadSafe<UserPolicyDiskCache>; - ~UserPolicyDiskCache(); - - // Tries to load the cache file on the FILE thread. - void LoadOnFileThread(); - - // Forwards the result to the UI thread. - void LoadDone(LoadResult result, - const enterprise_management::CachedCloudPolicyResponse& policy); - - // Passes back the successfully read policy to the cache on the UI thread. - void ReportResultOnUIThread( - LoadResult result, - const enterprise_management::CachedCloudPolicyResponse& policy); - - // Saves a policy blob on the FILE thread. - void StoreOnFileThread( - const enterprise_management::CachedCloudPolicyResponse& policy); - - base::WeakPtr<Delegate> delegate_; - const base::FilePath backing_file_path_; - scoped_refptr<base::SequencedTaskRunner> origin_task_runner_; - scoped_refptr<base::SequencedTaskRunner> background_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(UserPolicyDiskCache); -}; - -} // namespace policy - -#endif // CHROME_BROWSER_CHROMEOS_POLICY_USER_POLICY_DISK_CACHE_H_
diff --git a/chrome/browser/component_updater/recovery_component_installer.cc b/chrome/browser/component_updater/recovery_component_installer.cc index 9f4e58d..868e5c7e 100644 --- a/chrome/browser/component_updater/recovery_component_installer.cc +++ b/chrome/browser/component_updater/recovery_component_installer.cc
@@ -493,8 +493,7 @@ void RegisterRecoveryComponent(ComponentUpdateService* cus, PrefService* prefs) { -#if defined(GOOGLE_CHROME_BUILD) -#if defined(OS_WIN) || defined(OS_MACOSX) +#if !defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD) if (SimulatingElevatedRecovery()) { BrowserThread::PostTask( BrowserThread::UI, @@ -509,8 +508,7 @@ FROM_HERE, base::Bind(&RecoveryRegisterHelper, cus, prefs), base::TimeDelta::FromSeconds(6)); -#endif -#endif +#endif // !defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD) } void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) {
diff --git a/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc b/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc new file mode 100644 index 0000000..a2451440 --- /dev/null +++ b/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc
@@ -0,0 +1,138 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/component_updater/ssl_error_assistant_component_installer.h" + +#include <memory> + +#include "base/bind.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "chrome/browser/ssl/ssl_error_handler.h" +#include "content/public/browser/browser_thread.h" + +using component_updater::ComponentUpdateService; + +namespace { + +const base::FilePath::CharType kConfigBinaryPbFileName[] = + FILE_PATH_LITERAL("ssl_error_assistant.pb"); + +// The SHA256 of the SubjectPublicKeyInfo used to sign the extension. +// The extension id is: giekcmmlnklenlaomppkphknjmnnpneh +const uint8_t kPublicKeySHA256[32] = { + 0x68, 0x4a, 0x2c, 0xcb, 0xda, 0xb4, 0xdb, 0x0e, 0xcf, 0xfa, 0xf7, + 0xad, 0x9c, 0xdd, 0xfd, 0x47, 0x97, 0xe4, 0x73, 0x24, 0x67, 0x93, + 0x9c, 0xb1, 0x14, 0xcd, 0x3f, 0x54, 0x66, 0x25, 0x99, 0x3f}; + +void LoadProtoFromDisk(const base::FilePath& pb_path) { + if (pb_path.empty()) + return; + + std::string binary_pb; + if (!base::ReadFileToString(pb_path, &binary_pb)) { + // The file won't exist on new installations, so this is not always an + // error. + DVLOG(1) << "Failed reading from " << pb_path.value(); + return; + } + auto proto = base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + if (!proto->ParseFromString(binary_pb)) { + DVLOG(1) << "Failed parsing proto " << pb_path.value(); + return; + } + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&SSLErrorHandler::SetErrorAssistantProto, + base::Passed(std::move(proto)))); +} + +} // namespace + +namespace component_updater { + +bool SSLErrorAssistantComponentInstallerTraits:: + SupportsGroupPolicyEnabledComponentUpdates() const { + return false; +} + +bool SSLErrorAssistantComponentInstallerTraits::RequiresNetworkEncryption() + const { + return false; +} + +update_client::CrxInstaller::Result +SSLErrorAssistantComponentInstallerTraits::OnCustomInstall( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) { + return update_client::CrxInstaller::Result(0); // Nothing custom here. +} + +base::FilePath SSLErrorAssistantComponentInstallerTraits::GetInstalledPath( + const base::FilePath& base) { + return base.Append(kConfigBinaryPbFileName); +} + +void SSLErrorAssistantComponentInstallerTraits::ComponentReady( + const base::Version& version, + const base::FilePath& install_dir, + std::unique_ptr<base::DictionaryValue> manifest) { + DVLOG(1) << "Component ready, version " << version.GetString() << " in " + << install_dir.value(); + + if (!content::BrowserThread::PostBlockingPoolTask( + FROM_HERE, + base::Bind(&LoadProtoFromDisk, GetInstalledPath(install_dir)))) { + NOTREACHED(); + } +} + +// Called during startup and installation before ComponentReady(). +bool SSLErrorAssistantComponentInstallerTraits::VerifyInstallation( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) const { + // No need to actually validate the proto here, since we'll do the checking + // in PopulateFromDynamicUpdate(). + return base::PathExists(GetInstalledPath(install_dir)); +} + +base::FilePath +SSLErrorAssistantComponentInstallerTraits::GetRelativeInstallDir() const { + return base::FilePath(FILE_PATH_LITERAL("SSLErrorAssistant")); +} + +void SSLErrorAssistantComponentInstallerTraits::GetHash( + std::vector<uint8_t>* hash) const { + hash->assign(kPublicKeySHA256, + kPublicKeySHA256 + arraysize(kPublicKeySHA256)); +} + +std::string SSLErrorAssistantComponentInstallerTraits::GetName() const { + return "SSL Error Assistant"; +} + +update_client::InstallerAttributes +SSLErrorAssistantComponentInstallerTraits::GetInstallerAttributes() const { + return update_client::InstallerAttributes(); +} + +std::vector<std::string> +SSLErrorAssistantComponentInstallerTraits::GetMimeTypes() const { + return std::vector<std::string>(); +} + +void RegisterSSLErrorAssistantComponent(ComponentUpdateService* cus, + const base::FilePath& user_data_dir) { + DVLOG(1) << "Registering SSL Error Assistant component."; + + std::unique_ptr<ComponentInstallerTraits> traits( + new SSLErrorAssistantComponentInstallerTraits()); + // |cus| takes ownership of |installer|. + DefaultComponentInstaller* installer = + new DefaultComponentInstaller(std::move(traits)); + installer->Register(cus, base::Closure()); +} + +} // namespace component_updater
diff --git a/chrome/browser/component_updater/ssl_error_assistant_component_installer.h b/chrome/browser/component_updater/ssl_error_assistant_component_installer.h new file mode 100644 index 0000000..88cfd07f --- /dev/null +++ b/chrome/browser/component_updater/ssl_error_assistant_component_installer.h
@@ -0,0 +1,54 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COMPONENT_UPDATER_SSL_ERROR_ASSISTANT_COMPONENT_INSTALLER_H_ +#define CHROME_BROWSER_COMPONENT_UPDATER_SSL_ERROR_ASSISTANT_COMPONENT_INSTALLER_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/values.h" +#include "components/component_updater/default_component_installer.h" + +namespace base { +class FilePath; +} // namespace base + +namespace component_updater { +class SSLErrorAssistantComponentInstallerTraits + : public ComponentInstallerTraits { + public: + SSLErrorAssistantComponentInstallerTraits() {} + ~SSLErrorAssistantComponentInstallerTraits() override {} + + private: + // ComponentInstallerTraits methods: + bool SupportsGroupPolicyEnabledComponentUpdates() const override; + bool RequiresNetworkEncryption() const override; + update_client::CrxInstaller::Result OnCustomInstall( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) override; + bool VerifyInstallation(const base::DictionaryValue& manifest, + const base::FilePath& install_dir) const override; + void ComponentReady(const base::Version& version, + const base::FilePath& install_dir, + std::unique_ptr<base::DictionaryValue> manifest) override; + base::FilePath GetRelativeInstallDir() const override; + void GetHash(std::vector<uint8_t>* hash) const override; + std::string GetName() const override; + update_client::InstallerAttributes GetInstallerAttributes() const override; + std::vector<std::string> GetMimeTypes() const override; + + static base::FilePath GetInstalledPath(const base::FilePath& base); + + DISALLOW_COPY_AND_ASSIGN(SSLErrorAssistantComponentInstallerTraits); +}; + +void RegisterSSLErrorAssistantComponent(ComponentUpdateService* cus, + const base::FilePath& user_data_dir); + +} // namespace component_updater + +#endif // CHROME_BROWSER_COMPONENT_UPDATER_SSL_ERROR_ASSISTANT_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc index 2f082c3..f3307b4 100644 --- a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc +++ b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
@@ -259,7 +259,8 @@ EXPECT_TRUE(error().empty()); } -IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, WriteCancel) { +// TODO(crbug.com/690717): test is flaky. +IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, DISABLED_WriteCancel) { FillImageFileWithPattern('a'); FillDeviceFileWithPattern(0); @@ -305,7 +306,8 @@ EXPECT_TRUE(error().empty()); } -IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, VerifyCancel) { +// TODO(crbug.com/690717): test is flaky. +IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, DISABLED_VerifyCancel) { FillImageFileWithPattern('s'); FillDeviceFileWithPattern('s');
diff --git a/chrome/browser/manifest/OWNERS b/chrome/browser/manifest/OWNERS index da7cb5a..24b83f5d 100644 --- a/chrome/browser/manifest/OWNERS +++ b/chrome/browser/manifest/OWNERS
@@ -1,2 +1,4 @@ mlamouri@chromium.org dfalcantara@chromium.org + +# COMPONENT: Manifest
diff --git a/chrome/browser/media/android/router/OWNERS b/chrome/browser/media/android/router/OWNERS index 9dcb9a6..a1a8cd5 100644 --- a/chrome/browser/media/android/router/OWNERS +++ b/chrome/browser/media/android/router/OWNERS
@@ -1,3 +1,5 @@ avayvod@chromium.org mfoltz@chromium.org -mlamouri@chromium.org \ No newline at end of file +mlamouri@chromium.org + +# COMPONENT: Blink>PresentationAPI
diff --git a/chrome/browser/permissions/OWNERS b/chrome/browser/permissions/OWNERS index a1538844..0011758 100644 --- a/chrome/browser/permissions/OWNERS +++ b/chrome/browser/permissions/OWNERS
@@ -3,3 +3,5 @@ miguelg@chromium.org mlamouri@chromium.org raymes@chromium.org + +# COMPONENT: Internals>Permissions
diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc index dc71dce..e9aef46 100644 --- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc +++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
@@ -271,6 +271,33 @@ DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver); }; +// This class observes all the text selection updates within a WebContents. +class TextSelectionObserver : public TextInputManagerObserverBase { + public: + explicit TextSelectionObserver(content::WebContents* web_contents) + : TextInputManagerObserverBase(web_contents) { + tester()->SetOnTextSelectionChangedCallback(base::Bind( + &TextSelectionObserver::VerifyChange, base::Unretained(this))); + } + + void WaitForSelectedText(const std::string& text) { + selected_text_ = text; + Wait(); + } + + private: + void VerifyChange() { + if (base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText()) == + selected_text_) { + OnSuccess(); + } + } + + std::string selected_text_; + + DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver); +}; + // This class is used to verify the result of form field data requests. class FormFieldDataVerifier { public: @@ -792,6 +819,51 @@ } } +// This test verifies that committing text works as expected for all the frames +// on the page. Specifically, the test sends an IPC to the RenderWidget +// corresponding to a focused frame with a focused <input> to commit some text. +// Then, it verifies that the <input>'s value matches the committed text +// (https://crbug.com/688842). +IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest, + ImeCommitTextForAllFrames) { + CreateIframePage("a(b,c(a))"); + std::vector<content::RenderFrameHost*> frames{ + GetFrame(IndexVector{}), GetFrame(IndexVector{0}), + GetFrame(IndexVector{1}), GetFrame(IndexVector{1, 0})}; + for (size_t i = 0; i < frames.size(); ++i) + AddInputFieldToFrame(frames[i], "text", "", true); + + std::vector<std::string> sample_text{"main", "child_b", "child_c", "child_a"}; + ASSERT_EQ(frames.size(), sample_text.size()); + + // An observer of all text selection updates within a WebContents. + TextSelectionObserver observer(active_contents()); + for (size_t index = 0; index < frames.size(); ++index) { + // Focus the input and listen to 'input' event inside the frame. When the + // event fires, select all the text inside the input. This will trigger a + // selection update on the browser side. + ASSERT_TRUE(ExecuteScript(frames[index], + "window.focus();" + "var input = document.querySelector('input');" + "input.focus();" + "window.addEventListener('input', function(e) {" + " input.select();" + "});")) + << "Could not run script in frame with index:" << index; + + // Commit some text for this frame. + content::SendImeCommitTextToWidget( + frames[index]->GetView()->GetRenderWidgetHost(), + base::UTF8ToUTF16(sample_text[index]), + std::vector<ui::CompositionUnderline>(), gfx::Range(), 0); + + // Verify that the text we committed is now selected by listening to a + // selection update from a RenderWidgetHostView which has the expected + // selected text. + observer.WaitForSelectedText(sample_text[index]); + } +} + // TODO(ekaramad): Some of the following tests should be active on Android as // well. Enable them when the corresponding feature is implemented for Android // (https://crbug.com/602723).
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.html b/chrome/browser/resources/settings/date_time_page/date_time_page.html index a85f2b62..345c0ed9 100644 --- a/chrome/browser/resources/settings/date_time_page/date_time_page.html +++ b/chrome/browser/resources/settings/date_time_page/date_time_page.html
@@ -1,6 +1,7 @@ <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/web_ui_listener_behavior.html"> +<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="../controls/settings_dropdown_menu.html"> @@ -17,6 +18,7 @@ --md-select-width: 400px; } + paper-toggle-button, cr-policy-pref-indicator { -webkit-margin-start: var(--checkbox-spacing); } @@ -29,8 +31,8 @@ </div> <div class="settings-box continuation"> <div class="start">$i18n{timeZoneGeolocation}</div> - <template is="dom-if" if="[[hasTimeZoneAutoDetectPolicy_]]"> - <cr-policy-pref-indicator pref="[[timeZonePolicyPref_]]"> + <template is="dom-if" if="[[hasTimeZoneAutoDetectPolicy_]]" restamp> + <cr-policy-pref-indicator pref="[[fakeTimeZonePolicyPref_]]"> </cr-policy-pref-indicator> </template> <paper-toggle-button
diff --git a/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py b/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py index 0b546657..2c69d28 100755 --- a/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py +++ b/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py
@@ -7,6 +7,7 @@ Convert the ASCII ssl_error_assistant.asciipb proto into a binary resource. """ +import base64 import os import sys @@ -29,6 +30,10 @@ def ValidatePb(self, opts, pb): assert pb.version_id > 0 assert len(pb.captive_portal_cert) > 0 + for cert in pb.captive_portal_cert: + assert(cert.sha256_hash.startswith("sha256/")) + decoded_hash = base64.b64decode(cert.sha256_hash[len("sha256/"):]) + assert(len(decoded_hash) == 32) def ProcessPb(self, opts, pb): binary_pb_str = pb.SerializeToString()
diff --git a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc index 39f0dcd..5b30648 100644 --- a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc +++ b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
@@ -63,16 +63,20 @@ const base::FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data"); -// Inject a script into the page. Used by tests that check for visible -// password fields to wait for notifications about these -// fields. Notifications about visible password fields are queued at the -// end of the event loop, so waiting for a dummy script to run ensures -// that these notifcations have been sent. +// Inject a script into every frame in the page. Used by tests that check for +// visible password fields to wait for notifications about these +// fields. Notifications about visible password fields are queued at the end of +// the event loop, so waiting for a dummy script to run ensures that these +// notifications have been sent. void InjectScript(content::WebContents* contents) { - bool js_result = false; - EXPECT_TRUE(content::ExecuteScriptAndExtractBool( - contents, "window.domAutomationController.send(true);", &js_result)); - EXPECT_TRUE(js_result); + // Any frame in the page might have a password field, so inject scripts into + // all of them to ensure that notifications from all of them have been sent. + for (const auto& frame : contents->GetAllFrames()) { + bool js_result = false; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + frame, "window.domAutomationController.send(true);", &js_result)); + EXPECT_TRUE(js_result); + } } // A WebContentsObserver useful for testing the DidChangeVisibleSecurityState() @@ -1152,16 +1156,8 @@ // on an HTTP page load, and when the command-line flag is set, the // security level is downgraded to HTTP_SHOW_WARNING, even if the iframe // itself was loaded over HTTPS. -#if defined(OS_LINUX) -// Flaky on Linux. See https://crbug.com/662485. -#define MAYBE_PasswordSecurityLevelDowngradedFromHttpsIframe \ - DISABLED_PasswordSecurityLevelDowngradedFromHttpsIframe -#else -#define MAYBE_PasswordSecurityLevelDowngradedFromHttpsIframe \ - PasswordSecurityLevelDowngradedFromHttpsIframe -#endif IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch, - MAYBE_PasswordSecurityLevelDowngradedFromHttpsIframe) { + PasswordSecurityLevelDowngradedFromHttpsIframe) { content::WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); ASSERT_TRUE(contents);
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc index 20fc6186..47899dd 100644 --- a/chrome/browser/ssl/ssl_browser_tests.cc +++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -3937,8 +3937,7 @@ // Tests that the captive portal certificate list is not used when the feature // is disabled via Finch. The list is passed to SSLErrorHandler via a proto. -IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest, - CaptivePortalCertificateList_Disabled) { +IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest, Disabled) { base::test::ScopedFeatureList scoped_feature_list; // Use InitFromCommandLine instead of InitAndDisableFeature to avoid making // the feature public in SSLErrorHandler header. @@ -3952,10 +3951,11 @@ // Mark the server's cert as a captive portal cert. const net::HashValue server_spki_hash = GetSPKIHash(https_server_mismatched_.GetCertificate().get()); - chrome_browser_ssl::SSLErrorAssistantConfig config_proto; - config_proto.add_captive_portal_cert()->set_sha256_hash( + auto config_proto = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + config_proto->add_captive_portal_cert()->set_sha256_hash( server_spki_hash.ToString()); - SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto); + SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); // Navigate to an unsafe page on the server. A normal SSL interstitial should // be displayed since CaptivePortalCertificateList feature is disabled. @@ -3983,8 +3983,7 @@ // Tests that the captive portal certificate list is used when the feature // is enabled via Finch. The list is passed to SSLErrorHandler via a proto. -IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest, - CaptivePortalCertificateList_Enabled_FromProto) { +IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest, Enabled_FromProto) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine( "CaptivePortalCertificateList" /* enabled */, @@ -3996,10 +3995,11 @@ // Mark the server's cert as a captive portal cert. const net::HashValue server_spki_hash = GetSPKIHash(https_server_mismatched_.GetCertificate().get()); - chrome_browser_ssl::SSLErrorAssistantConfig config_proto; - config_proto.add_captive_portal_cert()->set_sha256_hash( + auto config_proto = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + config_proto->add_captive_portal_cert()->set_sha256_hash( server_spki_hash.ToString()); - SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto); + SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); // Navigate to an unsafe page on the server. The captive portal interstitial // should be displayed since CaptivePortalCertificateList feature is enabled. @@ -4027,6 +4027,11 @@ namespace { +// SPKI hash to captive-portal.badssl.com leaf certificate. This +// doesn't match the actual cert (ok_cert.pem) but is good enough for testing. +const char kCaptivePortalSPKI[] = + "sha256/fjZPHewEHTrMDX3I1ecEIeoy3WFxHyGplOLv28kIbtI="; + // Test class that mimics a URL request with a certificate whose SPKI hash is in // ssl_error_assistant.asciipb resource. A better way of testing the SPKI hashes // inside the resource bundle would be to serve the actual certificate from the @@ -4049,7 +4054,7 @@ void SetUp() override { CertVerifierBrowserTest::SetUp(); SSLErrorHandler::ResetConfigForTesting(); - SetUpCertVerifier(0, net::OK); + SetUpCertVerifier(0, net::OK, std::string()); } void TearDown() override { @@ -4058,7 +4063,9 @@ } protected: - void SetUpCertVerifier(net::CertStatus cert_status, int net_result) { + void SetUpCertVerifier(net::CertStatus cert_status, + int net_result, + const std::string& spki_hash) { scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate()); net::CertVerifyResult verify_result; verify_result.is_issued_by_known_root = @@ -4066,13 +4073,12 @@ verify_result.verified_cert = cert; verify_result.cert_status = cert_status; - // Set the SPKI hash to captive-portal.badssl.com leaf certificate. This - // doesn't match the actual cert (ok_cert.pem) but is good enough for - // testing. - net::HashValue hash; - ASSERT_TRUE( - hash.FromString("sha256/fjZPHewEHTrMDX3I1ecEIeoy3WFxHyGplOLv28kIbtI=")); - verify_result.public_key_hashes.push_back(hash); + // Set the SPKI hash to captive-portal.badssl.com leaf certificate. + if (!spki_hash.empty()) { + net::HashValue hash; + ASSERT_TRUE(hash.FromString(spki_hash)); + verify_result.public_key_hashes.push_back(hash); + } mock_cert_verifier()->AddResultForCert(cert, verify_result, net_result); } @@ -4090,8 +4096,7 @@ // Same as CaptivePortalCertificateList_Enabled_FromProto, but this time the // cert's SPKI hash is listed in ssl_error_assistant.asciipb. -IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest, - Enabled_FromResource) { +IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest, Enabled) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine( "CaptivePortalCertificateList" /* enabled */, @@ -4101,7 +4106,7 @@ // Mark the server's cert as a captive portal cert. SetUpCertVerifier(net::CERT_STATUS_COMMON_NAME_INVALID, - net::ERR_CERT_COMMON_NAME_INVALID); + net::ERR_CERT_COMMON_NAME_INVALID, kCaptivePortalSPKI); // Navigate to an unsafe page on the server. The captive portal interstitial // should be displayed since CaptivePortalCertificateList feature is enabled. @@ -4126,10 +4131,131 @@ SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1); } +// Same as SSLUICaptivePortalListResourceBundleTest.Enabled, but this time the +// proto is dynamically updated (e.g. by the component updater). The dynamic +// update should always override the proto loaded from the resource bundle. +IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest, + Enabled_DynamicUpdate) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitFromCommandLine( + "CaptivePortalCertificateList" /* enabled */, + std::string() /* disabled */); + ASSERT_TRUE(https_server()->Start()); + + // Mark the server's cert as a captive portal cert. + SetUpCertVerifier(net::CERT_STATUS_COMMON_NAME_INVALID, + net::ERR_CERT_COMMON_NAME_INVALID, kCaptivePortalSPKI); + + WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); + + { + // Dynamically update the SSL error assistant config, do not include the + // captive portal SPKI hash. + auto config_proto = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + config_proto->add_captive_portal_cert()->set_sha256_hash( + "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + config_proto->add_captive_portal_cert()->set_sha256_hash( + "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); + SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); + + // Navigate to an unsafe page on the server. A generic SSL interstitial + // should be displayed because the dynamic update doesn't contain the hash + // of the captive portal certificate. + base::HistogramTester histograms; + SSLInterstitialTimerObserver interstitial_timer_observer(tab); + ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/")); + content::WaitForInterstitialAttach(tab); + + InterstitialPage* interstitial_page = tab->GetInterstitialPage(); + ASSERT_EQ(SSLBlockingPage::kTypeForTesting, + interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); + EXPECT_TRUE(interstitial_timer_observer.timer_started()); + + // Check that the histogram was recorded for an SSL interstitial. + histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), + 2); + histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::HANDLE_ALL, 1); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1); + } + { + // Dynamically update the error assistant config and add the captive portal + // SPKI hash. + auto config_proto = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + config_proto->set_version_id(1); + config_proto->add_captive_portal_cert()->set_sha256_hash( + "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + config_proto->add_captive_portal_cert()->set_sha256_hash( + "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); + config_proto->add_captive_portal_cert()->set_sha256_hash( + kCaptivePortalSPKI); + SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); + + // Navigate to the unsafe page again. This time, a captive portal + // interstitial should be displayed. + base::HistogramTester histograms; + SSLInterstitialTimerObserver interstitial_timer_observer(tab); + ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/")); + content::WaitForInterstitialAttach(tab); + + InterstitialPage* interstitial_page = tab->GetInterstitialPage(); + ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting, + interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); + EXPECT_FALSE(interstitial_timer_observer.timer_started()); + + // Check that the histogram was recorded for a captive portal interstitial. + histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), + 3); + histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::HANDLE_ALL, 1); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1); + histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1); + } + { + // Try dynamically updating the error assistant config with an empty config + // with the same version number. The update should be ignored, and a captive + // portal interstitial should still be displayed. + auto empty_config = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + empty_config->set_version_id(1); + SSLErrorHandler::SetErrorAssistantProto(std::move(empty_config)); + + // Navigate to the unsafe page again. This time, a captive portal + // interstitial should be displayed. + base::HistogramTester histograms; + SSLInterstitialTimerObserver interstitial_timer_observer(tab); + ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/")); + content::WaitForInterstitialAttach(tab); + + InterstitialPage* interstitial_page = tab->GetInterstitialPage(); + ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting, + interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); + EXPECT_FALSE(interstitial_timer_observer.timer_started()); + + // Check that the histogram was recorded for a captive portal interstitial. + histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), + 3); + histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::HANDLE_ALL, 1); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1); + histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1); + } +} + // Same as SSLUICaptivePortalNameMismatchTest, but this time the error is // authority-invalid. Captive portal interstitial should not be shown. IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest, - Enabled_FromResource_AuthorityInvalid) { + Enabled_AuthorityInvalid) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine( "CaptivePortalCertificateList" /* enabled */, @@ -4137,12 +4263,10 @@ ASSERT_TRUE(https_server()->Start()); base::HistogramTester histograms; - // Set interstitial delay to zero. - SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta()); // Mark the server's cert as a captive portal cert, but with an // authority-invalid error. SetUpCertVerifier(net::CERT_STATUS_AUTHORITY_INVALID, - net::ERR_CERT_AUTHORITY_INVALID); + net::ERR_CERT_AUTHORITY_INVALID, kCaptivePortalSPKI); // Navigate to an unsafe page on the server. CaptivePortalCertificateList // feature is enabled but the error is not a name mismatch, so a generic SSL @@ -4184,10 +4308,11 @@ // Mark the server's cert as a captive portal cert. const net::HashValue server_spki_hash = GetSPKIHash(https_server_mismatched_.GetCertificate().get()); - chrome_browser_ssl::SSLErrorAssistantConfig config_proto; - config_proto.add_captive_portal_cert()->set_sha256_hash( + auto config_proto = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + config_proto->add_captive_portal_cert()->set_sha256_hash( server_spki_hash.ToString()); - SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto); + SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); // Navigate to an unsafe page on the server. The captive portal interstitial // should be displayed since CaptivePortalCertificateList feature is enabled.
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc index 5cbf4bec..0b852f40 100644 --- a/chrome/browser/ssl/ssl_error_handler.cc +++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -139,15 +139,16 @@ } // Reads the SSL error assistant configuration from the resource bundle. -bool ReadErrorAssistantProtoFromResourceBundle( - chrome_browser_ssl::SSLErrorAssistantConfig* proto) { +std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> +ReadErrorAssistantProtoFromResourceBundle() { + auto proto = base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(proto); ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); base::StringPiece data = bundle.GetRawDataResource(IDR_SSL_ERROR_ASSISTANT_PB); google::protobuf::io::ArrayInputStream stream(data.data(), data.size()); - return proto->ParseFromZeroCopyStream(&stream); + return proto->ParseFromZeroCopyStream(&stream) ? std::move(proto) : nullptr; } std::unique_ptr<std::unordered_set<std::string>> LoadCaptivePortalCertHashes( @@ -192,8 +193,9 @@ network_time::NetworkTimeTracker* tracker); #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) - void SetErrorAssistantProtoForTesting( - const chrome_browser_ssl::SSLErrorAssistantConfig& error_assistant_proto); + void SetErrorAssistantProto( + std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> + error_assistant_proto); #endif private: @@ -210,8 +212,12 @@ network_time::NetworkTimeTracker* network_time_tracker_ = nullptr; #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) + // Error assistant configuration. + std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> + error_assistant_proto_; + // SPKI hashes belonging to certs treated as captive portals. Null until the - // first time IsKnownCaptivePortalCert() or SetErrorAssistantProtoForTesting() + // first time IsKnownCaptivePortalCert() or SetErrorAssistantProto() // is called. std::unique_ptr<std::unordered_set<std::string>> captive_portal_spki_hashes_; #endif @@ -248,6 +254,7 @@ network_time_tracker_ = nullptr; testing_clock_ = nullptr; #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) + error_assistant_proto_.reset(); captive_portal_spki_hashes_.reset(); #endif } @@ -273,20 +280,27 @@ } #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) -void ConfigSingleton::SetErrorAssistantProtoForTesting( - const chrome_browser_ssl::SSLErrorAssistantConfig& error_assistant_proto) { +void ConfigSingleton::SetErrorAssistantProto( + std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> proto) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(!captive_portal_spki_hashes_); + CHECK(proto); + // Ignore versions that are not new. + if (error_assistant_proto_ && + proto->version_id() <= error_assistant_proto_->version_id()) { + return; + } + error_assistant_proto_ = std::move(proto); captive_portal_spki_hashes_ = - LoadCaptivePortalCertHashes(error_assistant_proto); + LoadCaptivePortalCertHashes(*error_assistant_proto_); } bool ConfigSingleton::IsKnownCaptivePortalCert(const net::SSLInfo& ssl_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!captive_portal_spki_hashes_) { - chrome_browser_ssl::SSLErrorAssistantConfig proto; - CHECK(ReadErrorAssistantProtoFromResourceBundle(&proto)); - captive_portal_spki_hashes_ = LoadCaptivePortalCertHashes(proto); + error_assistant_proto_ = ReadErrorAssistantProtoFromResourceBundle(); + CHECK(error_assistant_proto_); + captive_portal_spki_hashes_ = + LoadCaptivePortalCertHashes(*error_assistant_proto_); } for (const net::HashValue& hash_value : ssl_info.public_key_hashes) { @@ -496,10 +510,10 @@ return timer_.IsRunning(); } -void SSLErrorHandler::SetErrorAssistantProtoForTesting( - const chrome_browser_ssl::SSLErrorAssistantConfig& config_proto) { +void SSLErrorHandler::SetErrorAssistantProto( + std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> config_proto) { #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) - g_config.Pointer()->SetErrorAssistantProtoForTesting(config_proto); + g_config.Pointer()->SetErrorAssistantProto(std::move(config_proto)); #endif }
diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h index 80089d737..f0dc06b 100644 --- a/chrome/browser/ssl/ssl_error_handler.h +++ b/chrome/browser/ssl/ssl_error_handler.h
@@ -110,6 +110,12 @@ const base::Callback<void(content::CertificateRequestResultType)>& callback); + // Sets the binary proto for SSL error assistant. The binary proto + // can be downloaded by the component updater, or set by tests. + static void SetErrorAssistantProto( + std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> + config_proto); + // Testing methods. static void ResetConfigForTesting(); static void SetInterstitialDelayForTesting(const base::TimeDelta& delay); @@ -119,8 +125,6 @@ static void SetClockForTesting(base::Clock* testing_clock); static void SetNetworkTimeTrackerForTesting( network_time::NetworkTimeTracker* tracker); - static void SetErrorAssistantProtoForTesting( - const chrome_browser_ssl::SSLErrorAssistantConfig& config_proto); static std::string GetHistogramNameForTesting(); static void SetErrorAssistantConfig( std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
diff --git a/chrome/browser/ssl/ssl_error_handler_unittest.cc b/chrome/browser/ssl/ssl_error_handler_unittest.cc index 97e3793b..0beff0a 100644 --- a/chrome/browser/ssl/ssl_error_handler_unittest.cc +++ b/chrome/browser/ssl/ssl_error_handler_unittest.cc
@@ -706,22 +706,23 @@ TEST_F(SSLErrorHandlerNameMismatchTest, CaptivePortalCertificateList_Enabled) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine( - "CaptivePortalCertificateList" /* enabled */, "" /* disabled */); - - base::HistogramTester histograms; + "CaptivePortalCertificateList" /* enabled */, + std::string() /* disabled */); EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); - chrome_browser_ssl::SSLErrorAssistantConfig config_proto; - config_proto.add_captive_portal_cert()->set_sha256_hash( + auto config_proto = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + config_proto->add_captive_portal_cert()->set_sha256_hash( "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - config_proto.add_captive_portal_cert()->set_sha256_hash( + config_proto->add_captive_portal_cert()->set_sha256_hash( ssl_info().public_key_hashes[0].ToString()); - config_proto.add_captive_portal_cert()->set_sha256_hash( + config_proto->add_captive_portal_cert()->set_sha256_hash( "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); - SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto); + SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); + base::HistogramTester histograms; error_handler()->StartHandlingError(); // Timer shouldn't start for a known captive portal certificate. @@ -731,8 +732,8 @@ EXPECT_TRUE(delegate()->captive_portal_interstitial_shown()); EXPECT_FALSE(delegate()->suggested_url_checked()); - // A buggy SSL error handler might have incorrectly started the timer. Run to - // completion to ensure the timer is expired. + // A buggy SSL error handler might have incorrectly started the timer. Run + // to completion to ensure the timer is expired. base::RunLoop().RunUntilIdle(); EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); @@ -758,25 +759,28 @@ TEST_F(SSLErrorHandlerNameMismatchTest, CaptivePortalCertificateList_Disabled) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine( - "" /* enabled */, "CaptivePortalCertificateList" /* disabled */); + std::string() /* enabled */, + "CaptivePortalCertificateList" /* disabled */); base::HistogramTester histograms; EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); - chrome_browser_ssl::SSLErrorAssistantConfig config_proto; - config_proto.add_captive_portal_cert()->set_sha256_hash( + auto config_proto = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + config_proto->add_captive_portal_cert()->set_sha256_hash( "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - config_proto.add_captive_portal_cert()->set_sha256_hash( + config_proto->add_captive_portal_cert()->set_sha256_hash( ssl_info().public_key_hashes[0].ToString()); - config_proto.add_captive_portal_cert()->set_sha256_hash( + config_proto->add_captive_portal_cert()->set_sha256_hash( "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); - SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto); + SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); error_handler()->StartHandlingError(); - // Timer shouldn't start for a known captive portal certificate. + // Timer should start since captive portal certificate list feature is + // disabled. EXPECT_TRUE(error_handler()->IsTimerRunningForTesting()); EXPECT_TRUE(delegate()->captive_portal_checked()); EXPECT_FALSE(delegate()->ssl_interstitial_shown()); @@ -809,21 +813,23 @@ CaptivePortalCertificateList_ShouldShowGenericInterstitial) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine( - "CaptivePortalCertificateList" /* enabled */, "" /* disabled */); + "CaptivePortalCertificateList" /* enabled */, + std::string() /* disabled */); base::HistogramTester histograms; EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); - chrome_browser_ssl::SSLErrorAssistantConfig config_proto; - config_proto.add_captive_portal_cert()->set_sha256_hash( + auto config_proto = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + config_proto->add_captive_portal_cert()->set_sha256_hash( "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - config_proto.add_captive_portal_cert()->set_sha256_hash( + config_proto->add_captive_portal_cert()->set_sha256_hash( ssl_info().public_key_hashes[0].ToString()); - config_proto.add_captive_portal_cert()->set_sha256_hash( + config_proto->add_captive_portal_cert()->set_sha256_hash( "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); - SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto); + SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); error_handler()->StartHandlingError();
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos_browsertest_chromeos.cc b/chrome/browser/ui/ash/system_tray_delegate_chromeos_browsertest_chromeos.cc index b061e67..a64eb66 100644 --- a/chrome/browser/ui/ash/system_tray_delegate_chromeos_browsertest_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos_browsertest_chromeos.cc
@@ -6,7 +6,6 @@ #include <string> -#include "ash/common/material_design/material_design_controller.h" #include "ash/common/system/date/date_default_view.h" #include "ash/common/system/date/date_view.h" #include "ash/common/system/date/system_info_default_view.h" @@ -38,39 +37,22 @@ const char kUser2[] = "user2@gmail.com"; base::HourClockType GetHourType() { - if (ash::MaterialDesignController::IsSystemTrayMenuMaterial()) { - const ash::TraySystemInfo* tray_system_info = - ash::Shell::GetInstance() - ->GetPrimarySystemTray() - ->GetTraySystemInfoForTesting(); - const ash::SystemInfoDefaultView* system_info_default_view = - tray_system_info->GetDefaultViewForTesting(); + const ash::TraySystemInfo* tray_system_info = + ash::Shell::GetInstance() + ->GetPrimarySystemTray() + ->GetTraySystemInfoForTesting(); + const ash::SystemInfoDefaultView* system_info_default_view = + tray_system_info->GetDefaultViewForTesting(); - return system_info_default_view->GetDateView()->GetHourTypeForTesting(); - } - - const ash::TrayDate* tray_date = ash::Shell::GetInstance() - ->GetPrimarySystemTray() - ->GetTrayDateForTesting(); - const ash::DateDefaultView* date_default_view = - tray_date->GetDefaultViewForTesting(); - - return date_default_view->GetDateView()->GetHourTypeForTesting(); + return system_info_default_view->GetDateView()->GetHourTypeForTesting(); } void CreateDefaultView() { - if (ash::MaterialDesignController::IsSystemTrayMenuMaterial()) { - ash::TraySystemInfo* tray_system_info = ash::Shell::GetInstance() - ->GetPrimarySystemTray() - ->GetTraySystemInfoForTesting(); - tray_system_info->CreateDefaultViewForTesting( - ash::LoginStatus::NOT_LOGGED_IN); - } else { - ash::TrayDate* tray_date = ash::Shell::GetInstance() - ->GetPrimarySystemTray() - ->GetTrayDateForTesting(); - tray_date->CreateDefaultViewForTesting(ash::LoginStatus::NOT_LOGGED_IN); - } + ash::TraySystemInfo* tray_system_info = ash::Shell::GetInstance() + ->GetPrimarySystemTray() + ->GetTraySystemInfoForTesting(); + tray_system_info->CreateDefaultViewForTesting( + ash::LoginStatus::NOT_LOGGED_IN); } } // namespace
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index 0eb187b7..9af374e 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -319,8 +319,8 @@ toolbarController_.reset([[ToolbarController alloc] initWithCommands:browser->command_controller()->command_updater() profile:browser->profile() - browser:browser - resizeDelegate:self]); + browser:browser]); + [[toolbarController_ toolbarView] setResizeDelegate:self]; [toolbarController_ setHasToolbar:[self hasToolbar] hasLocationBar:[self hasLocationBar]];
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h index 62b049a..0cfae25 100644 --- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h +++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
@@ -28,6 +28,7 @@ class Profile; @class ReloadButton; @class ToolbarButton; +@class ToolbarView; @class AppMenuController; namespace content { @@ -99,12 +100,13 @@ // Initialize the toolbar and register for command updates. The profile is // needed for initializing the location bar. The browser is needed for -// the toolbar model and back/forward menus. The resizeDelegate is used -// to smoothly animate height changes for the toolbar. +// the toolbar model and back/forward menus. - (id)initWithCommands:(CommandUpdater*)commands profile:(Profile*)profile - browser:(Browser*)browser - resizeDelegate:(id<ViewResizer>)resizeDelegate; + browser:(Browser*)browser; + +// Strongly typed controlled view. +- (ToolbarView*)toolbarView; // Get the C++ bridge object representing the location bar for this tab. - (LocationBarViewMac*)locationBarBridge;
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm index 4b3458fa..2ab43137 100644 --- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm +++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
@@ -117,7 +117,6 @@ - (void)addAccessibilityDescriptions; - (void)initCommandStatus:(CommandUpdater*)commands; - (void)prefChanged:(const std::string&)prefName; -- (ToolbarView*)toolbarView; // Height of the toolbar in pixels when the bookmark bar is closed. - (CGFloat)baseToolbarHeight; - (void)toolbarFrameChanged; @@ -212,8 +211,7 @@ - (id)initWithCommands:(CommandUpdater*)commands profile:(Profile*)profile - browser:(Browser*)browser - resizeDelegate:(id<ViewResizer>)resizeDelegate { + browser:(Browser*)browser { DCHECK(commands && profile); if ((self = [super initWithNibName:@"Toolbar" bundle:base::mac::FrameworkBundle()])) { @@ -236,8 +234,6 @@ // autoreleased at about the same time as the CommandUpdater (owned by the // Browser), so |commands_| may not be valid any more. - [[self toolbarView] setResizeDelegate:resizeDelegate]; - // Start global error services now so we badge the menu correctly. SyncGlobalErrorFactory::GetForProfile(profile); RecoveryInstallGlobalErrorFactory::GetForProfile(profile); @@ -566,6 +562,10 @@ [self mouseMoved:event]; } +- (ToolbarView*)toolbarView { + return base::mac::ObjCCastStrict<ToolbarView>([self view]); +} + - (LocationBarViewMac*)locationBarBridge { return locationBarView_.get(); } @@ -665,11 +665,6 @@ [self showLocationBarOnly]; } -// (Private) Returns the backdrop to the toolbar as a ToolbarView. -- (ToolbarView*)toolbarView{ - return base::mac::ObjCCastStrict<ToolbarView>([self view]); -} - - (id)customFieldEditorForObject:(id)obj { if (obj == locationBar_) { // Lazily construct Field editor, Cocoa UI code always runs on the
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm index 01b22da..ffa76aa 100644 --- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
@@ -25,6 +25,7 @@ #include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h" #include "chrome/browser/ui/cocoa/test/scoped_force_rtl_mac.h" #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" +#import "chrome/browser/ui/cocoa/toolbar/toolbar_view_cocoa.h" #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" #import "chrome/browser/ui/cocoa/view_resizer_pong.h" @@ -125,8 +126,8 @@ bar_.reset([[TestToolbarController alloc] initWithCommands:browser()->command_controller()->command_updater() profile:profile() - browser:browser() - resizeDelegate:resizeDelegate_.get()]); + browser:browser()]); + [[bar_ toolbarView] setResizeDelegate:resizeDelegate_.get()]; EXPECT_TRUE([bar_ view]); NSView* parent = [test_window() contentView]; [parent addSubview:[bar_ view]];
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index 351229a..778e5e8 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -7,7 +7,6 @@ #include "ash/common/ash_constants.h" #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/common/frame/header_painter.h" -#include "ash/common/material_design/material_design_controller.h" #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm_shell.h" #include "ash/shell.h" @@ -196,21 +195,12 @@ EXPECT_LT(Tab::GetImmersiveHeight(), frame_view->header_painter_->GetHeaderHeightForPainting()); - // Ending the reveal. In MD, immersive browser should have the same behavior - // as full screen, i.e., no light bar and having an origin of (0,0). In - // non-MD, immersive browser will show a 3 dp light bar on the top. + // Ending the reveal. Immersive browser should have the same behavior as full + // screen, i.e., no light bar and having an origin of (0,0). revealed_lock.reset(); - if (ash::MaterialDesignController::IsImmersiveModeMaterial()) { - EXPECT_FALSE(frame_view->ShouldPaint()); - EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle()); - EXPECT_EQ(0, frame_view->header_painter_->GetHeaderHeightForPainting()); - } else { - EXPECT_TRUE(frame_view->ShouldPaint()); - EXPECT_FALSE(frame_view->caption_button_container_->visible()); - EXPECT_TRUE(frame_view->UseImmersiveLightbarHeaderStyle()); - EXPECT_EQ(Tab::GetImmersiveHeight(), - frame_view->header_painter_->GetHeaderHeightForPainting()); - } + EXPECT_FALSE(frame_view->ShouldPaint()); + EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle()); + EXPECT_EQ(0, frame_view->header_painter_->GetHeaderHeightForPainting()); // Exiting immersive fullscreen should make the caption buttons and the frame // visible again.
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc index 9fb9c7a..bbd3db8 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h" -#include "ash/common/material_design/material_design_controller.h" #include "ash/common/shelf/shelf_layout_manager.h" #include "ash/public/cpp/shelf_types.h" #include "ash/root_window_controller.h" @@ -131,26 +130,15 @@ EXPECT_TRUE(controller()->IsEnabled()); EXPECT_FALSE(controller()->IsRevealed()); EXPECT_FALSE(toolbar->visible()); - // For MD, the browser's top chrome is completely offscreen with tapstrip - // visible. + // The browser's top chrome is completely offscreen with tapstrip visible. EXPECT_TRUE(tabstrip->visible()); - bool is_using_material_design = - ash::MaterialDesignController::IsImmersiveModeMaterial(); - if (!is_using_material_design) - EXPECT_TRUE(tabstrip->IsImmersiveStyle()); // The tab indicators should be flush with the top of the widget. EXPECT_EQ(0, GetBoundsInWidget(tabstrip).y()); - // In MD, since the tab strip and tool bar are both hidden in immersive - // fullscreen mode, the web contents should extend to the edge of screen. In - // non-MD, the web contents should be immediately below the tab indicators. - if (is_using_material_design) { - EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y()); - } else { - EXPECT_EQ(Tab::GetImmersiveHeight(), - GetBoundsInWidget(contents_web_view).y()); - } + // Since the tab strip and tool bar are both hidden in immersive fullscreen + // mode, the web contents should extend to the edge of screen. + EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y()); // Revealing the top-of-window views should set the tab strip back to the // normal style and show the toolbar. @@ -167,12 +155,7 @@ // The web contents should be at the same y position as they were when the // top-of-window views were hidden. - if (is_using_material_design) { - EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y()); - } else { - EXPECT_EQ(Tab::GetImmersiveHeight(), - GetBoundsInWidget(contents_web_view).y()); - } + EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y()); // Repeat the test for when in both immersive fullscreen and tab fullscreen. SetTabFullscreen(true); @@ -257,32 +240,24 @@ ToggleFullscreen(); ASSERT_TRUE(controller()->IsEnabled()); EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state()); - if (!ash::MaterialDesignController::IsImmersiveModeMaterial()) - EXPECT_FALSE(controller()->ShouldHideTabIndicators()); SetTabFullscreen(true); ASSERT_TRUE(controller()->IsEnabled()); EXPECT_EQ(ash::SHELF_HIDDEN, shelf->visibility_state()); - if (!ash::MaterialDesignController::IsImmersiveModeMaterial()) - EXPECT_TRUE(controller()->ShouldHideTabIndicators()); // 2) Test that exiting tab fullscreen shows the tab indicators and autohides // the shelf. SetTabFullscreen(false); ASSERT_TRUE(controller()->IsEnabled()); EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state()); - if (!ash::MaterialDesignController::IsImmersiveModeMaterial()) - EXPECT_FALSE(controller()->ShouldHideTabIndicators()); - // 3) Test that exiting tab fullscreen and immersive fullscreen - // simultaneously correctly updates the shelf visibility and whether the tab - // indicators should be hidden. + // 3) Test that exiting tab fullscreen and immersive fullscreen simultaneously + // correctly updates the shelf visibility and whether the tab indicators + // should be hidden. SetTabFullscreen(true); ToggleFullscreen(); ASSERT_FALSE(controller()->IsEnabled()); EXPECT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state()); - if (!ash::MaterialDesignController::IsImmersiveModeMaterial()) - EXPECT_TRUE(controller()->ShouldHideTabIndicators()); } // Ensure the circular tab-loading throbbers are not painted as layers in
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui_browsertest.cc b/chrome/browser/ui/webui/settings/md_settings_ui_browsertest.cc index 9a19676..a6da5edc 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui_browsertest.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui_browsertest.cc
@@ -24,9 +24,9 @@ using content::WaitForLoadStop; IN_PROC_BROWSER_TEST_F(MdSettingsUITest, ViewSourceDoesntCrash) { - NavigateToURL(browser(), - GURL(content::kViewSourceScheme + std::string(":") + - chrome::kChromeUIMdSettingsURL)); + NavigateToURL(browser(), GURL(content::kViewSourceScheme + std::string(":") + + chrome::kChromeUIMdSettingsURL + + std::string("strings.js"))); } // May not complete on memory and Windows debug bots. TODO(dbeam): investigate
diff --git a/chrome/test/data/webui/settings/date_time_page_tests.js b/chrome/test/data/webui/settings/date_time_page_tests.js index 7cf96a7..b5889bf5 100644 --- a/chrome/test/data/webui/settings/date_time_page_tests.js +++ b/chrome/test/data/webui/settings/date_time_page_tests.js
@@ -121,11 +121,10 @@ if (policy) { assertTrue(!!indicator); - assertGT(indicator.clientHeight, 0); + assertTrue(indicator.isActive()); } else { - // Indicator should be missing or hidden. - if (indicator) - assertEquals(0, indicator.clientHeight); + // Indicator should be missing dom-ifed out. + assertFalse(!!indicator); } assertEquals(policy, dateTime.$.timeZoneAutoDetect.disabled); @@ -165,6 +164,7 @@ var prefs = getFakePrefs(); prefs.settings.resolve_timezone_by_geolocation.value = false; dateTime = initializeDateTime(prefs, false); + cr.webUIListenerCallback('time-zone-auto-detect-policy', false); assertTrue(dateTimePageReadyCalled); assertTrue(getTimeZonesCalled); @@ -186,6 +186,7 @@ var prefs = getFakePrefs(); prefs.settings.resolve_timezone_by_geolocation.value = false; dateTime = initializeDateTime(prefs, true, true); + cr.webUIListenerCallback('time-zone-auto-detect-policy', true, true); assertTrue(dateTimePageReadyCalled); assertFalse(getTimeZonesCalled); @@ -214,6 +215,7 @@ test('auto-detect forced off', function(done) { var prefs = getFakePrefs(); dateTime = initializeDateTime(prefs, true, false); + cr.webUIListenerCallback('time-zone-auto-detect-policy', true, false); assertTrue(dateTimePageReadyCalled); assertTrue(getTimeZonesCalled); @@ -238,6 +240,7 @@ test('set date and time button', function() { dateTime = initializeDateTime(getFakePrefs(), false); + cr.webUIListenerCallback('time-zone-auto-detect-policy', false); var showSetDateTimeUICalled = false; registerMessageCallback('showSetDateTimeUI', null, function() {
diff --git a/chromecast/media/base/supported_codec_profile_levels_memo.cc b/chromecast/media/base/supported_codec_profile_levels_memo.cc index 8af25951..be1e9a7 100644 --- a/chromecast/media/base/supported_codec_profile_levels_memo.cc +++ b/chromecast/media/base/supported_codec_profile_levels_memo.cc
@@ -10,7 +10,8 @@ namespace chromecast { namespace media { -SupportedCodecProfileLevelsMemo::SupportedCodecProfileLevelsMemo() {} +SupportedCodecProfileLevelsMemo::SupportedCodecProfileLevelsMemo() + : codec_profile_levels_(), thread_checker_() {} SupportedCodecProfileLevelsMemo::~SupportedCodecProfileLevelsMemo() {}
diff --git a/chromecast/media/cdm/BUILD.gn b/chromecast/media/cdm/BUILD.gn index b2dd9da..2cf3f96f 100644 --- a/chromecast/media/cdm/BUILD.gn +++ b/chromecast/media/cdm/BUILD.gn
@@ -6,29 +6,37 @@ source_set("cdm") { sources = [ - "cast_cdm.cc", - "cast_cdm.h", - "cast_cdm_context.cc", - "cast_cdm_context.h", - "cast_cdm_factory.cc", - "cast_cdm_factory.h", "chromecast_init_data.cc", "chromecast_init_data.h", ] deps = [ "//base", - "//chromecast/media/base", "//media", - "//url:url", ] - if (is_android && use_playready) { + if (!is_android) { sources += [ - "playready_drm_delegate_android.cc", - "playready_drm_delegate_android.h", + "cast_cdm.cc", + "cast_cdm.h", + "cast_cdm_context.cc", + "cast_cdm_context.h", + "cast_cdm_factory.cc", + "cast_cdm_factory.h", ] - deps += [ "//media/base/android" ] + deps += [ + "//chromecast/media/base", + "//url:url", + ] + } else { + if (use_playready) { + sources += [ + "playready_drm_delegate_android.cc", + "playready_drm_delegate_android.h", + ] + + deps += [ "//media/base/android" ] + } } }
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc index 0cedd5ff..c3d11d5 100644 --- a/content/app/content_main_runner.cc +++ b/content/app/content_main_runner.cc
@@ -15,6 +15,7 @@ #include "base/allocator/allocator_check.h" #include "base/allocator/allocator_extension.h" +#include "base/allocator/features.h" #include "base/at_exit.h" #include "base/base_switches.h" #include "base/command_line.h" @@ -86,6 +87,7 @@ #include "ui/base/win/atl_module.h" #include "ui/display/win/dpi.h" #elif defined(OS_MACOSX) +#include "base/allocator/allocator_shim.h" #include "base/mac/scoped_nsautorelease_pool.h" #include "base/power_monitor/power_monitor_device_source.h" #include "content/app/mac/mac_init.h" @@ -515,6 +517,9 @@ env_mode_ = params.env_mode; #endif +#if defined(OS_MACOSX) && BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) + base::allocator::InitializeAllocatorShim(); +#endif base::EnableTerminationOnOutOfMemory(); #if defined(OS_WIN) base::win::RegisterInvalidParamHandler();
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index c4efd39..ca778a4 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -13,6 +13,7 @@ #include "base/strings/string_util.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/common/accessibility_messages.h" +#include "ui/accessibility/ax_role_properties.h" #include "ui/accessibility/ax_text_utils.h" #include "ui/accessibility/platform/ax_platform_node.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -348,7 +349,7 @@ return GetData().location; } -int32_t BrowserAccessibility::GetRole() const { +ui::AXRole BrowserAccessibility::GetRole() const { return GetData().role; } @@ -1026,29 +1027,7 @@ } bool BrowserAccessibility::IsClickable() const { - switch (GetRole()) { - case ui::AX_ROLE_BUTTON: - case ui::AX_ROLE_CHECK_BOX: - case ui::AX_ROLE_COLOR_WELL: - case ui::AX_ROLE_DISCLOSURE_TRIANGLE: - case ui::AX_ROLE_IMAGE_MAP_LINK: - case ui::AX_ROLE_LINK: - case ui::AX_ROLE_LIST_BOX_OPTION: - case ui::AX_ROLE_MENU_BUTTON: - case ui::AX_ROLE_MENU_ITEM: - case ui::AX_ROLE_MENU_ITEM_CHECK_BOX: - case ui::AX_ROLE_MENU_ITEM_RADIO: - case ui::AX_ROLE_MENU_LIST_OPTION: - case ui::AX_ROLE_MENU_LIST_POPUP: - case ui::AX_ROLE_POP_UP_BUTTON: - case ui::AX_ROLE_RADIO_BUTTON: - case ui::AX_ROLE_SWITCH: - case ui::AX_ROLE_TAB: - case ui::AX_ROLE_TOGGLE_BUTTON: - return true; - default: - return false; - } + return ui::IsRoleClickable(GetRole()); } bool BrowserAccessibility::IsControl() const {
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h index 78047df..4a785e5 100644 --- a/content/browser/accessibility/browser_accessibility.h +++ b/content/browser/accessibility/browser_accessibility.h
@@ -235,7 +235,7 @@ int32_t GetId() const; const ui::AXNodeData& GetData() const; gfx::RectF GetLocation() const; - int32_t GetRole() const; + ui::AXRole GetRole() const; int32_t GetState() const; typedef base::StringPairs HtmlAttributes;
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 934cdc6..78fc0709 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -432,6 +432,8 @@ case ui::AX_ROLE_POP_UP_BUTTON: case ui::AX_ROLE_TEXT_FIELD: return value; + default: + break; } } @@ -534,6 +536,9 @@ case ui::AX_ROLE_ARTICLE: message_id = IDS_AX_ROLE_ARTICLE; break; + case ui::AX_ROLE_AUDIO: + message_id = IDS_AX_MEDIA_AUDIO_ELEMENT; + break; case ui::AX_ROLE_BANNER: message_id = IDS_AX_ROLE_BANNER; break; @@ -624,6 +629,9 @@ case ui::AX_ROLE_EMBEDDED_OBJECT: message_id = IDS_AX_ROLE_EMBEDDED_OBJECT; break; + case ui::AX_ROLE_FEED: + // TODO(patricialor): Add a string for this role. + break; case ui::AX_ROLE_FIGCAPTION: // No role description. break; @@ -716,6 +724,9 @@ case ui::AX_ROLE_MATH: message_id = IDS_AX_ROLE_MATH; break; + case ui::AX_ROLE_MENU: + message_id = IDS_AX_ROLE_MENU; + break; case ui::AX_ROLE_MENU_BAR: message_id = IDS_AX_ROLE_MENU_BAR; break; @@ -737,9 +748,6 @@ case ui::AX_ROLE_MENU_LIST_POPUP: // No role description. break; - case ui::AX_ROLE_MENU: - message_id = IDS_AX_ROLE_MENU; - break; case ui::AX_ROLE_METER: message_id = IDS_AX_ROLE_METER; break; @@ -854,6 +862,9 @@ case ui::AX_ROLE_TABLE: message_id = IDS_AX_ROLE_TABLE; break; + case ui::AX_ROLE_TERM: + message_id = IDS_AX_ROLE_DESCRIPTION_TERM; + break; case ui::AX_ROLE_TEXT_FIELD: // No role description. break; @@ -887,6 +898,9 @@ case ui::AX_ROLE_TOOLTIP: message_id = IDS_AX_ROLE_TOOLTIP; break; + case ui::AX_ROLE_VIDEO: + message_id = IDS_AX_MEDIA_VIDEO_ELEMENT; + break; case ui::AX_ROLE_WEB_AREA: // No role description. break; @@ -896,6 +910,9 @@ case ui::AX_ROLE_WINDOW: // No role description. break; + case ui::AX_ROLE_NONE: + // No role description. + break; } if (message_id != -1) @@ -923,6 +940,8 @@ index = static_cast<int>(((value - min)) * 100 / (max - min)); break; } + default: + break; } return index; } @@ -942,6 +961,8 @@ // in RangeMin and RangeMax. count = 100; break; + default: + break; } return count; }
diff --git a/content/browser/manifest/OWNERS b/content/browser/manifest/OWNERS index 2d28246..edb36297 100644 --- a/content/browser/manifest/OWNERS +++ b/content/browser/manifest/OWNERS
@@ -1 +1,3 @@ mlamouri@chromium.org + +# COMPONENT: Manifest
diff --git a/content/browser/media/session/OWNERS b/content/browser/media/session/OWNERS index dc2593f..3fdb002 100644 --- a/content/browser/media/session/OWNERS +++ b/content/browser/media/session/OWNERS
@@ -1,2 +1,4 @@ avayvod@chromium.org mlamouri@chromium.org + +# COMPONENT: Internals>Media>Session
diff --git a/content/browser/media/session/media_session_impl_visibility_browsertest.cc b/content/browser/media/session/media_session_impl_visibility_browsertest.cc index a6840e57..77032875 100644 --- a/content/browser/media/session/media_session_impl_visibility_browsertest.cc +++ b/content/browser/media/session/media_session_impl_visibility_browsertest.cc
@@ -33,11 +33,6 @@ DISABLED, }; -enum class Pipeline { - WMPI, - WMPA, -}; - enum class BackgroundResuming { ENABLED, DISABLED, @@ -65,8 +60,7 @@ // media_session_visibility_browsertest_instances.cc for examples. class MediaSessionImplVisibilityBrowserTest : public ContentBrowserTest, - public ::testing::WithParamInterface< - std::tr1::tuple<VisibilityTestData, Pipeline>> { + public ::testing::WithParamInterface<VisibilityTestData> { public: MediaSessionImplVisibilityBrowserTest() = default; ~MediaSessionImplVisibilityBrowserTest() override = default; @@ -116,12 +110,6 @@ else command_line->AppendSwitch(switches::kDisableMediaSuspend); -#if defined(OS_ANDROID) - Pipeline pipeline = std::tr1::get<1>(GetParam()); - if (pipeline == Pipeline::WMPA) - command_line->AppendSwitch(switches::kDisableUnifiedMediaPipeline); -#endif // defined(OS_ANDROID) - if (params.background_resuming == BackgroundResuming::ENABLED) { command_line->AppendSwitchASCII(switches::kEnableFeatures, media::kResumeBackgroundVideo.name); @@ -132,7 +120,7 @@ } const VisibilityTestData& GetVisibilityTestData() { - return std::tr1::get<0>(GetParam()); + return GetParam(); } void StartPlayer() { @@ -276,14 +264,6 @@ SessionState::SUSPENDED, SessionState::SUSPENDED}, }; -Pipeline kPipelines[] = { - Pipeline::WMPI, -#if defined(OS_ANDROID) -// Disabling WMPA tests because of https://crbug.com/646312 -// Pipeline::WMPA, -#endif // defined(OS_ANDROID) -}; - } // anonymous namespace IN_PROC_BROWSER_TEST_P(MediaSessionImplVisibilityBrowserTest, TestEntryPoint) { @@ -295,7 +275,6 @@ INSTANTIATE_TEST_CASE_P(MediaSessionImplVisibilityBrowserTestInstances, MediaSessionImplVisibilityBrowserTest, - ::testing::Combine(::testing::ValuesIn(kTestParams), - ::testing::ValuesIn(kPipelines))); + ::testing::ValuesIn(kTestParams)); } // namespace content
diff --git a/content/browser/permissions/OWNERS b/content/browser/permissions/OWNERS index fee7a6d..8338bc51 100644 --- a/content/browser/permissions/OWNERS +++ b/content/browser/permissions/OWNERS
@@ -1,2 +1,4 @@ mlamouri@chromium.org -timvolodine@chromium.org \ No newline at end of file +timvolodine@chromium.org + +# COMPONENT: Internals>Permissions
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 8e4112c0..17896da 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1872,7 +1872,6 @@ switches::kDisableLowEndDeviceMode, #if defined(OS_ANDROID) switches::kDisableMediaSessionAPI, - switches::kDisableUnifiedMediaPipeline, switches::kEnableContentIntentDetection, switches::kRendererWaitForJavaDebugger, #endif
diff --git a/content/common/feature_policy/OWNERS b/content/common/feature_policy/OWNERS index ffdb022..ab9c820 100644 --- a/content/common/feature_policy/OWNERS +++ b/content/common/feature_policy/OWNERS
@@ -3,3 +3,5 @@ iclelland@chromium.org raymes@chromium.org + +# COMPONENT: Blink>FeaturePolicy
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index bdf2af3..648b0c86 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -1171,9 +1171,9 @@ RenderWidgetHostViewChildFrame* target_view) { if (!container_surface_id.is_valid()) return false; - for (cc::SurfaceId id : - GetSurfaceManager()->GetSurfaceForId(container_surface_id) - ->referenced_surfaces()) { + for (cc::SurfaceId id : GetSurfaceManager() + ->GetSurfaceForId(container_surface_id) + ->active_referenced_surfaces()) { if (id == target_view->SurfaceIdForTesting() || ContainsSurfaceId(id, target_view)) return true;
diff --git a/content/public/test/text_input_test_utils.cc b/content/public/test/text_input_test_utils.cc index e37b5dc..5405d908 100644 --- a/content/public/test/text_input_test_utils.cc +++ b/content/public/test/text_input_test_utils.cc
@@ -71,7 +71,7 @@ on_text_selection_changed_callback_ = callback; } - const RenderWidgetHostView* GetUpdatedView() const { return updated_view_; } + RenderWidgetHostView* GetUpdatedView() const { return updated_view_; } bool text_input_state_changed() const { return text_input_state_changed_; } @@ -262,6 +262,23 @@ ->has_focused_editable_element(); } +void SendImeCommitTextToWidget( + RenderWidgetHost* rwh, + const base::string16& text, + const std::vector<ui::CompositionUnderline>& underlines, + const gfx::Range& replacement_range, + int relative_cursor_pos) { + std::vector<blink::WebCompositionUnderline> web_composition_underlines; + for (auto underline : underlines) { + web_composition_underlines.emplace_back( + static_cast<int>(underline.start_offset), + static_cast<int>(underline.end_offset), underline.color, + underline.thick, underline.background_color); + } + RenderWidgetHostImpl::From(rwh)->ImeCommitText( + text, web_composition_underlines, replacement_range, relative_cursor_pos); +} + size_t GetRegisteredViewsCountFromTextInputManager(WebContents* web_contents) { std::unordered_set<RenderWidgetHostView*> views; TextInputManager* manager = @@ -325,7 +342,7 @@ return observer_->text_input_manager()->active_view_for_testing(); } -const RenderWidgetHostView* TextInputManagerTester::GetUpdatedView() { +RenderWidgetHostView* TextInputManagerTester::GetUpdatedView() { return observer_->GetUpdatedView(); }
diff --git a/content/public/test/text_input_test_utils.h b/content/public/test/text_input_test_utils.h index 6c0c2bc..f377320 100644 --- a/content/public/test/text_input_test_utils.h +++ b/content/public/test/text_input_test_utils.h
@@ -25,6 +25,10 @@ class Range; } +namespace ui { +struct CompositionUnderline; +} + namespace content { class MessageLoopRunner; @@ -65,6 +69,15 @@ // Returns true if |frame| has a focused editable element. bool DoesFrameHaveFocusedEditableElement(RenderFrameHost* frame); +// Sends a request to the RenderWidget corresponding to |rwh| to commit the +// given |text|. +void SendImeCommitTextToWidget( + RenderWidgetHost* rwh, + const base::string16& text, + const std::vector<ui::CompositionUnderline>& underlines, + const gfx::Range& replacement_range, + int relative_cursor_pos); + // This class provides the necessary API for accessing the state of and also // observing the TextInputManager for WebContents. class TextInputManagerTester { @@ -106,7 +119,7 @@ // Returns the RenderWidgetHostView which has most recently updated any of its // state (e.g., TextInputState or otherwise). - const RenderWidgetHostView* GetUpdatedView(); + RenderWidgetHostView* GetUpdatedView(); // Returns true if a call to TextInputManager::UpdateTextInputState has led // to a change in TextInputState (since the time the observer has been
diff --git a/content/renderer/manifest/OWNERS b/content/renderer/manifest/OWNERS index 2d28246..edb36297 100644 --- a/content/renderer/manifest/OWNERS +++ b/content/renderer/manifest/OWNERS
@@ -1 +1,3 @@ mlamouri@chromium.org + +# COMPONENT: Manifest
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index effe56d..7143f42 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -822,55 +822,38 @@ } #if defined(OS_ANDROID) -// Returns true if WMPI should be used for playback, false otherwise. +// Returns true if the MediaPlayerRenderer should be used for playback, false +// if the default renderer should be used instead. // // Note that HLS and MP4 detection are pre-redirect and path-based. It is // possible to load such a URL and find different content. -bool UseWebMediaPlayerImpl(const GURL& url) { - // Always use WMPI for playing blob URLs since WMPA could never play them very - // well and no longer has support for MSE based playbacks. +bool UseMediaPlayerRenderer(const GURL& url) { + // Always use the default renderer for playing blob URLs. if (url.SchemeIsBlob()) - return true; - - // WMPI does not support HLS. - if (media::MediaCodecUtil::IsHLSURL(url)) return false; - // Don't use WMPI if the container likely contains a codec we can't decode in - // software and platform decoders are not available. + // The default renderer does not support HLS. + if (media::MediaCodecUtil::IsHLSURL(url)) + return true; + + // Don't use the default renderer if the container likely contains a codec we + // can't decode in software and platform decoders are not available. if (!media::HasPlatformDecoderSupport()) { // Assume that "mp4" means H264. Without platform decoder support we cannot // play it with Spitzer, thus fall back to AVDA. http://crbug.com/642988. if (base::ToLowerASCII(url.spec()).find("mp4") != std::string::npos) - return false; + return true; } // Indicates if the Android MediaPlayer should be used instead of WMPI. if (GetContentClient()->renderer()->ShouldUseMediaPlayerForURL(url)) - return false; + return true; - // Otherwise enable WMPI if indicated via experiment or command line. - return media::IsUnifiedMediaPipelineEnabled(); + // Otherwise, use the default renderer. + return false; } #endif // defined(OS_ANDROID) -#if defined(ENABLE_MOJO_CDM) -// Returns whether mojo CDM should be used at runtime. Note that even when mojo -// CDM is enabled at compile time (ENABLE_MOJO_CDM is defined), there are cases -// where we want to choose other CDM types. For example, in the future, when we -// experiment mojo CDM on desktop, we will choose between mojo CDM and pepper -// CDM at runtime. -// TODO(xhwang): Remove this when we use mojo CDM for all remote CDM cases by -// default. -bool UseMojoCdm() { -#if defined(OS_ANDROID) - return media::IsUnifiedMediaPipelineEnabled(); -#else - return true; -#endif -} -#endif // defined(ENABLE_MOJO_CDM) - double ConvertToBlinkTime(const base::TimeTicks& time_ticks) { return (time_ticks - base::TimeTicks()).InSecondsF(); } @@ -2821,7 +2804,7 @@ new RenderMediaLog(url::Origin(frame_->getSecurityOrigin()).GetURL())); #if defined(OS_ANDROID) - if (UseWebMediaPlayerImpl(url) && !media_surface_manager_) + if (!UseMediaPlayerRenderer(url) && !media_surface_manager_) media_surface_manager_ = new RendererSurfaceViewManager(this); #endif // defined(OS_ANDROID) @@ -2860,7 +2843,7 @@ bool use_fallback_path = false; #if defined(OS_ANDROID) - use_fallback_path = !UseWebMediaPlayerImpl(url); + use_fallback_path = UseMediaPlayerRenderer(url); #endif // defined(OS_ANDROID) std::unique_ptr<media::RendererFactory> media_renderer_factory; @@ -6562,10 +6545,8 @@ return cdm_factory_.get(); #if defined(ENABLE_MOJO_CDM) - if (UseMojoCdm()) { - cdm_factory_.reset(new media::MojoCdmFactory(GetMediaInterfaceProvider())); - return cdm_factory_.get(); - } + cdm_factory_.reset(new media::MojoCdmFactory(GetMediaInterfaceProvider())); + return cdm_factory_.get(); #endif // defined(ENABLE_MOJO_CDM) #if BUILDFLAG(ENABLE_PEPPER_CDMS)
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 5b60ffc..36baa7d 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -670,7 +670,13 @@ } bool RenderWidget::ShouldHandleImeEvents() const { - return GetWebWidget() && GetWebWidget()->isWebFrameWidget() && has_focus_; + // TODO(ekaramad): We track page focus in all RenderViews on the page but the + // RenderWidgets corresponding to OOPIFs do not get the update. For now, this + // method returns true when the RenderWidget is for an OOPIF, i.e., IME events + // will be processed regardless of page focus. We should revisit this after + // page focus for OOPIFs has been fully resolved (https://crbug.com/689777). + return GetWebWidget() && GetWebWidget()->isWebFrameWidget() && + (has_focus_ || for_oopif_); } void RenderWidget::SetWindowRectSynchronously( @@ -1605,7 +1611,7 @@ #endif ImeEventGuard guard(this); input_handler_->set_handling_input_event(true); - if (auto* controller = GetInputMethodController()) + if (auto* controller = GetInputMethodController()) { controller->commitText( WebString::fromUTF16(text), WebVector<WebCompositionUnderline>(underlines), @@ -1613,6 +1619,7 @@ ? WebRange(replacement_range.start(), replacement_range.length()) : WebRange(), relative_cursor_pos); + } input_handler_->set_handling_input_event(false); UpdateCompositionInfo(false /* not an immediate request */); }
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h index 5343b92..819a198 100644 --- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h +++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
@@ -18,7 +18,7 @@ namespace content { // Implements fake adapters with named mock data set for use in tests as a -// result of layout tests calling testRunner.setBluetoothMockDataSet. +// result of layout tests calling testRunner.setBluetoothFakeAdapter. // An adapter named 'FooAdapter' in // https://webbluetoothcg.github.io/web-bluetooth/tests/ is provided by a
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc index 1f0ac7bb..3fe409fdd 100644 --- a/content/test/content_browser_test_utils_internal.cc +++ b/content/test/content_browser_test_utils_internal.cc
@@ -324,7 +324,7 @@ return false; for (cc::SurfaceId id : surface_manager_->GetSurfaceForId(container_surface_id) - ->referenced_surfaces()) { + ->active_referenced_surfaces()) { if (id == target_view_->SurfaceIdForTesting() || ContainsSurfaceId(id)) return true; }
diff --git a/extensions/browser/api/cast_channel/logger.h b/extensions/browser/api/cast_channel/logger.h index 3453f541..905ba8b8 100644 --- a/extensions/browser/api/cast_channel/logger.h +++ b/extensions/browser/api/cast_channel/logger.h
@@ -35,7 +35,7 @@ // Logs information of each channel and sockets and exports the log as // a blob. Logger is done on the IO thread. -class Logger : public base::RefCounted<Logger> { +class Logger : public base::RefCountedThreadSafe<Logger> { public: // |clock|: Clock used for generating timestamps for the events. Owned by // this class. @@ -92,7 +92,7 @@ LastErrors GetLastErrors(int channel_id) const; private: - friend class base::RefCounted<Logger>; + friend class base::RefCountedThreadSafe<Logger>; ~Logger(); struct AggregatedSocketEventLog {
diff --git a/extensions/renderer/argument_spec.cc b/extensions/renderer/argument_spec.cc index c1e2132..b72e3c0 100644 --- a/extensions/renderer/argument_spec.cc +++ b/extensions/renderer/argument_spec.cc
@@ -75,6 +75,8 @@ type_ = ArgumentType::BOOLEAN; else if (type_string == "string") type_ = ArgumentType::STRING; + else if (type_string == "binary") + type_ = ArgumentType::BINARY; else if (type_string == "any") type_ = ArgumentType::ANY; else if (type_string == "function") @@ -172,6 +174,13 @@ v8::Local<v8::Array> array = value.As<v8::Array>(); return ParseArgumentToArray(context, array, refs, out_value, error); } + if (type_ == ArgumentType::BINARY) { + if (!value->IsArrayBuffer() && !value->IsArrayBufferView()) { + *error = "Wrong type"; + return false; + } + return ParseArgumentToAny(context, value, out_value, error); + } if (type_ == ArgumentType::ANY) return ParseArgumentToAny(context, value, out_value, error); NOTREACHED(); @@ -317,7 +326,7 @@ v8::Local<v8::Value> value, std::unique_ptr<base::Value>* out_value, std::string* error) const { - DCHECK_EQ(ArgumentType::ANY, type_); + DCHECK(type_ == ArgumentType::ANY || type_ == ArgumentType::BINARY); if (out_value) { std::unique_ptr<content::V8ValueConverter> converter( content::V8ValueConverter::create()); @@ -327,6 +336,8 @@ *error = "Could not convert to 'any'."; return false; } + if (type_ == ArgumentType::BINARY) + DCHECK_EQ(base::Value::Type::BINARY, converted->GetType()); *out_value = std::move(converted); } return true;
diff --git a/extensions/renderer/argument_spec.h b/extensions/renderer/argument_spec.h index 2f9c7ac..8145d01 100644 --- a/extensions/renderer/argument_spec.h +++ b/extensions/renderer/argument_spec.h
@@ -29,6 +29,7 @@ STRING, OBJECT, LIST, + BINARY, FUNCTION, ANY, REF,
diff --git a/extensions/renderer/argument_spec_unittest.cc b/extensions/renderer/argument_spec_unittest.cc index 12a8c61..da2ac4e4 100644 --- a/extensions/renderer/argument_spec_unittest.cc +++ b/extensions/renderer/argument_spec_unittest.cc
@@ -22,32 +22,40 @@ const std::string& script_source, const std::string& expected_json_single_quotes) { RunTest(spec, script_source, true, TestResult::PASS, - ReplaceSingleQuotes(expected_json_single_quotes), std::string()); + ReplaceSingleQuotes(expected_json_single_quotes), nullptr, + std::string()); + } + + void ExpectSuccess(const ArgumentSpec& spec, + const std::string& script_source, + const base::Value& expected_value) { + RunTest(spec, script_source, true, TestResult::PASS, std::string(), + &expected_value, std::string()); } void ExpectSuccessWithNoConversion(const ArgumentSpec& spec, const std::string& script_source) { - RunTest(spec, script_source, false, TestResult::PASS, - std::string(), std::string()); + RunTest(spec, script_source, false, TestResult::PASS, std::string(), + nullptr, std::string()); } void ExpectFailure(const ArgumentSpec& spec, const std::string& script_source) { - RunTest(spec, script_source, true, TestResult::FAIL, std::string(), + RunTest(spec, script_source, true, TestResult::FAIL, std::string(), nullptr, std::string()); } void ExpectFailureWithNoConversion(const ArgumentSpec& spec, const std::string& script_source) { RunTest(spec, script_source, false, TestResult::FAIL, std::string(), - std::string()); + nullptr, std::string()); } void ExpectThrow(const ArgumentSpec& spec, const std::string& script_source, const std::string& expected_thrown_message) { RunTest(spec, script_source, true, TestResult::THROW, std::string(), - expected_thrown_message); + nullptr, expected_thrown_message); } void AddTypeRef(const std::string& id, std::unique_ptr<ArgumentSpec> spec) { @@ -62,6 +70,7 @@ bool should_convert, TestResult expected_result, const std::string& expected_json, + const base::Value* expected_value, const std::string& expected_thrown_message); ArgumentSpec::RefMap type_refs_; @@ -74,6 +83,7 @@ bool should_convert, TestResult expected_result, const std::string& expected_json, + const base::Value* expected_value, const std::string& expected_thrown_message) { v8::Isolate* isolate = instance_->isolate(); v8::HandleScope handle_scope(instance_->isolate()); @@ -96,7 +106,10 @@ ASSERT_EQ(should_throw, try_catch.HasCaught()) << script_source; if (should_succeed && should_convert) { ASSERT_TRUE(out_value); - EXPECT_EQ(expected_json, ValueToString(*out_value)); + if (expected_value) + EXPECT_TRUE(expected_value->Equals(out_value.get())) << script_source; + else + EXPECT_EQ(expected_json, ValueToString(*out_value)); } else if (should_throw) { EXPECT_EQ(expected_thrown_message, gin::V8ToString(try_catch.Message()->Get())); @@ -242,6 +255,39 @@ ExpectFailureWithNoConversion(spec, "([function() {}])"); ExpectFailureWithNoConversion(spec, "1"); } + + { + const char kBinarySpec[] = "{ 'type': 'binary' }"; + ArgumentSpec spec(*ValueFromString(kBinarySpec)); + // Simple case: empty ArrayBuffer -> empty BinaryValue. + ExpectSuccess(spec, "(new ArrayBuffer())", base::BinaryValue()); + { + // A non-empty (but zero-filled) ArrayBufferView. + const char kBuffer[] = {0, 0, 0, 0}; + std::unique_ptr<base::BinaryValue> expected_value = + base::BinaryValue::CreateWithCopiedBuffer(kBuffer, + arraysize(kBuffer)); + ASSERT_TRUE(expected_value); + ExpectSuccessWithNoConversion(spec, "(new Int32Array(2))"); + } + { + // Actual data. + const char kBuffer[] = {'p', 'i', 'n', 'g'}; + std::unique_ptr<base::BinaryValue> expected_value = + base::BinaryValue::CreateWithCopiedBuffer(kBuffer, + arraysize(kBuffer)); + ASSERT_TRUE(expected_value); + ExpectSuccess(spec, + "var b = new ArrayBuffer(4);\n" + "var v = new Uint8Array(b);\n" + "var s = 'ping';\n" + "for (var i = 0; i < s.length; ++i)\n" + " v[i] = s.charCodeAt(i);\n" + "b;", + *expected_value); + } + ExpectFailure(spec, "1"); + } } TEST_F(ArgumentSpecUnitTest, TypeRefsTest) {
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm index 18cfa16..47f246b 100644 --- a/ios/chrome/browser/tabs/tab.mm +++ b/ios/chrome/browser/tabs/tab.mm
@@ -339,10 +339,6 @@ // Sets the favicon on the current NavigationItem. - (void)setFavicon:(const gfx::Image*)image; -// Updates the title field of the current session entry. Also updates the -// history database. -- (void)updateTitle:(NSString*)title; - // Saves the current title to the history database. - (void)saveTitleToHistoryDB; @@ -998,20 +994,6 @@ overscrollActionsControllerDelegate); } -- (void)updateTitle:(NSString*)title { - web::NavigationItem* item = [self navigationManager]->GetVisibleItem(); - if (!item) - return; - item->SetTitle(base::SysNSStringToUTF16(title)); - // TODO(crbug.com/546218): See if this can be removed; it's not clear that - // other platforms send this (tab sync triggers need to be compared against - // upstream). - if (webStateImpl_) - webStateImpl_->GetNavigationManagerImpl().OnNavigationItemChanged(); - - [self saveTitleToHistoryDB]; -} - - (void)saveTitleToHistoryDB { // If incognito, don't update history. if (browserState_->IsOffTheRecord()) @@ -1840,13 +1822,8 @@ - (void)webController:(CRWWebController*)webController titleDidChange:(NSString*)title { - NSString* oldTitle = [self title]; - BOOL isTitleChanged = (!oldTitle && title) || (oldTitle && !title) || - (![oldTitle isEqualToString:title]); - if (isTitleChanged) { - [self updateTitle:title]; - [parentTabModel_ notifyTabChanged:self]; - } + [self saveTitleToHistoryDB]; + [parentTabModel_ notifyTabChanged:self]; } - (BOOL)urlTriggersNativeAppLaunch:(const GURL&)url
diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm index c611f47d..d863fa3 100644 --- a/ios/chrome/browser/tabs/tab_unittest.mm +++ b/ios/chrome/browser/tabs/tab_unittest.mm
@@ -242,6 +242,8 @@ [[tab_ navigationManager]->GetSessionController() commitPendingItem]; [[tab_ webController] webStateImpl]->OnNavigationCommitted(redirectUrl); [tab_ webDidStartLoadingURL:redirectUrl shouldUpdateHistory:YES]; + base::string16 new_title = base::SysNSStringToUTF16(title); + [tab_ navigationManager]->GetLastCommittedItem()->SetTitle(new_title); [tab_ webController:mock_web_controller_ titleDidChange:title]; [[[(id)mock_web_controller_ expect] andReturnValue:OCMOCK_VALUE(kPageLoaded)] loadPhase];
diff --git a/ios/web/net/cookie_notification_bridge.h b/ios/web/net/cookie_notification_bridge.h index 0e4c1304..8e6273e 100644 --- a/ios/web/net/cookie_notification_bridge.h +++ b/ios/web/net/cookie_notification_bridge.h
@@ -7,7 +7,6 @@ #import "base/mac/scoped_nsobject.h" #include "base/macros.h" -#include "base/threading/thread_checker.h" @class NSNotification; @@ -22,9 +21,8 @@ ~CookieNotificationBridge(); private: - void OnNotificationReceived(NSNotification* notification); + static void OnNotificationReceived(NSNotification* notification); base::scoped_nsprotocol<id> observer_; - base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(CookieNotificationBridge); };
diff --git a/ios/web/net/cookie_notification_bridge.mm b/ios/web/net/cookie_notification_bridge.mm index 3c2d538..4ab27e0e 100644 --- a/ios/web/net/cookie_notification_bridge.mm +++ b/ios/web/net/cookie_notification_bridge.mm
@@ -34,7 +34,6 @@ void CookieNotificationBridge::OnNotificationReceived( NSNotification* notification) { - DCHECK(thread_checker_.CalledOnValidThread()); DCHECK([[notification name] isEqualToString:NSHTTPCookieManagerCookiesChangedNotification]); web::WebThread::PostTask(
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 8eacd96..3132253f 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -702,6 +702,8 @@ stateObject:(NSString*)stateObject; // Sets _documentURL to newURL, and updates any relevant state information. - (void)setDocumentURL:(const GURL&)newURL; +// Sets WKWebView's title to the last committed navigation item. +- (void)updateNavigationItemTitle; // Returns YES if the current navigation item corresponds to a web page // loaded by a POST request. - (BOOL)isCurrentNavigationItemPOST; @@ -1368,6 +1370,29 @@ } } +- (void)updateNavigationItemTitle { + NSString* webViewTitle = [_webView title]; + DCHECK(webViewTitle); + auto& navigationManager = _webStateImpl->GetNavigationManagerImpl(); + web::NavigationItem* item = navigationManager.GetLastCommittedItem(); + if (!item) + return; + + base::string16 newTitle = base::SysNSStringToUTF16(webViewTitle); + if (item->GetTitle() == newTitle) + return; + + item->SetTitle(newTitle); + // TODO(crbug.com/546218): See if this can be removed; it's not clear that + // other platforms send this (tab sync triggers need to be compared against + // upstream). + navigationManager.OnNavigationItemChanged(); + + if ([_delegate respondsToSelector:@selector(webController:titleDidChange:)]) { + [_delegate webController:self titleDidChange:webViewTitle]; + } +} + - (BOOL)isCurrentNavigationItemPOST { // |_pendingNavigationInfo| will be nil if the decidePolicy* delegate methods // were not called. @@ -4729,9 +4754,10 @@ DCHECK_EQ(_webView, webView); _certVerificationErrors->Clear(); - // This is the point where the document's URL has actually changed, and - // pending navigation information should be applied to state information. + // This is the point where the document's URL and title have actually changed, + // and pending navigation information should be applied to state information. [self setDocumentURL:net::GURLWithNSURL([_webView URL])]; + [self updateNavigationItemTitle]; if (!_lastRegisteredRequestURL.is_valid() && _documentURL != _lastRegisteredRequestURL) { @@ -4969,10 +4995,12 @@ return; } - if ([self.delegate - respondsToSelector:@selector(webController:titleDidChange:)]) { - DCHECK([_webView title]); - [self.delegate webController:self titleDidChange:[_webView title]]; + bool hasPendingNavigation = web::WKNavigationState::COMMITTED <= + [_navigationStates lastAddedNavigationState]; + if (hasPendingNavigation) { + // Do not update the title if there is a navigation in progress because + // there is no way to tell if KVO change fired for new or previous page. + [self updateNavigationItemTitle]; } }
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm index 02623a57..749b5b6c 100644 --- a/ios/web/web_state/ui/crw_web_controller_unittest.mm +++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -778,6 +778,7 @@ TEST_F(CRWWebControllerTest, WebUrlWithTrustLevel) { [[[mockWebView_ stub] andReturn:[NSURL URLWithString:@(kTestURLString)]] URL]; [[[mockWebView_ stub] andReturnBool:NO] hasOnlySecureContent]; + [[[mockWebView_ stub] andReturn:@""] title]; // Stub out the injection process. [[mockWebView_ stub] evaluateJavaScript:OCMOCK_ANY
diff --git a/ios/web/web_state/ui/crw_wk_navigation_states.h b/ios/web/web_state/ui/crw_wk_navigation_states.h index 5005e40..c16fc5b 100644 --- a/ios/web/web_state/ui/crw_wk_navigation_states.h +++ b/ios/web/web_state/ui/crw_wk_navigation_states.h
@@ -54,6 +54,10 @@ // last added navigation. Returns nil if there are no stored navigations. - (WKNavigation*)lastAddedNavigation; +// State of WKNavigation which was added the most recently via +// |setState:forNavigation:|. +- (web::WKNavigationState)lastAddedNavigationState; + @end #endif // IOS_WEB_WEB_STATE_UI_CRW_WK_NAVIGATION_STATES_H_
diff --git a/ios/web/web_state/ui/crw_wk_navigation_states.mm b/ios/web/web_state/ui/crw_wk_navigation_states.mm index f15ebc09..59f1c6d 100644 --- a/ios/web/web_state/ui/crw_wk_navigation_states.mm +++ b/ios/web/web_state/ui/crw_wk_navigation_states.mm
@@ -105,4 +105,13 @@ return result; } +- (web::WKNavigationState)lastAddedNavigationState { + CRWWKNavigationsStateRecord* lastAddedRecord = nil; + WKNavigation* lastAddedNavigation = [self lastAddedNavigation]; + if (lastAddedNavigation) + lastAddedRecord = [_records objectForKey:lastAddedNavigation]; + + return lastAddedRecord.state; +} + @end
diff --git a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm index 61c4409..5b3eb4f3 100644 --- a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm +++ b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
@@ -31,14 +31,22 @@ // navigation_1 is the only navigation and it is the latest. [states_ setState:WKNavigationState::REQUESTED forNavigation:navigation1_]; EXPECT_EQ(navigation1_, [states_ lastAddedNavigation]); + EXPECT_EQ(WKNavigationState::REQUESTED, [states_ lastAddedNavigationState]); // navigation_2 is added later and hence the latest. [states_ setState:WKNavigationState::REQUESTED forNavigation:navigation2_]; EXPECT_EQ(navigation2_, [states_ lastAddedNavigation]); + EXPECT_EQ(WKNavigationState::REQUESTED, [states_ lastAddedNavigationState]); // Updating state for existing navigation does not make it the latest. [states_ setState:WKNavigationState::STARTED forNavigation:navigation1_]; EXPECT_EQ(navigation2_, [states_ lastAddedNavigation]); + EXPECT_EQ(WKNavigationState::REQUESTED, [states_ lastAddedNavigationState]); + + // navigation_2 is still the latest. + [states_ setState:WKNavigationState::STARTED forNavigation:navigation2_]; + EXPECT_EQ(navigation2_, [states_ lastAddedNavigation]); + EXPECT_EQ(WKNavigationState::STARTED, [states_ lastAddedNavigationState]); } } // namespace web
diff --git a/media/base/key_systems.cc b/media/base/key_systems.cc index ef16ad6..6e3d4072 100644 --- a/media/base/key_systems.cc +++ b/media/base/key_systems.cc
@@ -443,7 +443,7 @@ #if defined(OS_ANDROID) // Ensure that the renderer can access the decoders necessary to use the // key system. - if (!properties->UseAesDecryptor() && !ArePlatformDecodersAvailable()) { + if (!properties->UseAesDecryptor() && !HasPlatformDecoderSupport()) { DLOG(WARNING) << properties->GetKeySystemName() << " not registered"; continue; }
diff --git a/media/base/media.cc b/media/base/media.cc index 38daf05b..8e9e719 100644 --- a/media/base/media.cc +++ b/media/base/media.cc
@@ -86,17 +86,6 @@ bool PlatformHasOpusSupport() { return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; } - -bool IsUnifiedMediaPipelineEnabled() { - return !base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableUnifiedMediaPipeline); -} - -bool ArePlatformDecodersAvailable() { - return IsUnifiedMediaPipelineEnabled() - ? HasPlatformDecoderSupport() - : MediaCodecUtil::IsMediaCodecAvailable(); -} #endif } // namespace media
diff --git a/media/base/media.h b/media/base/media.h index 7dd8765..f6a53f4 100644 --- a/media/base/media.h +++ b/media/base/media.h
@@ -27,20 +27,6 @@ // Indicates if the platform supports Opus. Determined *ONLY* by the platform // version, so does not guarantee that either can actually be played. MEDIA_EXPORT bool PlatformHasOpusSupport(); - -// Returns true if the unified media pipeline is enabled; the pipeline may still -// not work for all codecs if HasPlatformDecoderSupport() is false. Please see -// MimeUtil for an exhaustive listing of supported codecs. -// -// TODO(dalecurtis): These methods are temporary and should be removed once the -// unified media pipeline is supported everywhere. http://crbug.com/580626. -MEDIA_EXPORT bool IsUnifiedMediaPipelineEnabled(); - -// Returns whether the platform decoders are available for use. -// This includes decoders being available on the platform and accessible, such -// as via the GPU process. Should only be used for actual decoders -// (e.g. MediaCodec) and not full-featured players (e.g. MediaPlayer). -MEDIA_EXPORT bool ArePlatformDecodersAvailable(); #endif } // namespace media
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 49dc7289..b94cfcf 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -22,12 +22,6 @@ const char kReportVp9AsAnUnsupportedMimeType[] = "report-vp9-as-an-unsupported-mime-type"; -#if defined(OS_ANDROID) -// Use WebMediaPlayerAndroid instead of WebMediaPlayerImpl. This is a temporary -// switch for holding back the new unified media pipeline. -const char kDisableUnifiedMediaPipeline[] = "disable-unified-media-pipeline"; -#endif - #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_SOLARIS) // The Alsa device to use when opening an audio input stream. const char kAlsaInputDevice[] = "alsa-input-device";
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index c3e184b9..0f1d43aa 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -24,10 +24,6 @@ MEDIA_EXPORT extern const char kReportVp9AsAnUnsupportedMimeType[]; -#if defined(OS_ANDROID) -MEDIA_EXPORT extern const char kDisableUnifiedMediaPipeline[]; -#endif - #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_SOLARIS) MEDIA_EXPORT extern const char kAlsaInputDevice[]; MEDIA_EXPORT extern const char kAlsaOutputDevice[];
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc index cb5dfd55..f4cf92f 100644 --- a/media/base/mime_util_internal.cc +++ b/media/base/mime_util_internal.cc
@@ -122,12 +122,10 @@ MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { #if defined(OS_ANDROID) - platform_info_.is_unified_media_pipeline_enabled = - IsUnifiedMediaPipelineEnabled(); // When the unified media pipeline is enabled, we need support for both GPU // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport(). // When the Android pipeline is used, we only need access to MediaCodec. - platform_info_.has_platform_decoders = ArePlatformDecodersAvailable(); + platform_info_.has_platform_decoders = HasPlatformDecoderSupport(); platform_info_.has_platform_vp8_decoder = MediaCodecUtil::IsVp8DecoderAvailable(); platform_info_.has_platform_vp9_decoder = @@ -464,11 +462,11 @@ base::CompareCase::SENSITIVE)) { return false; } - return !is_encrypted && platform_info.is_unified_media_pipeline_enabled; + return !is_encrypted; case OPUS: // If clear, the unified pipeline can always decode Opus in software. - if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled) + if (!is_encrypted) return true; // Otherwise, platform support is required. @@ -491,10 +489,8 @@ case HEVC: #if BUILDFLAG(ENABLE_HEVC_DEMUXING) - if (platform_info.is_unified_media_pipeline_enabled && - !platform_info.has_platform_decoders) { + if (!platform_info.has_platform_decoders) return false; - } #if defined(OS_ANDROID) // HEVC/H.265 is supported in Lollipop+ (API Level 21), according to @@ -509,7 +505,7 @@ case VP8: // If clear, the unified pipeline can always decode VP8 in software. - if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled) + if (!is_encrypted) return true; if (is_encrypted) @@ -526,7 +522,7 @@ } // If clear, the unified pipeline can always decode VP9 in software. - if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled) + if (!is_encrypted) return true; if (!platform_info.has_platform_vp9_decoder)
diff --git a/media/base/mime_util_internal.h b/media/base/mime_util_internal.h index b6d98f44..e853b89 100644 --- a/media/base/mime_util_internal.h +++ b/media/base/mime_util_internal.h
@@ -52,8 +52,6 @@ bool has_platform_vp8_decoder = false; bool has_platform_vp9_decoder = false; bool supports_opus = false; - - bool is_unified_media_pipeline_enabled = false; }; // See mime_util.h for more information on these methods.
diff --git a/media/base/mime_util_unittest.cc b/media/base/mime_util_unittest.cc index 8d630dc..99be40b5 100644 --- a/media/base/mime_util_unittest.cc +++ b/media/base/mime_util_unittest.cc
@@ -57,7 +57,6 @@ MAKE_TEST_VECTOR(has_platform_vp8_decoder); MAKE_TEST_VECTOR(has_platform_vp9_decoder); MAKE_TEST_VECTOR(supports_opus); - MAKE_TEST_VECTOR(is_unified_media_pipeline_enabled); #undef MAKE_TEST_VECTOR MimeUtil::PlatformInfo info; @@ -71,20 +70,16 @@ RUN_TEST_VECTOR(has_platform_vp8_decoder) { RUN_TEST_VECTOR(has_platform_vp9_decoder) { RUN_TEST_VECTOR(supports_opus) { - RUN_TEST_VECTOR(is_unified_media_pipeline_enabled) { - for (int codec = MimeUtil::INVALID_CODEC; - codec <= MimeUtil::LAST_CODEC; ++codec) { - SCOPED_TRACE(base::StringPrintf( - "has_platform_decoders=%d, has_platform_vp8_decoder=%d, " - "supports_opus=%d, " - "has_platform_vp9_decoder=%d, " - "is_unified_media_pipeline_enabled=%d, " - "codec=%d", - info.has_platform_decoders, info.has_platform_vp8_decoder, - info.supports_opus, info.has_platform_vp9_decoder, - info.is_unified_media_pipeline_enabled, codec)); - test_func(info, static_cast<MimeUtil::Codec>(codec)); - } + for (int codec = MimeUtil::INVALID_CODEC; + codec <= MimeUtil::LAST_CODEC; ++codec) { + SCOPED_TRACE(base::StringPrintf( + "has_platform_decoders=%d, has_platform_vp8_decoder=%d, " + "supports_opus=%d, " + "has_platform_vp9_decoder=%d, " + "codec=%d", + info.has_platform_decoders, info.has_platform_vp8_decoder, + info.supports_opus, info.has_platform_vp9_decoder, codec)); + test_func(info, static_cast<MimeUtil::Codec>(codec)); } } } @@ -100,7 +95,6 @@ states_to_vary.has_platform_vp8_decoder = true; states_to_vary.has_platform_vp9_decoder = true; states_to_vary.supports_opus = true; - states_to_vary.is_unified_media_pipeline_enabled = true; states_to_vary.has_platform_decoders = true; return states_to_vary; } @@ -294,76 +288,10 @@ }); } -TEST(IsCodecSupportedOnPlatformTest, ClearCodecBehaviorWithAndroidPipeline) { - // Vary all parameters except |is_unified_media_pipeline_enabled|. +TEST(IsCodecSupportedOnPlatformTest, ClearCodecBehavior) { MimeUtil::PlatformInfo states_to_vary = VaryAllFields(); - states_to_vary.is_unified_media_pipeline_enabled = false; - // Disable the unified pipeline. MimeUtil::PlatformInfo test_states; - test_states.is_unified_media_pipeline_enabled = false; - - RunCodecSupportTest( - states_to_vary, test_states, - [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) { - const bool result = MimeUtil::IsCodecSupportedOnPlatform( - codec, kTestMimeType, false, info); - switch (codec) { - // These codecs are never supported by the Android platform. - case MimeUtil::INVALID_CODEC: - case MimeUtil::AC3: - case MimeUtil::EAC3: - case MimeUtil::MPEG2_AAC: - case MimeUtil::THEORA: - EXPECT_FALSE(result); - break; - - // These codecs are always available via MediaPlayer. - case MimeUtil::FLAC: - case MimeUtil::PCM: - case MimeUtil::MP3: - case MimeUtil::MPEG4_AAC: - case MimeUtil::VORBIS: - case MimeUtil::H264: - case MimeUtil::VP8: - EXPECT_TRUE(result); - break; - - // The remaining codecs depend on the platform version. - case MimeUtil::OPUS: - EXPECT_EQ(info.supports_opus, result); - break; - - case MimeUtil::VP9: - // MediaPlayer only supports VP9 in WebM. - EXPECT_FALSE(result); - break; - - case MimeUtil::HEVC: - EXPECT_EQ(HasHevcSupport(), result); - break; - } - }); - - // Verify vp9 support in WebM. - RunCodecSupportTest( - states_to_vary, test_states, - [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) { - const bool result = MimeUtil::IsCodecSupportedOnPlatform( - codec, "video/webm", true, info); - if (codec == MimeUtil::VP9) - EXPECT_EQ(info.has_platform_vp9_decoder, result); - }); -} - -TEST(IsCodecSupportedOnPlatformTest, ClearCodecBehaviorWithUnifiedPipeline) { - // Vary all parameters except |is_unified_media_pipeline_enabled|. - MimeUtil::PlatformInfo states_to_vary = VaryAllFields(); - states_to_vary.is_unified_media_pipeline_enabled = false; - - // Enable the unified pipeline. - MimeUtil::PlatformInfo test_states; - test_states.is_unified_media_pipeline_enabled = true; RunCodecSupportTest( states_to_vary, test_states, @@ -412,9 +340,8 @@ RunCodecSupportTest( states_to_vary, test_states, [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) { - EXPECT_EQ(info.is_unified_media_pipeline_enabled, - MimeUtil::IsCodecSupportedOnPlatform( - MimeUtil::OPUS, "audio/ogg", false, info)); + EXPECT_TRUE(MimeUtil::IsCodecSupportedOnPlatform( + MimeUtil::OPUS, "audio/ogg", false, info)); }); }
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index c34175f..abab8e86 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -810,6 +810,8 @@ crbug.com/526463 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Failure Timeout ] crbug.com/526463 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Failure Timeout ] +crbug.com/526463 virtual/wheelscrolllatching/fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Timeout Pass ] + crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/scrollstate-basic.html [ Pass Failure ] crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/scrollstate-consume-deltas.html [ Pass Failure ] crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/scrollstate-consume-deltas-throw.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/add-listener-after-promise.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/add-listener-after-promise.html index a1e7c69..9fae0051 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/add-listener-after-promise.html +++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/add-listener-after-promise.html
@@ -14,7 +14,7 @@ .then(characteristic => { return characteristic.startNotifications() .then(() => new Promise(resolve => { - let event_listener = e => { + let event_listener = () => { characteristic.removeEventListener( 'characteristicvaluechanged', event_listener); resolve();
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/notification-after-disconnection.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/notification-after-disconnection.html index 591596a..c2671353 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/notification-after-disconnection.html +++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/notification-after-disconnection.html
@@ -8,7 +8,7 @@ // The iframe we create will subscribe to notifications and will ensure // that the browser keeps receiving notifications even after this frame's // device disconnects. - let iframe_connected = new Promise(resolve => { + let iframe_connected = new Promise((resolve, reject) => { window.onmessage = messageEvent => { if (messageEvent.data === 'Ready') { let iframe = document.querySelector('iframe'); @@ -41,7 +41,7 @@ .then(characteristic => characteristic.startNotifications()) .then(characteristic => new Promise(resolve => { // Make sure we are receiving events. - let event_listener = e => { + let event_listener = () => { characteristic.removeEventListener( 'characteristicvaluechanged', event_listener); resolve(characteristic);
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners-expected.txt new file mode 100644 index 0000000..f9c92dc --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners-expected.txt
@@ -0,0 +1,147 @@ +A +B +C + +Fetching listeners for depth = undefined and pierce = undefined +{ + "listeners": [ + { + "type": "documentListener", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + } + ] +} +Fetching listeners for depth = 1 and pierce = undefined +{ + "listeners": [ + { + "type": "documentListener", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + } + ] +} +Fetching listeners for depth = 4 and pierce = undefined +{ + "listeners": [ + { + "type": "documentListener", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + }, + { + "type": "listenerA", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + } + ] +} +Fetching listeners for depth = -1 and pierce = undefined +{ + "listeners": [ + { + "type": "documentListener", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + }, + { + "type": "listenerA", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + }, + { + "type": "listenerB", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + }, + { + "type": "listenerC", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + } + ] +} +Fetching listeners for depth = -1 and pierce = true +{ + "listeners": [ + { + "type": "documentListener", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + }, + { + "type": "listenerA", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + }, + { + "type": "listenerB", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + }, + { + "type": "listenerC", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + }, + { + "type": "iframeListener", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": "<number>", + "columnNumber": "<number>" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners.html b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners.html new file mode 100644 index 0000000..42d704d --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners.html
@@ -0,0 +1,74 @@ +<html> +<head> +<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script> +<script> + +function test() +{ + var objectId; + InspectorTest.sendCommand("DOM.enable", {}); + InspectorTest.sendCommand("Runtime.enable", {}); + InspectorTest.sendCommand("DOMDebugger.enable", {}); + InspectorTest.sendCommandPromise("Runtime.evaluate", { expression: "document" }) + .then((result) => { objectId = result.result.result.objectId }) + .then(() => dumpListeners(objectId)) + .then(() => dumpListeners(objectId, 1)) + .then(() => dumpListeners(objectId, 4)) + .then(() => dumpListeners(objectId, -1)) + .then(() => dumpListeners(objectId, -1, true)) + .then(() => InspectorTest.completeTest()); + + function dumpListeners(objectId, depth, pierce) { + var params = {objectId : objectId}; + if (depth) + params.depth = depth; + if (pierce !== undefined) + params.pierce = pierce; + InspectorTest.log(`Fetching listeners for depth = ${depth} and pierce = ${pierce}`); + return InspectorTest.sendCommandPromise("DOMDebugger.getEventListeners", params).then((result) => logResponse(result.result)); + } + + function stabilize(key, value) { + var unstableKeys = ["scriptId", "lineNumber", "columnNumber"]; + if (unstableKeys.indexOf(key) !== -1) + return "<" + typeof(value) + ">"; + return value; + } + + function logResponse(response) { + InspectorTest.log(JSON.stringify(response, stabilize, 2)); + } +} + +</script> +<template id="shadow-template" onclick="clickTemplate"> +<style> +:host { + color: red; +} +</style> +<div></div><h1>Hi from a template!</h1></div> +</template> +</head> +<body class="body-class" onload="runTest()"> + <div id="A"> A + <div id="B"> B + <div id="C"> C + </div> + </div> + </div> + + <iframe src="../dom/resources/iframe-with-listener.html" width="400" height="200"></iframe> + <div id="shadow-host"></div> + <script type="text/javascript"> + var host = document.querySelector("#shadow-host").createShadowRoot(); + var template = document.querySelector("#shadow-template"); + host.appendChild(template.content); + template.remove(); + document.getElementById("A").addEventListener("listenerA", () => {}); + document.getElementById("B").addEventListener("listenerB", () => {}); + document.getElementById("C").addEventListener("listenerC", () => {}); + document.addEventListener("documentListener", () => {}); + </script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom/resources/iframe-with-listener.html b/third_party/WebKit/LayoutTests/inspector-protocol/dom/resources/iframe-with-listener.html new file mode 100644 index 0000000..37ae1cb --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom/resources/iframe-with-listener.html
@@ -0,0 +1,10 @@ +<html> +<body> +<div id="iframenode"> +Hello from the iframe. +</div> +<script> +document.getElementById("iframenode").addEventListener("iframeListener", () => { }); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html index 1073b34..99ee444b 100644 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html
@@ -54,7 +54,6 @@ var view = new Timeline.EventsTimelineTreeView(UI.panels.timeline._filters, null); view.setModel(model); view.updateContents(Timeline.TimelineSelection.fromRange(model.timelineModel().minimumRecordTime(), model.timelineModel().maximumRecordTime())); - var filtersControl = view._filtersControl; function printEventMessage(event, level) { InspectorTest.addResult(" ".repeat(level) + event.args["data"].message); @@ -70,12 +69,11 @@ dumpRecords(); InspectorTest.addResult("Filtered by 'bar':"); - var textFilterUI = filtersControl._textFilterUI; - textFilterUI._internalSetValue("bar", true); + view._textFilterUI._internalSetValue("bar", true); dumpRecords(); InspectorTest.addResult("Filtered by 'foo':"); - textFilterUI._internalSetValue("foo", true); + view._textFilterUI._internalSetValue("foo", true); dumpRecords(); InspectorTest.completeTest();
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js index 89392da9..0f56560 100644 --- a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js +++ b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
@@ -325,7 +325,7 @@ class EventCatcher { constructor(object, event) { this.eventFired = false; - let event_listener = e => { + let event_listener = () => { object.removeEventListener(event, event_listener); this.eventFired = true; }
diff --git a/third_party/WebKit/Source/bindings/bindings.gni b/third_party/WebKit/Source/bindings/bindings.gni index ad3994a0..a4ba8791 100644 --- a/third_party/WebKit/Source/bindings/bindings.gni +++ b/third_party/WebKit/Source/bindings/bindings.gni
@@ -114,8 +114,6 @@ "core/v8/ScriptString.h", "core/v8/ScriptValue.cpp", "core/v8/ScriptValue.h", - "core/v8/ScriptValueSerializer.cpp", - "core/v8/ScriptValueSerializer.h", "core/v8/ScriptWrappable.cpp", "core/v8/ScriptWrappable.h", "core/v8/ScriptWrappableVisitor.cpp", @@ -231,7 +229,6 @@ "core/v8/ScriptPromiseResolverTest.cpp", "core/v8/ScriptPromiseTest.cpp", "core/v8/ScriptStreamerTest.cpp", - "core/v8/ScriptValueSerializerTest.cpp", "core/v8/ScriptWrappableVisitorTest.cpp", "core/v8/SerializedScriptValueTest.cpp", "core/v8/ToV8Test.cpp",
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp deleted file mode 100644 index 2108dc9..0000000 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp +++ /dev/null
@@ -1,2631 +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 "bindings/core/v8/ScriptValueSerializer.h" - -#include "bindings/core/v8/Transferables.h" -#include "bindings/core/v8/V8ArrayBuffer.h" -#include "bindings/core/v8/V8ArrayBufferView.h" -#include "bindings/core/v8/V8Blob.h" -#include "bindings/core/v8/V8CompositorProxy.h" -#include "bindings/core/v8/V8File.h" -#include "bindings/core/v8/V8FileList.h" -#include "bindings/core/v8/V8ImageBitmap.h" -#include "bindings/core/v8/V8ImageData.h" -#include "bindings/core/v8/V8MessagePort.h" -#include "bindings/core/v8/V8OffscreenCanvas.h" -#include "bindings/core/v8/V8SharedArrayBuffer.h" -#include "core/dom/CompositorProxy.h" -#include "core/dom/DOMDataView.h" -#include "core/dom/DOMSharedArrayBuffer.h" -#include "core/dom/DOMTypedArray.h" -#include "core/fileapi/Blob.h" -#include "core/fileapi/File.h" -#include "core/fileapi/FileList.h" -#include "platform/RuntimeEnabledFeatures.h" -#include "public/platform/Platform.h" -#include "public/platform/WebBlobInfo.h" -#include "wtf/DateMath.h" -#include "wtf/text/StringHash.h" -#include "wtf/text/StringUTF8Adaptor.h" -#include <memory> - -// FIXME: consider crashing in debug mode on deserialization errors -// NOTE: be sure to change wireFormatVersion as necessary! - -namespace blink { - -namespace { - -// This code implements the HTML5 Structured Clone algorithm: -// http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-passing-of-structured-data - -// ZigZag encoding helps VarInt encoding stay small for negative -// numbers with small absolute values. -class ZigZag { - public: - static uint32_t encode(uint32_t value) { - if (value & (1U << 31)) - value = ((~value) << 1) + 1; - else - value <<= 1; - return value; - } - - static uint32_t decode(uint32_t value) { - if (value & 1) - value = ~(value >> 1); - else - value >>= 1; - return value; - } - - private: - ZigZag(); -}; - -const int maxDepth = 20000; - -bool shouldCheckForCycles(int depth) { - ASSERT(depth >= 0); - // Since we are not required to spot the cycle as soon as it - // happens we can check for cycles only when the current depth - // is a power of two. - return !(depth & (depth - 1)); -} - -// Returns true if the provided object is to be considered a 'host object', as -// used in the HTML5 structured clone algorithm. -bool isHostObject(v8::Local<v8::Object> object) { - // If the object has any internal fields, then we won't be able to serialize - // or deserialize them; conveniently, this is also a quick way to detect DOM - // wrapper objects, because the mechanism for these relies on data stored in - // these fields. We should catch external array data as a special case. - return object->InternalFieldCount(); -} - -} // namespace - -void SerializedScriptValueWriter::writeUndefined() { - append(UndefinedTag); -} - -void SerializedScriptValueWriter::writeNull() { - append(NullTag); -} - -void SerializedScriptValueWriter::writeTrue() { - append(TrueTag); -} - -void SerializedScriptValueWriter::writeFalse() { - append(FalseTag); -} - -void SerializedScriptValueWriter::writeBooleanObject(bool value) { - append(value ? TrueObjectTag : FalseObjectTag); -} - -void SerializedScriptValueWriter::writeRawStringBytes( - v8::Local<v8::String>& string) { - int rawLength = string->Length(); - string->WriteOneByte(byteAt(m_position), 0, rawLength, - v8StringWriteOptions()); - m_position += rawLength; -} - -void SerializedScriptValueWriter::writeUtf8String( - v8::Local<v8::String>& string) { - int utf8Length = string->Utf8Length(); - char* buffer = reinterpret_cast<char*>(byteAt(m_position)); - string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions()); - m_position += utf8Length; -} - -void SerializedScriptValueWriter::writeOneByteString( - v8::Local<v8::String>& string) { - int stringLength = string->Length(); - int utf8Length = string->Utf8Length(); - ASSERT(stringLength >= 0 && utf8Length >= 0); - - append(StringTag); - doWriteUint32(static_cast<uint32_t>(utf8Length)); - ensureSpace(utf8Length); - - // ASCII fast path. - if (stringLength == utf8Length) { - writeRawStringBytes(string); - } else { - writeUtf8String(string); - } -} - -void SerializedScriptValueWriter::writeUCharString( - v8::Local<v8::String>& string) { - int length = string->Length(); - ASSERT(length >= 0); - - int size = length * sizeof(UChar); - int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size)); - if ((m_position + 1 + bytes) & 1) - append(PaddingTag); - - append(StringUCharTag); - doWriteUint32(static_cast<uint32_t>(size)); - ensureSpace(size); - - ASSERT(!(m_position & 1)); - uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position)); - string->Write(buffer, 0, length, v8StringWriteOptions()); - m_position += size; -} - -void SerializedScriptValueWriter::writeStringObject(const char* data, - int length) { - ASSERT(length >= 0); - append(StringObjectTag); - doWriteString(data, length); -} - -void SerializedScriptValueWriter::writeWebCoreString(const String& string) { - // Uses UTF8 encoding so we can read it back as either V8 or - // WebCore string. - append(StringTag); - doWriteWebCoreString(string); -} - -void SerializedScriptValueWriter::writeVersion() { - append(VersionTag); - doWriteUint32(SerializedScriptValue::wireFormatVersion); -} - -void SerializedScriptValueWriter::writeInt32(int32_t value) { - append(Int32Tag); - doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value))); -} - -void SerializedScriptValueWriter::writeUint32(uint32_t value) { - append(Uint32Tag); - doWriteUint32(value); -} - -void SerializedScriptValueWriter::writeDate(double numberValue) { - append(DateTag); - doWriteNumber(numberValue); -} - -void SerializedScriptValueWriter::writeNumber(double number) { - append(NumberTag); - doWriteNumber(number); -} - -void SerializedScriptValueWriter::writeNumberObject(double number) { - append(NumberObjectTag); - doWriteNumber(number); -} - -void SerializedScriptValueWriter::writeBlob(const String& uuid, - const String& type, - unsigned long long size) { - append(BlobTag); - doWriteWebCoreString(uuid); - doWriteWebCoreString(type); - doWriteUint64(size); -} - -void SerializedScriptValueWriter::writeBlobIndex(int blobIndex) { - ASSERT(blobIndex >= 0); - append(BlobIndexTag); - doWriteUint32(blobIndex); -} - -void SerializedScriptValueWriter::writeCompositorProxy( - const CompositorProxy& compositorProxy) { - append(CompositorProxyTag); - doWriteUint64(compositorProxy.elementId()); - doWriteUint32(compositorProxy.compositorMutableProperties()); -} - -void SerializedScriptValueWriter::writeFile(const File& file) { - append(FileTag); - doWriteFile(file); -} - -void SerializedScriptValueWriter::writeFileIndex(int blobIndex) { - append(FileIndexTag); - doWriteUint32(blobIndex); -} - -void SerializedScriptValueWriter::writeFileList(const FileList& fileList) { - append(FileListTag); - uint32_t length = fileList.length(); - doWriteUint32(length); - for (unsigned i = 0; i < length; ++i) - doWriteFile(*fileList.item(i)); -} - -void SerializedScriptValueWriter::writeFileListIndex( - const Vector<int>& blobIndices) { - append(FileListIndexTag); - uint32_t length = blobIndices.size(); - doWriteUint32(length); - for (unsigned i = 0; i < length; ++i) - doWriteUint32(blobIndices[i]); -} - -void SerializedScriptValueWriter::writeArrayBuffer( - const DOMArrayBuffer& arrayBuffer) { - append(ArrayBufferTag); - doWriteArrayBuffer(arrayBuffer); -} - -void SerializedScriptValueWriter::writeArrayBufferView( - const DOMArrayBufferView& arrayBufferView) { - append(ArrayBufferViewTag); -#if DCHECK_IS_ON() - ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBase()->data()) + - arrayBufferView.byteOffset() == - static_cast<const uint8_t*>(arrayBufferView.baseAddress())); -#endif - DOMArrayBufferView::ViewType type = arrayBufferView.type(); - - switch (type) { - case DOMArrayBufferView::TypeInt8: - append(ByteArrayTag); - break; - case DOMArrayBufferView::TypeUint8Clamped: - append(UnsignedByteClampedArrayTag); - break; - case DOMArrayBufferView::TypeUint8: - append(UnsignedByteArrayTag); - break; - case DOMArrayBufferView::TypeInt16: - append(ShortArrayTag); - break; - case DOMArrayBufferView::TypeUint16: - append(UnsignedShortArrayTag); - break; - case DOMArrayBufferView::TypeInt32: - append(IntArrayTag); - break; - case DOMArrayBufferView::TypeUint32: - append(UnsignedIntArrayTag); - break; - case DOMArrayBufferView::TypeFloat32: - append(FloatArrayTag); - break; - case DOMArrayBufferView::TypeFloat64: - append(DoubleArrayTag); - break; - case DOMArrayBufferView::TypeDataView: - append(DataViewTag); - break; - default: - ASSERT_NOT_REACHED(); - } - doWriteUint32(arrayBufferView.byteOffset()); - doWriteUint32(arrayBufferView.byteLength()); -} - -// Helper function shared by writeImageData and writeImageBitmap -void SerializedScriptValueWriter::doWriteImageData(uint32_t width, - uint32_t height, - const uint8_t* pixelData, - uint32_t pixelDataLength) { - doWriteUint32(width); - doWriteUint32(height); - doWriteUint32(pixelDataLength); - append(pixelData, pixelDataLength); -} - -void SerializedScriptValueWriter::writeImageData(uint32_t width, - uint32_t height, - const uint8_t* pixelData, - uint32_t pixelDataLength) { - append(ImageDataTag); - doWriteImageData(width, height, pixelData, pixelDataLength); -} - -void SerializedScriptValueWriter::writeImageBitmap(uint32_t width, - uint32_t height, - uint32_t isOriginClean, - uint32_t isPremultiplied, - const uint8_t* pixelData, - uint32_t pixelDataLength) { - append(ImageBitmapTag); - append(isOriginClean); - append(isPremultiplied); - doWriteImageData(width, height, pixelData, pixelDataLength); -} - -void SerializedScriptValueWriter::writeRegExp(v8::Local<v8::String> pattern, - v8::RegExp::Flags flags) { - append(RegExpTag); - v8::String::Utf8Value patternUtf8Value(pattern); - doWriteString(*patternUtf8Value, patternUtf8Value.length()); - doWriteUint32(static_cast<uint32_t>(flags)); -} - -void SerializedScriptValueWriter::writeTransferredMessagePort(uint32_t index) { - append(MessagePortTag); - doWriteUint32(index); -} - -void SerializedScriptValueWriter::writeTransferredArrayBuffer(uint32_t index) { - append(ArrayBufferTransferTag); - doWriteUint32(index); -} - -void SerializedScriptValueWriter::writeTransferredImageBitmap(uint32_t index) { - append(ImageBitmapTransferTag); - doWriteUint32(index); -} - -void SerializedScriptValueWriter::writeTransferredOffscreenCanvas( - uint32_t width, - uint32_t height, - uint32_t canvasId, - uint32_t clientId, - uint32_t sinkId) { - append(OffscreenCanvasTransferTag); - doWriteUint32(width); - doWriteUint32(height); - doWriteUint32(canvasId); - doWriteUint32(clientId); - doWriteUint32(sinkId); -} - -void SerializedScriptValueWriter::writeTransferredSharedArrayBuffer( - uint32_t index) { - ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); - append(SharedArrayBufferTransferTag); - doWriteUint32(index); -} - -void SerializedScriptValueWriter::writeObjectReference(uint32_t reference) { - append(ObjectReferenceTag); - doWriteUint32(reference); -} - -void SerializedScriptValueWriter::writeObject(uint32_t numProperties) { - append(ObjectTag); - doWriteUint32(numProperties); -} - -void SerializedScriptValueWriter::writeSparseArray(uint32_t numProperties, - uint32_t length) { - append(SparseArrayTag); - doWriteUint32(numProperties); - doWriteUint32(length); -} - -void SerializedScriptValueWriter::writeDenseArray(uint32_t numProperties, - uint32_t length) { - append(DenseArrayTag); - doWriteUint32(numProperties); - doWriteUint32(length); -} - -String SerializedScriptValueWriter::takeWireString() { - static_assert(sizeof(BufferValueType) == 2, - "BufferValueType should be 2 bytes"); - fillHole(); - ASSERT((m_position + 1) / sizeof(BufferValueType) <= m_buffer.size()); - return String(m_buffer.data(), (m_position + 1) / sizeof(BufferValueType)); -} - -void SerializedScriptValueWriter::writeReferenceCount( - uint32_t numberOfReferences) { - append(ReferenceCountTag); - doWriteUint32(numberOfReferences); -} - -void SerializedScriptValueWriter::writeGenerateFreshObject() { - append(GenerateFreshObjectTag); -} - -void SerializedScriptValueWriter::writeGenerateFreshSparseArray( - uint32_t length) { - append(GenerateFreshSparseArrayTag); - doWriteUint32(length); -} - -void SerializedScriptValueWriter::writeGenerateFreshDenseArray( - uint32_t length) { - append(GenerateFreshDenseArrayTag); - doWriteUint32(length); -} - -void SerializedScriptValueWriter::writeGenerateFreshMap() { - append(GenerateFreshMapTag); -} - -void SerializedScriptValueWriter::writeGenerateFreshSet() { - append(GenerateFreshSetTag); -} - -void SerializedScriptValueWriter::writeMap(uint32_t length) { - append(MapTag); - doWriteUint32(length); -} - -void SerializedScriptValueWriter::writeSet(uint32_t length) { - append(SetTag); - doWriteUint32(length); -} - -void SerializedScriptValueWriter::doWriteFile(const File& file) { - doWriteWebCoreString(file.hasBackingFile() ? file.path() : ""); - doWriteWebCoreString(file.name()); - doWriteWebCoreString(file.webkitRelativePath()); - doWriteWebCoreString(file.uuid()); - doWriteWebCoreString(file.type()); - - // FIXME don't use 1 byte to encode a flag. - if (file.hasValidSnapshotMetadata()) { - doWriteUint32(static_cast<uint8_t>(1)); - - long long size; - double lastModifiedMS; - file.captureSnapshot(size, lastModifiedMS); - doWriteUint64(static_cast<uint64_t>(size)); - doWriteNumber(lastModifiedMS); - } else { - doWriteUint32(static_cast<uint8_t>(0)); - } - - doWriteUint32(static_cast<uint8_t>( - (file.getUserVisibility() == File::IsUserVisible) ? 1 : 0)); -} - -void SerializedScriptValueWriter::doWriteArrayBuffer( - const DOMArrayBuffer& arrayBuffer) { - uint32_t byteLength = arrayBuffer.byteLength(); - doWriteUint32(byteLength); - append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength); -} - -void SerializedScriptValueWriter::doWriteString(const char* data, int length) { - doWriteUint32(static_cast<uint32_t>(length)); - append(reinterpret_cast<const uint8_t*>(data), length); -} - -void SerializedScriptValueWriter::doWriteWebCoreString(const String& string) { - StringUTF8Adaptor stringUTF8(string); - doWriteString(stringUTF8.data(), stringUTF8.length()); -} - -int SerializedScriptValueWriter::bytesNeededToWireEncode(uint32_t value) { - int bytes = 1; - while (true) { - value >>= SerializedScriptValue::varIntShift; - if (!value) - break; - ++bytes; - } - - return bytes; -} - -void SerializedScriptValueWriter::doWriteUint32(uint32_t value) { - doWriteUintHelper(value); -} - -void SerializedScriptValueWriter::doWriteUint64(uint64_t value) { - doWriteUintHelper(value); -} - -void SerializedScriptValueWriter::doWriteNumber(double number) { - append(reinterpret_cast<uint8_t*>(&number), sizeof(number)); -} - -void SerializedScriptValueWriter::append(SerializationTag tag) { - append(static_cast<uint8_t>(tag)); -} - -void SerializedScriptValueWriter::append(uint8_t b) { - ensureSpace(1); - *byteAt(m_position++) = b; -} - -void SerializedScriptValueWriter::append(const uint8_t* data, int length) { - ensureSpace(length); - memcpy(byteAt(m_position), data, length); - m_position += length; -} - -void SerializedScriptValueWriter::ensureSpace(unsigned extra) { - static_assert(sizeof(BufferValueType) == 2, - "BufferValueType should be 2 bytes"); - m_buffer.resize((m_position + extra + 1) / - sizeof(BufferValueType)); // "+ 1" to round up. -} - -void SerializedScriptValueWriter::fillHole() { - static_assert(sizeof(BufferValueType) == 2, - "BufferValueType should be 2 bytes"); - // If the writer is at odd position in the buffer, then one of - // the bytes in the last UChar is not initialized. - if (m_position % 2) - *byteAt(m_position) = static_cast<uint8_t>(PaddingTag); -} - -uint8_t* SerializedScriptValueWriter::byteAt(int position) { - return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; -} - -int SerializedScriptValueWriter::v8StringWriteOptions() { - return v8::String::NO_NULL_TERMINATION; -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::AbstractObjectState::serializeProperties( - ScriptValueSerializer& serializer) { - while (m_index < m_propertyNames->Length()) { - v8::Local<v8::Value> propertyName; - if (!m_propertyNames->Get(serializer.context(), m_index) - .ToLocal(&propertyName)) - return serializer.handleError( - Status::JSException, - "Failed to get a property while cloning an object.", this); - - bool hasProperty = false; - if (propertyName->IsString()) { - hasProperty = v8CallBoolean(composite()->HasRealNamedProperty( - serializer.context(), propertyName.As<v8::String>())); - } else if (propertyName->IsUint32()) { - hasProperty = v8CallBoolean(composite()->HasRealIndexedProperty( - serializer.context(), propertyName.As<v8::Uint32>()->Value())); - } - if (StateBase* newState = serializer.checkException(this)) - return newState; - if (!hasProperty) { - ++m_index; - continue; - } - - // |propertyName| is v8::String or v8::Uint32, so its serialization cannot - // be recursive. - serializer.doSerialize(propertyName, nullptr); - - v8::Local<v8::Value> value; - if (!composite()->Get(serializer.context(), propertyName).ToLocal(&value)) - return serializer.handleError( - Status::JSException, - "Failed to get a property while cloning an object.", this); - ++m_index; - ++m_numSerializedProperties; - // If we return early here, it's either because we have pushed a new state - // onto the serialization state stack or because we have encountered an - // error (and in both cases we are unwinding the native stack). - if (StateBase* newState = serializer.doSerialize(value, this)) - return newState; - } - return objectDone(m_numSerializedProperties, serializer); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::ObjectState::advance( - ScriptValueSerializer& serializer) { - if (m_propertyNames.IsEmpty()) { - if (!composite() - ->GetOwnPropertyNames(serializer.context()) - .ToLocal(&m_propertyNames)) - return serializer.checkException(this); - } - return serializeProperties(serializer); -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::ObjectState::objectDone( - unsigned numProperties, - ScriptValueSerializer& serializer) { - return serializer.writeObject(numProperties, this); -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::DenseArrayState::advance( - ScriptValueSerializer& serializer) { - while (m_arrayIndex < m_arrayLength) { - v8::Local<v8::Value> value; - if (!composite() - .As<v8::Array>() - ->Get(serializer.context(), m_arrayIndex) - .ToLocal(&value)) - return serializer.handleError( - Status::JSException, - "Failed to get an element while cloning an array.", this); - m_arrayIndex++; - if (StateBase* newState = serializer.checkException(this)) - return newState; - if (StateBase* newState = serializer.doSerialize(value, this)) - return newState; - } - return serializeProperties(serializer); -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::DenseArrayState::objectDone( - unsigned numProperties, - ScriptValueSerializer& serializer) { - return serializer.writeDenseArray(numProperties, m_arrayLength, this); -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::SparseArrayState::advance( - ScriptValueSerializer& serializer) { - return serializeProperties(serializer); -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::SparseArrayState::objectDone( - unsigned numProperties, - ScriptValueSerializer& serializer) { - return serializer.writeSparseArray( - numProperties, composite().As<v8::Array>()->Length(), this); -} - -template <typename T> -ScriptValueSerializer::StateBase* -ScriptValueSerializer::CollectionState<T>::advance( - ScriptValueSerializer& serializer) { - while (m_index < m_length) { - v8::Local<v8::Value> value; - if (!m_entries->Get(serializer.context(), m_index).ToLocal(&value)) - return serializer.handleError( - Status::JSException, - "Failed to get an element while cloning a collection.", this); - m_index++; - if (StateBase* newState = serializer.checkException(this)) - return newState; - if (StateBase* newState = serializer.doSerialize(value, this)) - return newState; - } - return serializer.writeCollection<T>(m_length, this); -} - -ScriptValueSerializer::ScriptValueSerializer( - SerializedScriptValueWriter& writer, - WebBlobInfoArray* blobInfo, - ScriptState* scriptState) - : m_scriptState(scriptState), - m_writer(writer), - m_tryCatch(scriptState->isolate()), - m_depth(0), - m_status(Status::Success), - m_nextObjectReference(0), - m_blobInfo(blobInfo), - m_blobDataHandles(nullptr) { - DCHECK(!m_tryCatch.HasCaught()); -} - -void ScriptValueSerializer::copyTransferables( - const Transferables& transferables) { - v8::Local<v8::Object> creationContext = m_scriptState->context()->Global(); - - // Also kept in separate ObjectPools, iterate and copy the contents - // of each kind of transferable vector. - - const auto& messagePorts = transferables.messagePorts; - for (size_t i = 0; i < messagePorts.size(); ++i) { - v8::Local<v8::Object> v8MessagePort = - ToV8(messagePorts[i].get(), creationContext, isolate()) - .As<v8::Object>(); - m_transferredMessagePorts.set(v8MessagePort, i); - } - - const auto& arrayBuffers = transferables.arrayBuffers; - for (size_t i = 0; i < arrayBuffers.size(); ++i) { - v8::Local<v8::Object> v8ArrayBuffer = - ToV8(arrayBuffers[i].get(), creationContext, isolate()) - .As<v8::Object>(); - // Coalesce multiple occurences of the same buffer to the first index. - if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) - m_transferredArrayBuffers.set(v8ArrayBuffer, i); - } - - const auto& imageBitmaps = transferables.imageBitmaps; - for (size_t i = 0; i < imageBitmaps.size(); ++i) { - v8::Local<v8::Object> v8ImageBitmap = - ToV8(imageBitmaps[i].get(), creationContext, isolate()) - .As<v8::Object>(); - if (!m_transferredImageBitmaps.contains(v8ImageBitmap)) - m_transferredImageBitmaps.set(v8ImageBitmap, i); - } - - const auto& offscreenCanvases = transferables.offscreenCanvases; - for (size_t i = 0; i < offscreenCanvases.size(); ++i) { - v8::Local<v8::Object> v8OffscreenCanvas = - ToV8(offscreenCanvases[i].get(), creationContext, isolate()) - .As<v8::Object>(); - if (!m_transferredOffscreenCanvas.contains(v8OffscreenCanvas)) - m_transferredOffscreenCanvas.set(v8OffscreenCanvas, i); - } -} - -PassRefPtr<SerializedScriptValue> ScriptValueSerializer::serialize( - v8::Local<v8::Value> value, - Transferables* transferables, - ExceptionState& exceptionState) { - DCHECK(!m_blobDataHandles); - - RefPtr<SerializedScriptValue> serializedValue = - SerializedScriptValue::create(); - - m_blobDataHandles = &serializedValue->blobDataHandles(); - if (transferables) - copyTransferables(*transferables); - - v8::HandleScope scope(isolate()); - writer().writeVersion(); - StateBase* state = doSerialize(value, nullptr); - while (state) - state = state->advance(*this); - - switch (m_status) { - case Status::Success: - transferData(transferables, exceptionState, serializedValue.get()); - break; - case Status::InputError: - case Status::DataCloneError: - exceptionState.throwDOMException(blink::DataCloneError, m_errorMessage); - break; - case Status::JSException: - exceptionState.rethrowV8Exception(m_tryCatch.Exception()); - break; - default: - NOTREACHED(); - } - - return serializedValue.release(); -} - -void ScriptValueSerializer::transferData( - Transferables* transferables, - ExceptionState& exceptionState, - SerializedScriptValue* serializedValue) { - serializedValue->setData(m_writer.takeWireString()); - DCHECK(serializedValue->dataHasOneRef()); - if (!transferables) - return; - - serializedValue->transferImageBitmaps(isolate(), transferables->imageBitmaps, - exceptionState); - if (exceptionState.hadException()) - return; - serializedValue->transferArrayBuffers(isolate(), transferables->arrayBuffers, - exceptionState); - if (exceptionState.hadException()) - return; - serializedValue->transferOffscreenCanvas( - isolate(), transferables->offscreenCanvases, exceptionState); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerialize( - v8::Local<v8::Value> value, - StateBase* next) { - m_writer.writeReferenceCount(m_nextObjectReference); - - if (value.IsEmpty()) - return handleError(Status::InputError, - "The empty property cannot be cloned.", next); - - uint32_t objectReference; - if ((value->IsObject() || value->IsDate() || value->IsRegExp()) && - m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { - // Note that IsObject() also detects wrappers (eg, it will catch the things - // that we grey and write below). - ASSERT(!value->IsString()); - m_writer.writeObjectReference(objectReference); - return nullptr; - } - if (value->IsObject()) - return doSerializeObject(value.As<v8::Object>(), next); - - if (value->IsUndefined()) { - m_writer.writeUndefined(); - } else if (value->IsNull()) { - m_writer.writeNull(); - } else if (value->IsTrue()) { - m_writer.writeTrue(); - } else if (value->IsFalse()) { - m_writer.writeFalse(); - } else if (value->IsInt32()) { - m_writer.writeInt32(value.As<v8::Int32>()->Value()); - } else if (value->IsUint32()) { - m_writer.writeUint32(value.As<v8::Uint32>()->Value()); - } else if (value->IsNumber()) { - m_writer.writeNumber(value.As<v8::Number>()->Value()); - } else if (value->IsString()) { - writeString(value); - } else { - return handleError(Status::DataCloneError, "A value could not be cloned.", - next); - } - return nullptr; -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeObject( - v8::Local<v8::Object> object, - StateBase* next) { - DCHECK(!object.IsEmpty()); - - if (object->IsArrayBufferView()) { - return writeAndGreyArrayBufferView(object, next); - } - if (object->IsArrayBuffer()) { - return writeAndGreyArrayBuffer(object, next); - } - if (object->IsSharedArrayBuffer()) { - uint32_t index; - if (!m_transferredArrayBuffers.tryGet(object, &index)) { - return handleError(Status::DataCloneError, - "A SharedArrayBuffer could not be cloned.", next); - } - return writeTransferredSharedArrayBuffer(object, index, next); - } - - if (object->IsWebAssemblyCompiledModule()) - return writeWasmCompiledModule(object, next); - - // Transferable only objects - if (V8MessagePort::hasInstance(object, isolate())) { - uint32_t index; - if (!m_transferredMessagePorts.tryGet(object, &index)) { - return handleError(Status::DataCloneError, - "A MessagePort could not be cloned.", next); - } - m_writer.writeTransferredMessagePort(index); - return nullptr; - } - if (V8OffscreenCanvas::hasInstance(object, isolate())) { - uint32_t index; - if (!m_transferredOffscreenCanvas.tryGet(object, &index)) { - return handleError(Status::DataCloneError, - "A OffscreenCanvas could not be cloned.", next); - } - return writeTransferredOffscreenCanvas(object, next); - } - if (V8ImageBitmap::hasInstance(object, isolate())) { - return writeAndGreyImageBitmap(object, next); - } - - greyObject(object); - - if (object->IsDate()) { - m_writer.writeDate(object.As<v8::Date>()->ValueOf()); - return nullptr; - } - if (object->IsStringObject()) { - writeStringObject(object); - return nullptr; - } - if (object->IsNumberObject()) { - writeNumberObject(object); - return nullptr; - } - if (object->IsBooleanObject()) { - writeBooleanObject(object); - return nullptr; - } - if (object->IsArray()) { - return startArrayState(object.As<v8::Array>(), next); - } - if (object->IsMap()) { - return startMapState(object.As<v8::Map>(), next); - } - if (object->IsSet()) { - return startSetState(object.As<v8::Set>(), next); - } - - if (V8File::hasInstance(object, isolate())) { - return writeFile(object, next); - } - if (V8Blob::hasInstance(object, isolate())) { - return writeBlob(object, next); - } - if (V8FileList::hasInstance(object, isolate())) { - return writeFileList(object, next); - } - if (V8ImageData::hasInstance(object, isolate())) { - writeImageData(object); - return nullptr; - } - if (object->IsRegExp()) { - writeRegExp(object); - return nullptr; - } - if (V8CompositorProxy::hasInstance(object, isolate())) { - return writeCompositorProxy(object, next); - } - - // Since IsNativeError is expensive, this check should always be the last - // check. - if (isHostObject(object) || object->IsCallable() || object->IsNativeError()) { - return handleError(Status::DataCloneError, "An object could not be cloned.", - next); - } - - return startObjectState(object, next); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeArrayBuffer( - v8::Local<v8::Value> arrayBuffer, - StateBase* next) { - return doSerialize(arrayBuffer, next); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::checkException( - StateBase* state) { - return m_tryCatch.HasCaught() ? handleError(Status::JSException, "", state) - : nullptr; -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::writeObject( - uint32_t numProperties, - StateBase* state) { - m_writer.writeObject(numProperties); - return pop(state); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::writeSparseArray( - uint32_t numProperties, - uint32_t length, - StateBase* state) { - m_writer.writeSparseArray(numProperties, length); - return pop(state); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::writeDenseArray( - uint32_t numProperties, - uint32_t length, - StateBase* state) { - m_writer.writeDenseArray(numProperties, length); - return pop(state); -} - -template <> -ScriptValueSerializer::StateBase* -ScriptValueSerializer::writeCollection<v8::Map>(uint32_t length, - StateBase* state) { - m_writer.writeMap(length); - return pop(state); -} - -template <> -ScriptValueSerializer::StateBase* -ScriptValueSerializer::writeCollection<v8::Set>(uint32_t length, - StateBase* state) { - m_writer.writeSet(length); - return pop(state); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::handleError( - ScriptValueSerializer::Status errorStatus, - const String& message, - StateBase* state) { - DCHECK(errorStatus != Status::Success); - m_status = errorStatus; - m_errorMessage = message; - while (state) { - state = pop(state); - } - return new ErrorState; -} - -bool ScriptValueSerializer::checkComposite(StateBase* top) { - ASSERT(top); - if (m_depth > maxDepth) - return false; - if (!shouldCheckForCycles(m_depth)) - return true; - v8::Local<v8::Value> composite = top->composite(); - for (StateBase* state = top->nextState(); state; state = state->nextState()) { - if (state->composite() == composite) - return false; - } - return true; -} - -void ScriptValueSerializer::writeString(v8::Local<v8::Value> value) { - v8::Local<v8::String> string = value.As<v8::String>(); - if (!string->Length() || string->IsOneByte()) - m_writer.writeOneByteString(string); - else - m_writer.writeUCharString(string); -} - -void ScriptValueSerializer::writeStringObject(v8::Local<v8::Value> value) { - v8::Local<v8::StringObject> stringObject = value.As<v8::StringObject>(); - v8::String::Utf8Value stringValue(stringObject->ValueOf()); - m_writer.writeStringObject(*stringValue, stringValue.length()); -} - -void ScriptValueSerializer::writeNumberObject(v8::Local<v8::Value> value) { - v8::Local<v8::NumberObject> numberObject = value.As<v8::NumberObject>(); - m_writer.writeNumberObject(numberObject->ValueOf()); -} - -void ScriptValueSerializer::writeBooleanObject(v8::Local<v8::Value> value) { - v8::Local<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>(); - m_writer.writeBooleanObject(booleanObject->ValueOf()); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::writeBlob( - v8::Local<v8::Value> value, - StateBase* next) { - Blob* blob = V8Blob::toImpl(value.As<v8::Object>()); - if (!blob) - return nullptr; - if (blob->isClosed()) - return handleError( - Status::DataCloneError, - "A Blob object has been closed, and could therefore not be cloned.", - next); - int blobIndex = -1; - m_blobDataHandles->set(blob->uuid(), blob->blobDataHandle()); - if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex)) - m_writer.writeBlobIndex(blobIndex); - else - m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); - return nullptr; -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::writeCompositorProxy( - v8::Local<v8::Value> value, - StateBase* next) { - CompositorProxy* compositorProxy = - V8CompositorProxy::toImpl(value.As<v8::Object>()); - if (!compositorProxy) - return nullptr; - if (!compositorProxy->connected()) - return handleError(Status::DataCloneError, - "A CompositorProxy object has been disconnected, and " - "could therefore not be cloned.", - next); - m_writer.writeCompositorProxy(*compositorProxy); - return nullptr; -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::writeFile( - v8::Local<v8::Value> value, - StateBase* next) { - File* file = V8File::toImpl(value.As<v8::Object>()); - if (!file) - return nullptr; - if (file->isClosed()) - return handleError( - Status::DataCloneError, - "A File object has been closed, and could therefore not be cloned.", - next); - int blobIndex = -1; - m_blobDataHandles->set(file->uuid(), file->blobDataHandle()); - if (appendFileInfo(file, &blobIndex)) { - ASSERT(blobIndex >= 0); - m_writer.writeFileIndex(blobIndex); - } else { - m_writer.writeFile(*file); - } - return nullptr; -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::writeFileList( - v8::Local<v8::Value> value, - StateBase* next) { - FileList* fileList = V8FileList::toImpl(value.As<v8::Object>()); - if (!fileList) - return nullptr; - unsigned length = fileList->length(); - Vector<int> blobIndices; - for (unsigned i = 0; i < length; ++i) { - int blobIndex = -1; - const File* file = fileList->item(i); - if (file->isClosed()) - return handleError( - Status::DataCloneError, - "A File object has been closed, and could therefore not be cloned.", - next); - m_blobDataHandles->set(file->uuid(), file->blobDataHandle()); - if (appendFileInfo(file, &blobIndex)) { - ASSERT(!i || blobIndex > 0); - ASSERT(blobIndex >= 0); - blobIndices.push_back(blobIndex); - } - } - if (!blobIndices.isEmpty()) - m_writer.writeFileListIndex(blobIndices); - else - m_writer.writeFileList(*fileList); - return nullptr; -} - -void ScriptValueSerializer::writeImageData(v8::Local<v8::Value> value) { - ImageData* imageData = V8ImageData::toImpl(value.As<v8::Object>()); - if (!imageData) - return; - DOMUint8ClampedArray* pixelArray = imageData->data(); - m_writer.writeImageData(imageData->width(), imageData->height(), - pixelArray->data(), pixelArray->length()); -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::writeAndGreyImageBitmap(v8::Local<v8::Object> object, - StateBase* next) { - ImageBitmap* imageBitmap = V8ImageBitmap::toImpl(object); - if (!imageBitmap) - return nullptr; - if (imageBitmap->isNeutered()) - return handleError(Status::DataCloneError, - "An ImageBitmap is detached and could not be cloned.", - next); - - uint32_t index; - if (m_transferredImageBitmaps.tryGet(object, &index)) { - m_writer.writeTransferredImageBitmap(index); - } else { - greyObject(object); - RefPtr<Uint8Array> pixelData = imageBitmap->copyBitmapData( - imageBitmap->isPremultiplied() ? PremultiplyAlpha - : DontPremultiplyAlpha, - N32ColorType); - m_writer.writeImageBitmap( - imageBitmap->width(), imageBitmap->height(), - static_cast<uint32_t>(imageBitmap->originClean()), - static_cast<uint32_t>(imageBitmap->isPremultiplied()), - pixelData->data(), imageBitmap->width() * imageBitmap->height() * 4); - } - return nullptr; -} - -void ScriptValueSerializer::writeRegExp(v8::Local<v8::Value> value) { - v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); - m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::writeAndGreyArrayBufferView(v8::Local<v8::Object> object, - StateBase* next) { - ASSERT(!object.IsEmpty()); - DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); - if (!arrayBufferView) - return nullptr; - if (!arrayBufferView->bufferBase()) - return handleError(Status::DataCloneError, - "An ArrayBuffer could not be cloned.", next); - v8::Local<v8::Value> underlyingBuffer = - ToV8(arrayBufferView->bufferBase(), m_scriptState->context()->Global(), - isolate()); - if (underlyingBuffer.IsEmpty()) - return handleError(Status::DataCloneError, - "An ArrayBuffer could not be cloned.", next); - StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); - if (stateOut) - return stateOut; - m_writer.writeArrayBufferView(*arrayBufferView); - // This should be safe: we serialize something that we know to be a wrapper - // (see the toV8 call above), so the call to doSerializeArrayBuffer should - // neither cause the system stack to overflow nor should it have potential to - // reach this ArrayBufferView again. - // - // We do need to grey the underlying buffer before we grey its view, however; - // ArrayBuffers may be shared, so they need to be given reference IDs, and an - // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer - // (or without an additional tag that would allow us to do two-stage - // construction like we do for Objects and Arrays). - greyObject(object); - return nullptr; -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::writeWasmCompiledModule(v8::Local<v8::Object> object, - StateBase* next) { - CHECK(RuntimeEnabledFeatures::webAssemblySerializationEnabled()); - // TODO (mtrofin): explore mechanism avoiding data copying / buffer resizing. - v8::Local<v8::WasmCompiledModule> wasmModule = - object.As<v8::WasmCompiledModule>(); - v8::Local<v8::String> wireBytes = wasmModule->GetWasmWireBytes(); - DCHECK(wireBytes->IsOneByte()); - - v8::WasmCompiledModule::SerializedModule data = wasmModule->Serialize(); - m_writer.append(WasmModuleTag); - uint32_t wireBytesLength = static_cast<uint32_t>(wireBytes->Length()); - // We place a tag so we may evolve the format in which we store the - // wire bytes. We plan to move them to a blob. - // We want to control how we write the string, though, so we explicitly - // call writeRawStringBytes. - m_writer.append(RawBytesTag); - m_writer.doWriteUint32(wireBytesLength); - m_writer.ensureSpace(wireBytesLength); - m_writer.writeRawStringBytes(wireBytes); - m_writer.doWriteUint32(static_cast<uint32_t>(data.second)); - m_writer.append(data.first.get(), static_cast<int>(data.second)); - return nullptr; -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::writeAndGreyArrayBuffer(v8::Local<v8::Object> object, - StateBase* next) { - DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(object); - if (!arrayBuffer) - return nullptr; - if (arrayBuffer->isNeutered()) - return handleError(Status::DataCloneError, - "An ArrayBuffer is neutered and could not be cloned.", - next); - - uint32_t index; - if (m_transferredArrayBuffers.tryGet(object, &index)) { - m_writer.writeTransferredArrayBuffer(index); - } else { - greyObject(object); - m_writer.writeArrayBuffer(*arrayBuffer); - } - return nullptr; -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::writeTransferredOffscreenCanvas( - v8::Local<v8::Value> value, - StateBase* next) { - OffscreenCanvas* offscreenCanvas = - V8OffscreenCanvas::toImpl(value.As<v8::Object>()); - if (!offscreenCanvas) - return nullptr; - if (offscreenCanvas->isNeutered()) - return handleError( - Status::DataCloneError, - "An OffscreenCanvas is detached and could not be cloned.", next); - if (offscreenCanvas->renderingContext()) - return handleError(Status::DataCloneError, - "An OffscreenCanvas with a context could not be cloned.", - next); - m_writer.writeTransferredOffscreenCanvas( - offscreenCanvas->width(), offscreenCanvas->height(), - offscreenCanvas->placeholderCanvasId(), offscreenCanvas->clientId(), - offscreenCanvas->sinkId()); - return nullptr; -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializer::writeTransferredSharedArrayBuffer( - v8::Local<v8::Value> value, - uint32_t index, - StateBase* next) { - ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); - DOMSharedArrayBuffer* sharedArrayBuffer = - V8SharedArrayBuffer::toImpl(value.As<v8::Object>()); - if (!sharedArrayBuffer) - return 0; - m_writer.writeTransferredSharedArrayBuffer(index); - return nullptr; -} - -bool ScriptValueSerializer::shouldSerializeDensely(uint32_t length, - uint32_t propertyCount) { - // Let K be the cost of serializing all property values that are there - // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t - // key) - // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all - // properties that are not there) - // so densely is better than sparsly whenever 6*propertyCount > length - return 6 * propertyCount >= length; -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::startArrayState( - v8::Local<v8::Array> array, - StateBase* next) { - v8::Local<v8::Array> propertyNames; - if (!array->GetOwnPropertyNames(context()).ToLocal(&propertyNames)) - return checkException(next); - uint32_t length = array->Length(); - - if (shouldSerializeDensely(length, propertyNames->Length())) { - // In serializing a dense array, indexed properties are ignored, so we get - // non indexed own property names here. - if (!array - ->GetPropertyNames(context(), - v8::KeyCollectionMode::kIncludePrototypes, - static_cast<v8::PropertyFilter>( - v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS), - v8::IndexFilter::kSkipIndices) - .ToLocal(&propertyNames)) - return checkException(next); - - m_writer.writeGenerateFreshDenseArray(length); - return push(new DenseArrayState(array, propertyNames, next, isolate())); - } - - m_writer.writeGenerateFreshSparseArray(length); - return push(new SparseArrayState(array, propertyNames, next, isolate())); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::startMapState( - v8::Local<v8::Map> map, - StateBase* next) { - m_writer.writeGenerateFreshMap(); - return push(new MapState(map, next)); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::startSetState( - v8::Local<v8::Set> set, - StateBase* next) { - m_writer.writeGenerateFreshSet(); - return push(new SetState(set, next)); -} - -ScriptValueSerializer::StateBase* ScriptValueSerializer::startObjectState( - v8::Local<v8::Object> object, - StateBase* next) { - m_writer.writeGenerateFreshObject(); - // FIXME: check not a wrapper - return push(new ObjectState(object, next)); -} - -// Marks object as having been visited by the serializer and assigns it a unique -// object reference ID. An object may only be greyed once. -void ScriptValueSerializer::greyObject(const v8::Local<v8::Object>& object) { - ASSERT(!m_objectPool.contains(object)); - uint32_t objectReference = m_nextObjectReference++; - m_objectPool.set(object, objectReference); -} - -bool ScriptValueSerializer::appendBlobInfo(const String& uuid, - const String& type, - unsigned long long size, - int* index) { - if (!m_blobInfo) - return false; - *index = m_blobInfo->size(); - m_blobInfo->push_back(WebBlobInfo(uuid, type, size)); - return true; -} - -bool ScriptValueSerializer::appendFileInfo(const File* file, int* index) { - if (!m_blobInfo) - return false; - - long long size = -1; - double lastModifiedMS = invalidFileTime(); - file->captureSnapshot(size, lastModifiedMS); - *index = m_blobInfo->size(); - // FIXME: transition WebBlobInfo.lastModified to be milliseconds-based also. - double lastModified = lastModifiedMS / msPerSecond; - m_blobInfo->push_back(WebBlobInfo(file->uuid(), file->path(), file->name(), - file->type(), lastModified, size)); - return true; -} - -bool SerializedScriptValueReader::read(v8::Local<v8::Value>* value, - ScriptValueDeserializer& deserializer) { - SerializationTag tag; - if (!readTag(&tag)) - return false; - return readWithTag(tag, value, deserializer); -} - -bool SerializedScriptValueReader::readWithTag( - SerializationTag tag, - v8::Local<v8::Value>* value, - ScriptValueDeserializer& deserializer) { - switch (tag) { - case ReferenceCountTag: { - if (!m_version) - return false; - uint32_t referenceTableSize; - if (!doReadUint32(&referenceTableSize)) - return false; - // If this test fails, then the serializer and deserializer disagree about - // the assignment of object reference IDs. On the deserialization side, - // this means there are too many or too few calls to pushObjectReference. - if (referenceTableSize != deserializer.objectReferenceCount()) - return false; - return true; - } - case InvalidTag: - return false; - case PaddingTag: - return true; - case UndefinedTag: - *value = v8::Undefined(isolate()); - break; - case NullTag: - *value = v8::Null(isolate()); - break; - case TrueTag: - *value = v8Boolean(true, isolate()); - break; - case FalseTag: - *value = v8Boolean(false, isolate()); - break; - case TrueObjectTag: - *value = v8::BooleanObject::New(isolate(), true); - deserializer.pushObjectReference(*value); - break; - case FalseObjectTag: - *value = v8::BooleanObject::New(isolate(), false); - deserializer.pushObjectReference(*value); - break; - case StringTag: - if (!readString(value)) - return false; - break; - case StringUCharTag: - if (!readUCharString(value)) - return false; - break; - case StringObjectTag: - if (!readStringObject(value)) - return false; - deserializer.pushObjectReference(*value); - break; - case Int32Tag: - if (!readInt32(value)) - return false; - break; - case Uint32Tag: - if (!readUint32(value)) - return false; - break; - case DateTag: - if (!readDate(value)) - return false; - deserializer.pushObjectReference(*value); - break; - case NumberTag: - if (!readNumber(value)) - return false; - break; - case NumberObjectTag: - if (!readNumberObject(value)) - return false; - deserializer.pushObjectReference(*value); - break; - case BlobTag: - case BlobIndexTag: - if (!readBlob(value, tag == BlobIndexTag)) - return false; - deserializer.pushObjectReference(*value); - break; - case FileTag: - case FileIndexTag: - if (!readFile(value, tag == FileIndexTag)) - return false; - deserializer.pushObjectReference(*value); - break; - case FileListTag: - case FileListIndexTag: - if (!readFileList(value, tag == FileListIndexTag)) - return false; - deserializer.pushObjectReference(*value); - break; - case CompositorProxyTag: - if (!readCompositorProxy(value)) - return false; - deserializer.pushObjectReference(*value); - break; - - case ImageDataTag: - if (!readImageData(value)) - return false; - deserializer.pushObjectReference(*value); - break; - case ImageBitmapTag: - if (!readImageBitmap(value)) - return false; - deserializer.pushObjectReference(*value); - break; - - case RegExpTag: - if (!readRegExp(value)) - return false; - deserializer.pushObjectReference(*value); - break; - case ObjectTag: { - uint32_t numProperties; - if (!doReadUint32(&numProperties)) - return false; - if (!deserializer.completeObject(numProperties, value)) - return false; - break; - } - case SparseArrayTag: { - uint32_t numProperties; - uint32_t length; - if (!doReadUint32(&numProperties)) - return false; - if (!doReadUint32(&length)) - return false; - if (!deserializer.completeSparseArray(numProperties, length, value)) - return false; - break; - } - case DenseArrayTag: { - uint32_t numProperties; - uint32_t length; - if (!doReadUint32(&numProperties)) - return false; - if (!doReadUint32(&length)) - return false; - if (!deserializer.completeDenseArray(numProperties, length, value)) - return false; - break; - } - case MapTag: { - uint32_t length; - if (!doReadUint32(&length)) - return false; - if (!deserializer.completeMap(length, value)) - return false; - break; - } - case SetTag: { - uint32_t length; - if (!doReadUint32(&length)) - return false; - if (!deserializer.completeSet(length, value)) - return false; - break; - } - case ArrayBufferViewTag: { - if (!m_version) - return false; - if (!readArrayBufferView(value, deserializer)) - return false; - deserializer.pushObjectReference(*value); - break; - } - case WasmModuleTag: { - if (!readWasmCompiledModule(value)) - return false; - deserializer.pushObjectReference(*value); - break; - } - case ArrayBufferTag: { - if (!m_version) - return false; - if (!readArrayBuffer(value)) - return false; - deserializer.pushObjectReference(*value); - break; - } - case GenerateFreshObjectTag: { - if (!m_version) - return false; - if (!deserializer.newObject()) - return false; - return true; - } - case GenerateFreshSparseArrayTag: { - if (!m_version) - return false; - uint32_t length; - if (!doReadUint32(&length)) - return false; - if (!deserializer.newSparseArray(length)) - return false; - return true; - } - case GenerateFreshDenseArrayTag: { - if (!m_version) - return false; - uint32_t length; - if (!doReadUint32(&length)) - return false; - if (!deserializer.newDenseArray(length)) - return false; - return true; - } - case GenerateFreshMapTag: { - if (!m_version) - return false; - if (!deserializer.newMap()) - return false; - return true; - } - case GenerateFreshSetTag: { - if (!m_version) - return false; - if (!deserializer.newSet()) - return false; - return true; - } - case MessagePortTag: { - if (!m_version) - return false; - uint32_t index; - if (!doReadUint32(&index)) - return false; - if (!deserializer.tryGetTransferredMessagePort(index, value)) - return false; - break; - } - case ArrayBufferTransferTag: { - if (!m_version) - return false; - uint32_t index; - if (!doReadUint32(&index)) - return false; - if (!deserializer.tryGetTransferredArrayBuffer(index, value)) - return false; - break; - } - case ImageBitmapTransferTag: { - if (!m_version) - return false; - uint32_t index; - if (!doReadUint32(&index)) - return false; - if (!deserializer.tryGetTransferredImageBitmap(index, value)) - return false; - break; - } - case OffscreenCanvasTransferTag: { - if (!m_version) - return false; - uint32_t width, height, canvasId, clientId, sinkId; - if (!doReadUint32(&width)) - return false; - if (!doReadUint32(&height)) - return false; - if (!doReadUint32(&canvasId)) - return false; - if (!doReadUint32(&clientId)) - return false; - if (!doReadUint32(&sinkId)) - return false; - if (!deserializer.tryGetTransferredOffscreenCanvas( - width, height, canvasId, clientId, sinkId, value)) - return false; - break; - } - case SharedArrayBufferTransferTag: { - if (!m_version) - return false; - uint32_t index; - if (!doReadUint32(&index)) - return false; - if (!deserializer.tryGetTransferredSharedArrayBuffer(index, value)) - return false; - break; - } - case ObjectReferenceTag: { - if (!m_version) - return false; - uint32_t reference; - if (!doReadUint32(&reference)) - return false; - if (!deserializer.tryGetObjectFromObjectReference(reference, value)) - return false; - break; - } - case DOMFileSystemTag: - case CryptoKeyTag: - ASSERT_NOT_REACHED(); - default: - return false; - } - return !value->IsEmpty(); -} - -bool SerializedScriptValueReader::readVersion(uint32_t& version) { - SerializationTag tag; - if (!readTag(&tag)) { - // This is a nullary buffer. We're still version 0. - version = 0; - return true; - } - if (tag != VersionTag) { - // Versions of the format past 0 start with the version tag. - version = 0; - // Put back the tag. - undoReadTag(); - return true; - } - // Version-bearing messages are obligated to finish the version tag. - return doReadUint32(&version); -} - -void SerializedScriptValueReader::setVersion(uint32_t version) { - m_version = version; -} - -bool SerializedScriptValueReader::readTag(SerializationTag* tag) { - if (m_position >= m_length) - return false; - *tag = static_cast<SerializationTag>(m_buffer[m_position++]); - return true; -} - -void SerializedScriptValueReader::undoReadTag() { - if (m_position > 0) - --m_position; -} - -bool SerializedScriptValueReader::readArrayBufferViewSubTag( - ArrayBufferViewSubTag* tag) { - if (m_position >= m_length) - return false; - *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]); - return true; -} - -bool SerializedScriptValueReader::readString(v8::Local<v8::Value>* value) { - uint32_t length; - if (!doReadUint32(&length)) - return false; - if (m_position + length > m_length) - return false; - *value = v8StringFromUtf8( - isolate(), reinterpret_cast<const char*>(m_buffer + m_position), length); - m_position += length; - return true; -} - -bool SerializedScriptValueReader::readUCharString(v8::Local<v8::Value>* value) { - uint32_t length; - if (!doReadUint32(&length) || (length & 1)) - return false; - if (m_position + length > m_length) - return false; - ASSERT(!(m_position & 1)); - if (!v8::String::NewFromTwoByte( - isolate(), reinterpret_cast<const uint16_t*>(m_buffer + m_position), - v8::NewStringType::kNormal, length / sizeof(UChar)) - .ToLocal(value)) - return false; - m_position += length; - return true; -} - -bool SerializedScriptValueReader::readStringObject( - v8::Local<v8::Value>* value) { - v8::Local<v8::Value> stringValue; - if (!readString(&stringValue) || !stringValue->IsString()) - return false; - *value = v8::StringObject::New(stringValue.As<v8::String>()); - return true; -} - -bool SerializedScriptValueReader::readWebCoreString(String* string) { - uint32_t length; - if (!doReadUint32(&length)) - return false; - if (m_position + length > m_length) - return false; - *string = String::fromUTF8( - reinterpret_cast<const char*>(m_buffer + m_position), length); - m_position += length; - return true; -} - -bool SerializedScriptValueReader::readInt32(v8::Local<v8::Value>* value) { - uint32_t rawValue; - if (!doReadUint32(&rawValue)) - return false; - *value = v8::Integer::New(isolate(), - static_cast<int32_t>(ZigZag::decode(rawValue))); - return true; -} - -bool SerializedScriptValueReader::readUint32(v8::Local<v8::Value>* value) { - uint32_t rawValue; - if (!doReadUint32(&rawValue)) - return false; - *value = v8::Integer::NewFromUnsigned(isolate(), rawValue); - return true; -} - -bool SerializedScriptValueReader::readDate(v8::Local<v8::Value>* value) { - double numberValue; - if (!doReadNumber(&numberValue)) - return false; - if (!v8DateOrNaN(isolate(), numberValue).ToLocal(value)) - return false; - return true; -} - -bool SerializedScriptValueReader::readNumber(v8::Local<v8::Value>* value) { - double number; - if (!doReadNumber(&number)) - return false; - *value = v8::Number::New(isolate(), number); - return true; -} - -bool SerializedScriptValueReader::readNumberObject( - v8::Local<v8::Value>* value) { - double number; - if (!doReadNumber(&number)) - return false; - *value = v8::NumberObject::New(isolate(), number); - return true; -} - -// Helper function used by readImageData and readImageBitmap. -bool SerializedScriptValueReader::doReadImageDataProperties( - uint32_t* width, - uint32_t* height, - uint32_t* pixelDataLength) { - if (!doReadUint32(width)) - return false; - if (!doReadUint32(height)) - return false; - if (!doReadUint32(pixelDataLength)) - return false; - if (m_length - m_position < *pixelDataLength) - return false; - return true; -} - -bool SerializedScriptValueReader::readImageData(v8::Local<v8::Value>* value) { - uint32_t width; - uint32_t height; - uint32_t pixelDataLength; - if (!doReadImageDataProperties(&width, &height, &pixelDataLength)) - return false; - ImageData* imageData = ImageData::create(IntSize(width, height)); - DOMUint8ClampedArray* pixelArray = imageData->data(); - ASSERT(pixelArray); - ASSERT(pixelArray->length() >= pixelDataLength); - memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); - m_position += pixelDataLength; - if (!imageData) - return false; - *value = ToV8(imageData, m_scriptState->context()->Global(), isolate()); - return !value->IsEmpty(); -} - -bool SerializedScriptValueReader::readImageBitmap(v8::Local<v8::Value>* value) { - uint32_t isOriginClean; - if (!doReadUint32(&isOriginClean)) - return false; - uint32_t isPremultiplied; - if (!doReadUint32(&isPremultiplied)) - return false; - uint32_t width; - uint32_t height; - uint32_t pixelDataLength; - if (!doReadImageDataProperties(&width, &height, &pixelDataLength)) - return false; - const void* pixelData = m_buffer + m_position; - m_position += pixelDataLength; - ImageBitmap* imageBitmap = ImageBitmap::create( - pixelData, width, height, isPremultiplied, isOriginClean); - if (!imageBitmap) - return false; - *value = ToV8(imageBitmap, m_scriptState->context()->Global(), isolate()); - return !value->IsEmpty(); -} - -bool SerializedScriptValueReader::readCompositorProxy( - v8::Local<v8::Value>* value) { - uint32_t attributes; - uint64_t element; - if (!doReadUint64(&element)) - return false; - if (!doReadUint32(&attributes)) - return false; - - CompositorProxy* compositorProxy = CompositorProxy::create( - m_scriptState->getExecutionContext(), element, attributes); - *value = ToV8(compositorProxy, m_scriptState->context()->Global(), isolate()); - return !value->IsEmpty(); -} - -DOMArrayBuffer* SerializedScriptValueReader::doReadArrayBuffer() { - uint32_t byteLength; - if (!doReadUint32(&byteLength)) - return nullptr; - if (m_position + byteLength > m_length) - return nullptr; - const void* bufferStart = m_buffer + m_position; - m_position += byteLength; - return DOMArrayBuffer::create(bufferStart, byteLength); -} - -bool SerializedScriptValueReader::readWasmCompiledModule( - v8::Local<v8::Value>* value) { - CHECK(RuntimeEnabledFeatures::webAssemblySerializationEnabled()); - // First, read the tag of the wire bytes. - SerializationTag wireBytesFormat = InvalidTag; - if (!readTag(&wireBytesFormat)) - return false; - DCHECK(wireBytesFormat == RawBytesTag); - // Just like when writing, we don't rely on the default string serialization - // mechanics for the wire bytes. We don't even want a string, because - // that would lead to a memory copying API implementation on the V8 side. - uint32_t wireBytesSize = 0; - uint32_t compiledBytesSize = 0; - if (!doReadUint32(&wireBytesSize)) - return false; - if (m_position + wireBytesSize > m_length) - return false; - const uint8_t* wireBytesStart = m_buffer + m_position; - m_position += wireBytesSize; - - if (!doReadUint32(&compiledBytesSize)) - return false; - if (m_position + compiledBytesSize > m_length) - return false; - const uint8_t* compiledBytesStart = m_buffer + m_position; - m_position += compiledBytesSize; - - v8::WasmCompiledModule::CallerOwnedBuffer wireBytes = { - wireBytesStart, static_cast<size_t>(wireBytesSize)}; - - v8::WasmCompiledModule::CallerOwnedBuffer compiledBytes = { - compiledBytesStart, static_cast<size_t>(compiledBytesSize)}; - - v8::MaybeLocal<v8::WasmCompiledModule> retval = - v8::WasmCompiledModule::DeserializeOrCompile(isolate(), compiledBytes, - wireBytes); - - return retval.ToLocal(value); -} - -bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) { - DOMArrayBuffer* arrayBuffer = doReadArrayBuffer(); - if (!arrayBuffer) - return false; - *value = ToV8(arrayBuffer, m_scriptState->context()->Global(), isolate()); - return !value->IsEmpty(); -} - -bool SerializedScriptValueReader::readArrayBufferView( - v8::Local<v8::Value>* value, - ScriptValueDeserializer& deserializer) { - ArrayBufferViewSubTag subTag; - uint32_t byteOffset; - uint32_t byteLength; - DOMArrayBufferBase* arrayBuffer = nullptr; - v8::Local<v8::Value> arrayBufferV8Value; - if (!readArrayBufferViewSubTag(&subTag)) - return false; - if (!doReadUint32(&byteOffset)) - return false; - if (!doReadUint32(&byteLength)) - return false; - if (!deserializer.consumeTopOfStack(&arrayBufferV8Value)) - return false; - if (arrayBufferV8Value.IsEmpty()) - return false; - if (arrayBufferV8Value->IsArrayBuffer()) { - arrayBuffer = V8ArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>()); - if (!arrayBuffer) - return false; - } else if (arrayBufferV8Value->IsSharedArrayBuffer()) { - arrayBuffer = - V8SharedArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>()); - if (!arrayBuffer) - return false; - } else { - ASSERT_NOT_REACHED(); - } - - // Check the offset, length and alignment. - int elementByteSize; - switch (subTag) { - case ByteArrayTag: - elementByteSize = sizeof(DOMInt8Array::ValueType); - break; - case UnsignedByteArrayTag: - elementByteSize = sizeof(DOMUint8Array::ValueType); - break; - case UnsignedByteClampedArrayTag: - elementByteSize = sizeof(DOMUint8ClampedArray::ValueType); - break; - case ShortArrayTag: - elementByteSize = sizeof(DOMInt16Array::ValueType); - break; - case UnsignedShortArrayTag: - elementByteSize = sizeof(DOMUint16Array::ValueType); - break; - case IntArrayTag: - elementByteSize = sizeof(DOMInt32Array::ValueType); - break; - case UnsignedIntArrayTag: - elementByteSize = sizeof(DOMUint32Array::ValueType); - break; - case FloatArrayTag: - elementByteSize = sizeof(DOMFloat32Array::ValueType); - break; - case DoubleArrayTag: - elementByteSize = sizeof(DOMFloat64Array::ValueType); - break; - case DataViewTag: - elementByteSize = sizeof(DOMDataView::ValueType); - break; - default: - return false; - } - const unsigned numElements = byteLength / elementByteSize; - const unsigned remainingElements = - (arrayBuffer->byteLength() - byteOffset) / elementByteSize; - if (byteOffset % elementByteSize || byteOffset > arrayBuffer->byteLength() || - numElements > remainingElements) - return false; - - v8::Local<v8::Object> creationContext = m_scriptState->context()->Global(); - switch (subTag) { - case ByteArrayTag: - *value = ToV8(DOMInt8Array::create(arrayBuffer, byteOffset, numElements), - creationContext, isolate()); - break; - case UnsignedByteArrayTag: - *value = ToV8(DOMUint8Array::create(arrayBuffer, byteOffset, numElements), - creationContext, isolate()); - break; - case UnsignedByteClampedArrayTag: - *value = ToV8( - DOMUint8ClampedArray::create(arrayBuffer, byteOffset, numElements), - creationContext, isolate()); - break; - case ShortArrayTag: - *value = ToV8(DOMInt16Array::create(arrayBuffer, byteOffset, numElements), - creationContext, isolate()); - break; - case UnsignedShortArrayTag: - *value = - ToV8(DOMUint16Array::create(arrayBuffer, byteOffset, numElements), - creationContext, isolate()); - break; - case IntArrayTag: - *value = ToV8(DOMInt32Array::create(arrayBuffer, byteOffset, numElements), - creationContext, isolate()); - break; - case UnsignedIntArrayTag: - *value = - ToV8(DOMUint32Array::create(arrayBuffer, byteOffset, numElements), - creationContext, isolate()); - break; - case FloatArrayTag: - *value = - ToV8(DOMFloat32Array::create(arrayBuffer, byteOffset, numElements), - creationContext, isolate()); - break; - case DoubleArrayTag: - *value = - ToV8(DOMFloat64Array::create(arrayBuffer, byteOffset, numElements), - creationContext, isolate()); - break; - case DataViewTag: - *value = ToV8(DOMDataView::create(arrayBuffer, byteOffset, byteLength), - creationContext, isolate()); - break; - } - return !value->IsEmpty(); -} - -bool SerializedScriptValueReader::readRegExp(v8::Local<v8::Value>* value) { - v8::Local<v8::Value> pattern; - if (!readString(&pattern)) - return false; - uint32_t flags; - if (!doReadUint32(&flags)) - return false; - if (!v8::RegExp::New(getScriptState()->context(), pattern.As<v8::String>(), - static_cast<v8::RegExp::Flags>(flags)) - .ToLocal(value)) - return false; - return true; -} - -bool SerializedScriptValueReader::readBlob(v8::Local<v8::Value>* value, - bool isIndexed) { - if (m_version < 3) - return false; - Blob* blob = nullptr; - if (isIndexed) { - if (m_version < 6) - return false; - ASSERT(m_blobInfo); - uint32_t index; - if (!doReadUint32(&index) || index >= m_blobInfo->size()) - return false; - const WebBlobInfo& info = (*m_blobInfo)[index]; - blob = Blob::create( - getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size())); - } else { - ASSERT(!m_blobInfo); - String uuid; - String type; - uint64_t size; - ASSERT(!m_blobInfo); - if (!readWebCoreString(&uuid)) - return false; - if (!readWebCoreString(&type)) - return false; - if (!doReadUint64(&size)) - return false; - blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size)); - } - *value = ToV8(blob, m_scriptState->context()->Global(), isolate()); - return !value->IsEmpty(); -} - -bool SerializedScriptValueReader::readFile(v8::Local<v8::Value>* value, - bool isIndexed) { - File* file = nullptr; - if (isIndexed) { - if (m_version < 6) - return false; - file = readFileIndexHelper(); - } else { - file = readFileHelper(); - } - if (!file) - return false; - *value = ToV8(file, m_scriptState->context()->Global(), isolate()); - return !value->IsEmpty(); -} - -bool SerializedScriptValueReader::readFileList(v8::Local<v8::Value>* value, - bool isIndexed) { - if (m_version < 3) - return false; - uint32_t length; - if (!doReadUint32(&length)) - return false; - FileList* fileList = FileList::create(); - for (unsigned i = 0; i < length; ++i) { - File* file = nullptr; - if (isIndexed) { - if (m_version < 6) - return false; - file = readFileIndexHelper(); - } else { - file = readFileHelper(); - } - if (!file) - return false; - fileList->append(file); - } - *value = ToV8(fileList, m_scriptState->context()->Global(), isolate()); - return !value->IsEmpty(); -} - -File* SerializedScriptValueReader::readFileHelper() { - if (m_version < 3) - return nullptr; - ASSERT(!m_blobInfo); - String path; - String name; - String relativePath; - String uuid; - String type; - uint32_t hasSnapshot = 0; - uint64_t size = 0; - double lastModifiedMS = 0; - if (!readWebCoreString(&path)) - return nullptr; - if (m_version >= 4 && !readWebCoreString(&name)) - return nullptr; - if (m_version >= 4 && !readWebCoreString(&relativePath)) - return nullptr; - if (!readWebCoreString(&uuid)) - return nullptr; - if (!readWebCoreString(&type)) - return nullptr; - if (m_version >= 4 && !doReadUint32(&hasSnapshot)) - return nullptr; - if (hasSnapshot) { - if (!doReadUint64(&size)) - return nullptr; - if (!doReadNumber(&lastModifiedMS)) - return nullptr; - if (m_version < 8) - lastModifiedMS *= msPerSecond; - } - uint32_t isUserVisible = 1; - if (m_version >= 7 && !doReadUint32(&isUserVisible)) - return nullptr; - const File::UserVisibility userVisibility = - (isUserVisible > 0) ? File::IsUserVisible : File::IsNotUserVisible; - return File::createFromSerialization(path, name, relativePath, userVisibility, - hasSnapshot > 0, size, lastModifiedMS, - getOrCreateBlobDataHandle(uuid, type)); -} - -File* SerializedScriptValueReader::readFileIndexHelper() { - if (m_version < 3) - return nullptr; - ASSERT(m_blobInfo); - uint32_t index; - if (!doReadUint32(&index) || index >= m_blobInfo->size()) - return nullptr; - const WebBlobInfo& info = (*m_blobInfo)[index]; - // FIXME: transition WebBlobInfo.lastModified to be milliseconds-based also. - double lastModifiedMS = info.lastModified() * msPerSecond; - return File::createFromIndexedSerialization( - info.filePath(), info.fileName(), info.size(), lastModifiedMS, - getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size())); -} - -bool SerializedScriptValueReader::doReadUint32(uint32_t* value) { - return doReadUintHelper(value); -} - -bool SerializedScriptValueReader::doReadUint64(uint64_t* value) { - return doReadUintHelper(value); -} - -bool SerializedScriptValueReader::doReadNumber(double* number) { - if (m_position + sizeof(double) > m_length) - return false; - uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number); - for (unsigned i = 0; i < sizeof(double); ++i) - numberAsByteArray[i] = m_buffer[m_position++]; - return true; -} - -PassRefPtr<BlobDataHandle> -SerializedScriptValueReader::getOrCreateBlobDataHandle(const String& uuid, - const String& type, - long long size) { - // The containing ssv may have a BDH for this uuid if this ssv is just being - // passed from main to worker thread (for example). We use those values when - // creating the new blob instead of cons'ing up a new BDH. - // - // FIXME: Maybe we should require that it work that way where the ssv must - // have a BDH for any blobs it comes across during deserialization. Would - // require callers to explicitly populate the collection of BDH's for blobs to - // work, which would encourage lifetimes to be considered when passing ssv's - // around cross process. At present, we get 'lucky' in some cases because the - // blob in the src process happens to still exist at the time the dest process - // is deserializing. - // For example in sharedWorker.postMessage(...). - BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid); - if (it != m_blobDataHandles.end()) { - // make assertions about type and size? - return it->value; - } - return BlobDataHandle::create(uuid, type, size); -} - -v8::Local<v8::Value> ScriptValueDeserializer::deserialize() { - v8::Isolate* isolate = m_reader.getScriptState()->isolate(); - if (!m_reader.readVersion(m_version) || - m_version > SerializedScriptValue::wireFormatVersion) - return v8::Null(isolate); - m_reader.setVersion(m_version); - v8::EscapableHandleScope scope(isolate); - while (!m_reader.isEof()) { - if (!doDeserialize()) - return v8::Null(isolate); - } - if (stackDepth() != 1 || m_openCompositeReferenceStack.size()) - return v8::Null(isolate); - v8::Local<v8::Value> result = scope.Escape(element(0)); - return result; -} - -bool ScriptValueDeserializer::newSparseArray(uint32_t) { - v8::Local<v8::Array> array = - v8::Array::New(m_reader.getScriptState()->isolate(), 0); - openComposite(array); - return true; -} - -bool ScriptValueDeserializer::newDenseArray(uint32_t length) { - v8::Local<v8::Array> array = - v8::Array::New(m_reader.getScriptState()->isolate(), length); - openComposite(array); - return true; -} - -bool ScriptValueDeserializer::newMap() { - v8::Local<v8::Map> map = v8::Map::New(m_reader.getScriptState()->isolate()); - openComposite(map); - return true; -} - -bool ScriptValueDeserializer::newSet() { - v8::Local<v8::Set> set = v8::Set::New(m_reader.getScriptState()->isolate()); - openComposite(set); - return true; -} - -bool ScriptValueDeserializer::consumeTopOfStack(v8::Local<v8::Value>* object) { - if (stackDepth() < 1) - return false; - *object = element(stackDepth() - 1); - pop(1); - return true; -} - -bool ScriptValueDeserializer::newObject() { - v8::Local<v8::Object> object = - v8::Object::New(m_reader.getScriptState()->isolate()); - if (object.IsEmpty()) - return false; - openComposite(object); - return true; -} - -bool ScriptValueDeserializer::completeObject(uint32_t numProperties, - v8::Local<v8::Value>* value) { - v8::Local<v8::Object> object; - if (m_version > 0) { - v8::Local<v8::Value> composite; - if (!closeComposite(&composite)) - return false; - object = composite.As<v8::Object>(); - } else { - object = v8::Object::New(m_reader.getScriptState()->isolate()); - } - if (object.IsEmpty()) - return false; - return initializeObject(object, numProperties, value); -} - -bool ScriptValueDeserializer::completeSparseArray(uint32_t numProperties, - uint32_t length, - v8::Local<v8::Value>* value) { - v8::Local<v8::Array> array; - if (m_version > 0) { - v8::Local<v8::Value> composite; - if (!closeComposite(&composite)) - return false; - array = composite.As<v8::Array>(); - } else { - array = v8::Array::New(m_reader.getScriptState()->isolate()); - } - if (array.IsEmpty()) - return false; - return initializeObject(array, numProperties, value); -} - -bool ScriptValueDeserializer::completeDenseArray(uint32_t numProperties, - uint32_t length, - v8::Local<v8::Value>* value) { - v8::Local<v8::Array> array; - if (m_version > 0) { - v8::Local<v8::Value> composite; - if (!closeComposite(&composite)) - return false; - array = composite.As<v8::Array>(); - } - if (array.IsEmpty()) - return false; - if (!initializeObject(array, numProperties, value)) - return false; - if (length > stackDepth()) - return false; - v8::Local<v8::Context> context = m_reader.getScriptState()->context(); - for (unsigned i = 0, stackPos = stackDepth() - length; i < length; - i++, stackPos++) { - v8::Local<v8::Value> elem = element(stackPos); - if (!elem->IsUndefined()) { - if (!v8CallBoolean(array->CreateDataProperty(context, i, elem))) - return false; - } - } - pop(length); - return true; -} - -bool ScriptValueDeserializer::completeMap(uint32_t length, - v8::Local<v8::Value>* value) { - ASSERT(m_version > 0); - v8::Local<v8::Value> composite; - if (!closeComposite(&composite)) - return false; - v8::Local<v8::Map> map = composite.As<v8::Map>(); - if (map.IsEmpty()) - return false; - v8::Local<v8::Context> context = m_reader.getScriptState()->context(); - ASSERT(length % 2 == 0); - for (unsigned i = stackDepth() - length; i + 1 < stackDepth(); i += 2) { - v8::Local<v8::Value> key = element(i); - v8::Local<v8::Value> val = element(i + 1); - if (map->Set(context, key, val).IsEmpty()) - return false; - } - pop(length); - *value = map; - return true; -} - -bool ScriptValueDeserializer::completeSet(uint32_t length, - v8::Local<v8::Value>* value) { - ASSERT(m_version > 0); - v8::Local<v8::Value> composite; - if (!closeComposite(&composite)) - return false; - v8::Local<v8::Set> set = composite.As<v8::Set>(); - if (set.IsEmpty()) - return false; - v8::Local<v8::Context> context = m_reader.getScriptState()->context(); - for (unsigned i = stackDepth() - length; i < stackDepth(); i++) { - v8::Local<v8::Value> key = element(i); - if (set->Add(context, key).IsEmpty()) - return false; - } - pop(length); - *value = set; - return true; -} - -void ScriptValueDeserializer::pushObjectReference( - const v8::Local<v8::Value>& object) { - m_objectPool.push_back(object); -} - -bool ScriptValueDeserializer::tryGetTransferredMessagePort( - uint32_t index, - v8::Local<v8::Value>* object) { - if (!m_transferredMessagePorts) - return false; - if (index >= m_transferredMessagePorts->size()) - return false; - v8::Local<v8::Object> creationContext = - m_reader.getScriptState()->context()->Global(); - *object = ToV8(m_transferredMessagePorts->at(index).get(), creationContext, - m_reader.getScriptState()->isolate()); - return !object->IsEmpty(); -} - -bool ScriptValueDeserializer::tryGetTransferredArrayBuffer( - uint32_t index, - v8::Local<v8::Value>* object) { - if (!m_arrayBufferContents) - return false; - if (index >= m_arrayBuffers.size()) - return false; - v8::Local<v8::Value> result = m_arrayBuffers.at(index); - if (result.IsEmpty()) { - DOMArrayBuffer* buffer = - DOMArrayBuffer::create(m_arrayBufferContents->at(index)); - v8::Isolate* isolate = m_reader.getScriptState()->isolate(); - v8::Local<v8::Object> creationContext = - m_reader.getScriptState()->context()->Global(); - result = ToV8(buffer, creationContext, isolate); - if (result.IsEmpty()) - return false; - m_arrayBuffers[index] = result; - } - *object = result; - return true; -} - -bool ScriptValueDeserializer::tryGetTransferredImageBitmap( - uint32_t index, - v8::Local<v8::Value>* object) { - if (!m_imageBitmapContents) - return false; - if (index >= m_imageBitmaps.size()) - return false; - v8::Local<v8::Value> result = m_imageBitmaps.at(index); - if (result.IsEmpty()) { - ImageBitmap* bitmap = ImageBitmap::create(m_imageBitmapContents->at(index)); - v8::Isolate* isolate = m_reader.getScriptState()->isolate(); - v8::Local<v8::Object> creationContext = - m_reader.getScriptState()->context()->Global(); - result = ToV8(bitmap, creationContext, isolate); - if (result.IsEmpty()) - return false; - m_imageBitmaps[index] = result; - } - *object = result; - return true; -} - -bool ScriptValueDeserializer::tryGetTransferredSharedArrayBuffer( - uint32_t index, - v8::Local<v8::Value>* object) { - ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); - if (!m_arrayBufferContents) - return false; - if (index >= m_arrayBuffers.size()) - return false; - v8::Local<v8::Value> result = m_arrayBuffers.at(index); - if (result.IsEmpty()) { - DOMSharedArrayBuffer* buffer = - DOMSharedArrayBuffer::create(m_arrayBufferContents->at(index)); - v8::Isolate* isolate = m_reader.getScriptState()->isolate(); - v8::Local<v8::Object> creationContext = - m_reader.getScriptState()->context()->Global(); - result = ToV8(buffer, creationContext, isolate); - if (result.IsEmpty()) - return false; - m_arrayBuffers[index] = result; - } - *object = result; - return true; -} - -bool ScriptValueDeserializer::tryGetTransferredOffscreenCanvas( - uint32_t width, - uint32_t height, - uint32_t canvasId, - uint32_t clientId, - uint32_t sinkId, - v8::Local<v8::Value>* object) { - OffscreenCanvas* offscreenCanvas = OffscreenCanvas::create(width, height); - offscreenCanvas->setPlaceholderCanvasId(canvasId); - offscreenCanvas->setFrameSinkId(clientId, sinkId); - *object = ToV8(offscreenCanvas, m_reader.getScriptState()); - if ((*object).IsEmpty()) - return false; - return true; -} - -bool ScriptValueDeserializer::tryGetObjectFromObjectReference( - uint32_t reference, - v8::Local<v8::Value>* object) { - if (reference >= m_objectPool.size()) - return false; - *object = m_objectPool[reference]; - return object; -} - -uint32_t ScriptValueDeserializer::objectReferenceCount() { - return m_objectPool.size(); -} - -bool ScriptValueDeserializer::initializeObject(v8::Local<v8::Object> object, - uint32_t numProperties, - v8::Local<v8::Value>* value) { - unsigned length = 2 * numProperties; - if (length > stackDepth()) - return false; - v8::Local<v8::Context> context = m_reader.getScriptState()->context(); - for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) { - v8::Local<v8::Value> propertyName = element(i); - v8::Local<v8::Value> propertyValue = element(i + 1); - bool result = false; - if (propertyName->IsString()) - result = v8CallBoolean(object->CreateDataProperty( - context, propertyName.As<v8::String>(), propertyValue)); - else if (propertyName->IsUint32()) - result = v8CallBoolean(object->CreateDataProperty( - context, propertyName.As<v8::Uint32>()->Value(), propertyValue)); - else - ASSERT_NOT_REACHED(); - if (!result) - return false; - } - pop(length); - *value = object; - return true; -} - -bool ScriptValueDeserializer::read(v8::Local<v8::Value>* value) { - return m_reader.read(value, *this); -} - -bool ScriptValueDeserializer::doDeserialize() { - v8::Local<v8::Value> value; - if (!read(&value)) - return false; - if (!value.IsEmpty()) - push(value); - return true; -} - -v8::Local<v8::Value> ScriptValueDeserializer::element(unsigned index) { - SECURITY_DCHECK(index < m_stack.size()); - return m_stack[index]; -} - -void ScriptValueDeserializer::openComposite( - const v8::Local<v8::Value>& object) { - uint32_t newObjectReference = m_objectPool.size(); - m_openCompositeReferenceStack.push_back(newObjectReference); - m_objectPool.push_back(object); -} - -bool ScriptValueDeserializer::closeComposite(v8::Local<v8::Value>* object) { - if (!m_openCompositeReferenceStack.size()) - return false; - uint32_t objectReference = - m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1]; - m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - - 1); - if (objectReference >= m_objectPool.size()) - return false; - *object = m_objectPool[objectReference]; - return true; -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h deleted file mode 100644 index 03ca5c5..0000000 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h +++ /dev/null
@@ -1,675 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ScriptValueSerializer_h -#define ScriptValueSerializer_h - -#include "base/gtest_prod_util.h" -#include "bindings/core/v8/SerializationTag.h" -#include "bindings/core/v8/SerializedScriptValue.h" -#include "bindings/core/v8/V8Binding.h" -#include "core/CoreExport.h" -#include "wtf/HashMap.h" -#include "wtf/Noncopyable.h" -#include "wtf/Vector.h" -#include "wtf/text/WTFString.h" -#include "wtf/typed_arrays/ArrayBufferContents.h" -#include <v8.h> - -namespace blink { - -class CompositorProxy; -class DOMArrayBuffer; -class DOMArrayBufferView; -class File; -class FileList; -class StaticBitmapImage; - -typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray; -typedef Vector<RefPtr<StaticBitmapImage>, 1> ImageBitmapContentsArray; - -// V8ObjectMap is a map from V8 objects to arbitrary values of type T. -// V8 objects (or handles to V8 objects) cannot be used as keys in ordinary -// wtf::HashMaps; this class should be used instead. GCObject must be a subtype -// of v8::Object. -// Suggested usage: -// V8ObjectMap<v8::Object, int> map; -// v8::Local<v8::Object> obj = ...; -// map.set(obj, 42); -template <typename GCObject, typename T> -class V8ObjectMap { - STACK_ALLOCATED(); - - public: - bool contains(const v8::Local<GCObject>& handle) { - return m_map.contains(*handle); - } - - bool tryGet(const v8::Local<GCObject>& handle, T* valueOut) { - typename HandleToT::iterator result = m_map.find(*handle); - if (result != m_map.end()) { - *valueOut = result->value; - return true; - } - return false; - } - - void set(const v8::Local<GCObject>& handle, const T& value) { - m_map.set(*handle, value); - } - - private: - // This implementation uses GetIdentityHash(), which sets a hidden property on - // the object containing a random integer (or returns the one that had been - // previously set). This ensures that the table never needs to be rebuilt - // across garbage collections at the expense of doing additional allocation - // and making more round trips into V8. Note that since GetIdentityHash() is - // defined only on v8::Objects, this V8ObjectMap cannot be used to map - // v8::Strings to T (because the public V8 API considers a v8::String to be a - // v8::Primitive). - - // If V8 exposes a way to get at the address of the object held by a handle, - // then we can produce an alternate implementation that does not need to do - // any V8-side allocation; however, it will need to rehash after every garbage - // collection because a key object may have been moved. - template <typename G> - struct V8HandlePtrHash { - STATIC_ONLY(V8HandlePtrHash); - static v8::Local<G> unsafeHandleFromRawValue(const G* value) { - const v8::Local<G>* handle = - reinterpret_cast<const v8::Local<G>*>(&value); - return *handle; - } - - static unsigned hash(const G* key) { - return static_cast<unsigned>( - unsafeHandleFromRawValue(key)->GetIdentityHash()); - } - static bool equal(const G* a, const G* b) { - return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b); - } - // For HashArg. - static const bool safeToCompareToEmptyOrDeleted = false; - }; - - typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject>> HandleToT; - HandleToT m_map; -}; - -// SerializedScriptValueWriter is responsible for serializing primitive types -// and storing information used to reconstruct composite types. -class CORE_EXPORT SerializedScriptValueWriter { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(SerializedScriptValueWriter); - - public: - typedef UChar BufferValueType; - - SerializedScriptValueWriter() : m_position(0) {} - - protected: - friend class ScriptValueSerializer; - - String takeWireString(); - - // Write functions for primitive types. - void writeUndefined(); - void writeNull(); - void writeTrue(); - void writeFalse(); - void writeBooleanObject(bool value); - void writeOneByteString(v8::Local<v8::String>&); - void writeRawStringBytes(v8::Local<v8::String>&); - void writeUtf8String(v8::Local<v8::String>&); - void writeUCharString(v8::Local<v8::String>&); - void writeStringObject(const char* data, int length); - void writeWebCoreString(const String&); - void writeVersion(); - void writeInt32(int32_t value); - void writeUint32(uint32_t value); - void writeDate(double numberValue); - void writeNumber(double number); - void writeNumberObject(double number); - void writeBlob(const String& uuid, - const String& type, - unsigned long long size); - void writeBlobIndex(int blobIndex); - void writeCompositorProxy(const CompositorProxy&); - void writeFile(const File&); - void writeFileIndex(int blobIndex); - void writeFileList(const FileList&); - void writeFileListIndex(const Vector<int>& blobIndices); - void writeArrayBuffer(const DOMArrayBuffer&); - void writeArrayBufferView(const DOMArrayBufferView&); - void doWriteImageData(uint32_t width, - uint32_t height, - const uint8_t* pixelData, - uint32_t pixelDataLength); - void writeImageData(uint32_t width, - uint32_t height, - const uint8_t* pixelData, - uint32_t pixelDataLength); - void writeImageBitmap(uint32_t width, - uint32_t height, - uint32_t isOriginClean, - uint32_t isPremultiplied, - const uint8_t* pixelData, - uint32_t pixelDataLength); - void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags); - void writeTransferredMessagePort(uint32_t index); - void writeTransferredArrayBuffer(uint32_t index); - void writeTransferredImageBitmap(uint32_t index); - void writeTransferredOffscreenCanvas(uint32_t width, - uint32_t height, - uint32_t canvasId, - uint32_t clientId, - uint32_t sinkId); - void writeTransferredSharedArrayBuffer(uint32_t index); - void writeObjectReference(uint32_t reference); - void writeObject(uint32_t numProperties); - void writeSparseArray(uint32_t numProperties, uint32_t length); - void writeDenseArray(uint32_t numProperties, uint32_t length); - void writeReferenceCount(uint32_t numberOfReferences); - void writeGenerateFreshObject(); - void writeGenerateFreshSparseArray(uint32_t length); - void writeGenerateFreshDenseArray(uint32_t length); - void writeGenerateFreshMap(); - void writeGenerateFreshSet(); - void writeMap(uint32_t length); - void writeSet(uint32_t length); - - void doWriteFile(const File&); - void doWriteArrayBuffer(const DOMArrayBuffer&); - void doWriteString(const char* data, int length); - void doWriteWebCoreString(const String&); - int bytesNeededToWireEncode(uint32_t value); - - template <class T> - void doWriteUintHelper(T value) { - while (true) { - uint8_t b = (value & SerializedScriptValue::varIntMask); - value >>= SerializedScriptValue::varIntShift; - if (!value) { - append(b); - break; - } - append(b | (1 << SerializedScriptValue::varIntShift)); - } - } - - void doWriteUint32(uint32_t value); - void doWriteUint64(uint64_t value); - void doWriteNumber(double number); - void append(SerializationTag); - void append(uint8_t b); - void append(const uint8_t* data, int length); - void ensureSpace(unsigned extra); - void fillHole(); - uint8_t* byteAt(int position); - int v8StringWriteOptions(); - - private: - Vector<BufferValueType> m_buffer; - unsigned m_position; -}; - -class CORE_EXPORT ScriptValueSerializer { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(ScriptValueSerializer); - - protected: - class StateBase; - enum class Status { Success, InputError, DataCloneError, JSException }; - - public: - ScriptValueSerializer(SerializedScriptValueWriter&, - WebBlobInfoArray*, - ScriptState*); - v8::Isolate* isolate() { return m_scriptState->isolate(); } - v8::Local<v8::Context> context() { return m_scriptState->context(); } - - PassRefPtr<SerializedScriptValue> serialize(v8::Local<v8::Value>, - Transferables*, - ExceptionState&); - - protected: - class StateBase { - USING_FAST_MALLOC(StateBase); - WTF_MAKE_NONCOPYABLE(StateBase); - - public: - virtual ~StateBase() {} - - // Link to the next state to form a stack. - StateBase* nextState() { return m_next; } - - // Composite object we're processing in this state. - v8::Local<v8::Value> composite() { return m_composite; } - - // Serializes (a part of) the current composite and returns - // the next state to process or null when this is the final - // state. - virtual StateBase* advance(ScriptValueSerializer&) = 0; - - protected: - StateBase(v8::Local<v8::Value> composite, StateBase* next) - : m_composite(composite), m_next(next) {} - - private: - v8::Local<v8::Value> m_composite; - StateBase* m_next; - }; - - // Dummy state that is used to signal serialization errors. - class ErrorState final : public StateBase { - public: - ErrorState() : StateBase(v8Undefined(), 0) {} - - StateBase* advance(ScriptValueSerializer&) override { - delete this; - return 0; - } - }; - - template <typename T> - class State : public StateBase { - public: - v8::Local<T> composite() { - return v8::Local<T>::Cast(StateBase::composite()); - } - - protected: - State(v8::Local<T> composite, StateBase* next) - : StateBase(composite, next) {} - }; - - class AbstractObjectState : public State<v8::Object> { - public: - AbstractObjectState(v8::Local<v8::Object> object, StateBase* next) - : State<v8::Object>(object, next), - m_index(0), - m_numSerializedProperties(0) {} - - protected: - virtual StateBase* objectDone(unsigned numProperties, - ScriptValueSerializer&) = 0; - - StateBase* serializeProperties(ScriptValueSerializer&); - v8::Local<v8::Array> m_propertyNames; - - private: - unsigned m_index; - unsigned m_numSerializedProperties; - }; - - class ObjectState final : public AbstractObjectState { - public: - ObjectState(v8::Local<v8::Object> object, StateBase* next) - : AbstractObjectState(object, next) {} - - StateBase* advance(ScriptValueSerializer&) override; - - protected: - StateBase* objectDone(unsigned numProperties, - ScriptValueSerializer&) override; - }; - - class DenseArrayState final : public AbstractObjectState { - public: - DenseArrayState(v8::Local<v8::Array> array, - v8::Local<v8::Array> propertyNames, - StateBase* next, - v8::Isolate* isolate) - : AbstractObjectState(array, next), - m_arrayIndex(0), - m_arrayLength(array->Length()) { - m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); - } - - StateBase* advance(ScriptValueSerializer&) override; - - protected: - StateBase* objectDone(unsigned numProperties, - ScriptValueSerializer&) override; - - private: - uint32_t m_arrayIndex; - uint32_t m_arrayLength; - }; - - class SparseArrayState final : public AbstractObjectState { - public: - SparseArrayState(v8::Local<v8::Array> array, - v8::Local<v8::Array> propertyNames, - StateBase* next, - v8::Isolate* isolate) - : AbstractObjectState(array, next) { - m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); - } - - StateBase* advance(ScriptValueSerializer&) override; - - protected: - StateBase* objectDone(unsigned numProperties, - ScriptValueSerializer&) override; - }; - - template <typename T> - class CollectionState : public State<T> { - public: - CollectionState(v8::Local<T> collection, StateBase* next) - : State<T>(collection, next), - m_entries(collection->AsArray()), - m_index(0), - m_length(m_entries->Length()) {} - - StateBase* advance(ScriptValueSerializer&) override; - - private: - v8::Local<v8::Array> m_entries; - uint32_t m_index; - uint32_t m_length; - }; - - typedef CollectionState<v8::Map> MapState; - typedef CollectionState<v8::Set> SetState; - - virtual StateBase* doSerializeObject(v8::Local<v8::Object>, StateBase* next); - - // Marks object as having been visited by the serializer and assigns it a - // unique object reference ID. An object may only be greyed once. - void greyObject(const v8::Local<v8::Object>&); - - StateBase* handleError(Status errorStatus, const String& message, StateBase*); - - SerializedScriptValueWriter& writer() { return m_writer; } - - private: - StateBase* doSerialize(v8::Local<v8::Value>, StateBase* next); - StateBase* doSerializeArrayBuffer(v8::Local<v8::Value> arrayBuffer, - StateBase* next); - void transferData(Transferables*, ExceptionState&, SerializedScriptValue*); - - StateBase* checkException(StateBase*); - StateBase* writeObject(uint32_t numProperties, StateBase*); - StateBase* writeSparseArray(uint32_t numProperties, - uint32_t length, - StateBase*); - StateBase* writeDenseArray(uint32_t numProperties, - uint32_t length, - StateBase*); - - template <typename T> - StateBase* writeCollection(uint32_t length, StateBase*); - - StateBase* push(StateBase* state) { - ASSERT(state); - ++m_depth; - return checkComposite(state) ? state - : handleError(Status::InputError, - "Value being cloned is either " - "cyclic or too deeply nested.", - state); - } - - StateBase* pop(StateBase* state) { - ASSERT(state); - --m_depth; - StateBase* next = state->nextState(); - delete state; - return next; - } - - bool checkComposite(StateBase* top); - void writeString(v8::Local<v8::Value>); - void writeStringObject(v8::Local<v8::Value>); - void writeNumberObject(v8::Local<v8::Value>); - void writeBooleanObject(v8::Local<v8::Value>); - StateBase* writeBlob(v8::Local<v8::Value>, StateBase* next); - StateBase* writeCompositorProxy(v8::Local<v8::Value>, StateBase* next); - StateBase* writeFile(v8::Local<v8::Value>, StateBase* next); - StateBase* writeFileList(v8::Local<v8::Value>, StateBase* next); - void writeImageData(v8::Local<v8::Value>); - StateBase* writeAndGreyImageBitmap(v8::Local<v8::Object>, StateBase* next); - void writeRegExp(v8::Local<v8::Value>); - StateBase* writeAndGreyArrayBufferView(v8::Local<v8::Object>, - StateBase* next); - StateBase* writeWasmCompiledModule(v8::Local<v8::Object>, StateBase* next); - StateBase* writeAndGreyArrayBuffer(v8::Local<v8::Object>, StateBase* next); - StateBase* writeTransferredOffscreenCanvas(v8::Local<v8::Value>, - StateBase* next); - StateBase* writeTransferredSharedArrayBuffer(v8::Local<v8::Value>, - uint32_t index, - StateBase* next); - static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount); - - StateBase* startArrayState(v8::Local<v8::Array>, StateBase* next); - StateBase* startObjectState(v8::Local<v8::Object>, StateBase* next); - StateBase* startMapState(v8::Local<v8::Map>, StateBase* next); - StateBase* startSetState(v8::Local<v8::Set>, StateBase* next); - - bool appendBlobInfo(const String& uuid, - const String& type, - unsigned long long size, - int* index); - bool appendFileInfo(const File*, int* index); - - void copyTransferables(const Transferables&); - - RefPtr<ScriptState> m_scriptState; - SerializedScriptValueWriter& m_writer; - v8::TryCatch m_tryCatch; - int m_depth; - Status m_status; - String m_errorMessage; - typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; - ObjectPool m_objectPool; - ObjectPool m_transferredMessagePorts; - ObjectPool m_transferredArrayBuffers; - ObjectPool m_transferredImageBitmaps; - ObjectPool m_transferredOffscreenCanvas; - uint32_t m_nextObjectReference; - WebBlobInfoArray* m_blobInfo; - BlobDataHandleMap* m_blobDataHandles; -}; - -class ScriptValueDeserializer; - -// SerializedScriptValueReader is responsible for deserializing primitive types -// and restoring information about saved objects of composite types. -class CORE_EXPORT SerializedScriptValueReader { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(SerializedScriptValueReader); - - public: - SerializedScriptValueReader(const uint8_t* buffer, - int length, - const WebBlobInfoArray* blobInfo, - BlobDataHandleMap& blobDataHandles, - ScriptState* scriptState) - : m_scriptState(scriptState), - m_buffer(buffer), - m_length(length), - m_position(0), - m_version(0), - m_blobInfo(blobInfo), - m_blobDataHandles(blobDataHandles) { - ASSERT(!(reinterpret_cast<size_t>(buffer) & 1)); - ASSERT(length >= 0); - } - - bool isEof() const { return m_position >= m_length; } - - ScriptState* getScriptState() const { return m_scriptState.get(); } - - virtual bool read(v8::Local<v8::Value>*, ScriptValueDeserializer&); - bool readVersion(uint32_t& version); - void setVersion(uint32_t); - - protected: - v8::Isolate* isolate() const { return m_scriptState->isolate(); } - v8::Local<v8::Context> context() const { return m_scriptState->context(); } - unsigned length() const { return m_length; } - unsigned position() const { return m_position; } - - const uint8_t* allocate(uint32_t size) { - const uint8_t* allocated = m_buffer + m_position; - m_position += size; - return allocated; - } - - bool readWithTag(SerializationTag, - v8::Local<v8::Value>*, - ScriptValueDeserializer&); - - bool readTag(SerializationTag*); - bool readWebCoreString(String*); - bool readUint32(v8::Local<v8::Value>*); - - bool doReadUint32(uint32_t* value); - - private: - void undoReadTag(); - bool readArrayBufferViewSubTag(ArrayBufferViewSubTag*); - bool readString(v8::Local<v8::Value>*); - bool readUCharString(v8::Local<v8::Value>*); - bool readStringObject(v8::Local<v8::Value>*); - bool readInt32(v8::Local<v8::Value>*); - bool readDate(v8::Local<v8::Value>*); - bool readNumber(v8::Local<v8::Value>*); - bool readNumberObject(v8::Local<v8::Value>*); - bool doReadImageDataProperties(uint32_t* width, - uint32_t* height, - uint32_t* pixelDataLength); - bool readImageData(v8::Local<v8::Value>*); - bool readImageBitmap(v8::Local<v8::Value>*); - bool readCompositorProxy(v8::Local<v8::Value>*); - DOMArrayBuffer* doReadArrayBuffer(); - bool readArrayBuffer(v8::Local<v8::Value>*); - bool readArrayBufferView(v8::Local<v8::Value>*, ScriptValueDeserializer&); - bool readWasmCompiledModule(v8::Local<v8::Value>*); - bool readRegExp(v8::Local<v8::Value>*); - bool readBlob(v8::Local<v8::Value>*, bool isIndexed); - bool readFile(v8::Local<v8::Value>*, bool isIndexed); - bool readFileList(v8::Local<v8::Value>*, bool isIndexed); - File* readFileHelper(); - File* readFileIndexHelper(); - - template <class T> - bool doReadUintHelper(T* value) { - *value = 0; - uint8_t currentByte; - int shift = 0; - do { - if (m_position >= m_length) - return false; - currentByte = m_buffer[m_position++]; - *value |= (static_cast<T>(currentByte & SerializedScriptValue::varIntMask) - << shift); - shift += SerializedScriptValue::varIntShift; - } while (currentByte & (1 << SerializedScriptValue::varIntShift)); - return true; - } - - bool doReadUint64(uint64_t* value); - bool doReadNumber(double* number); - PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, - const String& type, - long long size = -1); - - RefPtr<ScriptState> m_scriptState; - const uint8_t* m_buffer; - const unsigned m_length; - unsigned m_position; - uint32_t m_version; - const WebBlobInfoArray* m_blobInfo; - const BlobDataHandleMap& m_blobDataHandles; - - FRIEND_TEST_ALL_PREFIXES(ScriptValueSerializerTest, Uint64Decode); -}; - -class CORE_EXPORT ScriptValueDeserializer { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(ScriptValueDeserializer); - - public: - ScriptValueDeserializer(SerializedScriptValueReader& reader, - MessagePortArray* messagePorts, - ArrayBufferContentsArray* arrayBufferContents, - ImageBitmapContentsArray* imageBitmapContents) - : m_reader(reader), - m_transferredMessagePorts(messagePorts), - m_arrayBufferContents(arrayBufferContents), - m_imageBitmapContents(imageBitmapContents), - m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0), - m_imageBitmaps(imageBitmapContents ? imageBitmapContents->size() : 0), - m_version(0) {} - - v8::Local<v8::Value> deserialize(); - bool newSparseArray(uint32_t); - bool newDenseArray(uint32_t length); - bool newMap(); - bool newSet(); - bool consumeTopOfStack(v8::Local<v8::Value>*); - bool newObject(); - bool completeObject(uint32_t numProperties, v8::Local<v8::Value>*); - bool completeSparseArray(uint32_t numProperties, - uint32_t length, - v8::Local<v8::Value>*); - bool completeDenseArray(uint32_t numProperties, - uint32_t length, - v8::Local<v8::Value>*); - bool completeMap(uint32_t length, v8::Local<v8::Value>*); - bool completeSet(uint32_t length, v8::Local<v8::Value>*); - void pushObjectReference(const v8::Local<v8::Value>&); - bool tryGetTransferredMessagePort(uint32_t index, v8::Local<v8::Value>*); - bool tryGetTransferredArrayBuffer(uint32_t index, v8::Local<v8::Value>*); - bool tryGetTransferredImageBitmap(uint32_t index, v8::Local<v8::Value>*); - bool tryGetTransferredOffscreenCanvas(uint32_t width, - uint32_t height, - uint32_t canvasId, - uint32_t clientId, - uint32_t sinkId, - v8::Local<v8::Value>*); - bool tryGetTransferredSharedArrayBuffer(uint32_t index, - v8::Local<v8::Value>*); - bool tryGetObjectFromObjectReference(uint32_t reference, - v8::Local<v8::Value>*); - uint32_t objectReferenceCount(); - - protected: - SerializedScriptValueReader& reader() { return m_reader; } - virtual bool read(v8::Local<v8::Value>*); - - private: - bool initializeObject(v8::Local<v8::Object>, - uint32_t numProperties, - v8::Local<v8::Value>*); - bool doDeserialize(); - void push(v8::Local<v8::Value> value) { m_stack.push_back(value); }; - void pop(unsigned length) { - ASSERT(length <= m_stack.size()); - m_stack.shrink(m_stack.size() - length); - } - unsigned stackDepth() const { return m_stack.size(); } - - v8::Local<v8::Value> element(unsigned index); - void openComposite(const v8::Local<v8::Value>&); - bool closeComposite(v8::Local<v8::Value>*); - - SerializedScriptValueReader& m_reader; - Vector<v8::Local<v8::Value>> m_stack; - Vector<v8::Local<v8::Value>> m_objectPool; - Vector<uint32_t> m_openCompositeReferenceStack; - MessagePortArray* m_transferredMessagePorts; - ArrayBufferContentsArray* m_arrayBufferContents; - ImageBitmapContentsArray* m_imageBitmapContents; - Vector<v8::Local<v8::Value>> m_arrayBuffers; - Vector<v8::Local<v8::Value>> m_imageBitmaps; - uint32_t m_version; -}; - -} // namespace blink - -#endif // ScriptValueSerializer_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializerTest.cpp deleted file mode 100644 index 5c177dc7..0000000 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializerTest.cpp +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "bindings/core/v8/ScriptValueSerializer.h" - -#include "bindings/core/v8/ScriptController.h" -#include "core/layout/LayoutTestHelper.h" -#include "wtf/Alignment.h" - -namespace blink { - -class ScriptValueSerializerTest : public RenderingTest { - public: - FrameSettingOverrideFunction settingOverrider() const override { - return &overrideSettings; - } - - private: - static void overrideSettings(Settings& settings) { - settings.setScriptEnabled(true); - } -}; - -TEST_F(ScriptValueSerializerTest, Uint64Decode) { - // Even large 64-bit integers should decode properly. - const uint64_t expected = 0x123456789abcdef0; - WTF_ALIGNED(const uint8_t, buffer[], sizeof(UChar)) = { - 0xf0, 0xbd, 0xf3, 0xd5, 0x89, 0xcf, 0x95, 0x9a, 0x92, 0x00}; - BlobDataHandleMap blobDataHandleMap; - SerializedScriptValueReader reader( - buffer, sizeof(buffer), nullptr, blobDataHandleMap, - ScriptState::forMainWorld(document().frame())); - uint64_t actual; - ASSERT_TRUE(reader.doReadUint64(&actual)); - EXPECT_EQ(expected, actual); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp index 986d3f3c..b247d2c 100644 --- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
@@ -34,7 +34,6 @@ #include "bindings/core/v8/DOMWrapperWorld.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/ScriptState.h" -#include "bindings/core/v8/ScriptValueSerializer.h" #include "bindings/core/v8/SerializedScriptValueFactory.h" #include "bindings/core/v8/Transferables.h" #include "bindings/core/v8/V8ArrayBuffer.h" @@ -205,7 +204,7 @@ } } -std::unique_ptr<ImageBitmapContentsArray> +std::unique_ptr<SerializedScriptValue::ImageBitmapContentsArray> SerializedScriptValue::transferImageBitmapContents( v8::Isolate* isolate, const ImageBitmapArray& imageBitmaps, @@ -391,7 +390,7 @@ return true; } -std::unique_ptr<ArrayBufferContentsArray> +std::unique_ptr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBufferContents( v8::Isolate* isolate, const ArrayBufferArray& arrayBuffers,
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp index 9bc601d..84b662a5 100644 --- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp
@@ -4,17 +4,9 @@ #include "bindings/core/v8/SerializedScriptValueFactory.h" -#include "bindings/core/v8/ExceptionState.h" -#include "bindings/core/v8/ScriptValueSerializer.h" -#include "bindings/core/v8/Transferables.h" #include "bindings/core/v8/serialization/V8ScriptValueDeserializer.h" #include "bindings/core/v8/serialization/V8ScriptValueSerializer.h" -#include "core/dom/DOMArrayBuffer.h" -#include "core/dom/MessagePort.h" -#include "core/frame/ImageBitmap.h" #include "platform/instrumentation/tracing/TraceEvent.h" -#include "wtf/ByteOrder.h" -#include "wtf/text/StringBuffer.h" namespace blink { @@ -27,14 +19,8 @@ WebBlobInfoArray* blobInfo, ExceptionState& exceptionState) { TRACE_EVENT0("blink", "SerializedScriptValueFactory::create"); - if (RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) { - V8ScriptValueSerializer serializer(ScriptState::current(isolate)); - serializer.setBlobInfoArray(blobInfo); - return serializer.serialize(value, transferables, exceptionState); - } - SerializedScriptValueWriter writer; - ScriptValueSerializer serializer(writer, blobInfo, - ScriptState::current(isolate)); + V8ScriptValueSerializer serializer(ScriptState::current(isolate)); + serializer.setBlobInfoArray(blobInfo); return serializer.serialize(value, transferables, exceptionState); } @@ -44,35 +30,9 @@ MessagePortArray* messagePorts, const WebBlobInfoArray* blobInfo) { TRACE_EVENT0("blink", "SerializedScriptValueFactory::deserialize"); - if (RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) { - V8ScriptValueDeserializer deserializer(ScriptState::current(isolate), - value); - deserializer.setTransferredMessagePorts(messagePorts); - deserializer.setBlobInfoArray(blobInfo); - return deserializer.deserialize(); - } - // deserialize() can run arbitrary script (e.g., setters), which could result - // in |this| being destroyed. Holding a RefPtr ensures we are alive (along - // with our internal data) throughout the operation. - RefPtr<SerializedScriptValue> protect(value); - if (!value->dataLengthInBytes()) - return v8::Null(isolate); - static_assert(sizeof(SerializedScriptValueWriter::BufferValueType) == 2, - "BufferValueType should be 2 bytes"); - // FIXME: SerializedScriptValue shouldn't use String for its underlying - // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The - // information stored in m_data isn't even encoded in UTF-16. Instead, - // unicode characters are encoded as UTF-8 with two code units per UChar. - SerializedScriptValueReader reader(value->data(), value->dataLengthInBytes(), - blobInfo, value->blobDataHandles(), - ScriptState::current(isolate)); - ScriptValueDeserializer deserializer(reader, messagePorts, - value->getArrayBufferContentsArray(), - value->getImageBitmapContentsArray()); - - // deserialize() can run arbitrary script (e.g., setters), which could result - // in |this| being destroyed. Holding a RefPtr ensures we are alive (along - // with our internal data) throughout the operation. + V8ScriptValueDeserializer deserializer(ScriptState::current(isolate), value); + deserializer.setTransferredMessagePorts(messagePorts); + deserializer.setBlobInfoArray(blobInfo); return deserializer.deserialize(); }
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h index 183939e..b597799 100644 --- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h +++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h
@@ -5,7 +5,6 @@ #ifndef SerializedScriptValueFactory_h #define SerializedScriptValueFactory_h -#include "bindings/core/v8/ScriptValueSerializer.h" #include "bindings/core/v8/SerializedScriptValue.h" #include "core/CoreExport.h" #include "wtf/Allocator.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8EventListenerInfo.h b/third_party/WebKit/Source/bindings/core/v8/V8EventListenerInfo.h index c39b7c6..4b20e36 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8EventListenerInfo.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8EventListenerInfo.h
@@ -19,13 +19,15 @@ bool passive, bool once, v8::Local<v8::Object> handler, - v8::MaybeLocal<v8::Function> removeFunction) + v8::MaybeLocal<v8::Function> removeFunction, + int backendNodeId) : eventType(eventType), useCapture(useCapture), passive(passive), once(once), handler(handler), - removeFunction(removeFunction) {} + removeFunction(removeFunction), + backendNodeId(backendNodeId) {} AtomicString eventType; bool useCapture; @@ -33,6 +35,7 @@ bool once; v8::Local<v8::Object> handler; v8::MaybeLocal<v8::Function> removeFunction; + int backendNodeId; }; using V8EventListenerInfoList = Vector<V8EventListenerInfo>;
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp index a794acb..9e61550 100644 --- a/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
@@ -9,7 +9,6 @@ #include "core/dom/MessagePort.h" #include "core/frame/Settings.h" #include "core/testing/DummyPageHolder.h" -#include "platform/RuntimeEnabledFeatures.h" #include "platform/testing/BlinkFuzzerTestSupport.h" #include "public/platform/WebBlobInfo.h" #include "public/platform/WebMessagePortChannel.h" @@ -51,7 +50,6 @@ const char kExposeGC[] = "--expose_gc"; v8::V8::SetFlagsFromString(kExposeGC, sizeof(kExposeGC)); InitializeBlinkFuzzTest(argc, argv); - RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(true); pageHolder = DummyPageHolder::create().release(); pageHolder->frame().settings()->setScriptEnabled(true); blobInfoArray = new WebBlobInfoArray();
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp index 7df19a1..68a6afc8 100644 --- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp
@@ -32,7 +32,6 @@ m_serializedScriptValue->data(), m_serializedScriptValue->dataLengthInBytes(), this) { - DCHECK(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()); m_deserializer.SetSupportsLegacyWireFormat(true); }
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp index d4cfa6b6..377090f 100644 --- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
@@ -30,7 +30,6 @@ : m_scriptState(std::move(scriptState)), m_serializedScriptValue(SerializedScriptValue::create()), m_serializer(m_scriptState->isolate(), this) { - DCHECK(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()); } RefPtr<SerializedScriptValue> V8ScriptValueSerializer::serialize(
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp index 7e3a5d0..c9414d97 100644 --- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
@@ -44,20 +44,6 @@ namespace blink { namespace { -class ScopedEnableV8BasedStructuredClone { - public: - ScopedEnableV8BasedStructuredClone() - : m_wasEnabled(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) { - RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(true); - } - ~ScopedEnableV8BasedStructuredClone() { - RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(m_wasEnabled); - } - - private: - bool m_wasEnabled; -}; - RefPtr<SerializedScriptValue> serializedValue(const Vector<uint8_t>& bytes) { // TODO(jbroman): Fix this once SerializedScriptValue can take bytes without // endianness swapping. @@ -133,7 +119,6 @@ TEST(V8ScriptValueSerializerTest, RoundTripJSONLikeValue) { // Ensure that simple JavaScript objects work. // There are more exhaustive tests of JavaScript objects in V8. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; v8::Local<v8::Value> object = eval("({ foo: [1, 2, 3], bar: 'baz' })", scope); DCHECK(object->IsObject()); @@ -149,7 +134,6 @@ // are encountered in V8 (for example, cloning a symbol). It should be an // instance of DOMException, and it should have a proper descriptive // message. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); ExceptionState exceptionState(scope.isolate(), @@ -168,7 +152,6 @@ TEST(V8ScriptValueSerializerTest, RethrowsScriptError) { // Ensure that other exceptions, like those thrown by script, are properly // rethrown. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); ExceptionState exceptionState(scope.isolate(), @@ -187,7 +170,6 @@ TEST(V8ScriptValueSerializerTest, DeserializationErrorReturnsNull) { // If there's a problem during deserialization, it results in null, but no // exception. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); RefPtr<SerializedScriptValue> invalid = @@ -201,7 +183,6 @@ TEST(V8ScriptValueSerializerTest, NeuteringHappensAfterSerialization) { // This object will throw an exception before the [[Transfer]] step. // As a result, the ArrayBuffer will not be transferred. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ExceptionState exceptionState(scope.isolate(), ExceptionState::ExecutionContext, "Window", @@ -222,7 +203,6 @@ TEST(V8ScriptValueSerializerTest, RoundTripImageData) { // ImageData objects should serialize and deserialize correctly. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ImageData* imageData = ImageData::create(2, 1, ASSERT_NO_EXCEPTION); imageData->data()->data()[0] = 200; @@ -241,7 +221,6 @@ // Backward compatibility with existing serialized ImageData objects must be // maintained. Add more cases if the format changes; don't remove tests for // old versions. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); RefPtr<SerializedScriptValue> input = @@ -281,7 +260,6 @@ } TEST(V8ScriptValueSerializerTest, RoundTripMessagePort) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; WebMessagePortChannel* unownedChannel; @@ -301,7 +279,6 @@ } TEST(V8ScriptValueSerializerTest, NeuteredMessagePortThrowsDataCloneError) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ExceptionState exceptionState(scope.isolate(), ExceptionState::ExecutionContext, "Window", @@ -320,7 +297,6 @@ TEST(V8ScriptValueSerializerTest, UntransferredMessagePortThrowsDataCloneError) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ExceptionState exceptionState(scope.isolate(), ExceptionState::ExecutionContext, "Window", @@ -338,7 +314,6 @@ } TEST(V8ScriptValueSerializerTest, OutOfRangeMessagePortIndex) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); RefPtr<SerializedScriptValue> input = @@ -378,7 +353,6 @@ // A more exhaustive set of ImageBitmap cases are covered by LayoutTests. TEST(V8ScriptValueSerializerTest, RoundTripImageBitmap) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; // Make a 10x7 red ImageBitmap. @@ -409,7 +383,6 @@ // Backward compatibility with existing serialized ImageBitmap objects must be // maintained. Add more cases if the format changes; don't remove tests for // old versions. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -445,7 +418,6 @@ } TEST(V8ScriptValueSerializerTest, InvalidImageBitmapDecode) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); { @@ -484,7 +456,6 @@ TEST(V8ScriptValueSerializerTest, TransferImageBitmap) { // More thorough tests exist in LayoutTests/. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(10, 7); @@ -518,7 +489,6 @@ TEST(V8ScriptValueSerializerTest, TransferOffscreenCanvas) { // More exhaustive tests in LayoutTests/. This is a sanity check. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; OffscreenCanvas* canvas = OffscreenCanvas::create(10, 7); canvas->setPlaceholderCanvasId(519); @@ -537,7 +507,6 @@ } TEST(V8ScriptValueSerializerTest, RoundTripBlob) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; const char kHelloWorld[] = "Hello world!"; Blob* blob = @@ -555,7 +524,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeBlob) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue( {0xff, 0x09, 0x3f, 0x00, 0x62, 0x24, 0x64, 0x38, 0x37, 0x35, 0x64, @@ -573,7 +541,6 @@ } TEST(V8ScriptValueSerializerTest, RoundTripBlobIndex) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; const char kHelloWorld[] = "Hello world!"; Blob* blob = @@ -604,7 +571,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeBlobIndex) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue({0xff, 0x09, 0x3f, 0x00, 0x69, 0x00}); @@ -622,7 +588,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeBlobIndexOutOfRange) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue({0xff, 0x09, 0x3f, 0x00, 0x69, 0x01}); @@ -641,7 +606,6 @@ } TEST(V8ScriptValueSerializerTest, RoundTripFileNative) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; File* file = File::create("/native/path"); v8::Local<v8::Value> wrapper = ToV8(file, scope.getScriptState()); @@ -654,7 +618,6 @@ } TEST(V8ScriptValueSerializerTest, RoundTripFileBackedByBlob) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; const double modificationTime = 0.0; RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(); @@ -669,7 +632,6 @@ } TEST(V8ScriptValueSerializerTest, RoundTripFileNativeSnapshot) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; FileMetadata metadata; metadata.platformPath = "/native/snapshot"; @@ -686,7 +648,6 @@ TEST(V8ScriptValueSerializerTest, RoundTripFileNonNativeSnapshot) { // Preserving behavior, filesystem URL is not preserved across cloning. - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; KURL url(ParsedURLString, "filesystem:http://example.com/isolated/hash/non-native-file"); @@ -716,7 +677,6 @@ }; TEST(V8ScriptValueSerializerTest, DecodeFileV3) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; TimeIntervalChecker timeIntervalChecker; RefPtr<SerializedScriptValue> input = serializedValue( @@ -739,7 +699,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileV4) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; TimeIntervalChecker timeIntervalChecker; RefPtr<SerializedScriptValue> input = serializedValue( @@ -765,7 +724,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileV4WithSnapshot) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue( {0xff, 0x04, 0x3f, 0x00, 0x66, 0x04, 'p', 'a', 't', 'h', 0x04, 'n', @@ -792,7 +750,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileV7) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; TimeIntervalChecker timeIntervalChecker; RefPtr<SerializedScriptValue> input = serializedValue( @@ -818,7 +775,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileV8WithSnapshot) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue( {0xff, 0x08, 0x3f, 0x00, 0x66, 0x04, 'p', 'a', 't', 'h', 0x04, 'n', @@ -846,7 +802,6 @@ } TEST(V8ScriptValueSerializerTest, RoundTripFileIndex) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; File* file = File::create("/native/path"); v8::Local<v8::Value> wrapper = ToV8(file, scope.getScriptState()); @@ -871,7 +826,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileIndex) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue({0xff, 0x09, 0x3f, 0x00, 0x65, 0x00}); @@ -890,7 +844,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileIndexOutOfRange) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue({0xff, 0x09, 0x3f, 0x00, 0x65, 0x01}); @@ -912,7 +865,6 @@ // fairly basic. TEST(V8ScriptValueSerializerTest, RoundTripFileList) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; FileList* fileList = FileList::create(); fileList->append(File::create("/native/path")); @@ -927,7 +879,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeEmptyFileList) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue({0xff, 0x09, 0x3f, 0x00, 0x6c, 0x00}); @@ -939,7 +890,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileListWithInvalidLength) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue({0xff, 0x09, 0x3f, 0x00, 0x6c, 0x01}); @@ -949,7 +899,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileListV8WithoutSnapshot) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; TimeIntervalChecker timeIntervalChecker; RefPtr<SerializedScriptValue> input = serializedValue( @@ -977,7 +926,6 @@ } TEST(V8ScriptValueSerializerTest, RoundTripFileListIndex) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; FileList* fileList = FileList::create(); fileList->append(File::create("/native/path")); @@ -1003,7 +951,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeEmptyFileListIndex) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue({0xff, 0x09, 0x3f, 0x00, 0x4c, 0x00}); @@ -1017,7 +964,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileListIndexWithInvalidLength) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue({0xff, 0x09, 0x3f, 0x00, 0x4c, 0x02}); @@ -1029,7 +975,6 @@ } TEST(V8ScriptValueSerializerTest, DecodeFileListIndex) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; RefPtr<SerializedScriptValue> input = serializedValue({0xff, 0x09, 0x3f, 0x00, 0x4c, 0x01, 0x00, 0x00}); @@ -1064,7 +1009,6 @@ TEST(V8ScriptValueSerializerTest, RoundTripCompositorProxy) { ScopedEnableCompositorWorker enableCompositorWorker; - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; HTMLElement* element = scope.document().body(); Vector<String> properties{"transform"}; @@ -1088,7 +1032,6 @@ // TODO(jbroman): Update this if that turns out not to be the case. TEST(V8ScriptValueSerializerTest, DecodeHardcodedNullValue) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; EXPECT_TRUE(V8ScriptValueDeserializer(scope.getScriptState(), SerializedScriptValue::nullValue())
diff --git a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp b/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp deleted file mode 100644 index 2a66441..0000000 --- a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp +++ /dev/null
@@ -1,667 +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 "bindings/modules/v8/ScriptValueSerializerForModules.h" - -#include "bindings/core/v8/SerializationTag.h" -#include "bindings/core/v8/V8Binding.h" -#include "bindings/modules/v8/V8CryptoKey.h" -#include "bindings/modules/v8/V8DOMFileSystem.h" -#include "bindings/modules/v8/V8RTCCertificate.h" -#include "bindings/modules/v8/serialization/WebCryptoSubTags.h" -#include "modules/filesystem/DOMFileSystem.h" -#include "modules/peerconnection/RTCCertificate.h" -#include "public/platform/Platform.h" -#include "public/platform/WebRTCCertificate.h" -#include "public/platform/WebRTCCertificateGenerator.h" -#include "wtf/PtrUtil.h" -#include <memory> - -namespace blink { - -ScriptValueSerializerForModules::ScriptValueSerializerForModules( - SerializedScriptValueWriter& writer, - WebBlobInfoArray* blobInfo, - ScriptState* scriptState) - : ScriptValueSerializer(writer, blobInfo, scriptState) {} - -ScriptValueSerializer::StateBase* -ScriptValueSerializerForModules::writeDOMFileSystem(v8::Local<v8::Value> value, - StateBase* next) { - DOMFileSystem* fs = V8DOMFileSystem::toImpl(value.As<v8::Object>()); - if (!fs) - return 0; - if (!fs->clonable()) - return handleError(Status::DataCloneError, - "A FileSystem object could not be cloned.", next); - - toSerializedScriptValueWriterForModules(writer()).writeDOMFileSystem( - fs->type(), fs->name(), fs->rootURL().getString()); - return 0; -} - -bool ScriptValueSerializerForModules::writeCryptoKey( - v8::Local<v8::Value> value) { - CryptoKey* key = V8CryptoKey::toImpl(value.As<v8::Object>()); - if (!key) - return false; - return toSerializedScriptValueWriterForModules(writer()).writeCryptoKey( - key->key()); -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializerForModules::writeRTCCertificate(v8::Local<v8::Value> value, - StateBase* next) { - RTCCertificate* certificate = - V8RTCCertificate::toImpl(value.As<v8::Object>()); - if (!certificate) - return handleError(Status::DataCloneError, - "An RTCCertificate object could not be cloned.", next); - toSerializedScriptValueWriterForModules(writer()).writeRTCCertificate( - *certificate); - return nullptr; -} - -void SerializedScriptValueWriterForModules::writeDOMFileSystem( - int type, - const String& name, - const String& url) { - append(DOMFileSystemTag); - doWriteUint32(type); - doWriteWebCoreString(name); - doWriteWebCoreString(url); -} - -bool SerializedScriptValueWriterForModules::writeCryptoKey( - const WebCryptoKey& key) { - append(static_cast<uint8_t>(CryptoKeyTag)); - - switch (key.algorithm().paramsType()) { - case WebCryptoKeyAlgorithmParamsTypeAes: - doWriteAesKey(key); - break; - case WebCryptoKeyAlgorithmParamsTypeHmac: - doWriteHmacKey(key); - break; - case WebCryptoKeyAlgorithmParamsTypeRsaHashed: - doWriteRsaHashedKey(key); - break; - case WebCryptoKeyAlgorithmParamsTypeEc: - doWriteEcKey(key); - break; - case WebCryptoKeyAlgorithmParamsTypeNone: - doWriteKeyWithoutParams(key); - break; - } - - doWriteKeyUsages(key.usages(), key.extractable()); - - WebVector<uint8_t> keyData; - if (!Platform::current()->crypto()->serializeKeyForClone(key, keyData)) - return false; - - doWriteUint32(keyData.size()); - append(keyData.data(), keyData.size()); - return true; -} - -void SerializedScriptValueWriterForModules::writeRTCCertificate( - const RTCCertificate& certificate) { - append(RTCCertificateTag); - - WebRTCCertificatePEM pem = certificate.certificateShallowCopy()->toPEM(); - doWriteWebCoreString(pem.privateKey()); - doWriteWebCoreString(pem.certificate()); -} - -void SerializedScriptValueWriterForModules::doWriteHmacKey( - const WebCryptoKey& key) { - ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeHmac); - - append(static_cast<uint8_t>(HmacKeyTag)); - ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8)); - doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8); - doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id()); -} - -void SerializedScriptValueWriterForModules::doWriteAesKey( - const WebCryptoKey& key) { - ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeAes); - - append(static_cast<uint8_t>(AesKeyTag)); - doWriteAlgorithmId(key.algorithm().id()); - // Converting the key length from bits to bytes is lossless and makes - // it fit in 1 byte. - ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8)); - doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8); -} - -void SerializedScriptValueWriterForModules::doWriteRsaHashedKey( - const WebCryptoKey& key) { - ASSERT(key.algorithm().rsaHashedParams()); - append(static_cast<uint8_t>(RsaHashedKeyTag)); - - doWriteAlgorithmId(key.algorithm().id()); - doWriteAsymmetricKeyType(key.type()); - - const WebCryptoRsaHashedKeyAlgorithmParams* params = - key.algorithm().rsaHashedParams(); - doWriteUint32(params->modulusLengthBits()); - doWriteUint32(params->publicExponent().size()); - append(params->publicExponent().data(), params->publicExponent().size()); - doWriteAlgorithmId(params->hash().id()); -} - -void SerializedScriptValueWriterForModules::doWriteEcKey( - const WebCryptoKey& key) { - ASSERT(key.algorithm().ecParams()); - append(static_cast<uint8_t>(EcKeyTag)); - - doWriteAlgorithmId(key.algorithm().id()); - doWriteAsymmetricKeyType(key.type()); - doWriteNamedCurve(key.algorithm().ecParams()->namedCurve()); -} - -void SerializedScriptValueWriterForModules::doWriteKeyWithoutParams( - const WebCryptoKey& key) { - ASSERT(WebCryptoAlgorithm::isKdf(key.algorithm().id())); - append(static_cast<uint8_t>(NoParamsKeyTag)); - - doWriteAlgorithmId(key.algorithm().id()); -} - -void SerializedScriptValueWriterForModules::doWriteAlgorithmId( - WebCryptoAlgorithmId id) { - switch (id) { - case WebCryptoAlgorithmIdAesCbc: - return doWriteUint32(AesCbcTag); - case WebCryptoAlgorithmIdHmac: - return doWriteUint32(HmacTag); - case WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: - return doWriteUint32(RsaSsaPkcs1v1_5Tag); - case WebCryptoAlgorithmIdSha1: - return doWriteUint32(Sha1Tag); - case WebCryptoAlgorithmIdSha256: - return doWriteUint32(Sha256Tag); - case WebCryptoAlgorithmIdSha384: - return doWriteUint32(Sha384Tag); - case WebCryptoAlgorithmIdSha512: - return doWriteUint32(Sha512Tag); - case WebCryptoAlgorithmIdAesGcm: - return doWriteUint32(AesGcmTag); - case WebCryptoAlgorithmIdRsaOaep: - return doWriteUint32(RsaOaepTag); - case WebCryptoAlgorithmIdAesCtr: - return doWriteUint32(AesCtrTag); - case WebCryptoAlgorithmIdAesKw: - return doWriteUint32(AesKwTag); - case WebCryptoAlgorithmIdRsaPss: - return doWriteUint32(RsaPssTag); - case WebCryptoAlgorithmIdEcdsa: - return doWriteUint32(EcdsaTag); - case WebCryptoAlgorithmIdEcdh: - return doWriteUint32(EcdhTag); - case WebCryptoAlgorithmIdHkdf: - return doWriteUint32(HkdfTag); - case WebCryptoAlgorithmIdPbkdf2: - return doWriteUint32(Pbkdf2Tag); - } - ASSERT_NOT_REACHED(); -} - -void SerializedScriptValueWriterForModules::doWriteAsymmetricKeyType( - WebCryptoKeyType keyType) { - switch (keyType) { - case WebCryptoKeyTypePublic: - doWriteUint32(PublicKeyType); - break; - case WebCryptoKeyTypePrivate: - doWriteUint32(PrivateKeyType); - break; - case WebCryptoKeyTypeSecret: - ASSERT_NOT_REACHED(); - } -} - -void SerializedScriptValueWriterForModules::doWriteNamedCurve( - WebCryptoNamedCurve namedCurve) { - switch (namedCurve) { - case WebCryptoNamedCurveP256: - return doWriteUint32(P256Tag); - case WebCryptoNamedCurveP384: - return doWriteUint32(P384Tag); - case WebCryptoNamedCurveP521: - return doWriteUint32(P521Tag); - } - ASSERT_NOT_REACHED(); -} - -void SerializedScriptValueWriterForModules::doWriteKeyUsages( - const WebCryptoKeyUsageMask usages, - bool extractable) { - // Reminder to update this when adding new key usages. - static_assert(EndOfWebCryptoKeyUsage == (1 << 7) + 1, - "update required when adding new key usages"); - - uint32_t value = 0; - - if (extractable) - value |= ExtractableUsage; - - if (usages & WebCryptoKeyUsageEncrypt) - value |= EncryptUsage; - if (usages & WebCryptoKeyUsageDecrypt) - value |= DecryptUsage; - if (usages & WebCryptoKeyUsageSign) - value |= SignUsage; - if (usages & WebCryptoKeyUsageVerify) - value |= VerifyUsage; - if (usages & WebCryptoKeyUsageDeriveKey) - value |= DeriveKeyUsage; - if (usages & WebCryptoKeyUsageWrapKey) - value |= WrapKeyUsage; - if (usages & WebCryptoKeyUsageUnwrapKey) - value |= UnwrapKeyUsage; - if (usages & WebCryptoKeyUsageDeriveBits) - value |= DeriveBitsUsage; - - doWriteUint32(value); -} - -ScriptValueSerializer::StateBase* -ScriptValueSerializerForModules::doSerializeObject( - v8::Local<v8::Object> jsObject, - StateBase* next) { - DCHECK(!jsObject.IsEmpty()); - - if (V8DOMFileSystem::hasInstance(jsObject, isolate())) { - greyObject(jsObject); - return writeDOMFileSystem(jsObject, next); - } - if (V8CryptoKey::hasInstance(jsObject, isolate())) { - greyObject(jsObject); - if (!writeCryptoKey(jsObject)) - return handleError(Status::DataCloneError, "Couldn't serialize key data", - next); - return nullptr; - } - if (V8RTCCertificate::hasInstance(jsObject, isolate())) { - greyObject(jsObject); - return writeRTCCertificate(jsObject, next); - } - - return ScriptValueSerializer::doSerializeObject(jsObject, next); -} - -bool SerializedScriptValueReaderForModules::read( - v8::Local<v8::Value>* value, - ScriptValueDeserializer& deserializer) { - SerializationTag tag; - if (!readTag(&tag)) - return false; - switch (tag) { - case DOMFileSystemTag: - if (!readDOMFileSystem(value)) - return false; - deserializer.pushObjectReference(*value); - break; - case CryptoKeyTag: - if (!readCryptoKey(value)) - return false; - deserializer.pushObjectReference(*value); - break; - case RTCCertificateTag: - if (!readRTCCertificate(value)) - return false; - deserializer.pushObjectReference(*value); - break; - default: - return SerializedScriptValueReader::readWithTag(tag, value, deserializer); - } - return !value->IsEmpty(); -} - -bool SerializedScriptValueReaderForModules::readDOMFileSystem( - v8::Local<v8::Value>* value) { - uint32_t type; - String name; - String url; - if (!doReadUint32(&type)) - return false; - if (!readWebCoreString(&name)) - return false; - if (!readWebCoreString(&url)) - return false; - DOMFileSystem* fs = DOMFileSystem::create( - getScriptState()->getExecutionContext(), name, - static_cast<FileSystemType>(type), KURL(ParsedURLString, url)); - *value = ToV8(fs, getScriptState()->context()->Global(), isolate()); - return !value->IsEmpty(); -} - -bool SerializedScriptValueReaderForModules::readCryptoKey( - v8::Local<v8::Value>* value) { - uint32_t rawKeyType; - if (!doReadUint32(&rawKeyType)) - return false; - - WebCryptoKeyAlgorithm algorithm; - WebCryptoKeyType type = WebCryptoKeyTypeSecret; - - switch (static_cast<CryptoKeySubTag>(rawKeyType)) { - case AesKeyTag: - if (!doReadAesKey(algorithm, type)) - return false; - break; - case HmacKeyTag: - if (!doReadHmacKey(algorithm, type)) - return false; - break; - case RsaHashedKeyTag: - if (!doReadRsaHashedKey(algorithm, type)) - return false; - break; - case EcKeyTag: - if (!doReadEcKey(algorithm, type)) - return false; - break; - case NoParamsKeyTag: - if (!doReadKeyWithoutParams(algorithm, type)) - return false; - break; - default: - return false; - } - - WebCryptoKeyUsageMask usages; - bool extractable; - if (!doReadKeyUsages(usages, extractable)) - return false; - - uint32_t keyDataLength; - if (!doReadUint32(&keyDataLength)) - return false; - - if (position() + keyDataLength > length()) - return false; - - const uint8_t* keyData = allocate(keyDataLength); - WebCryptoKey key = WebCryptoKey::createNull(); - if (!Platform::current()->crypto()->deserializeKeyForClone( - algorithm, type, extractable, usages, keyData, keyDataLength, key)) { - return false; - } - - *value = ToV8(CryptoKey::create(key), getScriptState()->context()->Global(), - isolate()); - return !value->IsEmpty(); -} - -bool SerializedScriptValueReaderForModules::readRTCCertificate( - v8::Local<v8::Value>* value) { - String pemPrivateKey; - if (!readWebCoreString(&pemPrivateKey)) - return false; - String pemCertificate; - if (!readWebCoreString(&pemCertificate)) - return false; - - std::unique_ptr<WebRTCCertificateGenerator> certificateGenerator = - WTF::wrapUnique(Platform::current()->createRTCCertificateGenerator()); - - std::unique_ptr<WebRTCCertificate> certificate( - certificateGenerator->fromPEM(pemPrivateKey, pemCertificate)); - if (!certificate) - return false; - RTCCertificate* jsCertificate = new RTCCertificate(std::move(certificate)); - - *value = - ToV8(jsCertificate, getScriptState()->context()->Global(), isolate()); - return !value->IsEmpty(); -} - -bool SerializedScriptValueReaderForModules::doReadHmacKey( - WebCryptoKeyAlgorithm& algorithm, - WebCryptoKeyType& type) { - uint32_t lengthBytes; - if (!doReadUint32(&lengthBytes)) - return false; - WebCryptoAlgorithmId hash; - if (!doReadAlgorithmId(hash)) - return false; - algorithm = WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8); - type = WebCryptoKeyTypeSecret; - return !algorithm.isNull(); -} - -bool SerializedScriptValueReaderForModules::doReadAesKey( - WebCryptoKeyAlgorithm& algorithm, - WebCryptoKeyType& type) { - WebCryptoAlgorithmId id; - if (!doReadAlgorithmId(id)) - return false; - uint32_t lengthBytes; - if (!doReadUint32(&lengthBytes)) - return false; - algorithm = WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8); - type = WebCryptoKeyTypeSecret; - return !algorithm.isNull(); -} - -bool SerializedScriptValueReaderForModules::doReadRsaHashedKey( - WebCryptoKeyAlgorithm& algorithm, - WebCryptoKeyType& type) { - WebCryptoAlgorithmId id; - if (!doReadAlgorithmId(id)) - return false; - - if (!doReadAsymmetricKeyType(type)) - return false; - - uint32_t modulusLengthBits; - if (!doReadUint32(&modulusLengthBits)) - return false; - - uint32_t publicExponentSize; - if (!doReadUint32(&publicExponentSize)) - return false; - - if (position() + publicExponentSize > length()) - return false; - - const uint8_t* publicExponent = allocate(publicExponentSize); - WebCryptoAlgorithmId hash; - if (!doReadAlgorithmId(hash)) - return false; - algorithm = WebCryptoKeyAlgorithm::createRsaHashed( - id, modulusLengthBits, publicExponent, publicExponentSize, hash); - - return !algorithm.isNull(); -} - -bool SerializedScriptValueReaderForModules::doReadEcKey( - WebCryptoKeyAlgorithm& algorithm, - WebCryptoKeyType& type) { - WebCryptoAlgorithmId id; - if (!doReadAlgorithmId(id)) - return false; - - if (!doReadAsymmetricKeyType(type)) - return false; - - WebCryptoNamedCurve namedCurve; - if (!doReadNamedCurve(namedCurve)) - return false; - - algorithm = WebCryptoKeyAlgorithm::createEc(id, namedCurve); - return !algorithm.isNull(); -} - -bool SerializedScriptValueReaderForModules::doReadKeyWithoutParams( - WebCryptoKeyAlgorithm& algorithm, - WebCryptoKeyType& type) { - WebCryptoAlgorithmId id; - if (!doReadAlgorithmId(id)) - return false; - algorithm = WebCryptoKeyAlgorithm::createWithoutParams(id); - type = WebCryptoKeyTypeSecret; - return !algorithm.isNull(); -} - -bool SerializedScriptValueReaderForModules::doReadAlgorithmId( - WebCryptoAlgorithmId& id) { - uint32_t rawId; - if (!doReadUint32(&rawId)) - return false; - - switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) { - case AesCbcTag: - id = WebCryptoAlgorithmIdAesCbc; - return true; - case HmacTag: - id = WebCryptoAlgorithmIdHmac; - return true; - case RsaSsaPkcs1v1_5Tag: - id = WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; - return true; - case Sha1Tag: - id = WebCryptoAlgorithmIdSha1; - return true; - case Sha256Tag: - id = WebCryptoAlgorithmIdSha256; - return true; - case Sha384Tag: - id = WebCryptoAlgorithmIdSha384; - return true; - case Sha512Tag: - id = WebCryptoAlgorithmIdSha512; - return true; - case AesGcmTag: - id = WebCryptoAlgorithmIdAesGcm; - return true; - case RsaOaepTag: - id = WebCryptoAlgorithmIdRsaOaep; - return true; - case AesCtrTag: - id = WebCryptoAlgorithmIdAesCtr; - return true; - case AesKwTag: - id = WebCryptoAlgorithmIdAesKw; - return true; - case RsaPssTag: - id = WebCryptoAlgorithmIdRsaPss; - return true; - case EcdsaTag: - id = WebCryptoAlgorithmIdEcdsa; - return true; - case EcdhTag: - id = WebCryptoAlgorithmIdEcdh; - return true; - case HkdfTag: - id = WebCryptoAlgorithmIdHkdf; - return true; - case Pbkdf2Tag: - id = WebCryptoAlgorithmIdPbkdf2; - return true; - } - - return false; -} - -bool SerializedScriptValueReaderForModules::doReadAsymmetricKeyType( - WebCryptoKeyType& type) { - uint32_t rawType; - if (!doReadUint32(&rawType)) - return false; - - switch (static_cast<AsymmetricCryptoKeyType>(rawType)) { - case PublicKeyType: - type = WebCryptoKeyTypePublic; - return true; - case PrivateKeyType: - type = WebCryptoKeyTypePrivate; - return true; - } - - return false; -} - -bool SerializedScriptValueReaderForModules::doReadNamedCurve( - WebCryptoNamedCurve& namedCurve) { - uint32_t rawName; - if (!doReadUint32(&rawName)) - return false; - - switch (static_cast<NamedCurveTag>(rawName)) { - case P256Tag: - namedCurve = WebCryptoNamedCurveP256; - return true; - case P384Tag: - namedCurve = WebCryptoNamedCurveP384; - return true; - case P521Tag: - namedCurve = WebCryptoNamedCurveP521; - return true; - } - - return false; -} - -bool SerializedScriptValueReaderForModules::doReadKeyUsages( - WebCryptoKeyUsageMask& usages, - bool& extractable) { - // Reminder to update this when adding new key usages. - static_assert(EndOfWebCryptoKeyUsage == (1 << 7) + 1, - "update required when adding new key usages"); - const uint32_t allPossibleUsages = - ExtractableUsage | EncryptUsage | DecryptUsage | SignUsage | VerifyUsage | - DeriveKeyUsage | WrapKeyUsage | UnwrapKeyUsage | DeriveBitsUsage; - - uint32_t rawUsages; - if (!doReadUint32(&rawUsages)) - return false; - - // Make sure it doesn't contain an unrecognized usage value. - if (rawUsages & ~allPossibleUsages) - return false; - - usages = 0; - - extractable = rawUsages & ExtractableUsage; - - if (rawUsages & EncryptUsage) - usages |= WebCryptoKeyUsageEncrypt; - if (rawUsages & DecryptUsage) - usages |= WebCryptoKeyUsageDecrypt; - if (rawUsages & SignUsage) - usages |= WebCryptoKeyUsageSign; - if (rawUsages & VerifyUsage) - usages |= WebCryptoKeyUsageVerify; - if (rawUsages & DeriveKeyUsage) - usages |= WebCryptoKeyUsageDeriveKey; - if (rawUsages & WrapKeyUsage) - usages |= WebCryptoKeyUsageWrapKey; - if (rawUsages & UnwrapKeyUsage) - usages |= WebCryptoKeyUsageUnwrapKey; - if (rawUsages & DeriveBitsUsage) - usages |= WebCryptoKeyUsageDeriveBits; - - return true; -} - -ScriptValueDeserializerForModules::ScriptValueDeserializerForModules( - SerializedScriptValueReaderForModules& reader, - MessagePortArray* messagePorts, - ArrayBufferContentsArray* arrayBufferContents, - ImageBitmapContentsArray* imageBitmapContents) - : ScriptValueDeserializer(reader, - messagePorts, - arrayBufferContents, - imageBitmapContents) {} - -bool ScriptValueDeserializerForModules::read(v8::Local<v8::Value>* value) { - return toSerializedScriptValueReaderForModules(reader()).read(value, *this); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h b/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h deleted file mode 100644 index 285552e..0000000 --- a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h +++ /dev/null
@@ -1,120 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ScriptValueSerializerForModules_h -#define ScriptValueSerializerForModules_h - -#include "bindings/core/v8/ScriptValueSerializer.h" -#include "modules/peerconnection/RTCCertificate.h" -#include "public/platform/WebCrypto.h" -#include "public/platform/WebCryptoKey.h" -#include "public/platform/WebCryptoKeyAlgorithm.h" -#include <v8.h> - -namespace blink { - -class SerializedScriptValueWriterForModules final - : public SerializedScriptValueWriter { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(SerializedScriptValueWriterForModules); - - public: - SerializedScriptValueWriterForModules() : SerializedScriptValueWriter() {} - - void writeDOMFileSystem(int type, const String& name, const String& url); - bool writeCryptoKey(const WebCryptoKey&); - void writeRTCCertificate(const RTCCertificate&); - - private: - void doWriteHmacKey(const WebCryptoKey&); - void doWriteAesKey(const WebCryptoKey&); - void doWriteRsaHashedKey(const WebCryptoKey&); - void doWriteEcKey(const WebCryptoKey&); - void doWriteKeyWithoutParams(const WebCryptoKey&); - void doWriteAlgorithmId(WebCryptoAlgorithmId); - void doWriteAsymmetricKeyType(WebCryptoKeyType); - void doWriteNamedCurve(WebCryptoNamedCurve); - void doWriteKeyUsages(const WebCryptoKeyUsageMask usages, bool extractable); -}; - -DEFINE_TYPE_CASTS(SerializedScriptValueWriterForModules, - SerializedScriptValueWriter, - writer, - true, - true); - -class SerializedScriptValueReaderForModules final - : public SerializedScriptValueReader { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(SerializedScriptValueReaderForModules); - - public: - SerializedScriptValueReaderForModules(const uint8_t* buffer, - int length, - const WebBlobInfoArray* blobInfo, - BlobDataHandleMap& blobDataHandles, - ScriptState* scriptState) - : SerializedScriptValueReader(buffer, - length, - blobInfo, - blobDataHandles, - scriptState) {} - - bool read(v8::Local<v8::Value>*, ScriptValueDeserializer&) override; - - private: - bool readDOMFileSystem(v8::Local<v8::Value>*); - bool readCryptoKey(v8::Local<v8::Value>*); - bool readRTCCertificate(v8::Local<v8::Value>*); - bool doReadHmacKey(WebCryptoKeyAlgorithm&, WebCryptoKeyType&); - bool doReadAesKey(WebCryptoKeyAlgorithm&, WebCryptoKeyType&); - bool doReadRsaHashedKey(WebCryptoKeyAlgorithm&, WebCryptoKeyType&); - bool doReadEcKey(WebCryptoKeyAlgorithm&, WebCryptoKeyType&); - bool doReadKeyWithoutParams(WebCryptoKeyAlgorithm&, WebCryptoKeyType&); - bool doReadAlgorithmId(WebCryptoAlgorithmId&); - bool doReadAsymmetricKeyType(WebCryptoKeyType&); - bool doReadNamedCurve(WebCryptoNamedCurve&); - bool doReadKeyUsages(WebCryptoKeyUsageMask& usages, bool& extractable); -}; - -DEFINE_TYPE_CASTS(SerializedScriptValueReaderForModules, - SerializedScriptValueReader, - reader, - true, - true); - -class ScriptValueSerializerForModules final : public ScriptValueSerializer { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(ScriptValueSerializerForModules); - - public: - ScriptValueSerializerForModules(SerializedScriptValueWriter&, - WebBlobInfoArray*, - ScriptState*); - - private: - StateBase* doSerializeObject(v8::Local<v8::Object>, StateBase* next) override; - - StateBase* writeDOMFileSystem(v8::Local<v8::Value>, StateBase* next); - bool writeCryptoKey(v8::Local<v8::Value>); - StateBase* writeRTCCertificate(v8::Local<v8::Value>, StateBase* next); -}; - -class ScriptValueDeserializerForModules final : public ScriptValueDeserializer { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(ScriptValueDeserializerForModules); - - public: - ScriptValueDeserializerForModules(SerializedScriptValueReaderForModules&, - MessagePortArray* messagePorts, - ArrayBufferContentsArray*, - ImageBitmapContentsArray*); - - private: - bool read(v8::Local<v8::Value>*) override; -}; - -} // namespace blink - -#endif // ScriptValueSerializerForModules_h
diff --git a/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp b/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp index 621e899..adbf0630 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp +++ b/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp
@@ -4,12 +4,8 @@ #include "bindings/modules/v8/SerializedScriptValueForModulesFactory.h" -#include "bindings/core/v8/ExceptionState.h" -#include "bindings/core/v8/SerializedScriptValue.h" -#include "bindings/modules/v8/ScriptValueSerializerForModules.h" #include "bindings/modules/v8/serialization/V8ScriptValueDeserializerForModules.h" #include "bindings/modules/v8/serialization/V8ScriptValueSerializerForModules.h" -#include "core/dom/ExceptionCode.h" #include "platform/instrumentation/tracing/TraceEvent.h" namespace blink { @@ -21,14 +17,8 @@ WebBlobInfoArray* blobInfo, ExceptionState& exceptionState) { TRACE_EVENT0("blink", "SerializedScriptValueFactory::create"); - if (RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) { - V8ScriptValueSerializerForModules serializer(ScriptState::current(isolate)); - serializer.setBlobInfoArray(blobInfo); - return serializer.serialize(value, transferables, exceptionState); - } - SerializedScriptValueWriterForModules writer; - ScriptValueSerializerForModules serializer(writer, blobInfo, - ScriptState::current(isolate)); + V8ScriptValueSerializerForModules serializer(ScriptState::current(isolate)); + serializer.setBlobInfoArray(blobInfo); return serializer.serialize(value, transferables, exceptionState); } @@ -38,31 +28,10 @@ MessagePortArray* messagePorts, const WebBlobInfoArray* blobInfo) { TRACE_EVENT0("blink", "SerializedScriptValueFactory::deserialize"); - if (RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) { - V8ScriptValueDeserializerForModules deserializer( - ScriptState::current(isolate), value); - deserializer.setTransferredMessagePorts(messagePorts); - deserializer.setBlobInfoArray(blobInfo); - return deserializer.deserialize(); - } - // deserialize() can run arbitrary script (e.g., setters), which could result - // in |this| being destroyed. Holding a RefPtr ensures we are alive (along - // with our internal data) throughout the operation. - RefPtr<SerializedScriptValue> protect(value); - if (!value->dataLengthInBytes()) - return v8::Null(isolate); - static_assert(sizeof(SerializedScriptValueWriter::BufferValueType) == 2, - "BufferValueType should be 2 bytes"); - // FIXME: SerializedScriptValue shouldn't use String for its underlying - // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The - // information stored in m_data isn't even encoded in UTF-16. Instead, - // unicode characters are encoded as UTF-8 with two code units per UChar. - SerializedScriptValueReaderForModules reader( - value->data(), value->dataLengthInBytes(), blobInfo, - value->blobDataHandles(), ScriptState::current(isolate)); - ScriptValueDeserializerForModules deserializer( - reader, messagePorts, value->getArrayBufferContentsArray(), - value->getImageBitmapContentsArray()); + V8ScriptValueDeserializerForModules deserializer( + ScriptState::current(isolate), value); + deserializer.setTransferredMessagePorts(messagePorts); + deserializer.setBlobInfoArray(blobInfo); return deserializer.deserialize(); }
diff --git a/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp b/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp index 863e3519c..a08f28e6 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp +++ b/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp
@@ -32,20 +32,6 @@ namespace blink { namespace { -class ScopedEnableV8BasedStructuredClone { - public: - ScopedEnableV8BasedStructuredClone() - : m_wasEnabled(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) { - RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(true); - } - ~ScopedEnableV8BasedStructuredClone() { - RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(m_wasEnabled); - } - - private: - bool m_wasEnabled; -}; - RefPtr<SerializedScriptValue> serializedValue(const Vector<uint8_t>& bytes) { // TODO(jbroman): Fix this once SerializedScriptValue can take bytes without // endianness swapping. @@ -164,7 +150,6 @@ 0x2d, 0x0a}; TEST(V8ScriptValueSerializerForModulesTest, RoundTripRTCCertificate) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; // Make a certificate with the existing key above. @@ -190,7 +175,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeRTCCertificate) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; // This is encoded data generated from Chromium (around M55). @@ -212,7 +196,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeInvalidRTCCertificate) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; // This is valid, except that "private" is not a valid private key PEM and @@ -398,7 +381,6 @@ // AES-128-CBC uses AES key params. TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyAES) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -439,7 +421,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyAES) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -469,7 +450,6 @@ // HMAC-SHA256 uses HMAC key params. TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyHMAC) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -509,7 +489,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyHMAC) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -543,7 +522,6 @@ // RSA-PSS-SHA256 uses RSA hashed key params. TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyRSAHashed) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -586,7 +564,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyRSAHashed) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -637,7 +614,6 @@ // ECDSA uses EC key params. TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyEC) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -680,7 +656,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyEC) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -720,7 +695,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyNoParams) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -754,7 +728,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyNoParams) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -783,7 +756,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyInvalid) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState(); @@ -887,7 +859,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, RoundTripDOMFileSystem) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; DOMFileSystem* fs = DOMFileSystem::create( @@ -908,7 +879,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, RoundTripDOMFileSystemNotClonable) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ExceptionState exceptionState(scope.isolate(), ExceptionState::ExecutionContext, "Window", @@ -927,7 +897,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeDOMFileSystem) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; // This is encoded data generated from Chromium (around M56). @@ -953,7 +922,6 @@ } TEST(V8ScriptValueSerializerForModulesTest, DecodeInvalidDOMFileSystem) { - ScopedEnableV8BasedStructuredClone enable; V8TestingScope scope; ScriptState* scriptState = scope.getScriptState();
diff --git a/third_party/WebKit/Source/bindings/modules/v8/v8.gni b/third_party/WebKit/Source/bindings/modules/v8/v8.gni index 6fedd099..9a668b0 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/v8.gni +++ b/third_party/WebKit/Source/bindings/modules/v8/v8.gni
@@ -16,8 +16,6 @@ "DictionaryHelperForModules.cpp", "ModuleBindingsInitializer.cpp", "ModuleBindingsInitializer.h", - "ScriptValueSerializerForModules.cpp", - "ScriptValueSerializerForModules.h", "SerializedScriptValueForModulesFactory.cpp", "SerializedScriptValueForModulesFactory.h", "ToV8ForModules.h",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5 index d7758bc..6e4735ed 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.json5 +++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -1392,10 +1392,20 @@ }, { name: "overflow-x", + initial_keyword: "visible", + keyword_only: true, + keywords: [ + "visible", "hidden", "scroll", "auto", "overlay", "-webkit-paged-x", "-webkit-paged-y", + ], type_name: "EOverflow", }, { name: "overflow-y", + initial_keyword: "visible", + keyword_only: true, + keywords: [ + "visible", "hidden", "scroll", "auto", "overlay", "-webkit-paged-x", "-webkit-paged-y", + ], type_name: "EOverflow", }, {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp index 931f6e2..b11d023 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -126,16 +126,6 @@ return true; } -v8::Local<v8::Value> nodeV8Value(v8::Local<v8::Context> context, Node* node) { - v8::Isolate* isolate = context->GetIsolate(); - if (!node || - !BindingSecurity::shouldAllowAccessTo( - currentDOMWindow(isolate), node, - BindingSecurity::ErrorReportOption::DoNotReport)) - return v8::Null(isolate); - return ToV8(node, context->Global(), isolate); -} - } // namespace class InspectorRevalidateDOMTask final @@ -1837,6 +1827,7 @@ return distributedNodes; } +// static Node* InspectorDOMAgent::innerFirstChild(Node* node) { node = node->firstChild(); while (isWhitespace(node)) @@ -1844,6 +1835,7 @@ return node; } +// static Node* InspectorDOMAgent::innerNextSibling(Node* node) { do { node = node->nextSibling(); @@ -1851,6 +1843,7 @@ return node; } +// static Node* InspectorDOMAgent::innerPreviousSibling(Node* node) { do { node = node->previousSibling(); @@ -1858,6 +1851,7 @@ return node; } +// static unsigned InspectorDOMAgent::innerChildNodeCount(Node* node) { unsigned count = 0; Node* child = innerFirstChild(node); @@ -1868,6 +1862,7 @@ return count; } +// static Node* InspectorDOMAgent::innerParentNode(Node* node) { if (node->isDocumentNode()) { Document* document = toDocument(node); @@ -1878,12 +1873,71 @@ return node->parentOrShadowHostNode(); } +// static bool InspectorDOMAgent::isWhitespace(Node* node) { // TODO: pull ignoreWhitespace setting from the frontend and use here. return node && node->getNodeType() == Node::kTextNode && node->nodeValue().stripWhiteSpace().length() == 0; } +// static +v8::Local<v8::Value> InspectorDOMAgent::nodeV8Value( + v8::Local<v8::Context> context, + Node* node) { + v8::Isolate* isolate = context->GetIsolate(); + if (!node || + !BindingSecurity::shouldAllowAccessTo( + currentDOMWindow(isolate), node, + BindingSecurity::ErrorReportOption::DoNotReport)) + return v8::Null(isolate); + return ToV8(node, context->Global(), isolate); +} + +// static +void InspectorDOMAgent::collectNodes(Node* node, + int depth, + bool pierce, + Function<bool(Node*)>* filter, + HeapVector<Member<Node>>* result) { + if (filter && filter->operator()(node)) + result->push_back(node); + if (--depth <= 0) + return; + + if (pierce && node->isElementNode()) { + Element* element = toElement(node); + if (node->isFrameOwnerElement()) { + HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(node); + if (frameOwner->contentFrame() && + frameOwner->contentFrame()->isLocalFrame()) { + if (Document* doc = frameOwner->contentDocument()) + collectNodes(doc, depth, pierce, filter, result); + } + } + + ElementShadow* shadow = element->shadow(); + if (pierce && shadow) { + for (ShadowRoot* root = &shadow->youngestShadowRoot(); root; + root = root->olderShadowRoot()) { + collectNodes(root, depth, pierce, filter, result); + } + } + + if (isHTMLLinkElement(*element)) { + HTMLLinkElement& linkElement = toHTMLLinkElement(*element); + if (linkElement.isImport() && linkElement.import() && + innerParentNode(linkElement.import()) == linkElement) { + collectNodes(linkElement.import(), depth, pierce, filter, result); + } + } + } + + for (Node* child = innerFirstChild(node); child; + child = innerNextSibling(child)) { + collectNodes(child, depth, pierce, filter, result); + } +} + void InspectorDOMAgent::domContentLoadedEventFired(LocalFrame* frame) { if (frame != m_inspectedFrames->root()) return; @@ -2236,7 +2290,8 @@ : m_nodeId(DOMNodeIds::idForNode(node)) {} v8::Local<v8::Value> get(v8::Local<v8::Context> context) override { - return nodeV8Value(context, DOMNodeIds::nodeForId(m_nodeId)); + return InspectorDOMAgent::nodeV8Value(context, + DOMNodeIds::nodeForId(m_nodeId)); } private:
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h index e5f9cbc5..0b0212806 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
@@ -264,6 +264,12 @@ static unsigned innerChildNodeCount(Node*); static Node* innerParentNode(Node*); static bool isWhitespace(Node*); + static v8::Local<v8::Value> nodeV8Value(v8::Local<v8::Context>, Node*); + static void collectNodes(Node* root, + int depth, + bool pierce, + Function<bool(Node*)>*, + HeapVector<Member<Node>>* result); Response assertNode(int nodeId, Node*&); Response assertElement(int nodeId, Element*&);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp index 05e4a437..ebe550f9 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
@@ -32,6 +32,8 @@ #include "bindings/core/v8/ScriptEventListener.h" #include "bindings/core/v8/V8EventTarget.h" +#include "bindings/core/v8/V8Node.h" +#include "core/dom/DOMNodeIds.h" #include "core/dom/Element.h" #include "core/dom/Node.h" #include "core/events/Event.h" @@ -175,16 +177,13 @@ return removeFunction; } -void InspectorDOMDebuggerAgent::eventListenersInfoForTarget( - v8::Isolate* isolate, - v8::Local<v8::Value> value, - V8EventListenerInfoList& eventInformation) { - EventTarget* target = V8EventTarget::toImplWithTypeCheck(isolate, value); - // We need to handle LocalDOMWindow specially, because LocalDOMWindow wrapper - // exists on prototype chain. - if (!target) - target = toDOMWindow(isolate, value); - if (!target || !target->getExecutionContext()) +static void collectEventListeners(v8::Isolate* isolate, + EventTarget* target, + v8::Local<v8::Value> targetWrapper, + Node* targetNode, + bool reportForAllContexts, + V8EventListenerInfoList* eventInformation) { + if (!target->getExecutionContext()) return; ExecutionContext* executionContext = target->getExecutionContext(); @@ -205,8 +204,8 @@ static_cast<V8AbstractEventListener*>(eventListener); v8::Local<v8::Context> context = toV8Context(executionContext, v8Listener->world()); - // Hide listeners from other contexts. - if (context != isolate->GetCurrentContext()) + // Optionally hide listeners from other contexts. + if (!reportForAllContexts && context != isolate->GetCurrentContext()) continue; // getListenerObject() may cause JS in the event attribute to get // compiled, potentially unsuccessfully. In that case, the function @@ -216,14 +215,79 @@ if (handler.IsEmpty()) continue; bool useCapture = listeners->at(k).capture(); - eventInformation.push_back(V8EventListenerInfo( + int backendNodeId = 0; + if (targetNode) { + backendNodeId = DOMNodeIds::idForNode(targetNode); + targetWrapper = InspectorDOMAgent::nodeV8Value( + reportForAllContexts ? context : isolate->GetCurrentContext(), + targetNode); + } + v8::MaybeLocal<v8::Function> removeFunction = + !targetWrapper.IsEmpty() + ? createRemoveFunction(context, targetWrapper, handler, type, + useCapture) + : v8::MaybeLocal<v8::Function>(); + eventInformation->push_back(V8EventListenerInfo( type, useCapture, listeners->at(k).passive(), listeners->at(k).once(), - handler, - createRemoveFunction(context, value, handler, type, useCapture))); + handler, removeFunction, backendNodeId)); } } } +// static +void InspectorDOMDebuggerAgent::eventListenersInfoForTarget( + v8::Isolate* isolate, + v8::Local<v8::Value> value, + V8EventListenerInfoList* eventInformation) { + InspectorDOMDebuggerAgent::eventListenersInfoForTarget( + isolate, value, 1, false, eventInformation); +} + +static bool filterNodesWithListeners(Node* node) { + Vector<AtomicString> eventTypes = node->eventTypes(); + for (size_t j = 0; j < eventTypes.size(); ++j) { + EventListenerVector* listeners = node->getEventListeners(eventTypes[j]); + if (listeners && listeners->size()) + return true; + } + return false; +} + +// static +void InspectorDOMDebuggerAgent::eventListenersInfoForTarget( + v8::Isolate* isolate, + v8::Local<v8::Value> value, + int depth, + bool pierce, + V8EventListenerInfoList* eventInformation) { + // Special-case nodes, respect depth and pierce parameters in case of nodes. + Node* node = V8Node::toImplWithTypeCheck(isolate, value); + if (node) { + if (depth < 0) + depth = INT_MAX; + HeapVector<Member<Node>> nodes; + InspectorDOMAgent::collectNodes(node, depth, pierce, + WTF::bind(&filterNodesWithListeners).get(), + &nodes); + for (Node* n : nodes) { + // We are only interested in listeners from the current context. + collectEventListeners(isolate, n, v8::Local<v8::Value>(), n, pierce, + eventInformation); + } + return; + } + + EventTarget* target = V8EventTarget::toImplWithTypeCheck(isolate, value); + // We need to handle LocalDOMWindow specially, because LocalDOMWindow wrapper + // exists on prototype chain. + if (!target) + target = toDOMWindow(isolate, value); + if (target) { + collectEventListeners(isolate, target, value, nullptr, false, + eventInformation); + } +} + InspectorDOMDebuggerAgent::InspectorDOMDebuggerAgent( v8::Isolate* isolate, InspectorDOMAgent* domAgent, @@ -467,6 +531,8 @@ Response InspectorDOMDebuggerAgent::getEventListeners( const String& objectId, + Maybe<int> depth, + Maybe<bool> pierce, std::unique_ptr<protocol::Array<protocol::DOMDebugger::EventListener>>* listenersArray) { v8::HandleScope handles(m_isolate); @@ -483,7 +549,8 @@ protocol::Array<protocol::DOMDebugger::EventListener>::create(); V8EventListenerInfoList eventInformation; InspectorDOMDebuggerAgent::eventListenersInfoForTarget( - context->GetIsolate(), object, eventInformation); + context->GetIsolate(), object, depth.fromMaybe(1), + pierce.fromMaybe(false), &eventInformation); for (const auto& info : eventInformation) { if (!info.useCapture) continue; @@ -541,6 +608,8 @@ if (info.removeFunction.ToLocal(&removeFunction)) value->setRemoveFunction( m_v8Session->wrapObject(context, removeFunction, objectGroupId)); + if (info.backendNodeId) + value->setBackendNodeId(info.backendNodeId); } return value; }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h index 1656078..7349008e 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h
@@ -58,7 +58,7 @@ public: static void eventListenersInfoForTarget(v8::Isolate*, v8::Local<v8::Value>, - V8EventListenerInfoList& listeners); + V8EventListenerInfoList* listeners); InspectorDOMDebuggerAgent(v8::Isolate*, InspectorDOMAgent*, @@ -79,6 +79,8 @@ Response removeXHRBreakpoint(const String& url) override; Response getEventListeners( const String& objectId, + Maybe<int> depth, + Maybe<bool> pierce, std::unique_ptr<protocol::Array<protocol::DOMDebugger::EventListener>>* listeners) override; @@ -105,6 +107,11 @@ void didCommitLoadForLocalFrame(LocalFrame*) override; private: + static void eventListenersInfoForTarget(v8::Isolate*, + v8::Local<v8::Value>, + int depth, + bool pierce, + V8EventListenerInfoList* listeners); void pauseOnNativeEventIfNeeded( std::unique_ptr<protocol::DictionaryValue> eventData, bool synchronous);
diff --git a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp index 1b552c8..312f70a 100644 --- a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp +++ b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
@@ -394,7 +394,7 @@ if (groupId) debugger->muteMetrics(groupId); InspectorDOMDebuggerAgent::eventListenersInfoForTarget(isolate, info[0], - listenerInfo); + &listenerInfo); if (groupId) debugger->unmuteMetrics(groupId);
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 731b2dcb..224f7f28 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -3263,7 +3263,8 @@ { "name": "columnNumber", "type": "integer", "description": "Column number in the script (0-based)." }, { "name": "handler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event handler function value." }, { "name": "originalHandler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event original handler function value." }, - { "name": "removeFunction", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event listener remove function." } + { "name": "removeFunction", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event listener remove function." }, + { "name": "backendNodeId", "$ref": "DOM.BackendNodeId", "optional": true, "description": "Node the listener is added to (if any)." } ], "experimental": true } @@ -3335,7 +3336,9 @@ "name": "getEventListeners", "experimental": true, "parameters": [ - { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Identifier of the object to return listeners for." } + { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Identifier of the object to return listeners for." }, + { "name": "depth", "type": "integer", "optional": true, "description": "The maximum depth at which Node children should be retrieved, defaults to 1. Use -1 for the entire subtree or provide an integer larger than 0.", "experimental": true }, + { "name": "pierce", "type": "boolean", "optional": true, "description": "Whether or not iframes and shadow roots should be traversed when returning the subtree (default is false). Reports listeners for all contexts if pierce is enabled.", "experimental": true } ], "returns": [ { "name": "listeners", "type": "array", "items": { "$ref": "EventListener" }, "description": "Array of relevant listeners." }
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp index 54a33c0..5265d01 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -846,7 +846,10 @@ compositingContainerOffsetFromParentGraphicsLayer += compositingContainer->subpixelAccumulation(); -#if DCHECK_IS_ON() +#if 0 && DCHECK_IS_ON() + // TODO(trchen): We should enable this for below comment out |DCHECK()| once + // we have simple reproduce case and fix it. See http://crbug.com/646437 for + // details. const PaintLayer* commonTransformAncestor = nullptr; if (compositingContainer && compositingContainer->transform()) commonTransformAncestor = compositingContainer; @@ -867,7 +870,9 @@ // Store the local bounds of the Layer subtree before applying the offset. layers[i].compositedBounds = squashedBounds; -#if DCHECK_IS_ON() +#if 0 && DCHECK_IS_ON() + // TODO(trchen): We should enable this |DCHECK()| once we have simple + // reproduce case and fix it. See http://crbug.com/646437 for details. DCHECK(layers[i].paintLayer->transformAncestor() == commonTransformAncestor); #endif
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp index 60568dbb..2e70ff7 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp +++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -367,8 +367,6 @@ other.m_nonInheritedData.m_effectiveDisplay; m_nonInheritedData.m_originalDisplay = other.m_nonInheritedData.m_originalDisplay; - m_nonInheritedData.m_overflowX = other.m_nonInheritedData.m_overflowX; - m_nonInheritedData.m_overflowY = other.m_nonInheritedData.m_overflowY; m_nonInheritedData.m_verticalAlign = other.m_nonInheritedData.m_verticalAlign; m_nonInheritedData.m_position = other.m_nonInheritedData.m_position; m_nonInheritedData.m_hasViewportUnits = @@ -811,8 +809,7 @@ getWritingMode() != other.getWritingMode()) return true; - if (m_nonInheritedData.m_overflowX != other.m_nonInheritedData.m_overflowX || - m_nonInheritedData.m_overflowY != other.m_nonInheritedData.m_overflowY || + if (overflowX() != other.overflowX() || overflowY() != other.overflowY() || clear() != other.clear() || getUnicodeBidi() != other.getUnicodeBidi() || floating() != other.floating() || m_nonInheritedData.m_originalDisplay !=
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h index 33dc893..c07a410 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.h +++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -224,8 +224,6 @@ // Generated properties are compared in ComputedStyleBase return m_effectiveDisplay == other.m_effectiveDisplay && m_originalDisplay == other.m_originalDisplay && - m_overflowX == other.m_overflowX && - m_overflowY == other.m_overflowY && m_verticalAlign == other.m_verticalAlign && m_position == other.m_position && // hasViewportUnits @@ -251,8 +249,6 @@ unsigned m_effectiveDisplay : 5; // EDisplay unsigned m_originalDisplay : 5; // EDisplay - unsigned m_overflowX : 3; // EOverflow - unsigned m_overflowY : 3; // EOverflow unsigned m_verticalAlign : 4; // EVerticalAlign unsigned m_position : 3; // EPosition @@ -305,8 +301,6 @@ m_nonInheritedData.m_effectiveDisplay = m_nonInheritedData.m_originalDisplay = static_cast<unsigned>(initialDisplay()); - m_nonInheritedData.m_overflowX = static_cast<unsigned>(initialOverflowX()); - m_nonInheritedData.m_overflowY = static_cast<unsigned>(initialOverflowY()); m_nonInheritedData.m_verticalAlign = static_cast<unsigned>(initialVerticalAlign()); m_nonInheritedData.m_position = initialPosition(); @@ -1461,24 +1455,6 @@ SET_VAR(m_rareNonInheritedData, m_outline.m_offset, v); } - // overflow-x - static EOverflow initialOverflowX() { return EOverflow::kVisible; } - EOverflow overflowX() const { - return static_cast<EOverflow>(m_nonInheritedData.m_overflowX); - } - void setOverflowX(EOverflow v) { - m_nonInheritedData.m_overflowX = static_cast<unsigned>(v); - } - - // overflow-y - static EOverflow initialOverflowY() { return EOverflow::kVisible; } - EOverflow overflowY() const { - return static_cast<EOverflow>(m_nonInheritedData.m_overflowY); - } - void setOverflowY(EOverflow v) { - m_nonInheritedData.m_overflowY = static_cast<unsigned>(v); - } - // Padding properties. static Length initialPadding() { return Length(Fixed); }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h index 88b0c7c..61ad9f6c 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h +++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -145,16 +145,6 @@ // Random visual rendering model attributes. Not inherited. -enum class EOverflow : unsigned { - kVisible, - kHidden, - kScroll, - kAuto, - kOverlay, - kWebkitPagedX, - kWebkitPagedY -}; - enum class EVerticalAlign : unsigned { kBaseline, kMiddle,
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index 6b29676..4559983 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -2590,9 +2590,9 @@ if (!frame()) return; - frame()->reload( - bypassCache ? FrameLoadTypeReloadBypassingCache : FrameLoadTypeReload, - ClientRedirectPolicy::NotClientRedirect); + frame()->reload(bypassCache ? FrameLoadTypeReloadBypassingCache + : FrameLoadTypeReloadMainResource, + ClientRedirectPolicy::NotClientRedirect); } ClientRect* Internals::selectionBounds(ExceptionState& exceptionState) {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css index 08a83d8..98ff80f 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css +++ b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
@@ -323,6 +323,8 @@ top: 0; left: 0; cursor: pointer; + width: 15px; + height: 15px; } .gutter-menu-icon {
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js index cfd28b0..9dcb217 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js
@@ -45,13 +45,13 @@ this._contentElement = this.element.createChild('div', 'profile-launcher-view-content'); this._innerContentElement = this._contentElement.createChild('div'); - var targetSpan = this._contentElement.createChild('span'); - var selectTargetText = targetSpan.createChild('span'); - selectTargetText.textContent = Common.UIString('Target:'); - var targetsSelect = targetSpan.createChild('select', 'chrome-select'); - new Profiler.TargetsComboBoxController(targetsSelect, targetSpan); - this._controlButton = UI.createTextButton('', this._controlButtonClicked.bind(this), 'control-profiling'); - this._contentElement.appendChild(this._controlButton); + var controlDiv = this._contentElement.createChild('div', 'hbox profile-launcher-control'); + var targetDiv = controlDiv.createChild('div', 'hbox profile-launcher-target'); + targetDiv.createChild('div').textContent = Common.UIString('Target:'); + var targetsSelect = targetDiv.createChild('select', 'chrome-select'); + new Profiler.TargetsComboBoxController(targetsSelect, targetDiv); + this._controlButton = UI.createTextButton('', this._controlButtonClicked.bind(this)); + controlDiv.appendChild(this._controlButton); this._recordButtonEnabled = true; this._loadButton = UI.createTextButton(Common.UIString('Load'), this._loadButtonClicked.bind(this), 'load-profile'); this._contentElement.appendChild(this._loadButton);
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css b/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css index 7b257ec7..eb70b40 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css +++ b/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
@@ -117,9 +117,27 @@ text-align: left; } -.control-profiling { - -webkit-align-self: flex-start; - margin-right: 50px; +.profile-launcher-control { + align-items: center; + flex-wrap: wrap; +} + +.profile-launcher-control > * { + margin-top: 10px; + margin-right: 6px; +} + +.profile-launcher-control button { + min-width: 110px; +} + +.profile-launcher-target { + align-items: baseline; +} + +.profile-launcher-target > * { + flex: 0 0 auto; + margin-right: 8px; } .profile-launcher-view-content h1 { @@ -178,23 +196,15 @@ } .js_profiler.panel select.chrome-select, -.heap_profiler.panel select.chrome-select - { - font-size: 12px; +.heap_profiler.panel select.chrome-select { width: 150px; - margin-left: 10px; - margin-right: 10px; } button.load-profile { - margin-left: 20px; + margin-top: 10px; + min-width: 110px; } -button.load-profile.multi-target { - display: block; - margin-top: 14px; - margin-left: 0; -} .cpu-profile-flame-chart-overview-container { overflow: hidden;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js index 591eb5f5..f04e101 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
@@ -560,7 +560,7 @@ return; } - this.target().domdebuggerAgent().getEventListeners(this._objectId, mycallback.bind(this)); + this.target().domdebuggerAgent().getEventListeners(this._objectId, undefined, undefined, mycallback.bind(this)); /** * @this {SDK.RemoteObjectImpl}
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js index 8613bdc..692e451 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js
@@ -99,7 +99,8 @@ * @override * @param {!UI.Toolbar} toolbar */ - _populateToolbar(toolbar) { + populateToolbar(toolbar) { + super.populateToolbar(toolbar); this._filtersControl.populateToolbar(toolbar); } @@ -142,8 +143,7 @@ super(); this._categoryFilter = new Timeline.TimelineFilters.Category(); this._durationFilter = new Timeline.TimelineFilters.IsLong(); - this._textFilter = new Timeline.TimelineFilters.RegExp(); - this._filters = [this._categoryFilter, this._durationFilter, this._textFilter]; + this._filters = [this._categoryFilter, this._durationFilter]; } /** @@ -157,10 +157,6 @@ * @param {!UI.Toolbar} toolbar */ populateToolbar(toolbar) { - this._textFilterUI = new UI.ToolbarInput(Common.UIString('Filter')); - this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, textFilterChanged, this); - toolbar.appendToolbarItem(this._textFilterUI); - var durationFilterUI = new UI.ToolbarComboBox(durationFilterChanged.bind(this)); for (var durationMs of Timeline.EventsTimelineTreeView.Filters._durationFilterPresetsMs) { durationFilterUI.addOption(durationFilterUI.createOption( @@ -188,15 +184,6 @@ /** * @this {Timeline.EventsTimelineTreeView.Filters} */ - function textFilterChanged() { - var searchQuery = this._textFilterUI.value(); - this._textFilter.setRegExp(searchQuery ? createPlainTextSearchRegex(searchQuery, 'i') : null); - this._notifyFiltersChanged(); - } - - /** - * @this {Timeline.EventsTimelineTreeView.Filters} - */ function durationFilterChanged() { var duration = durationFilterUI.selectedOption().value; var minimumRecordDuration = parseInt(duration, 10);
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js index 2f19b974..8f038cc1 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -47,7 +47,8 @@ init(filters) { this._linkifier = new Components.Linkifier(); - this._filters = filters.slice(); + this._textFilter = new Timeline.TimelineFilters.RegExp(); + this._filters = [...filters, this._textFilter]; const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([]); this.populateColumns(columns); @@ -55,7 +56,7 @@ this._splitWidget = new UI.SplitWidget(true, true, 'timelineTreeViewDetailsSplitWidget'); var mainView = new UI.VBox(); var toolbar = new UI.Toolbar('', mainView.element); - this._populateToolbar(toolbar); + this.populateToolbar(toolbar); this._dataGrid = new DataGrid.SortableDataGrid(columns); this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._sortingChanged, this); @@ -109,9 +110,22 @@ } /** + * @protected * @param {!UI.Toolbar} toolbar */ - _populateToolbar(toolbar) { + populateToolbar(toolbar) { + this._textFilterUI = new UI.ToolbarInput(Common.UIString('Filter'), 0, 0, true); + this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, textFilterChanged, this); + toolbar.appendToolbarItem(this._textFilterUI); + + /** + * @this {Timeline.TimelineTreeView} + */ + function textFilterChanged() { + var searchQuery = this._textFilterUI.value(); + this._textFilter.setRegExp(searchQuery ? createPlainTextSearchRegex(searchQuery, 'i') : null); + this.refreshTree(); + } } /** @@ -574,7 +588,8 @@ * @override * @param {!UI.Toolbar} toolbar */ - _populateToolbar(toolbar) { + populateToolbar(toolbar) { + super.populateToolbar(toolbar); this._groupByCombobox = new UI.ToolbarComboBox(this._onGroupByChanged.bind(this)); /** * @param {string} name
diff --git a/third_party/WebKit/Source/modules/app_banner/OWNERS b/third_party/WebKit/Source/modules/app_banner/OWNERS index 92faaaf..d5bee6b2 100644 --- a/third_party/WebKit/Source/modules/app_banner/OWNERS +++ b/third_party/WebKit/Source/modules/app_banner/OWNERS
@@ -1,2 +1,4 @@ dominickn@chromium.org mlamouri@chromium.org + +# COMPONENT: Content>WebApps
diff --git a/third_party/WebKit/Source/modules/permissions/OWNERS b/third_party/WebKit/Source/modules/permissions/OWNERS index 2d28246..e9ad8e9 100644 --- a/third_party/WebKit/Source/modules/permissions/OWNERS +++ b/third_party/WebKit/Source/modules/permissions/OWNERS
@@ -1 +1,3 @@ mlamouri@chromium.org + +# COMPONENT: Blink>PermissionsAPI
diff --git a/third_party/WebKit/Source/modules/presentation/OWNERS b/third_party/WebKit/Source/modules/presentation/OWNERS index 357df4fc..9a20d44e 100644 --- a/third_party/WebKit/Source/modules/presentation/OWNERS +++ b/third_party/WebKit/Source/modules/presentation/OWNERS
@@ -2,3 +2,5 @@ imcheng@chromium.org mfoltz@chromium.org mlamouri@chromium.org + +# COMPONENT: Blink>PresentationAPI
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp index 6f37b391..7c192ecc 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -1151,6 +1151,13 @@ GLenum format, GLenum type, DOMArrayBufferView* data) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texImage2D(target, level, internalformat, width, height, border, format, type, data); } @@ -1165,6 +1172,13 @@ GLenum type, DOMArrayBufferView* data, GLuint srcOffset) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperDOMArrayBufferView(TexImage2D, target, level, internalformat, width, height, 1, border, format, type, 0, 0, 0, data, NullNotReachable, srcOffset); @@ -1180,6 +1194,13 @@ GLenum type, ImageData* pixels) { DCHECK(pixels); + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperImageData(TexImage2D, target, level, internalformat, 0, format, type, 1, 0, 0, 0, pixels, getTextureSourceSubRectangle(width, height), 0); @@ -1195,6 +1216,13 @@ GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLImageElement(TexImage2D, target, level, internalformat, format, type, 0, 0, 0, image, getTextureSourceSubRectangle(width, height), 1, @@ -1211,6 +1239,13 @@ GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLCanvasElement( TexImage2D, target, level, internalformat, format, type, 0, 0, 0, canvas, getTextureSourceSubRectangle(width, height), 1, 0, exceptionState); @@ -1226,6 +1261,13 @@ GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLVideoElement( TexImage2D, target, level, internalformat, format, type, 0, 0, 0, video, getTextureSourceSubRectangle(width, height), 1, 0, exceptionState); @@ -1242,6 +1284,13 @@ ImageBitmap* bitmap, ExceptionState& exceptionState) { DCHECK(bitmap); + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperImageBitmap( TexImage2D, target, level, internalformat, format, type, 0, 0, 0, bitmap, getTextureSourceSubRectangle(width, height), 1, 0, exceptionState); @@ -1253,6 +1302,13 @@ GLenum format, GLenum type, ImageData* imageData) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texImage2D(target, level, internalformat, format, type, imageData); } @@ -1264,6 +1320,13 @@ GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texImage2D(target, level, internalformat, format, type, image, exceptionState); } @@ -1275,6 +1338,13 @@ GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texImage2D(target, level, internalformat, format, type, canvas, exceptionState); } @@ -1286,6 +1356,13 @@ GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texImage2D(target, level, internalformat, format, type, video, exceptionState); } @@ -1297,6 +1374,13 @@ GLenum type, ImageBitmap* imageBitMap, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texImage2D(target, level, internalformat, format, type, imageBitMap, exceptionState); } @@ -1310,6 +1394,13 @@ GLenum format, GLenum type, DOMArrayBufferView* pixels) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); } @@ -1324,6 +1415,13 @@ GLenum type, DOMArrayBufferView* pixels, GLuint srcOffset) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperDOMArrayBufferView(TexSubImage2D, target, level, 0, width, height, 1, 0, format, type, xoffset, yoffset, 0, pixels, NullNotReachable, srcOffset); @@ -1339,6 +1437,13 @@ GLenum type, ImageData* pixels) { DCHECK(pixels); + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperImageData(TexSubImage2D, target, level, 0, 0, format, type, 1, xoffset, yoffset, 0, pixels, getTextureSourceSubRectangle(width, height), 0); @@ -1354,6 +1459,13 @@ GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLImageElement( TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, image, getTextureSourceSubRectangle(width, height), 1, 0, exceptionState); @@ -1369,6 +1481,13 @@ GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLCanvasElement(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, canvas, getTextureSourceSubRectangle(width, height), @@ -1385,6 +1504,13 @@ GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLVideoElement( TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, video, getTextureSourceSubRectangle(width, height), 1, 0, exceptionState); @@ -1401,6 +1527,13 @@ ImageBitmap* bitmap, ExceptionState& exceptionState) { DCHECK(bitmap); + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperImageBitmap(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, bitmap, getTextureSourceSubRectangle(width, height), 1, 0, @@ -1414,6 +1547,13 @@ GLenum format, GLenum type, ImageData* pixels) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texSubImage2D(target, level, xoffset, yoffset, format, type, pixels); } @@ -1426,6 +1566,13 @@ GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texSubImage2D(target, level, xoffset, yoffset, format, type, image, exceptionState); } @@ -1438,6 +1585,13 @@ GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texSubImage2D( target, level, xoffset, yoffset, format, type, canvas, exceptionState); } @@ -1462,6 +1616,13 @@ GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::texSubImage2D( target, level, xoffset, yoffset, format, type, bitmap, exceptionState); } @@ -1520,6 +1681,13 @@ GLenum type, DOMArrayBufferView* pixels, GLuint srcOffset) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperDOMArrayBufferView( TexImage3D, target, level, internalformat, width, height, depth, border, format, type, 0, 0, 0, pixels, NullNotReachable, srcOffset); @@ -1587,6 +1755,13 @@ GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLImageElement(TexImage3D, target, level, internalformat, format, type, 0, 0, 0, image, getTextureSourceSubRectangle(width, height), @@ -1604,6 +1779,13 @@ GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLCanvasElement(TexImage3D, target, level, internalformat, format, type, 0, 0, 0, canvas, getTextureSourceSubRectangle(width, height), @@ -1621,6 +1803,13 @@ GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLVideoElement(TexImage3D, target, level, internalformat, format, type, 0, 0, 0, video, getTextureSourceSubRectangle(width, height), @@ -1638,6 +1827,13 @@ GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperImageBitmap(TexImage3D, target, level, internalformat, format, type, 0, 0, 0, bitmap, getTextureSourceSubRectangle(width, height), depth, @@ -1656,6 +1852,13 @@ GLenum type, DOMArrayBufferView* pixels, GLuint srcOffset) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperDOMArrayBufferView( TexSubImage3D, target, level, 0, width, height, depth, 0, format, type, xoffset, yoffset, zoffset, pixels, NullNotReachable, srcOffset); @@ -1705,6 +1908,13 @@ GLenum type, ImageData* pixels) { DCHECK(pixels); + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperImageData(TexSubImage3D, target, level, 0, 0, format, type, depth, xoffset, yoffset, zoffset, pixels, getTextureSourceSubRectangle(width, height), @@ -1723,6 +1933,13 @@ GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLImageElement(TexSubImage3D, target, level, 0, format, type, xoffset, yoffset, zoffset, image, getTextureSourceSubRectangle(width, height), @@ -1741,6 +1958,13 @@ GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLCanvasElement(TexSubImage3D, target, level, 0, format, type, xoffset, yoffset, zoffset, canvas, getTextureSourceSubRectangle(width, height), @@ -1759,6 +1983,13 @@ GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperHTMLVideoElement(TexSubImage3D, target, level, 0, format, type, xoffset, yoffset, zoffset, video, getTextureSourceSubRectangle(width, height), @@ -1777,6 +2008,13 @@ GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } texImageHelperImageBitmap(TexSubImage3D, target, level, 0, format, type, xoffset, yoffset, zoffset, bitmap, getTextureSourceSubRectangle(width, height), depth, @@ -1814,6 +2052,13 @@ GLsizei height, GLint border, DOMArrayBufferView* data) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::compressedTexImage2D(target, level, internalformat, width, height, border, data); } @@ -1830,6 +2075,11 @@ GLuint srcLengthOverride) { if (isContextLost()) return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } if (!validateTexture2DBinding("compressedTexImage2D", target)) return; if (!validateCompressedTexFormat("compressedTexImage2D", internalformat)) @@ -1861,6 +2111,11 @@ GLintptr offset) { if (isContextLost()) return; + if (!m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage2D", + "no bound PIXEL_UNPACK_BUFFER"); + return; + } contextGL()->CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, reinterpret_cast<uint8_t*>(offset)); @@ -1875,6 +2130,13 @@ GLsizei height, GLenum format, DOMArrayBufferView* data) { + if (isContextLost()) + return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } WebGLRenderingContextBase::compressedTexSubImage2D( target, level, xoffset, yoffset, width, height, format, data); } @@ -1892,6 +2154,11 @@ GLuint srcLengthOverride) { if (isContextLost()) return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage2D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } if (!validateTexture2DBinding("compressedTexSubImage2D", target)) return; if (!validateCompressedTexFormat("compressedTexSubImage2D", format)) @@ -1924,6 +2191,11 @@ GLintptr offset) { if (isContextLost()) return; + if (!m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage2D", + "no bound PIXEL_UNPACK_BUFFER"); + return; + } contextGL()->CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, reinterpret_cast<uint8_t*>(offset)); @@ -1942,6 +2214,11 @@ GLuint srcLengthOverride) { if (isContextLost()) return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } if (!validateTexture3DBinding("compressedTexImage3D", target)) return; if (!validateCompressedTexFormat("compressedTexImage3D", internalformat)) @@ -1975,6 +2252,11 @@ GLintptr offset) { if (isContextLost()) return; + if (!m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage3D", + "no bound PIXEL_UNPACK_BUFFER"); + return; + } contextGL()->CompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, reinterpret_cast<uint8_t*>(offset)); @@ -1995,6 +2277,11 @@ GLuint srcLengthOverride) { if (isContextLost()) return; + if (m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage3D", + "a buffer is bound to PIXEL_UNPACK_BUFFER"); + return; + } if (!validateTexture3DBinding("compressedTexSubImage3D", target)) return; if (!validateCompressedTexFormat("compressedTexSubImage3D", format)) @@ -2030,6 +2317,11 @@ GLintptr offset) { if (isContextLost()) return; + if (!m_boundPixelUnpackBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage3D", + "no bound PIXEL_UNPACK_BUFFER"); + return; + } contextGL()->CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, reinterpret_cast<uint8_t*>(offset));
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 index 83cf3d4..f934de0 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -912,10 +912,6 @@ status: "experimental", }, { - name: "V8BasedStructuredClone", - status: "stable", - }, - { name: "V8IdleTasks", }, {
diff --git a/third_party/WebKit/Source/platform/json/OWNERS b/third_party/WebKit/Source/platform/json/OWNERS index cda1f0a..19f9406 100644 --- a/third_party/WebKit/Source/platform/json/OWNERS +++ b/third_party/WebKit/Source/platform/json/OWNERS
@@ -1,3 +1,5 @@ esprehn@chromium.org pfeldman@chromium.org iclelland@chromium.org + +# COMPONENT: Blink>Internals
diff --git a/third_party/WebKit/Source/platform/text/TextRun.h b/third_party/WebKit/Source/platform/text/TextRun.h index c6c78ce..2d4660a1 100644 --- a/third_party/WebKit/Source/platform/text/TextRun.h +++ b/third_party/WebKit/Source/platform/text/TextRun.h
@@ -183,19 +183,19 @@ } UChar32 codepointAt(unsigned i) const { + SECURITY_DCHECK(i < m_len); if (is8Bit()) return (*this)[i]; UChar32 codepoint; - SECURITY_DCHECK(i < m_len); U16_GET(characters16(), 0, i, m_len, codepoint); return codepoint; } UChar32 codepointAtAndNext(unsigned& i) const { + SECURITY_DCHECK(i < m_len); if (is8Bit()) return (*this)[i++]; UChar32 codepoint; - SECURITY_DCHECK(i < m_len); U16_NEXT(characters16(), i, m_len, codepoint); return codepoint; }
diff --git a/third_party/WebKit/public/platform/modules/permissions/OWNERS b/third_party/WebKit/public/platform/modules/permissions/OWNERS index 393b01f..ff69b875 100644 --- a/third_party/WebKit/public/platform/modules/permissions/OWNERS +++ b/third_party/WebKit/public/platform/modules/permissions/OWNERS
@@ -2,3 +2,5 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS + +# COMPONENT: Blink>PermissionsAPI
diff --git a/third_party/WebKit/public/platform/modules/presentation/OWNERS b/third_party/WebKit/public/platform/modules/presentation/OWNERS index 2f15bc6..bc1b773 100644 --- a/third_party/WebKit/public/platform/modules/presentation/OWNERS +++ b/third_party/WebKit/public/platform/modules/presentation/OWNERS
@@ -5,3 +5,5 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS + +# COMPONENT: Blink>PresentationAPI
diff --git a/tools/chrome_proxy/webdriver/compression_regression.py b/tools/chrome_proxy/webdriver/compression_regression.py index 3c9c2bf..f6b1ee6 100644 --- a/tools/chrome_proxy/webdriver/compression_regression.py +++ b/tools/chrome_proxy/webdriver/compression_regression.py
@@ -2,22 +2,98 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import datetime +import json +import math +import subprocess +import time + import common from common import TestDriver from common import IntegrationTest -# Technically not an Integration test, but we'll use the same infrastructure. -# -# This tests hits a test page and computes the compression rate for each of the -# resource types on it. These metrics are then output to the console. After -# metrics from several releases have been manually captured from the console, -# this test be changed to check compression rates against the known good rates -# and alert if they fall outside a tolerance. -class CompressionRegression(IntegrationTest): +# The maximum number of data points that will be saved. +MAX_DATA_POINTS = 365 - # TODO(robertogden): Once month-long metric gathering is up, remove print - # statements and make into a true test. +# The persistant storage for compression data is kept in Google Storage with +# this bucket name. +BUCKET = 'chrome_proxy_compression' + +# The data file name in the Google Storage bucket, above. The data file is also +# saved locally under the same name. +DATA_FILE = 'compression_data.json' + +class CompressionRegression(IntegrationTest): + """This class is responsible for alerting the Chrome Proxy team to regression + in the compression metrics of the proxy. At present, this class will simply + gather data and save it to a Google Storage bucket. Once enough data has been + gathered to form a reasonable model, alerting will be added to check for + regression. + + Before running the test, this class will fetch the JSON data file from Google + Storage in a subprocess and store it on the local disk with the same file + name. The data is then read from that file. After running the test, if the + data has changed the file will be uploaded back to Google Storage. + + The JSON data object and data dict object used widely in this class has the + following structure: + { + "2017-02-29": { + "html": 0.314, + "jpg": 0.1337, + "png": 0.1234, + "mp4": 0.9876 + } + } + where keys are date stamps in the form "YYYY-MM-DD", and each key in the child + object is the resource type with its compression value. + + Also frequently referenced is the compression_average dict object, which + contains the compression data just now gathered from Chrome in + getCurrentCompressionMetrics(). That object has the following structure: + { + "test/html": 0.314, + "image/jpg": 0.1337, + "image/png": 0.1234, + "video/mp4": 0.9876 + } + where keys are the content type with its compression value. + + Due to the complexity of several methods in this class, a number of local + unit tests can be found at the bottom of this file. + + Please note that while this test uses the IntegrationTest framework, it is + classified as a regression test. + """ + def testCompression(self): + """This function is the main test function for regression compression + checking and facilitates the test with all of the helper functions' + behavior. + """ + compression_average = self.getCurrentCompressionMetrics() + self.fetchFromGoogleStorage() + data = {} + with open(DATA_FILE, 'r') as data_fp: + data = json.load(data_fp) + if self.updateDataObject(compression_average, data): + with open(DATA_FILE, 'w') as data_fp: + json.dump(data, data_fp) + self.uploadToGoogleStorage() + + def getCurrentCompressionMetrics(self): + """This function uses the ChromeDriver framework to open Chrome and navigate + to a number of static resources of different types, like jpg, png, mp4, gif, + html. Multiple resources of a single type are supported. This function will + check that each resource was fetched via the Chrome Proxy, and then compute + the compression as a percentage from the Content-Length and + X-Original-Content-Length headers where compression = 1 - (cl / xocl). The + function will then return the average compression for each of the resource + types. + + Returns: + a dict object mapping resource type to compression + """ def AddToCompression(compression, key, value): if key in compression: compression[key].append(value) @@ -25,22 +101,119 @@ compression[key] = [value] with TestDriver() as t: t.AddChromeArg('--enable-spdy-proxy-auth') - t.LoadURL('http://check.googlezip.net/metrics/') - print '' + t.AddChromeArg('--data-reduction-proxy-server-experiments-disabled') + t.LoadURL('http://check.googlezip.net/metrics/local.gif') + t.LoadURL('http://check.googlezip.net/metrics/local.png') + t.LoadURL('http://check.googlezip.net/metrics/local.jpg') + t.LoadURL( + 'http://check.googlezip.net/cacheable/video/buck_bunny_tiny.html') compression = {} for response in t.GetHTTPResponses(): - if not response.url.endswith('webp'): - cl = response.response_headers['content-length'] - ocl = response.response_headers['x-original-content-length'] - compression_rate = 1.0 - (float(cl) / float(ocl)) - if 'html' in response.response_headers['content-type']: - AddToCompression(compression, 'html', compression_rate) - else: - resource = response.url[response.url.rfind('/'):] - AddToCompression(compression, resource[resource.rfind('.') + 1:], - compression_rate) - for url in sorted(compression): - average = sum(compression[url]) / float(len(compression[url])) - print url, average + # Check that the response was proxied. + self.assertHasChromeProxyViaHeader(response) + # Compute compression metrics. + cl = response.response_headers['content-length'] + ocl = response.response_headers['x-original-content-length'] + content_type = response.response_headers['content-type'] + compression_rate = 1.0 - (float(cl) / float(ocl)) + if 'html' in response.response_headers['content-type']: + AddToCompression(compression, 'html', compression_rate) + else: + resource = response.url[response.url.rfind('/'):] + AddToCompression(compression, resource[resource.rfind('.') + 1:], + compression_rate) + # Compute the average compression for each resource type. + compression_average = {} + for resource_type in compression: + compression_average[resource_type] = (sum(compression[resource_type]) / + float(len(compression[resource_type]))) + return compression_average + + def updateDataObject(self, compression_average, data, + today=datetime.date.today()): + """This function handles the updating of the data object when new data is + available. Given the existing data object, the results of the + getCurrentCompressionMetrics() func, and a date object, it will check if + data exists for today. If it does, the method will do nothing and return + False. Otherwise, it will update the data object with the compression data. + If needed, it will also find the least recent entry in the data object and + remove it. + + Args: + compression_average: the compression data from + getCurrentCompressionMetrics() + data: the current data object, a dict + today: a date object, specifiable here for testing purposes. + Returns: + True iff the data object was changed + """ + datestamp = today.strftime('%Y-%m-%d') + # Check if this data has already been recorded. + if datestamp in data: + return False + # Append new data, removing the least recent if needed. + data[datestamp] = compression_average + if len(data) > MAX_DATA_POINTS: + min_date = None + for date_str in data: + date = datetime.date(*[int(d) for d in date_str.split('-')]) + if min_date == None or date < min_date: + min_date = date + del data[min_date.strftime('%Y-%m-%d')] + return True + + def uploadToGoogleStorage(self): + """This function uses the gsutil command to upload the local data file to + Google Storage. + """ + gs_location = 'gs://%s/%s' % (BUCKET, DATA_FILE) + cmd = ['gsutil', 'cp', DATA_FILE, gs_location] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = proc.communicate() + if proc.returncode: + raise Exception('Uploading to Google Storage failed! output: %s %s' % + (stdout, stderr)) + + def fetchFromGoogleStorage(self): + """This function uses the gsutil command to fetch the local data file from + Google Storage. + """ + gs_location = 'gs://%s/%s' % (BUCKET, DATA_FILE) + cmd = ['gsutil', 'cp', gs_location, DATA_FILE] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = proc.communicate() + if proc.returncode: + raise Exception('Fetching to Google Storage failed! output: %s %s' % + (stdout, stderr)) + + def test0UpdateDataObject_NoUpdate(self): + """This unit test asserts that the updateDataObject() function doesn't + update the data object when today is already contained in the data object. + """ + data = { '2017-02-06': {'hello': 'world'}} + new_data = {'Benoit': 'Mandelbrot'} + test_day = datetime.date(2017, 02, 06) + changed = self.updateDataObject(new_data, data, today=test_day) + self.assertFalse(changed, "No data should have been recorded!") + + def test0UpdateDataObject_Update(self): + """This unit test asserts that the updateDataObject() function updates the + data object when there is new data available, also removing the least recent + data point. + """ + start_date = datetime.date(2017, 2, 6) + data = {} + for i in range(MAX_DATA_POINTS): + date_obj = start_date + datetime.timedelta(days=i) + datestamp = date_obj.strftime('%Y-%m-%d') + data[datestamp] = {'hello': 'world'} + new_data = {'Benoit': 'Mandelbrot'} + test_day = datetime.date(2017, 02, 06) + datetime.timedelta( + days=(MAX_DATA_POINTS)) + changed = self.updateDataObject(new_data, data, today=test_day) + self.assertTrue(changed, "Data should have been recorded!") + self.assertNotIn('2017-02-06', data) + self.assertIn(test_day.strftime('%Y-%m-%d'), data) + if __name__ == '__main__': IntegrationTest.RunAllTests()
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 1e7d499..a8d3666 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -1809,7 +1809,7 @@ 'gn_args': ('ozone_auto_platforms=false ozone_platform_wayland=true ' 'ozone_platform_x11=true ozone_platform_gbm=true ' 'enable_package_mash_services=true use_ash=false ' - 'use_xkbcommon=true'), + 'use_jessie_sysroot=true use_xkbcommon=true'), }, 'pdf_xfa': {
diff --git a/tools/perf/benchmarks/media.py b/tools/perf/benchmarks/media.py index 5c6faf38..02ae46d 100644 --- a/tools/perf/benchmarks/media.py +++ b/tools/perf/benchmarks/media.py
@@ -74,7 +74,7 @@ return 'media.media_cns_cases' -@benchmark.Disabled('android') # crbug.com/671628, WebView: crbug.com/419689. +@benchmark.Disabled('l', 'android-webview') # WebView: crbug.com/419689. class MediaAndroid(perf_benchmark.PerfBenchmark): """Obtains media metrics for key user scenarios on Android.""" test = media.Media @@ -85,18 +85,9 @@ @classmethod def ShouldDisable(cls, possible_browser): - # crbug.com/672059 if possible_browser.platform.GetOSName() != "android": return True - # crbug.com/448092 - if cls.IsSvelte(possible_browser): - return True - - # crbug.com/647372 - if possible_browser.platform.GetDeviceTypeName() == 'Nexus 5X': - return True - - return False + return cls.IsSvelte(possible_browser) @classmethod def Name(cls):
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index 4910aaa1..60d37720 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -27,6 +27,8 @@ "ax_range.h", "ax_relative_bounds.cc", "ax_relative_bounds.h", + "ax_role_properties.cc", + "ax_role_properties.h", "ax_serializable_tree.cc", "ax_serializable_tree.h", "ax_text_utils.cc",
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc new file mode 100644 index 0000000..aa712fa --- /dev/null +++ b/ui/accessibility/ax_role_properties.cc
@@ -0,0 +1,35 @@ +// 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 "ui/accessibility/ax_role_properties.h" + +namespace ui { + +bool IsRoleClickable(AXRole role) { + switch (role) { + case AX_ROLE_BUTTON: + case AX_ROLE_CHECK_BOX: + case AX_ROLE_COLOR_WELL: + case AX_ROLE_DISCLOSURE_TRIANGLE: + case AX_ROLE_IMAGE_MAP_LINK: + case AX_ROLE_LINK: + case AX_ROLE_LIST_BOX_OPTION: + case AX_ROLE_MENU_BUTTON: + case AX_ROLE_MENU_ITEM: + case AX_ROLE_MENU_ITEM_CHECK_BOX: + case AX_ROLE_MENU_ITEM_RADIO: + case AX_ROLE_MENU_LIST_OPTION: + case AX_ROLE_MENU_LIST_POPUP: + case AX_ROLE_POP_UP_BUTTON: + case AX_ROLE_RADIO_BUTTON: + case AX_ROLE_SWITCH: + case AX_ROLE_TAB: + case AX_ROLE_TOGGLE_BUTTON: + return true; + default: + return false; + } +} + +} // namespace ui
diff --git a/ui/accessibility/ax_role_properties.h b/ui/accessibility/ax_role_properties.h new file mode 100644 index 0000000..7d9ab796 --- /dev/null +++ b/ui/accessibility/ax_role_properties.h
@@ -0,0 +1,19 @@ +// 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 UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_ +#define UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_ + +#include "ui/accessibility/ax_enums.h" +#include "ui/accessibility/ax_export.h" + +namespace ui { + +// Checks if the given role should belong to a control that can respond to +// clicks. +AX_EXPORT bool IsRoleClickable(AXRole role); + +} // namespace ui + +#endif // UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm index 5bfa69c..3cf4db2 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -11,6 +11,7 @@ #include "base/strings/sys_string_conversions.h" #include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_node_data.h" +#include "ui/accessibility/ax_role_properties.h" #include "ui/accessibility/platform/ax_platform_node_delegate.h" #include "ui/base/l10n/l10n_util.h" #import "ui/gfx/mac/coordinate_conversion.h" @@ -304,7 +305,28 @@ } - (NSArray*)accessibilityActionNames { - return nil; + base::scoped_nsobject<NSMutableArray> axActions( + [[NSMutableArray alloc] init]); + + // VoiceOver expects the "press" action to be first. + if (ui::IsRoleClickable(node_->GetData().role)) + [axActions addObject:NSAccessibilityPressAction]; + + return axActions.autorelease(); +} + +- (void)accessibilityPerformAction:(NSString*)action { + DCHECK([[self accessibilityActionNames] containsObject:action]); + ui::AXActionData data; + if ([action isEqualToString:NSAccessibilityPressAction]) + data.action = ui::AX_ACTION_DO_DEFAULT; + + // Note ui::AX_ACTIONs which are just overwriting an accessibility attribute + // are already implemented in -accessibilitySetValue:forAttribute:, so ignore + // those here. + + if (data.action != ui::AX_ACTION_NONE) + node_->GetDelegate()->AccessibilityPerformAction(data); } - (NSArray*)accessibilityAttributeNames {
diff --git a/ui/views/widget/native_widget_mac_accessibility_unittest.mm b/ui/views/widget/native_widget_mac_accessibility_unittest.mm index 3d641d19..f7d373665 100644 --- a/ui/views/widget/native_widget_mac_accessibility_unittest.mm +++ b/ui/views/widget/native_widget_mac_accessibility_unittest.mm
@@ -39,19 +39,27 @@ // Add a child view and resize to fit the child. void FitBoundsToNewChild(View* view) { - View::AddChildView(view); + AddChildView(view); // Fit the parent widget to the size of the child for accurate hit tests. SetBoundsRect(view->bounds()); } + bool mouse_was_pressed() const { return mouse_was_pressed_; } + // View: void GetAccessibleNodeData(ui::AXNodeData* node_data) override { View::GetAccessibleNodeData(node_data); node_data->role = role_; } + bool OnMousePressed(const ui::MouseEvent& event) override { + mouse_was_pressed_ = true; + return false; + } + private: ui::AXRole role_; + bool mouse_was_pressed_ = false; DISALLOW_COPY_AND_ASSIGN(FlexibleRoleTestView); }; @@ -72,14 +80,16 @@ test::WidgetTest::TearDown(); } - id AttributeValueAtMidpoint(NSString* attribute) { + id A11yElementAtMidpoint() { // Accessibility hit tests come in Cocoa screen coordinates. NSPoint midpoint_in_screen_ = gfx::ScreenPointToNSPoint( widget_->GetWindowBoundsInScreen().CenterPoint()); - id hit = + return [widget_->GetNativeWindow() accessibilityHitTest:midpoint_in_screen_]; - id value = [hit accessibilityAttributeValue:attribute]; - return value; + } + + id AttributeValueAtMidpoint(NSString* attribute) { + return [A11yElementAtMidpoint() accessibilityAttributeValue:attribute]; } Textfield* AddChildTextfield(const gfx::Size& size) { @@ -311,14 +321,11 @@ view->SetSize(GetWidgetBounds().size()); widget()->GetContentsView()->AddChildView(view); - // Get the FlexibleRoleTestView accessibility object. - NSPoint midpoint = gfx::ScreenPointToNSPoint(GetWidgetBounds().CenterPoint()); - id ax_node = [widget()->GetNativeWindow() accessibilityHitTest:midpoint]; + // Make sure the accessibility object tested is the correct one. + id ax_node = A11yElementAtMidpoint(); EXPECT_TRUE(ax_node); - - // Make sure it's the correct accessibility object. - id value = [ax_node accessibilityAttributeValue:NSAccessibilityRoleAttribute]; - EXPECT_NSEQ(NSAccessibilityGroupRole, value); + EXPECT_NSEQ(NSAccessibilityGroupRole, + AttributeValueAtMidpoint(NSAccessibilityRoleAttribute)); // Make sure |view| is focusable, then focus/unfocus it. view->SetFocusBehavior(View::FocusBehavior::ALWAYS); @@ -413,4 +420,20 @@ textfield->GetSelectedRange()); } +// Test performing a 'click' on Views with clickable roles work. +TEST_F(NativeWidgetMacAccessibilityTest, PressAction) { + FlexibleRoleTestView* view = new FlexibleRoleTestView(ui::AX_ROLE_BUTTON); + widget()->GetContentsView()->AddChildView(view); + view->SetSize(GetWidgetBounds().size()); + + id ax_node = A11yElementAtMidpoint(); + EXPECT_NSEQ(NSAccessibilityButtonRole, + AttributeValueAtMidpoint(NSAccessibilityRoleAttribute)); + + EXPECT_TRUE([[ax_node accessibilityActionNames] + containsObject:NSAccessibilityPressAction]); + [ax_node accessibilityPerformAction:NSAccessibilityPressAction]; + EXPECT_TRUE(view->mouse_was_pressed()); +} + } // namespace views
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html index 2ed13112..814eced 100644 --- a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html +++ b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-tooltip/paper-tooltip.html"> <link rel="import" href="cr_policy_indicator_behavior.html"> <link rel="import" href="cr_policy_pref_behavior.html"> +<link rel="import" href="cr_policy_vars_css.html"> <dom-module id="cr-policy-pref-indicator"> <link rel="import" type="css" href="cr_policy_indicator.css">
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js index dcb58c4..5526eb5 100644 --- a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js +++ b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
@@ -40,5 +40,12 @@ var matches = pref && pref.value == pref.recommendedValue; return this.getPolicyIndicatorTooltip( type, pref.controlledByName || '', matches); - } + }, + + /** + * @return {boolean} Whether the policy indicator is on. Useful for testing. + */ + isActive: function() { + return this.isIndicatorVisible(this.indicatorType); + }, });