// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/extensions/extension_app_api.h" #include "base/stl_util.h" #include "base/values.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/render_messages.h" #include "content/common/notification_service.h" const char kBodyTextKey[] = "bodyText"; const char kExtensionIdKey[] = "extensionId"; const char kIconDataKey[] = "iconData"; const char kLinkTextKey[] = "linkText"; const char kLinkUrlKey[] = "linkUrl"; const char kTitleKey[] = "title"; const char kInvalidExtensionIdError[] = "Invalid extension id"; const char kMissingLinkTextError[] = "You must specify linkText if you use linkUrl"; AppNotification::AppNotification() {} AppNotification::~AppNotification() {} AppNotificationManager::AppNotificationManager() { registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, NotificationService::AllSources()); } AppNotificationManager::~AppNotificationManager() {} void AppNotificationManager::Add(AppNotification* item) { CHECK(!item->extension_id.empty()); NotificationMap::iterator found = notifications_.find(item->extension_id); if (found == notifications_.end()) { notifications_[item->extension_id] = AppNotificationList(); found = notifications_.find(item->extension_id); } CHECK(found != notifications_.end()); AppNotificationList& list = (*found).second; list.push_back(linked_ptr(item)); } const AppNotificationList* AppNotificationManager::GetAll( const std::string& extension_id) { if (ContainsKey(notifications_, extension_id)) return ¬ifications_[extension_id]; return NULL; } const AppNotification* AppNotificationManager::GetLast( const std::string& extension_id) { NotificationMap::iterator found = notifications_.find(extension_id); if (found == notifications_.end()) return NULL; const AppNotificationList& list = found->second; return list.rbegin()->get(); } void AppNotificationManager::ClearAll(const std::string& extension_id) { NotificationMap::iterator found = notifications_.find(extension_id); if (found != notifications_.end()) notifications_.erase(found); } void AppNotificationManager::Observe(int type, const NotificationSource& source, const NotificationDetails& details) { CHECK(type == chrome::NOTIFICATION_EXTENSION_UNINSTALLED); const std::string& id = Details(details)->extension_id; ClearAll(id); } bool AppNotifyFunction::RunImpl() { DictionaryValue* details; EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details)); EXTENSION_FUNCTION_VALIDATE(details != NULL); scoped_ptr item(new AppNotification()); // TODO(asargent) remove this before the API leaves experimental. std::string id = extension_id(); if (details->HasKey(kExtensionIdKey)) { EXTENSION_FUNCTION_VALIDATE(details->GetString(kExtensionIdKey, &id)); if (!profile()->GetExtensionService()->GetExtensionById(id, true)) { error_ = kInvalidExtensionIdError; return false; } } item->extension_id = id; if (details->HasKey(kTitleKey)) EXTENSION_FUNCTION_VALIDATE(details->GetString(kTitleKey, &item->title)); if (details->HasKey(kBodyTextKey)) EXTENSION_FUNCTION_VALIDATE(details->GetString(kBodyTextKey, &item->body)); if (details->HasKey(kLinkUrlKey)) { std::string link_url; EXTENSION_FUNCTION_VALIDATE(details->GetString(kLinkUrlKey, &link_url)); item->linkUrl = GURL(link_url); if (!item->linkUrl.is_valid()) { error_ = "Invalid url: " + link_url; return false; } if (!details->HasKey(kLinkTextKey)) { error_ = kMissingLinkTextError; return false; } EXTENSION_FUNCTION_VALIDATE(details->GetString(kLinkTextKey, &item->linkText)); } if (details->HasKey(kIconDataKey)) { base::BinaryValue* binary = NULL; EXTENSION_FUNCTION_VALIDATE(details->GetBinary(kIconDataKey, &binary)); IPC::Message bitmap_pickle(binary->GetBuffer(), binary->GetSize()); void* iter = NULL; SkBitmap bitmap; EXTENSION_FUNCTION_VALIDATE( IPC::ReadParam(&bitmap_pickle, &iter, &bitmap)); // TODO(asargent) - use the bitmap to set the NTP icon! } AppNotificationManager* manager = profile()->GetExtensionService()->app_notification_manager(); manager->Add(item.release()); NotificationService::current()->Notify( chrome::NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED, Source(profile_), Details(&id)); return true; } bool AppClearAllNotificationsFunction::RunImpl() { std::string id = extension_id(); DictionaryValue* details = NULL; if (args_->GetDictionary(0, &details) && details->HasKey(kExtensionIdKey)) { EXTENSION_FUNCTION_VALIDATE(details->GetString(kExtensionIdKey, &id)); if (!profile()->GetExtensionService()->GetExtensionById(id, true)) { error_ = kInvalidExtensionIdError; return false; } } AppNotificationManager* manager = profile()->GetExtensionService()->app_notification_manager(); manager->ClearAll(id); NotificationService::current()->Notify( chrome::NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED, Source(profile_), Details(&id)); return true; }