diff options
Diffstat (limited to 'chrome/browser/notifications/notification_ui_manager_android.cc')
-rw-r--r-- | chrome/browser/notifications/notification_ui_manager_android.cc | 226 |
1 files changed, 45 insertions, 181 deletions
diff --git a/chrome/browser/notifications/notification_ui_manager_android.cc b/chrome/browser/notifications/notification_ui_manager_android.cc index 7152638..aa5984c 100644 --- a/chrome/browser/notifications/notification_ui_manager_android.cc +++ b/chrome/browser/notifications/notification_ui_manager_android.cc @@ -9,7 +9,7 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/logging.h" -#include "base/pickle.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/notifications/notification.h" #include "chrome/browser/notifications/persistent_notification_delegate.h" @@ -29,91 +29,6 @@ using base::android::ConvertUTF8ToJavaString; namespace { -// The maximum size of the serialized pickle that carries a notification's meta -// information. Notifications carrying more data will be silently dropped - with -// an error being written to the log. -const int kMaximumSerializedNotificationSizeBytes = 1024 * 1024; - -// Persistent notifications are likely to outlive the browser process they were -// created by on Android. In order to be able to re-surface the notification -// when the user interacts with them, all relevant notification data needs to -// be serialized with the notification itself. -// -// In the near future, as more features get added to Chrome's notification -// implementation, this will be done by storing the persistent notification data -// in a database. However, to support launching Chrome for Android from a -// notification event until that exists, serialize the data in the Intent. -// -// TODO(peter): Move towards storing notification data in a database rather than -// as a serialized Intent extra. - -scoped_ptr<Pickle> SerializePersistentNotification( - const content::PlatformNotificationData& notification_data, - const GURL& origin, - int64 service_worker_registration_id) { - scoped_ptr<Pickle> pickle(new Pickle); - - // content::PlatformNotificationData - pickle->WriteString16(notification_data.title); - pickle->WriteInt(static_cast<int>(notification_data.direction)); - pickle->WriteString(notification_data.lang); - pickle->WriteString16(notification_data.body); - pickle->WriteString(notification_data.tag); - pickle->WriteString(notification_data.icon.spec()); - pickle->WriteBool(notification_data.silent); - - // The origin which is displaying the notification. - pickle->WriteString(origin.spec()); - - // The Service Worker registration this notification is associated with. - pickle->WriteInt64(service_worker_registration_id); - - if (pickle->size() > kMaximumSerializedNotificationSizeBytes) - return nullptr; - - return pickle.Pass(); -} - -bool UnserializePersistentNotification( - const Pickle& pickle, - content::PlatformNotificationData* notification_data, - GURL* origin, - int64* service_worker_registration_id) { - DCHECK(notification_data && origin && service_worker_registration_id); - PickleIterator iterator(pickle); - - std::string icon_url, origin_url; - int direction_value; - - // Unpack content::PlatformNotificationData. - if (!iterator.ReadString16(¬ification_data->title) || - !iterator.ReadInt(&direction_value) || - !iterator.ReadString(¬ification_data->lang) || - !iterator.ReadString16(¬ification_data->body) || - !iterator.ReadString(¬ification_data->tag) || - !iterator.ReadString(&icon_url) || - !iterator.ReadBool(¬ification_data->silent)) { - return false; - } - - notification_data->direction = - static_cast<content::PlatformNotificationData::NotificationDirection>( - direction_value); - notification_data->icon = GURL(icon_url); - - // Unpack the origin which displayed this notification. - if (!iterator.ReadString(&origin_url)) - return false; - - *origin = GURL(origin_url); - - // Unpack the Service Worker registration id. - if (!iterator.ReadInt64(service_worker_registration_id)) - return false; - - return true; -} - // Called when the "notificationclick" event in the Service Worker has finished // executing for a notification that was created in a previous instance of the // browser. @@ -143,8 +58,6 @@ NotificationUIManagerAndroid::NotificationUIManagerAndroid() { AttachCurrentThread(), reinterpret_cast<intptr_t>(this), base::android::GetApplicationContext())); - - // TODO(peter): Synchronize notifications with the Java side. } NotificationUIManagerAndroid::~NotificationUIManagerAndroid() { @@ -155,72 +68,35 @@ NotificationUIManagerAndroid::~NotificationUIManagerAndroid() { bool NotificationUIManagerAndroid::OnNotificationClicked( JNIEnv* env, jobject java_object, - jstring notification_id, - jbyteArray serialized_notification_data) { - std::string id = ConvertJavaStringToUTF8(env, notification_id); - - auto iter = profile_notifications_.find(id); - if (iter != profile_notifications_.end()) { - const Notification& notification = iter->second->notification(); - notification.delegate()->Click(); + jlong persistent_notification_id, + jstring java_origin, + jstring java_tag) { + GURL origin(ConvertJavaStringToUTF8(env, java_origin)); + std::string tag = ConvertJavaStringToUTF8(env, java_tag); - return true; - } - - // If the Notification were not found, it may be a persistent notification - // that outlived the Chrome browser process. In this case, try to - // unserialize the notification's serialized data and trigger the click - // event manually. - - std::vector<uint8> bytes; - base::android::JavaByteArrayToByteVector(env, serialized_notification_data, - &bytes); - if (!bytes.size()) - return false; - - content::PlatformNotificationData notification_data; - GURL origin; - int64 service_worker_registration_id; - - Pickle pickle(reinterpret_cast<const char*>(&bytes[0]), bytes.size()); - if (!UnserializePersistentNotification(pickle, ¬ification_data, &origin, - &service_worker_registration_id)) { - return false; - } - - // Store the tag and origin of this notification so that it can later be - // closed using these details. - regenerated_notification_infos_[id] = - std::make_pair(notification_data.tag, origin.spec()); - - PlatformNotificationServiceImpl* service = - PlatformNotificationServiceImpl::GetInstance(); + regenerated_notification_infos_[persistent_notification_id] = + std::make_pair(origin.spec(), tag); // TODO(peter): Rather than assuming that the last used profile is the // appropriate one for this notification, the used profile should be // stored as part of the notification's data. See https://crbug.com/437574. - service->OnPersistentNotificationClick( + PlatformNotificationServiceImpl::GetInstance()->OnPersistentNotificationClick( ProfileManager::GetLastUsedProfile(), - service_worker_registration_id, - id, + persistent_notification_id, origin, - notification_data, base::Bind(&OnEventDispatchComplete)); return true; } bool NotificationUIManagerAndroid::OnNotificationClosed( - JNIEnv* env, jobject java_object, jstring notification_id) { - std::string id = ConvertJavaStringToUTF8(env, notification_id); - - auto iter = profile_notifications_.find(id); - if (iter == profile_notifications_.end()) - return false; - - const Notification& notification = iter->second->notification(); - notification.delegate()->Close(true /** by_user **/); - RemoveProfileNotification(iter->second, true /* close */); + JNIEnv* env, + jobject java_object, + jlong persistent_notification_id, + jstring java_origin, + jstring java_tag) { + // TODO(peter): Implement handling when a notification has been closed. The + // notification database has to reflect this in its own state. return true; } @@ -242,16 +118,21 @@ void NotificationUIManagerAndroid::Add(const Notification& notification, JNIEnv* env = AttachCurrentThread(); + PersistentNotificationDelegate* delegate = + static_cast<PersistentNotificationDelegate*>(notification.delegate()); + DCHECK(delegate); + + int64_t persistent_notification_id = delegate->persistent_notification_id(); + GURL origin_url(notification.origin_url().GetOrigin()); + + ScopedJavaLocalRef<jstring> origin = ConvertUTF8ToJavaString( + env, origin_url.spec()); ScopedJavaLocalRef<jstring> tag = ConvertUTF8ToJavaString(env, notification.tag()); - ScopedJavaLocalRef<jstring> id = ConvertUTF8ToJavaString( - env, profile_notification->notification().id()); ScopedJavaLocalRef<jstring> title = ConvertUTF16ToJavaString( env, notification.title()); ScopedJavaLocalRef<jstring> body = ConvertUTF16ToJavaString( env, notification.message()); - ScopedJavaLocalRef<jstring> origin = ConvertUTF8ToJavaString( - env, notification.origin_url().GetOrigin().spec()); ScopedJavaLocalRef<jobject> icon; @@ -259,41 +140,19 @@ void NotificationUIManagerAndroid::Add(const Notification& notification, if (!icon_bitmap.isNull()) icon = gfx::ConvertToJavaBitmap(&icon_bitmap); - ScopedJavaLocalRef<jbyteArray> notification_data; - if (true /** is_persistent_notification **/) { - PersistentNotificationDelegate* delegate = - static_cast<PersistentNotificationDelegate*>(notification.delegate()); - scoped_ptr<Pickle> pickle = SerializePersistentNotification( - delegate->notification_data(), - notification.origin_url(), - delegate->service_worker_registration_id()); - - if (!pickle) { - LOG(ERROR) << - "Unable to serialize the notification, payload too large (max 1MB)."; - RemoveProfileNotification(profile_notification, true /* close */); - return; - } - - notification_data = base::android::ToJavaByteArray( - env, static_cast<const uint8*>(pickle->data()), pickle->size()); - } - Java_NotificationUIManager_displayNotification( env, java_object_.obj(), + persistent_notification_id, + origin.obj(), tag.obj(), - id.obj(), title.obj(), body.obj(), icon.obj(), - origin.obj(), - notification.silent(), - notification_data.obj()); + notification.silent()); - regenerated_notification_infos_[profile_notification->notification().id()] = - std::make_pair(notification.tag(), - notification.origin_url().GetOrigin().spec()); + regenerated_notification_infos_[persistent_notification_id] = + std::make_pair(origin_url.spec(), notification.tag()); notification.delegate()->Display(); } @@ -408,25 +267,30 @@ bool NotificationUIManagerAndroid::RegisterNotificationUIManager(JNIEnv* env) { void NotificationUIManagerAndroid::PlatformCloseNotification( const std::string& notification_id) { - auto iterator = regenerated_notification_infos_.find(notification_id); + int64_t persistent_notification_id = 0; + if (!base::StringToInt64(notification_id, &persistent_notification_id)) + return; + + const auto iterator = + regenerated_notification_infos_.find(persistent_notification_id); if (iterator == regenerated_notification_infos_.end()) return; RegeneratedNotificationInfo notification_info = iterator->second; JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> tag = - ConvertUTF8ToJavaString(env, notification_info.first); ScopedJavaLocalRef<jstring> origin = + ConvertUTF8ToJavaString(env, notification_info.first); + ScopedJavaLocalRef<jstring> tag = ConvertUTF8ToJavaString(env, notification_info.second); - ScopedJavaLocalRef<jstring> java_notification_id = - ConvertUTF8ToJavaString(env, notification_id); - regenerated_notification_infos_.erase(notification_id); + regenerated_notification_infos_.erase(iterator); - Java_NotificationUIManager_closeNotification( - env, java_object_.obj(), tag.obj(), java_notification_id.obj(), - origin.obj()); + Java_NotificationUIManager_closeNotification(env, + java_object_.obj(), + persistent_notification_id, + origin.obj(), + tag.obj()); } void NotificationUIManagerAndroid::AddProfileNotification( |