| Index: chrome/browser/ui/google_now/google_now_service.cc
|
| diff --git a/chrome/browser/ui/google_now/google_now_service.cc b/chrome/browser/ui/google_now/google_now_service.cc
|
| index e6e91771ae5177156b356ae6738d4a55906b1f94..0d334509d7ea6156735dc211fcc4c000ceca1781 100644
|
| --- a/chrome/browser/ui/google_now/google_now_service.cc
|
| +++ b/chrome/browser/ui/google_now/google_now_service.cc
|
| @@ -5,8 +5,17 @@
|
| #include "chrome/browser/ui/google_now/google_now_service.h"
|
|
|
| #include "base/command_line.h"
|
| +#include "base/json/json_reader.h"
|
| +#include "base/memory/scoped_vector.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "base/values.h"
|
| +#include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/notifications/notification.h"
|
| +#include "chrome/browser/notifications/notification_ui_manager.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/ui/google_now/google_now_notification_delegate.h"
|
| #include "chrome/common/chrome_switches.h"
|
| +#include "chrome/common/extensions/api/experimental_notification.h"
|
| #include "content/public/browser/geolocation.h"
|
| #include "content/public/common/geoposition.h"
|
| #include "net/http/http_status_code.h"
|
| @@ -14,8 +23,11 @@
|
| #include "net/url_request/url_request_context.h"
|
|
|
| using base::Bind;
|
| +using base::JSONReader;
|
| using base::TimeDelta;
|
| +using base::Value;
|
| using content::Geoposition;
|
| +using extensions::api::experimental_notification::ShowOptions;
|
| using net::HTTP_OK;
|
| using net::URLFetcher;
|
| using net::URLRequestStatus;
|
| @@ -31,10 +43,17 @@ namespace {
|
| const int kDefaultPollingPeriodMs = 300000; // 5 minutes
|
| // Time allocated to a geolocation request.
|
| const int kGeolocationRequestTimeoutMs = 60000; // 1 minute
|
| +// JSON key for expiration timestamp.
|
| +const char kExpirationTimestampKey[] = "expiration_timestamp_seconds";
|
| +// JSON key for cards.
|
| +const char kCardsKey[] = "cards";
|
| } // namespace
|
|
|
| +// Google Now cards in the server response.
|
| +typedef ScopedVector<ShowOptions> ParsedCards;
|
| +
|
| struct GoogleNowService::ServerResponse {
|
| - // TODO(vadimt): Populate this structure with real fields.
|
| + ParsedCards cards;
|
| TimeDelta next_request_delay;
|
| };
|
|
|
| @@ -158,15 +177,121 @@ void GoogleNowService::StartServerRequest(
|
|
|
| bool GoogleNowService::ParseServerResponse(const std::string& response_string,
|
| ServerResponse* server_response) {
|
| - // TODO(vadimt): Do real parsing.
|
| + // Server response is in JSON format.
|
| + scoped_ptr<Value> value(JSONReader::Read(response_string));
|
| +
|
| + if (value == NULL)
|
| + return false;
|
| +
|
| + const DictionaryValue* root;
|
| + if (!value->GetAsDictionary(&root))
|
| + return false;
|
| +
|
| + int expiration_timestamp_seconds;
|
| + if (!root->GetInteger(kExpirationTimestampKey,
|
| + &expiration_timestamp_seconds)) {
|
| + return false;
|
| + }
|
| +
|
| server_response->next_request_delay =
|
| - TimeDelta::FromMilliseconds(kDefaultPollingPeriodMs);
|
| + TimeDelta::FromSeconds(expiration_timestamp_seconds);
|
| +
|
| + const ListValue* cards;
|
| + if (!root->GetList(kCardsKey, &cards))
|
| + return false;
|
| +
|
| + for (size_t index = 0; index < cards->GetSize(); ++index) {
|
| + const base::DictionaryValue* card;
|
| + if (!cards->GetDictionary(index, &card))
|
| + return false;
|
| +
|
| + scoped_ptr<ShowOptions> show_options(new ShowOptions());
|
| +
|
| + if (!ShowOptions::Populate(*card, show_options.get()))
|
| + return false;
|
| +
|
| + server_response->cards.push_back(show_options.release());
|
| + }
|
| +
|
| return true;
|
| }
|
|
|
| void GoogleNowService::ShowNotifications(
|
| const ServerResponse& server_response) {
|
| - // TODO(vadimt): Implement using Chrome Notifications.
|
| + // TODO(vadimt): Most of the code below duplicates the code in
|
| + // NotificationShowFunction::RunImpl. Once we finally decide the format of the
|
| + // server response, remove the duplication. Before this, keep this code in
|
| + // sync with its origin.
|
| + for (ParsedCards::const_iterator it = server_response.cards.begin();
|
| + it != server_response.cards.end();
|
| + ++it) {
|
| + ShowOptions* show_options = *it;
|
| +
|
| + ui::notifications::NotificationType type =
|
| + ui::notifications::StringToNotificationType(show_options->type);
|
| + GURL icon_url(UTF8ToUTF16(show_options->icon_url));
|
| + string16 title(UTF8ToUTF16(show_options->title));
|
| + string16 message(UTF8ToUTF16(show_options->message));
|
| +
|
| + scoped_ptr<DictionaryValue> optional_fields(new DictionaryValue());
|
| +
|
| + // For all notification types.
|
| + if (show_options->priority.get())
|
| + optional_fields->SetInteger(ui::notifications::kPriorityKey,
|
| + *show_options->priority);
|
| + if (show_options->timestamp.get())
|
| + optional_fields->SetString(ui::notifications::kTimestampKey,
|
| + *show_options->timestamp);
|
| + if (show_options->second_icon_url.get())
|
| + optional_fields->SetString(ui::notifications::kSecondIconUrlKey,
|
| + UTF8ToUTF16(*show_options->second_icon_url));
|
| + if (show_options->unread_count.get())
|
| + optional_fields->SetInteger(ui::notifications::kUnreadCountKey,
|
| + *show_options->unread_count);
|
| + if (show_options->button_one_title.get())
|
| + optional_fields->SetString(ui::notifications::kButtonOneTitleKey,
|
| + UTF8ToUTF16(*show_options->button_one_title));
|
| + if (show_options->button_two_title.get())
|
| + optional_fields->SetString(ui::notifications::kButtonTwoTitleKey,
|
| + UTF8ToUTF16(*show_options->button_two_title));
|
| + if (show_options->expanded_message.get())
|
| + optional_fields->SetString(ui::notifications::kExpandedMessageKey,
|
| + UTF8ToUTF16(*show_options->expanded_message));
|
| +
|
| + // For image notifications (type == 'image').
|
| + if (show_options->image_url.get())
|
| + optional_fields->SetString(ui::notifications::kImageUrlKey,
|
| + UTF8ToUTF16(*show_options->image_url));
|
| +
|
| + // For multiple-item notifications (type == 'multiple').
|
| + if (show_options->items.get()) {
|
| + base::ListValue* items = new base::ListValue();
|
| + std::vector<
|
| + linked_ptr<
|
| + extensions::api::experimental_notification::NotificationItem> >::
|
| + iterator i;
|
| + for (i = show_options->items->begin();
|
| + i != show_options->items->end();
|
| + ++i) {
|
| + base::DictionaryValue* item = new base::DictionaryValue();
|
| + item->SetString(ui::notifications::kItemTitleKey,
|
| + UTF8ToUTF16(i->get()->title));
|
| + item->SetString(ui::notifications::kItemMessageKey,
|
| + UTF8ToUTF16(i->get()->message));
|
| + items->Append(item);
|
| + }
|
| + optional_fields->Set(ui::notifications::kItemsKey, items);
|
| + }
|
| +
|
| + string16 replace_id(UTF8ToUTF16(show_options->replace_id));
|
| +
|
| + Notification notification(type, icon_url, title, message,
|
| + WebKit::WebTextDirectionDefault,
|
| + string16(), replace_id,
|
| + optional_fields.get(),
|
| + new GoogleNowNotificationDelegate());
|
| + g_browser_process->notification_ui_manager()->Add(notification, profile_);
|
| + }
|
| }
|
|
|
| void GoogleNowService::OnURLFetchComplete(const net::URLFetcher* source) {
|
|
|