0

PDF: Avoid paint invalidates while painting.

PaintManager has a DCHECK that disallows this, but it can happen. To
prevent the DCHECK failure, keep track of whether OutOfProcessInstance
is painting or not. While painting, defer all invalidation requests
until after the painting finishes.

Bug: 1021800
Change-Id: I4326106df5c2bba30f8412f4d710aefb04e0aa03
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2154387
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Daniel Hosseinian <dhoss@chromium.org>
Cr-Commit-Position: refs/heads/master@{#760249}
This commit is contained in:
Lei Zhang
2020-04-17 23:10:26 +00:00
committed by Commit Bot
parent 30cdf24118
commit 8745db7d1a
2 changed files with 29 additions and 0 deletions

@ -12,6 +12,7 @@
#include <list>
#include <memory>
#include "base/auto_reset.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
@ -1151,6 +1152,7 @@ void OutOfProcessInstance::StopFind() {
void OutOfProcessInstance::OnPaint(const std::vector<pp::Rect>& paint_rects,
std::vector<PaintManager::ReadyRect>* ready,
std::vector<pp::Rect>* pending) {
base::AutoReset<bool> auto_reset_in_paint(&in_paint_, true);
if (image_data_.is_null()) {
DCHECK(plugin_size_.IsEmpty());
return;
@ -1214,6 +1216,12 @@ void OutOfProcessInstance::OnPaint(const std::vector<pp::Rect>& paint_rects,
}
engine_->PostPaint();
if (!deferred_invalidates_.empty()) {
pp::CompletionCallback callback = callback_factory_.NewCallback(
&OutOfProcessInstance::InvalidateAfterPaintDone);
pp::Module::Get()->core()->CallOnMainThread(0, callback);
}
}
void OutOfProcessInstance::DidOpen(int32_t result) {
@ -1302,6 +1310,11 @@ void OutOfProcessInstance::ProposeDocumentLayout(const DocumentLayout& layout) {
}
void OutOfProcessInstance::Invalidate(const pp::Rect& rect) {
if (in_paint_) {
deferred_invalidates_.push_back(rect);
return;
}
pp::Rect offset_rect(rect);
offset_rect.Offset(available_area_.point());
paint_manager_.InvalidateRect(offset_rect);
@ -1694,6 +1707,7 @@ void OutOfProcessInstance::SetTwoUpView(bool enable_two_up_view) {
engine_->SetTwoUpView(enable_two_up_view);
}
// static
std::string OutOfProcessInstance::GetFileNameFromUrl(const std::string& url) {
// Generate a file name. Unfortunately, MIME type can't be provided, since it
// requires IO.
@ -2043,6 +2057,14 @@ void OutOfProcessInstance::OnPrint(int32_t /*unused_but_required*/) {
pp::PDF::Print(this);
}
void OutOfProcessInstance::InvalidateAfterPaintDone(
int32_t /*unused_but_required*/) {
DCHECK(!in_paint_);
for (const pp::Rect& rect : deferred_invalidates_)
Invalidate(rect);
deferred_invalidates_.clear();
}
void OutOfProcessInstance::PrintSettings::Clear() {
is_printing = false;
print_pages_called = false;

@ -261,6 +261,9 @@ class OutOfProcessInstance : public pp::Instance,
// Callback to print without re-entrancy issues.
void OnPrint(int32_t /*unused_but_required*/);
// Callback to do invalidation after painting finishes.
void InvalidateAfterPaintDone(int32_t /*unused_but_required*/);
pp::ImageData image_data_;
// Used when the plugin is embedded in a page and we have to create the loader
// ourself.
@ -314,6 +317,10 @@ class OutOfProcessInstance : public pp::Instance,
// True if we haven't painted the plugin viewport yet.
bool first_paint_ = true;
// Whether OnPaint() is in progress or not.
bool in_paint_ = false;
// Deferred invalidates while |in_paint_| is true.
std::vector<pp::Rect> deferred_invalidates_;
struct BackgroundPart {
pp::Rect location;