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

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

Issue 2872053002: Linux native notifications: Support image notifications (Closed)
Patch Set: base::Optional<bool> 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 ac81ee8b194849ca7e19d8931cf01f3f8c1af069..260d97802b3f5444150a6f842a10df7d2133b88d 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <memory>
#include <set>
+#include <sstream>
#include <unordered_map>
#include <unordered_set>
#include <utility>
@@ -36,6 +37,8 @@
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
+#include "net/base/escape.h"
+#include "skia/ext/image_operations.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image_skia.h"
@@ -71,6 +74,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 +91,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 +132,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) {
+ 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 +268,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_.value()
+ ? 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 +372,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 +426,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);
@@ -472,32 +515,47 @@ class NotificationPlatformBridgeLinuxImpl
writer.AppendString(
base::UTF16ToUTF8(CreateNotificationTitle(*notification)));
- std::string body;
+ std::ostringstream body;
if (base::ContainsKey(capabilities_, kCapabilityBody)) {
- body = base::UTF16ToUTF8(notification->message());
const bool body_markup =
base::ContainsKey(capabilities_, kCapabilityBodyMarkup);
+ std::string message = base::UTF16ToUTF8(notification->message());
if (body_markup) {
- base::ReplaceSubstringsAfterOffset(&body, 0, "&", "&amp;");
- base::ReplaceSubstringsAfterOffset(&body, 0, "<", "&lt;");
- base::ReplaceSubstringsAfterOffset(&body, 0, ">", "&gt;");
+ base::ReplaceSubstringsAfterOffset(&message, 0, "&", "&amp;");
+ base::ReplaceSubstringsAfterOffset(&message, 0, "<", "&lt;");
+ base::ReplaceSubstringsAfterOffset(&message, 0, ">", "&gt;");
}
+ body << message;
+
if (notification->type() == message_center::NOTIFICATION_TYPE_MULTIPLE) {
for (const auto& item : notification->items()) {
- if (!body.empty())
- body += "\n";
+ if (body.tellp())
+ 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;
+ body << "<b>" << title << "</b> " << message;
else
- body += title + " - " + message;
+ body << title << " - " << message;
+ }
+ } else if (notification->type() ==
+ message_center::NOTIFICATION_TYPE_IMAGE &&
+ base::ContainsKey(capabilities_, kCapabilityBodyImages)) {
+ std::unique_ptr<ResourceFile> image_file = WriteDataToTmpFile(
+ ResizeImageToFdoMaxSize(notification->image()).As1xPNGBytes());
+ if (image_file) {
+ if (body.tellp())
+ body << "\n";
+ body << "<img src=\""
+ << net::EscapePath(image_file->file_path().value())
+ << "\" alt=\"\"/>";
+ data->resource_files.push_back(std::move(image_file));
}
}
}
- writer.AppendString(body);
+ writer.AppendString(body.str());
// Even-indexed elements in this vector are action IDs passed back to
// us in OnActionInvoked(). Odd-indexed ones contain the button text.
@@ -783,6 +841,10 @@ 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.
+ base::Optional<bool> body_images_supported_;
+
//////////////////////////////////////////////////////////////////////////////
// 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