Commit c3b18058 authored by Eric Stevenson's avatar Eric Stevenson Committed by Commit Bot

Add Badging experimental web API.

This CL introduces the badging api. The badging API will eventually
allow developers to set and clear badges for installed PWAs.

Intent to implement:
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/Fw764MVF5nI

Explainer:
https://github.com/WICG/badging/blob/master/explainer.md

Bug: 719176
Change-Id: I68aa5a9310469bd3a38b1029f2141be335121b06
Reviewed-on: https://chromium-review.googlesource.com/1166603Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarMatt Giuca <mgiuca@chromium.org>
Commit-Queue: Eric Stevenson <estevenson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595587}
parent f4fd7ba2
......@@ -3061,6 +3061,8 @@ jumbo_split_static_library("browser") {
sources += [
"ash_service_registry.cc",
"ash_service_registry.h",
"badging/badge_service_impl.cc",
"badging/badge_service_impl.h",
"component_updater/cros_component_installer_chromeos.cc",
"component_updater/cros_component_installer_chromeos.h",
"component_updater/metadata_table_chromeos.cc",
......
......@@ -186,6 +186,7 @@ include_rules = [
"+third_party/blink/public/platform/modules/presentation/presentation.mojom.h",
"+third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h",
"+third_party/blink/public/platform/modules/webshare/webshare.mojom.h",
"+third_party/blink/public/platform/modules/badging/badging.mojom.h",
"+third_party/blink/public/platform/oom_intervention.mojom.h",
"+third_party/blink/public/platform/site_engagement.mojom.h",
"+third_party/blink/public/web/window_features.mojom.h",
......
file://third_party/blink/renderer/modules/badging/OWNERS
// Copyright 2018 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 "chrome/browser/badging/badge_service_impl.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
BadgeServiceImpl::BadgeServiceImpl() = default;
BadgeServiceImpl::~BadgeServiceImpl() = default;
// static
void BadgeServiceImpl::Create(blink::mojom::BadgeServiceRequest request) {
mojo::MakeStrongBinding(std::make_unique<BadgeServiceImpl>(),
std::move(request));
}
void BadgeServiceImpl::SetBadge() {
NOTIMPLEMENTED();
}
void BadgeServiceImpl::ClearBadge() {
NOTIMPLEMENTED();
}
// Copyright 2018 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 CHROME_BROWSER_BADGING_BADGE_SERVICE_IMPL_H_
#define CHROME_BROWSER_BADGING_BADGE_SERVICE_IMPL_H_
#include "base/optional.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "third_party/blink/public/platform/modules/badging/badging.mojom.h"
class BadgeServiceImpl : public blink::mojom::BadgeService {
public:
BadgeServiceImpl();
~BadgeServiceImpl() override;
static void Create(mojo::InterfaceRequest<BadgeService> request);
// blink::mojom::BadgeService overrides.
void SetBadge() override;
void ClearBadge() override;
};
#endif // CHROME_BROWSER_BADGING_BADGE_SERVICE_IMPL_H_
......@@ -314,6 +314,7 @@
#elif defined(OS_CHROMEOS)
#include "ash/public/interfaces/constants.mojom.h"
#include "chrome/browser/ash_service_registry.h"
#include "chrome/browser/badging/badge_service_impl.h"
#include "chrome/browser/chromeos/apps/intent_helper/apps_navigation_throttle.h"
#include "chrome/browser/chromeos/arc/fileapi/arc_content_file_system_backend_delegate.h"
#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_backend_delegate.h"
......@@ -4247,6 +4248,11 @@ void ChromeContentBrowserClient::InitWebContextInterfaces() {
frame_interfaces_->AddInterface(base::Bind(&ShareServiceImpl::Create));
#endif
#if defined(OS_CHROMEOS)
frame_interfaces_->AddInterface(
base::BindRepeating(&BadgeServiceImpl::Create));
#endif
frame_interfaces_parameterized_->AddInterface(
base::BindRepeating(&NavigationPredictor::Create));
}
......
......@@ -81,6 +81,7 @@
"renderer": [
"autofill.mojom.AutofillDriver",
"autofill.mojom.PasswordManagerDriver",
"blink.mojom.BadgeService",
"blink.mojom.CredentialManager",
"blink.mojom.InstalledAppProvider",
"blink.mojom.MediaDownloadInProductHelp",
......
<!DOCTYPE html>
<html>
<head>
<title>Tests the values that the Badge API doesn't support.</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
<script src="file:///gen/third_party/blink/public/platform/modules/badging/badging.mojom.js"></script>
<script src="resources/mock-badge-service.js"></script>
</head>
<body>
<script>
badge_test(() => { Badge.set(-1); }, 'setBadge', 'TypeError');
badge_test(() => { Badge.set(0); }, 'setBadge', 'TypeError');
badge_test(() => { Badge.set(""); }, 'setBadge', 'TypeError');
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Test that Badge API accepts expected types.</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
<script src="file:///gen/third_party/blink/public/platform/modules/badging/badging.mojom.js"></script>
<script src="resources/mock-badge-service.js"></script>
</head>
<body>
<script>
badge_test(() => { Badge.set(); }, 'setBadge');
badge_test(() => { Badge.set(undefined); }, 'setBadge');
badge_test(() => { Badge.set(null); }, 'setBadge');
badge_test(() => { Badge.set(1); }, 'setBadge');
badge_test(() => { Badge.set("a string"); }, 'setBadge');
badge_test(() => { Badge.clear(); }, 'clearBadge');
</script>
</body>
</html>
<!DOCTYPE html>
<link rel="help" href="https://github.com/WICG/badging/blob/master/explainer.md">
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="../resources/webidl2.js"></script>
<script src="../resources/idlharness.js"></script>
<script type="text/plain" id="tested">
interface Badge {
[CallWith=ScriptState, RaisesException]
static void set(optional (USVString or long) contents);
[CallWith=ScriptState] static void clear();
};
</script>
<script>
"use strict";
var idl_array = new IdlArray();
idl_array.add_idls(document.querySelector('#tested').textContent);
idl_array.test();
</script>
'use strict';
class MockBadgeService {
constructor() {
this.bindingSet_ = new mojo.BindingSet(blink.mojom.BadgeService);
this.interceptor_ = new MojoInterfaceInterceptor(
blink.mojom.BadgeService.name);
this.interceptor_.oninterfacerequest =
e => this.bindingSet_.addBinding(this, e.handle);
this.interceptor_.start();
}
init_(expectCalled) {
this.expectCalled_ = expectCalled;
return new Promise((resolve, reject) => {
this.reject_ = reject;
this.resolve_ = resolve;
});
}
setBadge(contents) {
try {
assert_equals(this.expectCalled_, 'setBadge');
assert_equals(contents, undefined);
this.resolve_();
} catch (error) {
this.reject_(error);
}
}
clearBadge() {
try {
assert_equals(this.expectCalled_, 'clearBadge');
this.resolve_();
} catch (error) {
this.reject_(error);
}
}
}
let mockBadgeService = new MockBadgeService();
function callAndObserveErrors(func, expectedErrorName) {
return new Promise((resolve, reject) => {
try {
func();
} catch (error) {
try {
assert_equals(error.name, expectedErrorName);
resolve();
} catch (reason) {
reject(reason);
}
}
});
}
function badge_test(func, expectCalled, expectError) {
promise_test(() => {
let mockPromise = mockBadgeService.init_(expectCalled);
return Promise.race([callAndObserveErrors(func, expectError), mockPromise]);
});
}
......@@ -443,6 +443,11 @@ interface BackgroundFetchRegistration : EventTarget
method abort
method constructor
setter onprogress
interface Badge
static method clear
static method set
attribute @@toStringTag
method constructor
interface BarProp
attribute @@toStringTag
getter visible
......
......@@ -682,6 +682,7 @@ mojom("mojo_bindings") {
"platform/modules/app_banner/app_banner.mojom",
"platform/modules/background_fetch/background_fetch.mojom",
"platform/modules/background_sync/background_sync.mojom",
"platform/modules/badging/badging.mojom",
"platform/modules/bluetooth/web_bluetooth.mojom",
"platform/modules/cache_storage/cache_storage.mojom",
"platform/modules/credentialmanager/credential_manager.mojom",
......
file://third_party/blink/renderer/modules/badging/OWNERS
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
// Copyright 2018 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.
module blink.mojom;
// Interface for handling badge messages from frames and subframes.
interface BadgeService {
// Sets a badge for the PWA corresponding to the context sending the request
// if such a PWA exists.
// TODO(estevenson): Pass the badge contents from the API. Chrome OS will be
// the first client and will not show the data anyway so for now this is
// sufficient.
SetBadge();
// Clear badge (if it exists) for the PWA corresponding to the context sending
// the request if such a PWA exists.
ClearBadge();
};
......@@ -76,6 +76,8 @@ bindings_modules_generated_union_type_files = [
"$bindings_modules_v8_output_dir/string_or_unsigned_long.h",
"$bindings_modules_v8_output_dir/unsigned_long_or_unsigned_long_sequence.cc",
"$bindings_modules_v8_output_dir/unsigned_long_or_unsigned_long_sequence.h",
"$bindings_modules_v8_output_dir/usv_string_or_long.cc",
"$bindings_modules_v8_output_dir/usv_string_or_long.h",
"$bindings_modules_v8_output_dir/webgl_rendering_context_or_webgl2_rendering_context.cc",
"$bindings_modules_v8_output_dir/webgl_rendering_context_or_webgl2_rendering_context.h",
]
......
......@@ -94,6 +94,7 @@ target("jumbo_" + modules_target_type, "modules") {
"//third_party/blink/renderer/modules/audio_output_devices",
"//third_party/blink/renderer/modules/background_fetch",
"//third_party/blink/renderer/modules/background_sync",
"//third_party/blink/renderer/modules/badging",
"//third_party/blink/renderer/modules/battery",
"//third_party/blink/renderer/modules/beacon",
"//third_party/blink/renderer/modules/bluetooth",
......
# Copyright 2018 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("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("badging") {
sources = [
"badge.cc",
"badge.h",
]
}
estevenson@chromium.org
mgiuca@chromium.org
# TEAM: apps-dev@chromium.org
# COMPONENT: Platform>Apps
# Badging
This module contains the implementation of the [Badging API]. The implementation
is under [active development].
[Badging API]: https://github.com/WICG/badging
[active development]: https://crbug.com/719176
### API
See the [explainer] for details. The Badge interface is a member on Window
and exposes two static methods:
[explainer]: https://github.com/WICG/badging/blob/master/explainer.md
* `set(contents)`: Sets the associated app's badge as a "flag" (the argument
is ignored).
* `clear()`: Sets the associated app's badge to nothing.
### Testing
`LayoutTests/badging/*.html` tests that the API accepts/rejects the appropriate
inputs (with a mock Mojo service). Testing at other layers will be added
during implementation.
// Copyright 2018 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 "third_party/blink/renderer/modules/badging/badge.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/renderer/bindings/modules/v8/usv_string_or_long.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
const char Badge::kSupplementName[] = "Badge";
Badge::~Badge() = default;
// static
Badge* Badge::From(ExecutionContext* context) {
Badge* supplement = Supplement<ExecutionContext>::From<Badge>(context);
if (!supplement) {
supplement = new Badge(context);
ProvideTo(*context, supplement);
}
return supplement;
}
// static
void Badge::set(ScriptState* script_state, ExceptionState& exception_state) {
BadgeFromState(script_state)->Set(nullptr, exception_state);
}
// static
void Badge::set(ScriptState* script_state,
USVStringOrLong& contents,
ExceptionState& exception_state) {
BadgeFromState(script_state)->Set(&contents, exception_state);
}
// static
void Badge::clear(ScriptState* script_state) {
BadgeFromState(script_state)->Clear();
}
void Badge::Set(USVStringOrLong* contents, ExceptionState& exception_state) {
if (contents) {
if (contents->IsLong() && contents->GetAsLong() <= 0) {
exception_state.ThrowTypeError("Badge contents should be > 0");
return;
}
if (contents->IsUSVString() && contents->GetAsUSVString() == "") {
exception_state.ThrowTypeError(
"Badge contents cannot be the empty string");
return;
}
}
// TODO(estevenson): Add support for sending badge contents to the browser.
// TODO(estevenson): Verify that contents is a single grapheme cluster.
badge_service_->SetBadge();
}
void Badge::Clear() {
badge_service_->ClearBadge();
}
void Badge::Trace(blink::Visitor* visitor) {
Supplement<ExecutionContext>::Trace(visitor);
ScriptWrappable::Trace(visitor);
}
Badge::Badge(ExecutionContext* context) {
context->GetInterfaceProvider()->GetInterface(
mojo::MakeRequest(&badge_service_));
DCHECK(badge_service_);
}
// static
Badge* Badge::BadgeFromState(ScriptState* script_state) {
return Badge::From(ExecutionContext::From(script_state));
}
} // namespace blink
// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_BADGING_BADGE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BADGING_BADGE_H_
#include "third_party/blink/public/platform/modules/badging/badging.mojom-blink.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/supplementable.h"
namespace blink {
class ExceptionState;
class ExecutionContext;
class ScriptState;
class USVStringOrLong;
class Badge final : public ScriptWrappable,
public Supplement<ExecutionContext> {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(Badge);
public:
static const char kSupplementName[];
static Badge* From(ExecutionContext*);
~Badge() override;
// Badge IDL interface.
static void set(ScriptState*, ExceptionState&);
static void set(ScriptState*, USVStringOrLong&, ExceptionState&);
static void clear(ScriptState*);
void Set(USVStringOrLong*, ExceptionState&);
void Clear();
void Trace(blink::Visitor*) override;
private:
explicit Badge(ExecutionContext*);
static Badge* BadgeFromState(ScriptState* script_state);
blink::mojom::blink::BadgeServicePtr badge_service_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_BADGING_BADGE_H_
// Copyright 2018 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.
// TODO(estevenson): Add link to spec once complete.
// https://github.com/WICG/badging/blob/master/explainer.md
[
RuntimeEnabled=Badging,
// TODO(estevenson): Expose the Badge interface to Worker.
Exposed=Window
] interface Badge {
[CallWith=ScriptState, RaisesException]
static void set(optional (USVString or long) contents);
[CallWith=ScriptState] static void clear();
};
......@@ -73,6 +73,7 @@ modules_idl_files =
"background_fetch/background_fetch_update_ui_event.idl",
"background_sync/sync_event.idl",
"background_sync/sync_manager.idl",
"badging/badge.idl",
"battery/battery_manager.idl",
"bluetooth/bluetooth.idl",
"bluetooth/bluetooth_characteristic_properties.idl",
......
......@@ -120,6 +120,10 @@
name: "BackgroundVideoTrackOptimization",
status: "stable",
},
{
name: "Badging",
status: "test",
},
{
name: "BlinkGenPropertyTrees",
},
......
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