Commit 2c9da4f3 authored by ckitagawa's avatar ckitagawa Committed by Commit Bot

[Paint Preview] Refactor and test paint_preview_utils

paint_preview_utils will be used in an experiment. To this end it should
have test coverage and be refactored/cleaner. This also fixes a crash
that occurred in some situations.

Bug: 1049128
Change-Id: I66b031bd518996a13fdaedd437b80ce8c646bf8c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2038081Reviewed-by: default avatarMichael Thiessen <mthiesse@chromium.org>
Reviewed-by: default avatarMehran Mahmoudi <mahmoudi@chromium.org>
Commit-Queue: Calder Kitagawa <ckitagawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#739065}
parent 8cf28dcc
......@@ -320,6 +320,7 @@ test("components_unittests") {
"//components/invalidation/impl",
"//components/invalidation/impl:java",
"//components/paint_preview/browser/android:java",
"//components/paint_preview/browser/android:unit_tests",
"//components/paint_preview/player/android:unit_tests",
"//components/policy/android:policy_java",
"//components/signin/core/browser",
......
......@@ -26,7 +26,10 @@ android_library("java") {
}
source_set("android") {
sources = [ "paint_preview_utils.cc" ]
sources = [
"paint_preview_utils.cc",
"paint_preview_utils.h",
]
deps = [
":jni_headers",
......@@ -36,3 +39,24 @@ source_set("android") {
"//content/public/browser",
]
}
source_set("unit_tests") {
testonly = true
sources = [ "paint_preview_utils_unittest.cc" ]
deps = [
":android",
"//base",
"//base/test:test_support",
"//components/paint_preview/common:test_utils",
"//components/paint_preview/common/mojom",
"//content/public/browser",
"//content/test:test_support",
"//testing/gmock",
"//testing/gtest",
"//third_party/blink/public:blink_headers",
"//third_party/blink/public/common",
"//third_party/zlib/google:zip",
]
}
// Copyright 2020 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 COMPONENTS_PAINT_PREVIEW_BROWSER_ANDROID_PAINT_PREVIEW_UTILS_H_
#define COMPONENTS_PAINT_PREVIEW_BROWSER_ANDROID_PAINT_PREVIEW_UTILS_H_
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/optional.h"
namespace content {
class WebContents;
} // namespace content
namespace paint_preview {
using FinishedCallback =
base::OnceCallback<void(const base::Optional<base::FilePath>&)>;
// Captures a paint preview of |contents|. On completion returns the path of the
// zip archive in which the paint preview is stored via |finished| (or an empty
// path if the capture failed). The zip archive will exist only if |keep_zip| is
// true.
void Capture(content::WebContents* contents,
FinishedCallback finished,
bool keep_zip);
} // namespace paint_preview
#endif // COMPONENTS_PAINT_PREVIEW_BROWSER_ANDROID_PAINT_PREVIEW_UTILS_H_
// Copyright 2020 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 "components/paint_preview/browser/android/paint_preview_utils.h"
#include <utility>
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "components/paint_preview/common/mojom/paint_preview_recorder.mojom.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_renderer_host.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/zlib/google/zip.h"
namespace paint_preview {
namespace {
class MockPaintPreviewRecorder : public mojom::PaintPreviewRecorder {
public:
MockPaintPreviewRecorder() = default;
~MockPaintPreviewRecorder() override = default;
MockPaintPreviewRecorder(const MockPaintPreviewRecorder&) = delete;
MockPaintPreviewRecorder& operator=(const MockPaintPreviewRecorder&) = delete;
void CapturePaintPreview(
mojom::PaintPreviewCaptureParamsPtr params,
mojom::PaintPreviewRecorder::CapturePaintPreviewCallback callback)
override {
std::move(callback).Run(status_, mojom::PaintPreviewCaptureResponse::New());
}
void SetResponseStatus(mojom::PaintPreviewStatus status) { status_ = status; }
void BindRequest(mojo::ScopedInterfaceEndpointHandle handle) {
binding_.Bind(mojo::PendingAssociatedReceiver<mojom::PaintPreviewRecorder>(
std::move(handle)));
}
private:
mojom::PaintPreviewStatus status_;
mojo::AssociatedReceiver<mojom::PaintPreviewRecorder> binding_{this};
};
base::Optional<base::FilePath> Unzip(const base::FilePath& zip) {
base::FilePath dst_path = zip.RemoveExtension();
if (!base::CreateDirectory(dst_path))
return base::nullopt;
if (!zip::Unzip(zip, dst_path))
return base::nullopt;
base::DeleteFileRecursively(zip);
return dst_path;
}
} // namespace
class PaintPreviewUtilsRenderViewHostTest
: public content::RenderViewHostTestHarness {
public:
PaintPreviewUtilsRenderViewHostTest() {}
PaintPreviewUtilsRenderViewHostTest(
const PaintPreviewUtilsRenderViewHostTest&) = delete;
PaintPreviewUtilsRenderViewHostTest& operator=(
const PaintPreviewUtilsRenderViewHostTest&) = delete;
protected:
void SetUp() override {
RenderViewHostTestHarness::SetUp();
content::RenderFrameHostTester::For(main_rfh())
->InitializeRenderFrameIfNeeded();
}
void OverrideInterface(MockPaintPreviewRecorder* service) {
blink::AssociatedInterfaceProvider* remote_interfaces =
web_contents()->GetMainFrame()->GetRemoteAssociatedInterfaces();
remote_interfaces->OverrideBinderForTesting(
mojom::PaintPreviewRecorder::Name_,
base::BindRepeating(&MockPaintPreviewRecorder::BindRequest,
base::Unretained(service)));
}
};
TEST_F(PaintPreviewUtilsRenderViewHostTest, CaptureSingleFrameAndKeep) {
auto* contents = content::WebContents::FromRenderFrameHost(main_rfh());
MockPaintPreviewRecorder service;
service.SetResponseStatus(mojom::PaintPreviewStatus::kOk);
OverrideInterface(&service);
base::RunLoop loop;
Capture(contents,
base::BindOnce(
[](base::OnceClosure quit,
const base::Optional<base::FilePath>& maybe_zip_path) {
EXPECT_TRUE(maybe_zip_path.has_value());
const base::FilePath& zip_path = maybe_zip_path.value();
EXPECT_EQ(".zip", zip_path.Extension());
{
base::ScopedAllowBlockingForTesting scope;
EXPECT_TRUE(base::PathExists(zip_path));
auto unzipped_path = Unzip(zip_path);
EXPECT_TRUE(unzipped_path.has_value());
base::FileEnumerator enumerate(unzipped_path.value(), false,
base::FileEnumerator::FILES);
size_t count = 0;
bool has_proto = false;
bool has_skp = false;
for (base::FilePath name = enumerate.Next(); !name.empty();
name = enumerate.Next(), ++count) {
if (name.Extension() == ".skp")
has_skp = true;
if (name.BaseName().AsUTF8Unsafe() == "proto.pb")
has_proto = true;
}
EXPECT_EQ(2U, count);
EXPECT_TRUE(has_skp);
EXPECT_TRUE(has_proto);
base::DeleteFileRecursively(zip_path.DirName());
}
std::move(quit).Run();
},
loop.QuitClosure()),
true);
loop.Run();
}
TEST_F(PaintPreviewUtilsRenderViewHostTest, CaptureSingleFrameAndDelete) {
auto* contents = content::WebContents::FromRenderFrameHost(main_rfh());
MockPaintPreviewRecorder service;
service.SetResponseStatus(mojom::PaintPreviewStatus::kOk);
OverrideInterface(&service);
base::RunLoop loop;
Capture(contents,
base::BindOnce(
[](base::OnceClosure quit,
const base::Optional<base::FilePath>& maybe_zip_path) {
EXPECT_TRUE(maybe_zip_path.has_value());
const base::FilePath& zip_path = maybe_zip_path.value();
{
base::ScopedAllowBlockingForTesting scope;
EXPECT_FALSE(base::PathExists(zip_path));
EXPECT_FALSE(base::DirectoryExists(zip_path.DirName()));
}
std::move(quit).Run();
},
loop.QuitClosure()),
false);
loop.Run();
}
TEST_F(PaintPreviewUtilsRenderViewHostTest, SingleFrameFailure) {
auto* contents = content::WebContents::FromRenderFrameHost(main_rfh());
MockPaintPreviewRecorder service;
service.SetResponseStatus(mojom::PaintPreviewStatus::kFailed);
OverrideInterface(&service);
base::RunLoop loop;
Capture(contents,
base::BindOnce(
[](base::OnceClosure quit,
const base::Optional<base::FilePath>& zip_path) {
EXPECT_FALSE(zip_path.has_value());
std::move(quit).Run();
},
loop.QuitClosure()),
false);
loop.Run();
}
} // namespace paint_preview
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