Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5819)

Unified Diff: chrome/browser/notifications/notification_platform_bridge_linux.cc

Issue 2876603004: Linux native notifications: Add attribution (Closed)
Patch Set: Rebase Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/notifications/notification_platform_bridge_linux.cc
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc
index 602b7b3047963c747b8d7246f67cdb8750e763af..50005c6660b77d9771cb5524af0e76aa790b297d 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -31,11 +31,13 @@
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/shell_integration_linux.h"
#include "chrome/grit/generated_resources.h"
+#include "components/url_formatter/elide_url.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
+#include "skia/ext/image_operations.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image_skia.h"
@@ -71,6 +73,10 @@ const char kCapabilitySound[] = "sound";
const char kDefaultButtonId[] = "default";
const char kSettingsButtonId[] = "settings";
+// Max image size; specified in the FDO notification specification.
+const int kMaxImageWidth = 200;
+const int kMaxImageHeight = 100;
+
// The values in this enumeration correspond to those of the
// Linux.NotificationPlatformBridge.InitializationStatus histogram, so
// the ordering should not be changed. New error codes should be
@@ -84,6 +90,10 @@ enum class ConnectionInitializationStatusCode {
NUM_ITEMS
};
+int ClampInt(int value, int low, int hi) {
+ return std::max(std::min(value, hi), low);
+}
+
base::string16 CreateNotificationTitle(const Notification& notification) {
base::string16 title;
if (notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS) {
@@ -121,6 +131,28 @@ int NotificationPriorityToFdoUrgency(int priority) {
}
}
+// Constrain |image|'s size to |kMaxImageWidth|x|kMaxImageHeight|. If
+// the image does not need to be resized, or the image is empty,
+// returns |image| directly.
+gfx::Image ResizeImageToFdoMaxSize(const gfx::Image& image) {
yoshiki 2017/05/15 02:35:15 nit: Could you add a DCHECK to ensure it's not on
Tom (Use chromium acct) 2017/05/15 22:07:04 Done.
+ if (image.IsEmpty())
+ return image;
+ int width = image.Width();
+ int height = image.Height();
+ if (width <= kMaxImageWidth && height <= kMaxImageHeight) {
+ return image;
+ }
+ const SkBitmap* image_bitmap = image.ToSkBitmap();
+ double scale = std::min(static_cast<double>(kMaxImageWidth) / width,
+ static_cast<double>(kMaxImageHeight) / height);
+ width = ClampInt(scale * width, 1, kMaxImageWidth);
+ height = ClampInt(scale * height, 1, kMaxImageHeight);
+ return gfx::Image(
+ gfx::ImageSkia::CreateFrom1xBitmap(skia::ImageOperations::Resize(
+ *image_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, width,
+ height)));
+}
+
// Runs once the profile has been loaded in order to perform a given
// |operation| on a notification.
void ProfileLoadedCallback(NotificationCommon::Operation operation,
@@ -235,7 +267,9 @@ class NotificationPlatformBridgeLinuxImpl
// non-thread-safe reference counts) to the task runner thread.
auto notification_copy = base::MakeUnique<Notification>(notification);
notification_copy->set_icon(DeepCopyImage(notification_copy->icon()));
- notification_copy->set_image(gfx::Image());
+ notification_copy->set_image(body_images_supported_
+ ? DeepCopyImage(notification_copy->image())
+ : gfx::Image());
notification_copy->set_small_image(gfx::Image());
for (size_t i = 0; i < notification_copy->buttons().size(); i++)
notification_copy->SetButtonIcon(i, gfx::Image());
@@ -337,6 +371,11 @@ class NotificationPlatformBridgeLinuxImpl
CleanUp();
}
+ void SetBodyImagesSupported(bool body_images_supported) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ body_images_supported_ = body_images_supported;
+ }
+
void PostTaskToUiThread(base::OnceClosure closure) const {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
bool success = content::BrowserThread::PostTask(
@@ -386,6 +425,9 @@ class NotificationPlatformBridgeLinuxImpl
capabilities_.insert(capability);
}
RecordMetricsForCapabilities();
+ PostTaskToUiThread(base::BindOnce(
+ &NotificationPlatformBridgeLinuxImpl::SetBodyImagesSupported, this,
+ base::ContainsKey(capabilities_, kCapabilityBodyImages)));
dbus::MethodCall get_server_information_call(kFreedesktopNotificationsName,
kMethodGetServerInformation);
@@ -475,11 +517,55 @@ class NotificationPlatformBridgeLinuxImpl
std::string body;
if (base::ContainsKey(capabilities_, kCapabilityBody)) {
body = base::UTF16ToUTF8(notification->message());
- if (base::ContainsKey(capabilities_, kCapabilityBodyMarkup)) {
+ const bool body_markup =
+ base::ContainsKey(capabilities_, kCapabilityBodyMarkup);
+ if (body_markup) {
base::ReplaceSubstringsAfterOffset(&body, 0, "&", "&amp;");
base::ReplaceSubstringsAfterOffset(&body, 0, "<", "&lt;");
base::ReplaceSubstringsAfterOffset(&body, 0, ">", "&gt;");
}
+ if (notification->type() == message_center::NOTIFICATION_TYPE_MULTIPLE) {
+ for (const auto& item : notification->items()) {
+ if (!body.empty())
+ body += "\n";
+ const std::string title = base::UTF16ToUTF8(item.title);
+ const std::string message = base::UTF16ToUTF8(item.message);
+ // TODO(peter): Figure out the right way to internationalize
+ // this for RTL languages.
+ if (body_markup)
+ body += "<b>" + title + "</b> " + message;
+ else
+ body += title + " - " + message;
+ }
+ } else if (notification->type() ==
+ message_center::NOTIFICATION_TYPE_IMAGE &&
+ base::ContainsKey(capabilities_, "body-images")) {
+ std::unique_ptr<ResourceFile> image_file = WriteDataToTmpFile(
+ ResizeImageToFdoMaxSize(notification->image()).As1xPNGBytes());
+ if (image_file) {
+ if (!body.empty())
+ body += "\n";
+ body +=
+ "<img src=\"" + image_file->file_path().value() + "\" alt=\"\"/>";
+ data->resource_files.push_back(std::move(image_file));
+ }
+ }
+
+ // Attribute this notification to the origin, if any.
+ if (!notification->origin_url().is_empty()) {
Peter Beverloo 2017/05/15 16:19:41 If the notification has a context message, we shou
Peter Beverloo 2017/05/15 16:19:41 How certain are we that the attribution is going t
Tom (Use chromium acct) 2017/05/15 22:07:03 Done.
Tom (Use chromium acct) 2017/05/15 22:07:04 Ok, I moved the context to the beginning of the bo
+ if (!body.empty())
+ body += "\n";
+ std::string url_display_text =
+ base::UTF16ToUTF8(url_formatter::FormatUrlForSecurityDisplay(
+ notification->origin_url(),
+ url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS));
Peter Beverloo 2017/05/15 16:19:41 What would wrapped contents look like? For example
Tom (Use chromium acct) 2017/05/15 22:07:04 See the pictures on the bug to see how it looks on
+ std::string spec = notification->origin_url().spec();
+ if (base::ContainsKey(capabilities_, "body-hyperlinks")) {
+ body += "<a href=\"" + spec + "\">" + url_display_text + "</a>";
+ } else {
+ body += url_display_text;
+ }
+ }
}
writer.AppendString(body);
@@ -549,7 +635,9 @@ class NotificationPlatformBridgeLinuxImpl
writer.CloseContainer(&hints_writer);
const int32_t kExpireTimeoutDefault = -1;
- writer.AppendInt32(kExpireTimeoutDefault);
+ const int32_t kExpireTimeoutNever = 0;
+ writer.AppendInt32(notification->never_timeout() ? kExpireTimeoutNever
+ : kExpireTimeoutDefault);
std::unique_ptr<dbus::Response> response =
notification_proxy_->CallMethodAndBlock(
@@ -765,6 +853,12 @@ class NotificationPlatformBridgeLinuxImpl
base::Optional<bool> connected_;
std::vector<NotificationBridgeReadyCallback> on_connected_callbacks_;
+ // Notification servers very rarely have the 'body-images'
+ // capability, so try to avoid an image copy if possible. It is
+ // intialized to true so that the UI thread will conservatively copy
+ // the image before the GetCapabilities message completes.
+ bool body_images_supported_ = true;
+
//////////////////////////////////////////////////////////////////////////////
// Members used only on the task runner thread.
« no previous file with comments | « no previous file | chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698