Skip to content

Commit

Permalink
Shape Detection: Implement FaceDetection on Mac as out-of-process ser…
Browse files Browse the repository at this point in the history
…vice

This CL implements FaceDetection in //services/shape_detection. The Browser
forwards requests from the Renderer process to a Utility process, which detects
faces using Mac native CoreImage library and returns detection result.

DESIGN_DOC=http://tinyurl.com/shape-detection-in-chromium
BUG=659139
TEST=content/browser/shapedetection/shapedetection_browsertest.cc
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_site_isolation

Review-Url: https://codereview.chromium.org/2528743002
Cr-Commit-Position: refs/heads/master@{#445942}
  • Loading branch information
Nadia-mint authored and Commit bot committed Jan 25, 2017
1 parent 12040fd commit 6dd8f46
Show file tree
Hide file tree
Showing 24 changed files with 466 additions and 8 deletions.
4 changes: 3 additions & 1 deletion content/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ source_set("browser") {
"//services/service_manager/public/interfaces",
"//services/service_manager/runner/common",
"//services/service_manager/runner/host:lib",
"//services/shape_detection/public/interfaces:interfaces",
"//services/shape_detection:lib",
"//services/shape_detection/public/interfaces",
"//services/ui/gpu/interfaces",
"//services/ui/public/cpp/gpu",
"//skia",
Expand Down Expand Up @@ -1305,6 +1306,7 @@ source_set("browser") {
"service_worker/service_worker_version.h",
"service_worker/service_worker_write_to_cache_job.cc",
"service_worker/service_worker_write_to_cache_job.h",
"shapedetection/face_detection_service_dispatcher.h",
"shared_worker/shared_worker_host.cc",
"shared_worker/shared_worker_host.h",
"shared_worker/shared_worker_instance.cc",
Expand Down
7 changes: 7 additions & 0 deletions content/browser/renderer_host/render_process_host_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@
#if defined(OS_MACOSX)
#include "content/browser/bootstrap_sandbox_manager_mac.h"
#include "content/browser/mach_broker_mac.h"
#include "content/browser/shapedetection/face_detection_service_dispatcher.h"
#endif

#if defined(OS_POSIX)
Expand Down Expand Up @@ -1196,6 +1197,12 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
channel_->AddAssociatedInterfaceForIOThread(
base::Bind(&IndexedDBDispatcherHost::AddBinding, indexed_db_factory_));

#if defined(OS_MACOSX)
AddUIThreadInterface(
registry.get(),
base::Bind(&FaceDetectionServiceDispatcher::CreateMojoService));
#endif

#if defined(OS_ANDROID)
AddUIThreadInterface(registry.get(),
GetGlobalJavaInterfaces()
Expand Down
5 changes: 5 additions & 0 deletions content/browser/service_manager/service_manager_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/service_manager/merge_dictionary.h"
#include "content/common/service_manager/service_manager_connection_impl.h"
Expand All @@ -38,6 +39,7 @@
#include "services/service_manager/public/interfaces/service.mojom.h"
#include "services/service_manager/runner/common/client_util.h"
#include "services/service_manager/service_manager.h"
#include "services/shape_detection/public/interfaces/constants.mojom.h"

namespace content {

Expand Down Expand Up @@ -311,6 +313,9 @@ ServiceManagerContext::ServiceManagerContext() {
GetContentClient()
->browser()
->RegisterUnsandboxedOutOfProcessServices(&unsandboxed_services);
unsandboxed_services.insert(
std::make_pair(shape_detection::mojom::kServiceName,
base::ASCIIToUTF16("Shape Detection Service")));
for (const auto& service : unsandboxed_services) {
ServiceManagerConnection::GetForProcess()->AddServiceRequestHandler(
service.first,
Expand Down
33 changes: 33 additions & 0 deletions content/browser/shapedetection/face_detection_service_dispatcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2017 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 CONTENT_BROWSER_SHAPEDETECTION_FACE_DETECTION_SERVICE_DISPATCHER_H_
#define CONTENT_BROWSER_SHAPEDETECTION_FACE_DETECTION_SERVICE_DISPATCHER_H_

#include "content/common/content_export.h"
#include "content/public/common/service_manager_connection.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/shape_detection/public/interfaces/constants.mojom.h"
#include "services/shape_detection/public/interfaces/facedetection_provider.mojom.h"

namespace content {

// Because the renderer cannot launch an out-of-process service on its own, we
// use |FaceDetectionServiceDispatcher| to forward requests to Service Manager,
// which then starts Face Detection Service in a utility process.
namespace FaceDetectionServiceDispatcher {

static void CreateMojoService(
shape_detection::mojom::FaceDetectionProviderRequest request) {
service_manager::Connector* connector =
ServiceManagerConnection::GetForProcess()->GetConnector();
connector->BindInterface(shape_detection::mojom::kServiceName,
std::move(request));
}

} // namespace FaceDetectionServiceDispatcher

} // namespace content

#endif // CONTENT_BROWSER_SHAPEDETECTION_FACE_DETECTION_SERVICE_DISPATCHER_H_
19 changes: 13 additions & 6 deletions content/browser/shapedetection/shapedetection_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

namespace content {

// TODO(xianglu): Enable other platforms with support. https://crbug.com/646083
#if defined(OS_ANDROID)
// TODO(xianglu): Enable other platforms support. https://crbug.com/646083
#if defined(OS_ANDROID) || defined(OS_MACOSX)
#define MAYBE_ShapeDetectionBrowserTest ShapeDetectionBrowserTest
#else
#define MAYBE_ShapeDetectionBrowserTest DISABLED_ShapeDetectionBrowserTest
Expand All @@ -25,11 +25,11 @@ const char kFaceDetectionTestHtml[] = "/media/face_detection_test.html";
} // namespace

// This class contains content_browsertests for Shape Detection API, which
// allows for generating bounding boxes for faces on still images..
// allows for generating bounding boxes in still images.
class MAYBE_ShapeDetectionBrowserTest : public ContentBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
// Specific flag to enable ShapeDetection and DOMRect API.
// Flag to enable ShapeDetection and DOMRect API.
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kEnableBlinkFeatures, "ShapeDetection, GeometryInterfaces");
}
Expand Down Expand Up @@ -65,7 +65,7 @@ class MAYBE_ShapeDetectionBrowserTest : public ContentBrowserTest {
const std::vector<float> expected_result = expected_results[face_id];
const std::vector<float> result = results[face_id];
for (size_t i = 0; i < 4; ++i)
EXPECT_NEAR(expected_result[i], result[i], 0.1) << "At index " << i;
EXPECT_NEAR(expected_result[i], result[i], 2) << "At index " << i;
}
}
};
Expand All @@ -80,9 +80,16 @@ IN_PROC_BROWSER_TEST_F(MAYBE_ShapeDetectionBrowserTest,
IN_PROC_BROWSER_TEST_F(MAYBE_ShapeDetectionBrowserTest,
DetectFacesOnImageWithOneFace) {
const std::string image_path = "/single_face.jpg";
std::vector<std::vector<float>> expected_results;
#if defined(OS_ANDROID)
const std::vector<float> expected_result = {68.640625, 102.96875, 171.5625,
171.5625};
const std::vector<std::vector<float>> expected_results = {expected_result};
expected_results.push_back(expected_result);
#elif defined(OS_MACOSX)
const std::vector<float> expected_result = {0, 93, 290, 290};
expected_results.push_back(expected_result);
#endif

RunDetectFacesOnImageUrl(image_path, expected_results);
}

Expand Down
1 change: 1 addition & 0 deletions content/public/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ service_manifest("browser_manifest") {
"//media/mojo/services:media_manifest",
"//services/device:manifest",
"//services/file:manifest",
"//services/shape_detection:manifest",
]
}

Expand Down
6 changes: 5 additions & 1 deletion content/public/app/mojo/content_browser_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@
"service_manager:user_id"
],
"file": [ "file:filesystem", "file:leveldb" ],
"media": [ "media:media" ]
"media": [ "media:media" ],
"shape_detection": [
"barcode_detection",
"face_detection"
]
}
},
"navigation:frame": {
Expand Down
2 changes: 2 additions & 0 deletions content/utility/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ source_set("utility") {
"//services/service_manager",
"//services/service_manager/public/cpp",
"//services/service_manager/public/interfaces",
"//services/shape_detection:lib",
"//services/shape_detection/public/interfaces",
"//third_party/WebKit/public:blink_headers",
"//third_party/WebKit/public:mojo_bindings",
"//url",
Expand Down
1 change: 1 addition & 0 deletions content/utility/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ include_rules = [
"+content/public/utility",
"+services/service_manager",
"+services/service_manager",
"+services/shape_detection",
"+sandbox/win/src",
]
7 changes: 7 additions & 0 deletions content/utility/utility_service_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "content/public/utility/content_utility_client.h"
#include "content/public/utility/utility_thread.h"
#include "content/utility/utility_thread_impl.h"
#include "services/shape_detection/public/interfaces/constants.mojom.h"
#include "services/shape_detection/shape_detection_service.h"

#if defined(ENABLE_MOJO_MEDIA_IN_UTILITY_PROCESS)
#include "media/mojo/services/media_service_factory.h" // nogncheck
Expand All @@ -28,6 +30,11 @@ void UtilityServiceFactory::RegisterServices(ServiceMap* services) {
info.factory = base::Bind(&media::CreateMediaService);
services->insert(std::make_pair("media", info));
#endif
ServiceInfo shape_detection_info;
shape_detection_info.factory =
base::Bind(&shape_detection::ShapeDetectionService::Create);
services->insert(std::make_pair(shape_detection::mojom::kServiceName,
shape_detection_info));
}

void UtilityServiceFactory::OnServiceQuit() {
Expand Down
6 changes: 6 additions & 0 deletions services/service_manager/public/cpp/connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ class Connector {
mojo::InterfacePtr<Interface>* ptr) {
return BindInterface(Identity(name, mojom::kInheritUserID), ptr);
}
template <typename Interface>
void BindInterface(const std::string& name,
mojo::InterfaceRequest<Interface> request) {
return BindInterface(Identity(name, mojom::kInheritUserID),
Interface::Name_, request.PassMessagePipe());
}
virtual void BindInterface(const Identity& target,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) = 0;
Expand Down
45 changes: 45 additions & 0 deletions services/shape_detection/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright 2017 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.

import("//services/service_manager/public/cpp/service.gni")
import("//services/service_manager/public/service_manifest.gni")

source_set("lib") {
sources = [
"face_detection_provider_impl.h",
"shape_detection_service.cc",
"shape_detection_service.h",
]

if (is_mac) {
sources += [
"face_detection_impl_mac.h",
"face_detection_impl_mac.mm",
]
} else {
sources += [ "face_detection_provider_impl.cc" ]
}

deps = [
"//mojo/public/cpp/bindings",
"//ui/gfx",
"//ui/gfx/geometry",
]

public_deps = [
"//base",
"//media/capture",
"//services/service_manager/public/cpp",
"//services/shape_detection/public/interfaces",
]

data_deps = [
":manifest",
]
}

service_manifest("manifest") {
name = "shape_detection"
source = "manifest.json"
}
3 changes: 3 additions & 0 deletions services/shape_detection/DEPS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include_rules = [
"+media/capture/video/scoped_result_callback.h",
]
2 changes: 2 additions & 0 deletions services/shape_detection/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Shape Detection is an isolated service that exists to facilitate safe
face/barcode detection.
35 changes: 35 additions & 0 deletions services/shape_detection/face_detection_impl_mac.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2017 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 SERVICES_SHAPE_DETECTION_FACE_DETECTION_IMPL_MAC_H_
#define SERVICES_SHAPE_DETECTION_FACE_DETECTION_IMPL_MAC_H_

#import <QuartzCore/QuartzCore.h>

#include "base/mac/scoped_nsobject.h"
#include "services/shape_detection/public/interfaces/facedetection.mojom.h"

namespace shape_detection {

class FaceDetectionImplMac : public shape_detection::mojom::FaceDetection {
public:
FaceDetectionImplMac(shape_detection::mojom::FaceDetectorOptionsPtr options);
~FaceDetectionImplMac() override;

void Detect(mojo::ScopedSharedBufferHandle frame_data,
uint32_t width,
uint32_t height,
const shape_detection::mojom::FaceDetection::DetectCallback&
callback) override;

private:
base::scoped_nsobject<CIContext> context_;
base::scoped_nsobject<CIDetector> detector_;

DISALLOW_COPY_AND_ASSIGN(FaceDetectionImplMac);
};

} // namespace shape_detection

#endif // SERVICES_SHAPE_DETECTION_FACE_DETECTION_IMPL_MAC_H_
Loading

0 comments on commit 6dd8f46

Please sign in to comment.