Commit 21148739 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

Create validation message overlay page before main page lifecycle update

Previously we created validation message overlay page during main page
lifecycle update, and Microtask::PerformCheckpoint() called when the
overlay page FinishedParsing would execute some micro task of the
main page in wronglifecycle state.

Now create validation message overlay page when the overlay is created.

Bug: 945451
Change-Id: I618cd7ffe8c59cfee0b45452dc8dd9c0ee2e2fd8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1536992
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#644478}
parent d6a47e65
......@@ -75,25 +75,6 @@ void PagePopupClient::AddJavaScriptString(const String& str,
addLiteral("\"", data);
}
void PagePopupClient::AddHTMLString(const String& str, SharedBuffer* data) {
StringBuilder builder;
builder.ReserveCapacity(str.length());
for (unsigned i = 0; i < str.length(); ++i) {
if (str[i] == '&') {
builder.Append("&amp;");
} else if (str[i] == '<') {
builder.Append("&lt;");
} else if (str[i] == '\'') {
builder.Append("&apos;");
} else if (str[i] == '"') {
builder.Append("&quot;");
} else {
builder.Append(str[i]);
}
}
AddString(builder.ToString(), data);
}
void PagePopupClient::AddProperty(const char* name,
const String& value,
SharedBuffer* data) {
......
......@@ -82,7 +82,6 @@ class CORE_EXPORT PagePopupClient {
// Helper functions to be used in PagePopupClient::writeDocument().
static void AddString(const String&, SharedBuffer*);
static void AddJavaScriptString(const String&, SharedBuffer*);
static void AddHTMLString(const String&, SharedBuffer*);
static void AddProperty(const char* name, const String& value, SharedBuffer*);
static void AddProperty(const char* name, int value, SharedBuffer*);
static void AddProperty(const char* name, unsigned value, SharedBuffer*);
......
......@@ -89,6 +89,7 @@ void ValidationMessageClientImpl::ShowValidationMessage(
*page_, anchor, message_, message_dir, sub_message, sub_message_dir);
overlay_delegate_ = delegate.get();
overlay_ = std::make_unique<FrameOverlay>(target_frame, std::move(delegate));
overlay_delegate_->CreatePage(*overlay_);
bool success =
target_frame->View()->UpdateLifecycleToCompositingCleanPlusScrolling();
ValidationMessageVisibilityChanged(anchor);
......
......@@ -9,6 +9,7 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
......@@ -60,13 +61,13 @@ class ValidationMessageChromeClient : public EmptyChromeClient {
};
ValidationMessageOverlayDelegate::ValidationMessageOverlayDelegate(
Page& page,
Page& main_page,
const Element& anchor,
const String& message,
TextDirection message_dir,
const String& sub_message,
TextDirection sub_message_dir)
: main_page_(page),
: main_page_(main_page),
anchor_(anchor),
message_(message),
sub_message_(sub_message),
......@@ -74,13 +75,18 @@ ValidationMessageOverlayDelegate::ValidationMessageOverlayDelegate(
sub_message_dir_(sub_message_dir) {}
ValidationMessageOverlayDelegate::~ValidationMessageOverlayDelegate() {
if (page_)
if (page_) {
// This function can be called in EventDispatchForbiddenScope for the main
// document, and the following operations dispatch some events. It's safe
// because the page can't listen the events.
EventDispatchForbiddenScope::AllowUserAgentEvents allow_events;
page_->WillBeDestroyed();
}
}
LocalFrameView& ValidationMessageOverlayDelegate::FrameView() const {
DCHECK(page_)
<< "Do not call FrameView() before the first call of EnsurePage()";
<< "Do not call FrameView() before the first call of CreatePage()";
return *To<LocalFrame>(page_->MainFrame())->View();
}
......@@ -112,7 +118,6 @@ void ValidationMessageOverlayDelegate::PaintFrameOverlay(
void ValidationMessageOverlayDelegate::UpdateFrameViewState(
const FrameOverlay& overlay,
const IntSize& view_size) {
EnsurePage(overlay, view_size);
if (FrameView().Size() != view_size) {
FrameView().Resize(view_size);
page_->GetVisualViewport().SetSize(view_size);
......@@ -129,12 +134,12 @@ void ValidationMessageOverlayDelegate::UpdateFrameViewState(
DocumentLifecycle::LifecycleUpdateReason::kOther);
}
void ValidationMessageOverlayDelegate::EnsurePage(const FrameOverlay& overlay,
const IntSize& view_size) {
if (page_)
return;
void ValidationMessageOverlayDelegate::CreatePage(const FrameOverlay& overlay) {
DCHECK(!page_);
// TODO(tkent): Can we share code with WebPagePopupImpl and
// InspectorOverlayAgent?
IntSize view_size = overlay.Size();
Page::PageClients page_clients;
FillWithEmptyClients(page_clients);
chrome_client_ = MakeGarbageCollected<ValidationMessageChromeClient>(
......@@ -164,15 +169,18 @@ void ValidationMessageOverlayDelegate::EnsurePage(const FrameOverlay& overlay,
main_page_->DeviceScaleFactorDeprecated());
frame->ForceSynchronousDocumentInstall("text/html", data);
Element& main_message = GetElementById("main-message");
main_message.setTextContent(message_);
Element& sub_message = GetElementById("sub-message");
sub_message.setTextContent(sub_message_);
Element& container = GetElementById("container");
if (WebTestSupport::IsRunningWebTest()) {
container.SetInlineStyleProperty(CSSPropertyID::kTransition, "none");
GetElementById("icon").SetInlineStyleProperty(CSSPropertyID::kTransition,
"none");
GetElementById("main-message")
.SetInlineStyleProperty(CSSPropertyID::kTransition, "none");
GetElementById("sub-message")
.SetInlineStyleProperty(CSSPropertyID::kTransition, "none");
main_message.SetInlineStyleProperty(CSSPropertyID::kTransition, "none");
sub_message.SetInlineStyleProperty(CSSPropertyID::kTransition, "none");
}
// Get the size to decide position later.
// TODO(schenney): This says get size, so we only need to update to layout.
......@@ -207,17 +215,15 @@ void ValidationMessageOverlayDelegate::WriteDocument(SharedBuffer* data) {
data);
data->Append(Platform::Current()->GetDataResource("input_alert.svg"));
PagePopupClient::AddString(message_dir_ == TextDirection::kLtr
? "<div dir=ltr id=main-message>"
: "<div dir=rtl id=main-message>",
? "<div dir=ltr id=main-message></div>"
: "<div dir=rtl id=main-message></div>",
data);
PagePopupClient::AddHTMLString(message_, data);
PagePopupClient::AddString(sub_message_dir_ == TextDirection::kLtr
? "</div><div dir=ltr id=sub-message>"
: "</div><div dir=rtl id=sub-message>",
? "<div dir=ltr id=sub-message></div>"
: "<div dir=rtl id=sub-message></div>",
data);
PagePopupClient::AddHTMLString(sub_message_, data);
PagePopupClient::AddString(
"</div></main>"
"</main>"
"<div id=outer-arrow-bottom></div>"
"<div id=inner-arrow-bottom></div>"
"<div id=spacer-bottom></div>"
......
......@@ -25,7 +25,7 @@ class Page;
// Ownership: A FrameOverlay instance owns a ValidationMessageOverlayDelegate.
class ValidationMessageOverlayDelegate : public FrameOverlay::Delegate {
public:
ValidationMessageOverlayDelegate(Page&,
ValidationMessageOverlayDelegate(Page& main_page,
const Element& anchor,
const String& message,
TextDirection message_dir,
......@@ -33,6 +33,7 @@ class ValidationMessageOverlayDelegate : public FrameOverlay::Delegate {
TextDirection sub_message_dir);
~ValidationMessageOverlayDelegate() override;
void CreatePage(const FrameOverlay&);
void PaintFrameOverlay(const FrameOverlay&,
GraphicsContext&,
const IntSize& view_size) const override;
......@@ -42,7 +43,6 @@ class ValidationMessageOverlayDelegate : public FrameOverlay::Delegate {
private:
LocalFrameView& FrameView() const;
void UpdateFrameViewState(const FrameOverlay&, const IntSize& view_size);
void EnsurePage(const FrameOverlay&, const IntSize& view_size);
void WriteDocument(SharedBuffer*);
Element& GetElementById(const AtomicString&) const;
void AdjustBubblePosition(const IntRect& view_rect);
......
<!DOCTYPE html>
<select id="select" required></select>
<script>
select.reportValidity();
</script>
<input type="image">
<!DOCTYPE html>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<iframe id="iframe"></iframe>
<script>
var t = async_test();
var repeat = 3;
function test() {
if (repeat -- > 0)
iframe.src = 'resources/validation-message-crash-iframe.html';
else
t.done();
}
t.step(() => {
iframe.onload = test;
test();
});
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment