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/omnibox/browser:unit_tests",
|
||||||
"//components/open_from_clipboard:unit_tests",
|
"//components/open_from_clipboard:unit_tests",
|
||||||
"//components/os_crypt: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/browser:unit_tests",
|
||||||
"//components/password_manager/core/common:unit_tests",
|
"//components/password_manager/core/common:unit_tests",
|
||||||
"//components/payments/core: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