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

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

Issue 2872053002: Linux native notifications: Support image notifications (Closed)
Patch Set: Add unit test 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..a5b8c3a971459e21c342758b7859a4c95fe71dc4 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -36,6 +36,7 @@
#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 +72,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 +89,27 @@ enum class ConnectionInitializationStatusCode {
NUM_ITEMS
};
+class StringStreamSizable {
+ public:
+ StringStreamSizable& operator<<(const std::string& str) {
+ stream_ << str;
+ size_ += str.size();
+ return *this;
+ }
+
+ std::string str() const { return stream_.str(); }
+
+ size_t size() const { return size_; }
+
+ private:
+ size_t size_ = 0;
+ std::stringstream stream_;
Lei Zhang 2017/05/15 21:48:41 ostringstream to be more specific?
Lei Zhang 2017/05/15 21:48:41 #include <sstream>
Tom (Use chromium acct) 2017/05/16 00:22:00 Done.
Tom (Use chromium acct) 2017/05/16 00:22:00 Done.
+};
+
+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 +147,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 +283,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 +387,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 +441,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 +530,46 @@ class NotificationPlatformBridgeLinuxImpl
writer.AppendString(
base::UTF16ToUTF8(CreateNotificationTitle(*notification)));
- std::string body;
+ StringStreamSizable 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.size())
+ 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;
Peter Beverloo 2017/05/15 22:07:33 One downside of using StringStreamSizable as oppos
Tom (Use chromium acct) 2017/05/16 00:22:00 I just realized that tellp() exists :P
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.size())
+ body << "\n";
+ body << "<img src=\"" << image_file->file_path().value()
Lei Zhang 2017/05/15 22:13:11 BTW, we should escape the inside of the src= attri
Tom (Use chromium acct) 2017/05/16 00:22:00 Done.
+ << "\" 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 +855,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