Added initial page annotator code.
This is the first class in the image annotation client library, which will support the use of the image annotation service (see Google-internal doc go/chrome-image-annotation-dd) for images on webpages. The page annotator will be used to schedule and receive image annotations for one web page. This initial CL only contains minimal observer logic; the annotation logic (i.e. communication with the annotation service) will be added when the service is complete. Bug: crbug.com/916363 Change-Id: I74ff44ba707cab972866999cbe0c9542d509293d Reviewed-on: https://chromium-review.googlesource.com/c/1383756 Reviewed-by: Avi Drissman <avi@chromium.org> Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org> Reviewed-by: Colin Blundell <blundell@chromium.org> Reviewed-by: Charles . <charleszhao@chromium.org> Commit-Queue: Michael Martis <martis@chromium.org> Cr-Commit-Position: refs/heads/master@{#621336}
This commit is contained in:

committed by
Commit Bot

parent
87fd1bc02d
commit
1a57af941a
components
@ -128,6 +128,7 @@ test("components_unittests") {
|
||||
"//components/omnibox/browser:unit_tests",
|
||||
"//components/open_from_clipboard:unit_tests",
|
||||
"//components/os_crypt:unit_tests",
|
||||
"//components/page_image_annotation/core:unit_tests",
|
||||
"//components/password_manager/core/browser:unit_tests",
|
||||
"//components/password_manager/core/common:unit_tests",
|
||||
"//components/payments/core:unit_tests",
|
||||
|
5
components/page_image_annotation/DEPS
Normal file
5
components/page_image_annotation/DEPS
Normal file
@ -0,0 +1,5 @@
|
||||
include_rules = [
|
||||
# Page image annotation is a layered component; subdirectories must explicitly
|
||||
# introduce the ability to use the content layer as appropriate.
|
||||
"-components/page_image_annotation/content",
|
||||
]
|
3
components/page_image_annotation/OWNERS
Normal file
3
components/page_image_annotation/OWNERS
Normal file
@ -0,0 +1,3 @@
|
||||
amoylan@chromium.org
|
||||
dmazzoni@chromium.org
|
||||
martis@chromium.org
|
11
components/page_image_annotation/README.md
Normal file
11
components/page_image_annotation/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# //components/page_image_annotation
|
||||
|
||||
Library for using the image annotation service on images on webpages.
|
||||
|
||||
The image annotation service performs general image processing / labeling tasks
|
||||
in Chromium. This library enables use of the service with webpages; for example,
|
||||
by tracking images on webpages and sending their pixel data to the service.
|
||||
|
||||
This is a layered component
|
||||
(https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-design)
|
||||
which allows it to be shared cleanly on iOS.
|
4
components/page_image_annotation/content/DEPS
Normal file
4
components/page_image_annotation/content/DEPS
Normal file
@ -0,0 +1,4 @@
|
||||
include_rules = [
|
||||
"+components/page_image_annotation/core",
|
||||
"+content/public/common",
|
||||
]
|
17
components/page_image_annotation/content/renderer/BUILD.gn
Normal file
17
components/page_image_annotation/content/renderer/BUILD.gn
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright 2019 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.
|
||||
|
||||
static_library("renderer") {
|
||||
sources = [
|
||||
"content_page_annotator_driver.cc",
|
||||
"content_page_annotator_driver.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//components/page_image_annotation/core",
|
||||
"//content/public/common",
|
||||
"//content/public/renderer",
|
||||
]
|
||||
}
|
5
components/page_image_annotation/content/renderer/DEPS
Normal file
5
components/page_image_annotation/content/renderer/DEPS
Normal file
@ -0,0 +1,5 @@
|
||||
include_rules = [
|
||||
"+components/page_image_annotation/core",
|
||||
"+content/public/renderer",
|
||||
"+ui/base",
|
||||
]
|
@ -0,0 +1,45 @@
|
||||
// Copyright 2019 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/page_image_annotation/content/renderer/content_page_annotator_driver.h"
|
||||
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
|
||||
namespace page_image_annotation {
|
||||
|
||||
ContentPageAnnotatorDriver::ContentPageAnnotatorDriver(
|
||||
content::RenderFrame* const render_frame)
|
||||
: RenderFrameObserver(render_frame),
|
||||
RenderFrameObserverTracker<ContentPageAnnotatorDriver>(render_frame) {}
|
||||
|
||||
ContentPageAnnotatorDriver::~ContentPageAnnotatorDriver() {}
|
||||
|
||||
// static
|
||||
ContentPageAnnotatorDriver* ContentPageAnnotatorDriver::GetOrCreate(
|
||||
content::RenderFrame* const render_frame) {
|
||||
ContentPageAnnotatorDriver* const existing = Get(render_frame);
|
||||
if (existing)
|
||||
return existing;
|
||||
|
||||
return new ContentPageAnnotatorDriver(render_frame);
|
||||
}
|
||||
|
||||
PageAnnotator& ContentPageAnnotatorDriver::GetPageAnnotator() {
|
||||
return page_annotator_;
|
||||
}
|
||||
|
||||
void ContentPageAnnotatorDriver::DidCommitProvisionalLoad(
|
||||
const bool /* is_same_document_navigation */,
|
||||
const ui::PageTransition /* transition */) {
|
||||
// TODO(crbug.com/915076): schedule repeated DOM traversals to track image
|
||||
// addition / modification / removal.
|
||||
}
|
||||
|
||||
void ContentPageAnnotatorDriver::OnDestruct() {
|
||||
// TODO(crbug.com/915076): cancel DOM traversal.
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
} // namespace page_image_annotation
|
@ -0,0 +1,44 @@
|
||||
// Copyright 2019 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_PAGE_IMAGE_ANNOTATION_CONTENT_RENDERER_CONTENT_PAGE_ANNOTATOR_DRIVER_H_
|
||||
#define COMPONENTS_PAGE_IMAGE_ANNOTATION_CONTENT_RENDERER_CONTENT_PAGE_ANNOTATOR_DRIVER_H_
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "components/page_image_annotation/core/page_annotator.h"
|
||||
#include "content/public/renderer/render_frame_observer.h"
|
||||
#include "content/public/renderer/render_frame_observer_tracker.h"
|
||||
#include "ui/base/page_transition_types.h"
|
||||
|
||||
namespace page_image_annotation {
|
||||
|
||||
class ContentPageAnnotatorDriver
|
||||
: public content::RenderFrameObserver,
|
||||
public content::RenderFrameObserverTracker<ContentPageAnnotatorDriver> {
|
||||
public:
|
||||
~ContentPageAnnotatorDriver() override;
|
||||
|
||||
static ContentPageAnnotatorDriver* GetOrCreate(
|
||||
content::RenderFrame* render_frame);
|
||||
|
||||
PageAnnotator& GetPageAnnotator();
|
||||
|
||||
private:
|
||||
// We delete ourselves on frame destruction, so disallow construction on the
|
||||
// stack.
|
||||
ContentPageAnnotatorDriver(content::RenderFrame* render_frame);
|
||||
|
||||
// content::RenderFrameObserver:
|
||||
void DidCommitProvisionalLoad(bool is_same_document_navigation,
|
||||
ui::PageTransition transition) override;
|
||||
void OnDestruct() override;
|
||||
|
||||
PageAnnotator page_annotator_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ContentPageAnnotatorDriver);
|
||||
};
|
||||
|
||||
} // namespace page_image_annotation
|
||||
|
||||
#endif // COMPONENTS_PAGE_IMAGE_ANNOTATION_CONTENT_RENDERER_CONTENT_PAGE_ANNOTATOR_DRIVER_H_
|
29
components/page_image_annotation/core/BUILD.gn
Normal file
29
components/page_image_annotation/core/BUILD.gn
Normal file
@ -0,0 +1,29 @@
|
||||
# Copyright 2019 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.
|
||||
|
||||
static_library("core") {
|
||||
sources = [
|
||||
"page_annotator.cc",
|
||||
"page_annotator.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("unit_tests") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"page_annotator_unittest.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":core",
|
||||
"//base",
|
||||
"//base/test:test_support",
|
||||
"//testing/gmock",
|
||||
"//testing/gtest",
|
||||
]
|
||||
}
|
66
components/page_image_annotation/core/page_annotator.cc
Normal file
66
components/page_image_annotation/core/page_annotator.cc
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2019 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/page_image_annotation/core/page_annotator.h"
|
||||
|
||||
namespace page_image_annotation {
|
||||
|
||||
PageAnnotator::Observer::~Observer() {}
|
||||
|
||||
PageAnnotator::Subscription::Subscription(
|
||||
const Observer* const observer,
|
||||
base::WeakPtr<PageAnnotator> page_annotator)
|
||||
: observer_(observer), page_annotator_(page_annotator) {}
|
||||
|
||||
PageAnnotator::Subscription::Subscription(Subscription&& subscription) =
|
||||
default;
|
||||
|
||||
PageAnnotator::Subscription::~Subscription() {
|
||||
Cancel();
|
||||
}
|
||||
|
||||
void PageAnnotator::Subscription::Cancel() {
|
||||
if (page_annotator_)
|
||||
page_annotator_->RemoveObserver(observer_);
|
||||
}
|
||||
|
||||
PageAnnotator::PageAnnotator() : weak_ptr_factory_(this) {}
|
||||
|
||||
PageAnnotator::~PageAnnotator() {}
|
||||
|
||||
void PageAnnotator::ImageAdded(const uint64_t node_id,
|
||||
const std::string& source_id) {
|
||||
// TODO(crbug.com/916363): create a connection to the image annotation service
|
||||
// for this image.
|
||||
for (Observer& observer : observers_) {
|
||||
observer.OnImageAdded(node_id);
|
||||
}
|
||||
}
|
||||
|
||||
void PageAnnotator::ImageModified(const uint64_t node_id,
|
||||
const std::string& source_id) {
|
||||
// TODO(crbug.com/916363): reset the service connection for this image.
|
||||
|
||||
for (Observer& observer : observers_) {
|
||||
observer.OnImageModified(node_id);
|
||||
}
|
||||
}
|
||||
|
||||
void PageAnnotator::ImageRemoved(const uint64_t node_id) {
|
||||
// TODO(crbug.com/916363): close the service connection for this image.
|
||||
for (Observer& observer : observers_) {
|
||||
observer.OnImageRemoved(node_id);
|
||||
}
|
||||
}
|
||||
|
||||
PageAnnotator::Subscription PageAnnotator::AddObserver(Observer* observer) {
|
||||
observers_.AddObserver(observer);
|
||||
return Subscription(observer, weak_ptr_factory_.GetWeakPtr());
|
||||
}
|
||||
|
||||
void PageAnnotator::RemoveObserver(const Observer* observer) {
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
} // namespace page_image_annotation
|
90
components/page_image_annotation/core/page_annotator.h
Normal file
90
components/page_image_annotation/core/page_annotator.h
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright 2019 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_PAGE_IMAGE_ANNOTATION_CORE_PAGE_ANNOTATOR_H_
|
||||
#define COMPONENTS_PAGE_IMAGE_ANNOTATION_CORE_PAGE_ANNOTATOR_H_
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/observer_list_types.h"
|
||||
|
||||
namespace page_image_annotation {
|
||||
|
||||
// Notifies clients of page images that can be annotated and forwards annotation
|
||||
// requests for these images to the image annotation service.
|
||||
//
|
||||
// TODO(crbug.com/916363): this class is not yet complete - add more logic (e.g.
|
||||
// communication with the service).
|
||||
class PageAnnotator {
|
||||
public:
|
||||
// Clients (i.e. classes that annotate page images) should implement this
|
||||
// interface.
|
||||
class Observer : public base::CheckedObserver {
|
||||
public:
|
||||
~Observer() override;
|
||||
|
||||
// These methods are called during page lifecycle to notify the observer
|
||||
// about changes to page images.
|
||||
|
||||
// Called exactly once per image, at the point that the image appears on the
|
||||
// page (or at the point that the observer subscribes to the page annotator,
|
||||
// if the image already exists on page).
|
||||
virtual void OnImageAdded(uint64_t node_id) = 0;
|
||||
|
||||
// Called at the point that an image source is updated.
|
||||
virtual void OnImageModified(uint64_t node_id) = 0;
|
||||
|
||||
// Called at the point that an image disappears from the page.
|
||||
virtual void OnImageRemoved(uint64_t node_id) = 0;
|
||||
};
|
||||
|
||||
// A subscription instance must be held by each observer of the page
|
||||
// annotator; an observer will receive updates from the page annotator until
|
||||
// the Cancel method of the subscription is called (this occurs automatically
|
||||
// on subscription destruction).
|
||||
//
|
||||
// Typically, both the page annotator and its observers are scoped to the
|
||||
// lifetime of a render frame. Destruction of such objects can proceed in an
|
||||
// unspecified order, so subscriptions are used to ensure the page annotator
|
||||
// only communicates with an observers that are still alive.
|
||||
class Subscription {
|
||||
public:
|
||||
Subscription(const Observer* observer,
|
||||
base::WeakPtr<PageAnnotator> page_annotator);
|
||||
Subscription(Subscription&& subscription);
|
||||
~Subscription();
|
||||
|
||||
// Unsubscribe from updates from the page annotator.
|
||||
void Cancel();
|
||||
|
||||
private:
|
||||
const Observer* observer_;
|
||||
base::WeakPtr<PageAnnotator> page_annotator_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Subscription);
|
||||
};
|
||||
|
||||
PageAnnotator();
|
||||
~PageAnnotator();
|
||||
|
||||
// Called by platform drivers.
|
||||
void ImageAdded(uint64_t node_id, const std::string& source_id);
|
||||
void ImageModified(uint64_t node_id, const std::string& source_id);
|
||||
void ImageRemoved(uint64_t node_id);
|
||||
|
||||
Subscription AddObserver(Observer* observer) WARN_UNUSED_RESULT;
|
||||
|
||||
private:
|
||||
void RemoveObserver(const Observer* observer);
|
||||
|
||||
base::ObserverList<Observer> observers_;
|
||||
base::WeakPtrFactory<PageAnnotator> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PageAnnotator);
|
||||
};
|
||||
|
||||
} // namespace page_image_annotation
|
||||
|
||||
#endif // COMPONENTS_PAGE_IMAGE_ANNOTATION_CORE_PAGE_ANNOTATOR_H_
|
@ -0,0 +1,64 @@
|
||||
// Copyright 2019 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/page_image_annotation/core/page_annotator.h"
|
||||
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace page_image_annotation {
|
||||
|
||||
using testing::Eq;
|
||||
|
||||
// Tests that destroying subscriptions successfully prevents notifications.
|
||||
TEST(PageAnnotatorTest, Subscriptions) {
|
||||
class TestObserver : public PageAnnotator::Observer {
|
||||
public:
|
||||
TestObserver(PageAnnotator* const page_annotator)
|
||||
: sub_(page_annotator->AddObserver(this)), last_id_(0ul) {}
|
||||
|
||||
void OnImageAdded(const uint64_t node_id) override { last_id_ = node_id; }
|
||||
void OnImageModified(const uint64_t node_id) override {
|
||||
last_id_ = node_id;
|
||||
}
|
||||
void OnImageRemoved(const uint64_t node_id) override { last_id_ = node_id; }
|
||||
|
||||
PageAnnotator::Subscription sub_;
|
||||
uint64_t last_id_;
|
||||
};
|
||||
|
||||
PageAnnotator page_annotator;
|
||||
TestObserver o1(&page_annotator), o2(&page_annotator);
|
||||
|
||||
page_annotator.ImageAdded(1ul, "test.jpg");
|
||||
EXPECT_THAT(o1.last_id_, Eq(1ul));
|
||||
EXPECT_THAT(o2.last_id_, Eq(1ul));
|
||||
|
||||
page_annotator.ImageAdded(2ul, "example.png");
|
||||
EXPECT_THAT(o1.last_id_, Eq(2ul));
|
||||
EXPECT_THAT(o2.last_id_, Eq(2ul));
|
||||
|
||||
page_annotator.ImageModified(1ul, "demo.gif");
|
||||
EXPECT_THAT(o1.last_id_, Eq(1ul));
|
||||
EXPECT_THAT(o2.last_id_, Eq(1ul));
|
||||
|
||||
page_annotator.ImageRemoved(2ul);
|
||||
EXPECT_THAT(o1.last_id_, Eq(2ul));
|
||||
EXPECT_THAT(o2.last_id_, Eq(2ul));
|
||||
|
||||
o1.sub_.Cancel();
|
||||
page_annotator.ImageAdded(3ul, "placeholder.bmp");
|
||||
EXPECT_THAT(o1.last_id_, Eq(2ul));
|
||||
EXPECT_THAT(o2.last_id_, Eq(3ul));
|
||||
|
||||
o2.sub_.Cancel();
|
||||
page_annotator.ImageRemoved(1ul);
|
||||
EXPECT_THAT(o1.last_id_, Eq(2ul));
|
||||
EXPECT_THAT(o2.last_id_, Eq(3ul));
|
||||
}
|
||||
|
||||
// TODO(crbug.com/916363): add more tests when behavior is added to the
|
||||
// PageAnnotator class.
|
||||
|
||||
} // namespace page_image_annotation
|
Reference in New Issue
Block a user