#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.h"
#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
+#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
+#include "net/base/load_flags.h"
#include "skia/ext/image_operations.h"
#include "sync/protocol/sync.pb.h"
#include "sync/protocol/synced_notification_specifics.pb.h"
#include "ui/gfx/size.h"
#include "ui/gfx/skbitmap_operations.h"
#include "ui/message_center/message_center_style.h"
-#include "ui/message_center/message_center_util.h"
#include "ui/message_center/notification_types.h"
namespace {
// try to supply them with more than this number of buttons.
const unsigned int kMaxNotificationButtonIndex = 2;
-bool UseRichNotifications() {
- return message_center::IsRichNotificationEnabled();
-}
-
// Schema-less specs default badly in windows. If we find one, add the schema
// we expect instead of allowing windows specific GURL code to make it default
// to "file:".
sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED,
local_enum_must_match_protobuf_enum);
-SyncedNotification::SyncedNotification(const syncer::SyncData& sync_data)
- : notification_manager_(NULL),
- notifier_service_(NULL),
+SyncedNotification::SyncedNotification(
+ const syncer::SyncData& sync_data,
+ ChromeNotifierService* notifier_service,
+ NotificationUIManager* notification_manager)
+ : notification_manager_(notification_manager),
+ notifier_service_(notifier_service),
profile_(NULL),
toast_state_(true),
app_icon_bitmap_fetch_pending_(true),
specifics_.CopyFrom(sync_data.GetSpecifics().synced_notification());
}
-sync_pb::EntitySpecifics SyncedNotification::GetEntitySpecifics() const {
- sync_pb::EntitySpecifics entity_specifics;
- entity_specifics.mutable_synced_notification()->CopyFrom(specifics_);
- return entity_specifics;
-}
-
-// Check that we have either fetched or gotten an error on all the bitmaps we
-// asked for.
-bool SyncedNotification::AreAllBitmapsFetched() {
- bool app_icon_ready = GetAppIconUrl().is_empty() ||
- !app_icon_bitmap_.IsEmpty() || !app_icon_bitmap_fetch_pending_;
- bool images_ready = GetImageUrl().is_empty() || !image_bitmap_.IsEmpty() ||
- !image_bitmap_fetch_pending_;
- bool sender_picture_ready = GetProfilePictureUrl(0).is_empty() ||
- !sender_bitmap_.IsEmpty() || !sender_bitmap_fetch_pending_;
- bool button_bitmaps_ready = true;
- for (unsigned int j = 0; j < GetButtonCount(); ++j) {
- if (!GetButtonIconUrl(j).is_empty()
- && button_bitmaps_[j].IsEmpty()
- && button_bitmaps_fetch_pending_[j]) {
- button_bitmaps_ready = false;
- break;
- }
+void SyncedNotification::Show(Profile* profile) {
+ // Let NotificationUIManager know that the notification has been dismissed.
+ if (SyncedNotification::kRead == GetReadState() ||
+ SyncedNotification::kDismissed == GetReadState() ) {
+ notification_manager_->CancelById(GetKey());
+ DVLOG(2) << "Dismissed or read notification arrived"
+ << GetHeading() << " " << GetText();
+ return;
}
- return app_icon_ready && images_ready && sender_picture_ready &&
- button_bitmaps_ready;
-}
+ // |notifier_service| can be NULL in tests.
+ if (notifier_service_) {
+ notifier_service_->ShowWelcomeToastIfNecessary(this, notification_manager_);
+ }
-// TODO(petewil): The fetch mechanism appears to be returning two bitmaps on the
-// mac - perhaps one is regular, one is high dpi? If so, ensure we use the high
-// dpi bitmap when appropriate.
-void SyncedNotification::OnFetchComplete(const GURL url,
- const SkBitmap* bitmap) {
- // TODO(petewil): Add timeout mechanism in case bitmaps take too long. Do we
- // already have one built into URLFetcher?
- // Make sure we are on the thread we expect.
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ // Set up the fields we need to send and create a Notification object.
+ GURL image_url = GetImageUrl();
+ base::string16 text = base::UTF8ToUTF16(GetText());
+ base::string16 heading = base::UTF8ToUTF16(GetHeading());
+ base::string16 description = base::UTF8ToUTF16(GetDescription());
+ base::string16 annotation = base::UTF8ToUTF16(GetAnnotation());
+ // TODO(petewil): Eventually put the display name of the sending service here.
+ base::string16 display_source = base::UTF8ToUTF16(GetAppId());
+ base::string16 replace_key = base::UTF8ToUTF16(GetKey());
+ base::string16 notification_heading = heading;
+ base::string16 notification_text = description;
+ base::string16 newline = base::UTF8ToUTF16("\n");
- gfx::Image downloaded_image;
- if (bitmap != NULL)
- downloaded_image = gfx::Image::CreateFrom1xBitmap(*bitmap);
+ // The delegate will eventually catch calls that the notification
+ // was read or deleted, and send the changes back to the server.
+ scoped_refptr<NotificationDelegate> delegate =
+ new ChromeNotifierDelegate(GetKey(), notifier_service_);
- // Match the incoming bitmaps to URLs. In case this is a dup, make sure to
- // try all potentially matching urls.
- if (GetAppIconUrl() == url) {
- app_icon_bitmap_ = downloaded_image;
- if (app_icon_bitmap_.IsEmpty())
- app_icon_bitmap_fetch_pending_ = false;
+ // Some inputs and fields are only used if there is a notification center.
+ base::Time creation_time =
+ base::Time::FromDoubleT(static_cast<double>(GetCreationTime()));
+ int priority = GetPriority();
+ unsigned int button_count = GetButtonCount();
+
+ // Deduce which notification template to use from the data.
+ message_center::NotificationType notification_type =
+ message_center::NOTIFICATION_TYPE_BASE_FORMAT;
+ if (!image_url.is_empty()) {
+ notification_type = message_center::NOTIFICATION_TYPE_IMAGE;
+ } else if (button_count > 0) {
+ notification_type = message_center::NOTIFICATION_TYPE_BASE_FORMAT;
}
- if (GetImageUrl() == url) {
- image_bitmap_ = downloaded_image;
- if (image_bitmap_.IsEmpty())
- image_bitmap_fetch_pending_ = false;
+
+ // Fill the optional fields with the information we need to make a
+ // notification.
+ message_center::RichNotificationData rich_notification_data;
+ rich_notification_data.timestamp = creation_time;
+ if (priority != SyncedNotification::kUndefinedPriority)
+ rich_notification_data.priority = priority;
+
+ // Fill in the button data.
+ // TODO(petewil): Today Rich notifiations are limited to two buttons.
+ // When rich notifications supports more, remove the
+ // "&& i < kMaxNotificationButtonIndex" clause below.
+ for (unsigned int i = 0;
+ i < button_count
+ && i < button_bitmaps_.size()
+ && i < kMaxNotificationButtonIndex;
+ ++i) {
+ // Stop at the first button with no title
+ std::string title = GetButtonTitle(i);
+ if (title.empty())
+ break;
+ message_center::ButtonInfo button_info(base::UTF8ToUTF16(title));
+ if (!button_bitmaps_[i].IsEmpty())
+ button_info.icon = button_bitmaps_[i];
+ rich_notification_data.buttons.push_back(button_info);
}
- if (GetProfilePictureUrl(0) == url) {
- sender_bitmap_ = downloaded_image;
- if (sender_bitmap_.IsEmpty())
- sender_bitmap_fetch_pending_ = false;
+
+ // Fill in the bitmap images.
+ if (!image_bitmap_.IsEmpty())
+ rich_notification_data.image = image_bitmap_;
+
+ if (!app_icon_bitmap_.IsEmpty()) {
+ // Since we can't control the size of images we download, resize using a
+ // high quality filter down to the appropriate icon size.
+ // TODO(dewittj): Remove this when correct resources are sent via the
+ // protobuf.
+ SkBitmap new_app_icon =
+ skia::ImageOperations::Resize(app_icon_bitmap_.AsBitmap(),
+ skia::ImageOperations::RESIZE_BEST,
+ message_center::kSmallImageSize,
+ message_center::kSmallImageSize);
+
+ // The app icon should be in grayscale.
+ // TODO(dewittj): Remove this when correct resources are sent via the
+ // protobuf.
+ color_utils::HSL shift = {-1, 0, 0.6};
+ SkBitmap grayscale =
+ SkBitmapOperations::CreateHSLShiftedBitmap(new_app_icon, shift);
+ gfx::Image small_image =
+ gfx::Image(gfx::ImageSkia(gfx::ImageSkiaRep(grayscale, 1.0f)));
+ rich_notification_data.small_image = small_image;
}
- // If this URL matches one or more button bitmaps, save them off.
- for (unsigned int i = 0; i < GetButtonCount(); ++i) {
- if (GetButtonIconUrl(i) == url) {
- if (bitmap != NULL) {
- button_bitmaps_[i] = gfx::Image::CreateFrom1xBitmap(*bitmap);
- }
- button_bitmaps_fetch_pending_[i] = false;
- }
+ // Set the ContextMessage inside the rich notification data for the
+ // annotation.
+ rich_notification_data.context_message = annotation;
+
+ // Set the clickable flag to change the cursor on hover if a valid
+ // destination is found.
+ rich_notification_data.clickable = GetDefaultDestinationUrl().is_valid();
+
+ // If there is at least one person sending, use the first picture.
+ // TODO(petewil): Someday combine multiple profile photos here.
+ gfx::Image icon_bitmap = app_icon_bitmap_;
+ if (GetProfilePictureCount() >= 1) {
+ icon_bitmap = sender_bitmap_;
}
- DVLOG(2) << __FUNCTION__ << " popping bitmap " << url;
+ Notification ui_notification(notification_type,
+ GetOriginUrl(),
+ notification_heading,
+ notification_text,
+ icon_bitmap,
+ blink::WebTextDirectionDefault,
+ message_center::NotifierId(GetOriginUrl()),
+ display_source,
+ replace_key,
+ rich_notification_data,
+ delegate.get());
+ // In case the notification is not supposed to be toasted, pretend that it
+ // has already been shown.
+ ui_notification.set_shown_as_popup(!toast_state_);
+
+ notification_manager_->Add(ui_notification, profile);
- // See if all bitmaps are already accounted for, if so call Show.
- if (AreAllBitmapsFetched()) {
- Show(notification_manager_, notifier_service_, profile_);
+ DVLOG(1) << "Showing Synced Notification! " << heading << " " << text
+ << " " << GetAppIconUrl() << " " << replace_key << " "
+ << GetProfilePictureUrl(0) << " " << GetReadState();
+
+ return;
+}
+
+sync_pb::EntitySpecifics SyncedNotification::GetEntitySpecifics() const {
+ sync_pb::EntitySpecifics entity_specifics;
+ entity_specifics.mutable_synced_notification()->CopyFrom(specifics_);
+ return entity_specifics;
+}
+
+// Display the notification if it has the specified app_id_name.
+void SyncedNotification::ShowAllForAppId(Profile* profile,
+ std::string app_id_name) {
+ if (app_id_name == GetAppId())
+ Show(profile);
+}
+
+// Remove the notification if it has the specified app_id_name.
+void SyncedNotification::HideAllForAppId(std::string app_id_name) {
+ if (app_id_name == GetAppId()) {
+ notification_manager_->CancelById(GetKey());
}
}
void SyncedNotification::QueueBitmapFetchJobs(
- NotificationUIManager* notification_manager,
ChromeNotifierService* notifier_service,
Profile* profile) {
- // If we are not using the MessageCenter, call show now, and the existing
- // code will handle the bitmap fetch for us.
- if (!UseRichNotifications()) {
- Show(notification_manager, notifier_service, profile);
- return;
- }
-
// Save off the arguments for the call to Show.
- notification_manager_ = notification_manager;
notifier_service_ = notifier_service;
profile_ = profile;
for (unsigned int i = 0; i < GetButtonCount(); ++i) {
button_bitmaps_.push_back(gfx::Image());
button_bitmaps_fetch_pending_.push_back(true);
- AddBitmapToFetchQueue(GetButtonIconUrl(i));
+ CreateBitmapFetcher(GetButtonIconUrl(i));
}
// If there is a profile image bitmap, fetch it
if (GetProfilePictureCount() > 0) {
// TODO(petewil): When we have the capacity to display more than one bitmap,
// modify this code to fetch as many as we can display
- AddBitmapToFetchQueue(GetProfilePictureUrl(0));
+ CreateBitmapFetcher(GetProfilePictureUrl(0));
}
// If the URL is non-empty, add it to our queue of URLs to fetch.
- AddBitmapToFetchQueue(GetAppIconUrl());
- AddBitmapToFetchQueue(GetImageUrl());
+ CreateBitmapFetcher(GetAppIconUrl());
+ CreateBitmapFetcher(GetImageUrl());
// Check to see if we don't need to fetch images, either because we already
// did, or because the URLs are empty. If so, we can display the notification.
// See if all bitmaps are accounted for, if so call Show().
if (AreAllBitmapsFetched()) {
- Show(notification_manager_, notifier_service_, profile_);
+ Show(profile_);
}
}
// Now that we have queued and counted them all, start the fetching.
ScopedVector<chrome::BitmapFetcher>::iterator iter;
for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) {
- (*iter)->Start(profile_);
- }
-}
-
-void SyncedNotification::AddBitmapToFetchQueue(const GURL& url) {
- // Check for dups, ignore any request for a dup.
- ScopedVector<chrome::BitmapFetcher>::iterator iter;
- for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) {
- if ((*iter)->url() == url)
- return;
- }
-
- if (url.is_valid()) {
- fetchers_.push_back(new chrome::BitmapFetcher(url, this));
- DVLOG(2) << __FUNCTION__ << "Pushing bitmap " << url;
- }
-}
-
-void SyncedNotification::Show(NotificationUIManager* notification_manager,
- ChromeNotifierService* notifier_service,
- Profile* profile) {
- // Let NotificationUIManager know that the notification has been dismissed.
- if (SyncedNotification::kRead == GetReadState() ||
- SyncedNotification::kDismissed == GetReadState() ) {
- notification_manager->CancelById(GetKey());
- DVLOG(2) << "Dismissed or read notification arrived"
- << GetHeading() << " " << GetText();
- return;
- }
-
- // |notifier_service| can be NULL in tests.
- if (UseRichNotifications() && notifier_service) {
- notifier_service->ShowWelcomeToastIfNecessary(this, notification_manager);
- }
-
- // Set up the fields we need to send and create a Notification object.
- GURL image_url = GetImageUrl();
- base::string16 text = base::UTF8ToUTF16(GetText());
- base::string16 heading = base::UTF8ToUTF16(GetHeading());
- base::string16 description = base::UTF8ToUTF16(GetDescription());
- base::string16 annotation = base::UTF8ToUTF16(GetAnnotation());
- // TODO(petewil): Eventually put the display name of the sending service here.
- base::string16 display_source = base::UTF8ToUTF16(GetAppId());
- base::string16 replace_key = base::UTF8ToUTF16(GetKey());
- base::string16 notification_heading = heading;
- base::string16 notification_text = description;
- base::string16 newline = base::UTF8ToUTF16("\n");
-
- // The delegate will eventually catch calls that the notification
- // was read or deleted, and send the changes back to the server.
- scoped_refptr<NotificationDelegate> delegate =
- new ChromeNotifierDelegate(GetKey(), notifier_service);
-
- // Some inputs and fields are only used if there is a notification center.
- if (UseRichNotifications()) {
- base::Time creation_time =
- base::Time::FromDoubleT(static_cast<double>(GetCreationTime()));
- int priority = GetPriority();
- unsigned int button_count = GetButtonCount();
-
- // Deduce which notification template to use from the data.
- message_center::NotificationType notification_type =
- message_center::NOTIFICATION_TYPE_BASE_FORMAT;
- if (!image_url.is_empty()) {
- notification_type = message_center::NOTIFICATION_TYPE_IMAGE;
- } else if (button_count > 0) {
- notification_type = message_center::NOTIFICATION_TYPE_BASE_FORMAT;
- }
-
- // Fill the optional fields with the information we need to make a
- // notification.
- message_center::RichNotificationData rich_notification_data;
- rich_notification_data.timestamp = creation_time;
- if (priority != SyncedNotification::kUndefinedPriority)
- rich_notification_data.priority = priority;
-
- // Fill in the button data.
- // TODO(petewil): Today Rich notifiations are limited to two buttons.
- // When rich notifications supports more, remove the
- // "&& i < kMaxNotificationButtonIndex" clause below.
- for (unsigned int i = 0;
- i < button_count
- && i < button_bitmaps_.size()
- && i < kMaxNotificationButtonIndex;
- ++i) {
- // Stop at the first button with no title
- std::string title = GetButtonTitle(i);
- if (title.empty())
- break;
- message_center::ButtonInfo button_info(base::UTF8ToUTF16(title));
- if (!button_bitmaps_[i].IsEmpty())
- button_info.icon = button_bitmaps_[i];
- rich_notification_data.buttons.push_back(button_info);
- }
-
- // Fill in the bitmap images.
- if (!image_bitmap_.IsEmpty())
- rich_notification_data.image = image_bitmap_;
-
- if (!app_icon_bitmap_.IsEmpty()) {
- // Since we can't control the size of images we download, resize using a
- // high quality filter down to the appropriate icon size.
- // TODO(dewittj): Remove this when correct resources are sent via the
- // protobuf.
- SkBitmap new_app_icon =
- skia::ImageOperations::Resize(app_icon_bitmap_.AsBitmap(),
- skia::ImageOperations::RESIZE_BEST,
- message_center::kSmallImageSize,
- message_center::kSmallImageSize);
-
- // The app icon should be in grayscale.
- // TODO(dewittj): Remove this when correct resources are sent via the
- // protobuf.
- color_utils::HSL shift = {-1, 0, 0.6};
- SkBitmap grayscale =
- SkBitmapOperations::CreateHSLShiftedBitmap(new_app_icon, shift);
- gfx::Image small_image =
- gfx::Image(gfx::ImageSkia(gfx::ImageSkiaRep(grayscale, 1.0f)));
- rich_notification_data.small_image = small_image;
- }
-
- // Set the ContextMessage inside the rich notification data for the
- // annotation.
- rich_notification_data.context_message = annotation;
-
- // Set the clickable flag to change the cursor on hover if a valid
- // destination is found.
- rich_notification_data.clickable = GetDefaultDestinationUrl().is_valid();
-
- // If there is at least one person sending, use the first picture.
- // TODO(petewil): Someday combine multiple profile photos here.
- gfx::Image icon_bitmap = app_icon_bitmap_;
- if (GetProfilePictureCount() >= 1) {
- icon_bitmap = sender_bitmap_;
- }
-
- Notification ui_notification(notification_type,
- GetOriginUrl(),
- notification_heading,
- notification_text,
- icon_bitmap,
- blink::WebTextDirectionDefault,
- message_center::NotifierId(GetOriginUrl()),
- display_source,
- replace_key,
- rich_notification_data,
- delegate.get());
- // In case the notification is not supposed to be toasted, pretend that it
- // has already been shown.
- ui_notification.set_shown_as_popup(!toast_state_);
-
- notification_manager->Add(ui_notification, profile);
- } else {
- // In this case we have a Webkit Notification, not a Rich Notification.
- Notification ui_notification(GetOriginUrl(),
- GetAppIconUrl(),
- notification_heading,
- notification_text,
- blink::WebTextDirectionDefault,
- display_source,
- replace_key,
- delegate.get());
-
- notification_manager->Add(ui_notification, profile);
+ (*iter)->Start(
+ profile_->GetRequestContext(),
+ std::string(),
+ net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+ net::LOAD_NORMAL);
}
-
- DVLOG(1) << "Showing Synced Notification! " << heading << " " << text
- << " " << GetAppIconUrl() << " " << replace_key << " "
- << GetProfilePictureUrl(0) << " " << GetReadState();
-
- return;
}
// This should detect even small changes in case the server updated the
return false;
}
-void SyncedNotification::LogNotification() {
- std::string readStateString("Unread");
- if (SyncedNotification::kRead == GetReadState())
- readStateString = "Read";
- else if (SyncedNotification::kDismissed == GetReadState())
- readStateString = "Dismissed";
-
- DVLOG(2) << " Notification: Heading is " << GetHeading()
- << " description is " << GetDescription()
- << " key is " << GetKey()
- << " read state is " << readStateString;
-}
-
-// Set the read state on the notification, returns true for success.
-void SyncedNotification::SetReadState(const ReadState& read_state) {
-
- // Convert the read state to the protobuf type for read state.
- if (kDismissed == read_state)
- specifics_.mutable_coalesced_notification()->set_read_state(
- sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED);
- else if (kUnread == read_state)
- specifics_.mutable_coalesced_notification()->set_read_state(
- sync_pb::CoalescedSyncedNotification_ReadState_UNREAD);
- else if (kRead == read_state)
- specifics_.mutable_coalesced_notification()->set_read_state(
- sync_pb::CoalescedSyncedNotification_ReadState_READ);
- else
- NOTREACHED();
-}
-
void SyncedNotification::NotificationHasBeenRead() {
SetReadState(kRead);
}
// Convert the prioroty to the scheme used by the notification center.
if (protobuf_priority ==
- sync_pb::CoalescedSyncedNotification_Priority_LOW) {
+ sync_pb::CoalescedSyncedNotification_Priority_INVISIBLE) {
return message_center::LOW_PRIORITY;
} else if (protobuf_priority ==
- sync_pb::CoalescedSyncedNotification_Priority_STANDARD) {
+ sync_pb::CoalescedSyncedNotification_Priority_LOW) {
return message_center::DEFAULT_PRIORITY;
} else if (protobuf_priority ==
sync_pb::CoalescedSyncedNotification_Priority_HIGH) {
} else {
// Complain if this is a new priority we have not seen before.
DCHECK(protobuf_priority <
- sync_pb::CoalescedSyncedNotification_Priority_LOW ||
+ sync_pb::CoalescedSyncedNotification_Priority_INVISIBLE ||
sync_pb::CoalescedSyncedNotification_Priority_HIGH <
protobuf_priority);
return kUndefinedPriority;
}
}
-size_t SyncedNotification::GetNotificationCount() const {
- return specifics_.coalesced_notification().render_info().
- expanded_info().collapsed_info_size();
-}
-
-size_t SyncedNotification::GetButtonCount() const {
- return specifics_.coalesced_notification().render_info().collapsed_info().
- target_size();
-}
-
-size_t SyncedNotification::GetProfilePictureCount() const {
- return specifics_.coalesced_notification().render_info().collapsed_info().
- simple_collapsed_layout().profile_image_size();
-}
-
-GURL SyncedNotification::GetProfilePictureUrl(unsigned int which_url) const {
- if (GetProfilePictureCount() <= which_url)
- return GURL();
-
- std::string url_spec = specifics_.coalesced_notification().render_info().
- collapsed_info().simple_collapsed_layout().profile_image(which_url).
- image_url();
-
- return AddDefaultSchemaIfNeeded(url_spec);
-}
-
-
std::string SyncedNotification::GetDefaultDestinationTitle() const {
if (!specifics_.coalesced_notification().render_info().collapsed_info().
default_destination().icon().has_alt_text()) {
return AddDefaultSchemaIfNeeded(url_spec);
}
+GURL SyncedNotification::GetProfilePictureUrl(unsigned int which_url) const {
+ if (GetProfilePictureCount() <= which_url)
+ return GURL();
+
+ std::string url_spec = specifics_.coalesced_notification().render_info().
+ collapsed_info().simple_collapsed_layout().profile_image(which_url).
+ image_url();
+
+ return AddDefaultSchemaIfNeeded(url_spec);
+}
+
+size_t SyncedNotification::GetProfilePictureCount() const {
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ simple_collapsed_layout().profile_image_size();
+}
+
+size_t SyncedNotification::GetNotificationCount() const {
+ return specifics_.coalesced_notification().render_info().
+ expanded_info().collapsed_info_size();
+}
+
+size_t SyncedNotification::GetButtonCount() const {
+ return specifics_.coalesced_notification().render_info().collapsed_info().
+ target_size();
+}
std::string SyncedNotification::GetContainedNotificationTitle(
int index) const {
if (specifics_.coalesced_notification().render_info().expanded_info().
collapsed_info(index).simple_collapsed_layout().description();
}
-std::string SyncedNotification::GetSendingServiceId() const {
- // TODO(petewil): We are building a new protocol (a new sync datatype) to send
- // the service name and icon from the server. For now this method is
- // hardcoded to the name of our first service using synced notifications.
- // Once the new protocol is built, remove this hardcoding.
- return kFirstSyncedNotificationServiceId;
-}
-
const gfx::Image& SyncedNotification::GetAppIcon() const {
return app_icon_bitmap_;
}
-void SyncedNotification::SetToastState(bool toast_state) {
+void SyncedNotification::set_toast_state(bool toast_state) {
toast_state_ = toast_state;
}
+void SyncedNotification::LogNotification() {
+ std::string readStateString("Unread");
+ if (SyncedNotification::kRead == GetReadState())
+ readStateString = "Read";
+ else if (SyncedNotification::kDismissed == GetReadState())
+ readStateString = "Dismissed";
+
+ DVLOG(2) << " Notification: Heading is " << GetHeading()
+ << " description is " << GetDescription()
+ << " key is " << GetKey()
+ << " read state is " << readStateString;
+}
+
+// TODO(petewil): The fetch mechanism appears to be returning two bitmaps on the
+// mac - perhaps one is regular, one is high dpi? If so, ensure we use the high
+// dpi bitmap when appropriate.
+void SyncedNotification::OnFetchComplete(const GURL url,
+ const SkBitmap* bitmap) {
+ // Make sure we are on the thread we expect.
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ gfx::Image downloaded_image;
+ if (bitmap != NULL)
+ downloaded_image = gfx::Image::CreateFrom1xBitmap(*bitmap);
+
+ // Match the incoming bitmaps to URLs. In case this is a dup, make sure to
+ // try all potentially matching urls.
+ if (GetAppIconUrl() == url) {
+ app_icon_bitmap_ = downloaded_image;
+ if (app_icon_bitmap_.IsEmpty())
+ app_icon_bitmap_fetch_pending_ = false;
+ }
+ if (GetImageUrl() == url) {
+ image_bitmap_ = downloaded_image;
+ if (image_bitmap_.IsEmpty())
+ image_bitmap_fetch_pending_ = false;
+ }
+ if (GetProfilePictureUrl(0) == url) {
+ sender_bitmap_ = downloaded_image;
+ if (sender_bitmap_.IsEmpty())
+ sender_bitmap_fetch_pending_ = false;
+ }
+
+ // If this URL matches one or more button bitmaps, save them off.
+ for (unsigned int i = 0; i < GetButtonCount(); ++i) {
+ if (GetButtonIconUrl(i) == url) {
+ if (bitmap != NULL) {
+ button_bitmaps_[i] = gfx::Image::CreateFrom1xBitmap(*bitmap);
+ }
+ button_bitmaps_fetch_pending_[i] = false;
+ }
+ }
+
+ DVLOG(2) << __FUNCTION__ << " popping bitmap " << url;
+
+ // See if all bitmaps are already accounted for, if so call Show.
+ if (AreAllBitmapsFetched()) {
+ Show(profile_);
+ }
+}
+
+void SyncedNotification::CreateBitmapFetcher(const GURL& url) {
+ // Check for dups, ignore any request for a dup.
+ ScopedVector<chrome::BitmapFetcher>::iterator iter;
+ for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) {
+ if ((*iter)->url() == url)
+ return;
+ }
+
+ if (url.is_valid()) {
+ fetchers_.push_back(new chrome::BitmapFetcher(url, this));
+ DVLOG(2) << __FUNCTION__ << "Pushing bitmap " << url;
+ }
+}
+
+// Check that we have either fetched or gotten an error on all the bitmaps we
+// asked for.
+bool SyncedNotification::AreAllBitmapsFetched() {
+ bool app_icon_ready = GetAppIconUrl().is_empty() ||
+ !app_icon_bitmap_.IsEmpty() || !app_icon_bitmap_fetch_pending_;
+ bool images_ready = GetImageUrl().is_empty() || !image_bitmap_.IsEmpty() ||
+ !image_bitmap_fetch_pending_;
+ bool sender_picture_ready = GetProfilePictureUrl(0).is_empty() ||
+ !sender_bitmap_.IsEmpty() || !sender_bitmap_fetch_pending_;
+ bool button_bitmaps_ready = true;
+ for (unsigned int j = 0; j < GetButtonCount(); ++j) {
+ if (!GetButtonIconUrl(j).is_empty()
+ && button_bitmaps_[j].IsEmpty()
+ && button_bitmaps_fetch_pending_[j]) {
+ button_bitmaps_ready = false;
+ break;
+ }
+ }
+
+ return app_icon_ready && images_ready && sender_picture_ready &&
+ button_bitmaps_ready;
+}
+
+// Set the read state on the notification, returns true for success.
+void SyncedNotification::SetReadState(const ReadState& read_state) {
+
+ // Convert the read state to the protobuf type for read state.
+ if (kDismissed == read_state)
+ specifics_.mutable_coalesced_notification()->set_read_state(
+ sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED);
+ else if (kUnread == read_state)
+ specifics_.mutable_coalesced_notification()->set_read_state(
+ sync_pb::CoalescedSyncedNotification_ReadState_UNREAD);
+ else if (kRead == read_state)
+ specifics_.mutable_coalesced_notification()->set_read_state(
+ sync_pb::CoalescedSyncedNotification_ReadState_READ);
+ else
+ NOTREACHED();
+}
+
} // namespace notifier