[Region Capture][cropTo][#8] Move crop-ID prod out of Element
Crop-ID production should be done in the browser process. Rationale:
1. It removes concerns of interference by a malicious application
that could otherwise be forcing collisions of crop-ID.
2. When cropTo() is called, validation of that a crop-ID (a) exists
and (b) belongs to the current browsing-context will ultimately
be done in the browser process.
This CL performs the first step by moving the production of the crop-ID
out of Element and into MediaDevices (where produceCropId is exposed
to JS). The next CL(s?) will move the production further, to the
browser process, with MediaDevices holding a Resolver that can finally
fulfill its Promise when the browser process responds with a newly
minted crop-ID.
Drive-by: Make GetRegionCaptureCropId() return a const-ptr.
Bug: 1247761
Change-Id: Ie0aa515584a7ef312bee2fa740f0f318c9b13646
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3253017
Commit-Queue: Elad Alon <eladalon@chromium.org>
Reviewed-by: mark a. foltz <mfoltz@chromium.org>
Reviewed-by: Jordan Bayles <jophba@chromium.org>
Reviewed-by: Justin Novosad <junov@chromium.org>
Cr-Commit-Position: refs/heads/main@{#937320}
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 70801f79..6d2f8fc 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -32,7 +32,6 @@
#include <memory>
#include <utility>
-#include "base/guid.h"
#include "cc/input/snap_selection_strategy.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
@@ -3624,24 +3623,14 @@
layout_object->Layer()->SetNeedsRepaint();
}
-base::GUID Element::MarkWithRegionCaptureCropId() {
+void Element::SetRegionCaptureCropId(
+ std::unique_ptr<RegionCaptureCropId> crop_id) {
ElementRareData& rare_data = EnsureElementRareData();
- const RegionCaptureCropId* const region_capture_id =
- rare_data.GetRegionCaptureCropId();
- if (region_capture_id) {
- // Convert the pre-existing crop-ID back into its GUID-form.
- // This is the less efficient string-based form that we avoid propagating
- // through the rendering pipeline, but which the Web-application expects.
- return TokenToGUID(region_capture_id->value());
- }
-
- // Produce a new crop-ID.
- const base::GUID guid = base::GUID::GenerateRandomV4();
+ CHECK(!rare_data.GetRegionCaptureCropId());
// Propagate efficient form through the rendering pipeline.
- rare_data.SetRegionCaptureCropId(
- std::make_unique<RegionCaptureCropId>(GUIDToToken(guid)));
+ rare_data.SetRegionCaptureCropId(std::move(crop_id));
// The crop ID needs to be propagated to the paint system by the time that
// capture begins. The API requires the implementation to propagate the
@@ -3649,11 +3638,9 @@
if (GetLayoutObject()) {
GetLayoutObject()->SetShouldDoFullPaintInvalidation();
}
-
- return guid;
}
-RegionCaptureCropId* Element::GetRegionCaptureCropId() const {
+const RegionCaptureCropId* Element::GetRegionCaptureCropId() const {
return HasRareData() ? GetElementRareData()->GetRegionCaptureCropId()
: nullptr;
}
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index f7a16f5..487030f 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -27,7 +27,6 @@
#include "base/dcheck_is_on.h"
#include "base/gtest_prod_util.h"
-#include "base/guid.h"
#include "third_party/blink/public/common/input/pointer_id.h"
#include "third_party/blink/public/common/metrics/document_update_reason.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
@@ -567,15 +566,17 @@
void SetNeedsCompositingUpdate();
- // Generates a unique crop ID and returns its base::GUID representation.
- // Not all element types have a region capture crop id, however using it here
+ // Assigns a crop-ID to the element. It's an error to try to call this
+ // if the element already has a crop-ID attached (even if attempting to
+ // set the same crop-ID again).
+ //
+ // Not all element types have a region capture crop-ID, however using it here
// allows access to the element rare data struct. Currently, once an element
- // is marked for region capture it cannot be unmarked, and repeated calls to
- // this API will return the same token.
- base::GUID MarkWithRegionCaptureCropId();
+ // is marked for region capture it cannot be unmarked.
+ void SetRegionCaptureCropId(std::unique_ptr<RegionCaptureCropId> crop_id);
- // Returns nullptr if not marked for capture.
- RegionCaptureCropId* GetRegionCaptureCropId() const;
+ // Returns a pointer to the crop-ID if one was set; nullptr otherwise.
+ const RegionCaptureCropId* GetRegionCaptureCropId() const;
ShadowRoot* attachShadow(const ShadowRootInit*, ExceptionState&);
diff --git a/third_party/blink/renderer/core/dom/element_rare_data.h b/third_party/blink/renderer/core/dom/element_rare_data.h
index 460e06a..e21186b0 100644
--- a/third_party/blink/renderer/core/dom/element_rare_data.h
+++ b/third_party/blink/renderer/core/dom/element_rare_data.h
@@ -149,11 +149,18 @@
return element_internals_;
}
- RegionCaptureCropId* GetRegionCaptureCropId() const {
+ // Returns the crop-ID if one was set, or nullptr otherwise.
+ const RegionCaptureCropId* GetRegionCaptureCropId() const {
return region_capture_crop_id_.get();
}
- void SetRegionCaptureCropId(std::unique_ptr<RegionCaptureCropId> value) {
- region_capture_crop_id_ = std::move(value);
+
+ // Sets a crop-ID on the item. Must be called at most once. Cannot be used
+ // to unset a previously set crop-ID.
+ void SetRegionCaptureCropId(std::unique_ptr<RegionCaptureCropId> crop_id) {
+ DCHECK(!GetRegionCaptureCropId());
+ DCHECK(crop_id);
+ DCHECK(!crop_id->value().is_zero());
+ region_capture_crop_id_ = std::move(crop_id);
}
void SetStyleShouldForceLegacyLayout(bool force) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.cc b/third_party/blink/renderer/modules/mediastream/media_devices.cc
index 198ebcd..7c95810 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -350,13 +350,30 @@
element_union->IsHTMLDivElement()
? static_cast<Element*>(element_union->GetAsHTMLDivElement())
: static_cast<Element*>(element_union->GetAsHTMLIFrameElement());
- const base::GUID crop_id = element->MarkWithRegionCaptureCropId();
- DCHECK(crop_id.is_valid());
- // Guaranteed because the empty Token is not a valid UUID-v4.
- DCHECK_NE(crop_id, blink::TokenToGUID(base::Token()));
+
+ const RegionCaptureCropId* const old_crop_id =
+ element->GetRegionCaptureCropId();
+ if (old_crop_id) { // produceCropId() previously called on this element.
+ DCHECK(!old_crop_id->value().is_zero());
+ resolver->Resolve(WTF::String(
+ blink::TokenToGUID(old_crop_id->value()).AsLowercaseString()));
+ return promise;
+ }
+
+ // TODO(crbug.com/1247761): Produce the crop-ID in the browser process,
+ // where it's free from interference by potential malicious applications
+ // trying to produce collisions. Also, we need it there in order to
+ // validate IDs provided to cropTo() for (1) validity and (2) association
+ // with the current browsing context.
+ const base::GUID new_crop_id = base::GUID::GenerateRandomV4();
+ element->SetRegionCaptureCropId(
+ std::make_unique<RegionCaptureCropId>(blink::GUIDToToken(new_crop_id)));
// TODO(crbug.com/1247761): Delay resolution until ack from Viz received.
- const std::string& serialized_crop_id = crop_id.AsLowercaseString();
+ // Multiple calls to produceCropId() will be handled by returning distinct
+ // Promises which are all fulfilled (in sequence) when the first one is
+ // fulfilled.
+ const std::string& serialized_crop_id = new_crop_id.AsLowercaseString();
resolver->Resolve(
WTF::String(serialized_crop_id.c_str(), serialized_crop_id.length()));
return promise;