Home | History | Annotate | Download | only in prototype
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "cloud_print/gcp20/prototype/cloud_print_response_parser.h"
      6 
      7 #include "base/json/json_reader.h"
      8 #include "base/json/json_writer.h"
      9 #include "base/logging.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/values.h"
     12 
     13 namespace cloud_print_response_parser {
     14 
     15 Job::Job() {
     16 }
     17 
     18 Job::~Job() {
     19 }
     20 
     21 // Parses json base::Value to base::DictionaryValue.
     22 // If |success| value in JSON dictionary is |false| then |message| will
     23 // contain |message| from the JSON dictionary.
     24 // Returns |true| if no parsing error occurred.
     25 bool GetJsonDictinaryAndCheckSuccess(base::Value* json,
     26                                      std::string* error_description,
     27                                      bool* json_success,
     28                                      std::string* message,
     29                                      base::DictionaryValue** dictionary) {
     30   base::DictionaryValue* response_dictionary = NULL;
     31   if (!json || !json->GetAsDictionary(&response_dictionary)) {
     32     *error_description = "No JSON dictionary response received.";
     33     return false;
     34   }
     35 
     36   bool response_json_success = false;
     37   if (!response_dictionary->GetBoolean("success", &response_json_success)) {
     38     *error_description = "Cannot parse success state.";
     39     return false;
     40   }
     41 
     42   if (!response_json_success) {
     43     std::string response_message;
     44     if (!response_dictionary->GetString("message", &response_message)) {
     45       *error_description = "Cannot parse message from response.";
     46       return false;
     47     }
     48     *message = response_message;
     49   }
     50 
     51   *json_success = response_json_success;
     52   *dictionary = response_dictionary;
     53   return true;
     54 }
     55 
     56 bool ParseRegisterStartResponse(const std::string& response,
     57                                 std::string* error_description,
     58                                 std::string* polling_url,
     59                                 std::string* registration_token,
     60                                 std::string* complete_invite_url,
     61                                 std::string* device_id) {
     62   scoped_ptr<base::Value> json(base::JSONReader::Read(response));
     63   base::DictionaryValue* response_dictionary = NULL;
     64   bool json_success;
     65   std::string message;
     66   if (!GetJsonDictinaryAndCheckSuccess(json.get(), error_description,
     67                                        &json_success, &message,
     68                                        &response_dictionary)) {
     69     return false;
     70   }
     71   if (!json_success) {
     72     *error_description = message;
     73     return false;
     74   }
     75 
     76   std::string response_registration_token;
     77   if (!response_dictionary->GetString("registration_token",
     78                                       &response_registration_token)) {
     79     *error_description = "No registration_token specified.";
     80     return false;
     81   }
     82 
     83   std::string response_complete_invite_url;
     84   if (!response_dictionary->GetString("complete_invite_url",
     85                                       &response_complete_invite_url)) {
     86     *error_description = "No complete_invite_url specified.";
     87     return false;
     88   }
     89 
     90   std::string response_polling_url;
     91   if (!response_dictionary->GetString("polling_url", &response_polling_url)) {
     92     *error_description = "No polling_url specified.";
     93     return false;
     94   }
     95 
     96   base::ListValue* list = NULL;
     97   if (!response_dictionary->GetList("printers", &list)) {
     98     *error_description = "No printers list specified.";
     99     return false;
    100   }
    101 
    102   base::DictionaryValue* printer = NULL;
    103   if (!list->GetDictionary(0, &printer)) {
    104     *error_description = "Printers list is empty or printer is not dictionary.";
    105     return false;
    106   }
    107 
    108   std::string id;
    109   if (!printer->GetString("id", &id)) {
    110     *error_description = "No id specified.";
    111     return false;
    112   }
    113 
    114   if (id.empty()) {
    115     *error_description = "id is empty.";
    116     return false;
    117   }
    118 
    119   *polling_url = response_polling_url;
    120   *registration_token = response_registration_token;
    121   *complete_invite_url = response_complete_invite_url;
    122   *device_id = id;
    123   return true;
    124 }
    125 
    126 bool ParseRegisterCompleteResponse(const std::string& response,
    127                                    std::string* error_description,
    128                                    std::string* authorization_code,
    129                                    std::string* xmpp_jid) {
    130   scoped_ptr<base::Value> json(base::JSONReader::Read(response));
    131   base::DictionaryValue* response_dictionary = NULL;
    132   bool json_success;
    133   std::string message;
    134   if (!GetJsonDictinaryAndCheckSuccess(json.get(), error_description,
    135                                        &json_success, &message,
    136                                        &response_dictionary)) {
    137     return false;
    138   }
    139   if (!json_success) {
    140     *error_description = message;
    141     return false;
    142   }
    143 
    144   std::string response_authorization_code;
    145   if (!response_dictionary->GetString("authorization_code",
    146                                       &response_authorization_code)) {
    147     *error_description = "Cannot parse authorization_code.";
    148     return false;
    149   }
    150 
    151   std::string response_xmpp_jid;
    152   if (!response_dictionary->GetString("xmpp_jid", &response_xmpp_jid)) {
    153     *error_description = "Cannot parse xmpp jid.";
    154     return false;
    155   }
    156 
    157   *authorization_code = response_authorization_code;
    158   *xmpp_jid = response_xmpp_jid;
    159   return true;
    160 }
    161 
    162 bool ParseFetchResponse(const std::string& response,
    163                         std::string* error_description,
    164                         std::vector<Job>* list) {
    165   scoped_ptr<base::Value> json(base::JSONReader::Read(response));
    166   base::DictionaryValue* response_dictionary = NULL;
    167   bool json_success;
    168   std::string message;
    169   if (!GetJsonDictinaryAndCheckSuccess(json.get(), error_description,
    170                                        &json_success, &message,
    171                                        &response_dictionary)) {
    172     return false;
    173   }
    174 
    175   if (!json_success) {  // Let's suppose we have no jobs to proceed.
    176     list->clear();
    177     return true;
    178   }
    179 
    180   base::ListValue* jobs = NULL;
    181   if (!response_dictionary->GetList("jobs", &jobs)) {
    182     *error_description = "Cannot parse jobs list.";
    183     return false;
    184   }
    185 
    186   std::vector<Job> job_list(jobs->GetSize());
    187   std::string create_time_str;
    188   for (size_t idx = 0; idx < job_list.size(); ++idx) {
    189     base::DictionaryValue* job = NULL;
    190     jobs->GetDictionary(idx, &job);
    191     if (!job->GetString("id", &job_list[idx].job_id) ||
    192         !job->GetString("createTime", &create_time_str) ||
    193         !job->GetString("fileUrl", &job_list[idx].file_url) ||
    194         !job->GetString("ticketUrl", &job_list[idx].ticket_url) ||
    195         !job->GetString("title", &job_list[idx].title)) {
    196       *error_description = "Cannot parse job info.";
    197       return false;
    198     }
    199     int64 create_time_ms = 0;
    200     if (!base::StringToInt64(create_time_str, &create_time_ms)) {
    201       *error_description = "Cannot convert time.";
    202       return false;
    203     }
    204     job_list[idx].create_time =
    205         base::Time::UnixEpoch() +
    206         base::TimeDelta::FromMilliseconds(create_time_ms);
    207   }
    208 
    209   *list = job_list;
    210   return true;
    211 }
    212 
    213 bool ParseLocalSettingsResponse(const std::string& response,
    214                                 std::string* error_description,
    215                                 LocalSettings::State* state,
    216                                 LocalSettings* settings) {
    217   scoped_ptr<base::Value> json(base::JSONReader::Read(response));
    218   base::DictionaryValue* response_dictionary = NULL;
    219   bool json_success;
    220   std::string message;
    221   if (!GetJsonDictinaryAndCheckSuccess(json.get(), error_description,
    222                                        &json_success, &message,
    223                                        &response_dictionary)) {
    224     return false;
    225   }
    226 
    227   if (!json_success) {  // Let's suppose our printer was deleted.
    228     *state = LocalSettings::PRINTER_DELETED;
    229     return true;
    230   }
    231 
    232   base::ListValue* list = NULL;
    233   if (!response_dictionary->GetList("printers", &list)) {
    234     *error_description = "No printers list specified.";
    235     return false;
    236   }
    237 
    238   base::DictionaryValue* printer = NULL;
    239   if (!list->GetDictionary(0, &printer)) {
    240     *error_description = "Printers list is empty or printer is not dictionary.";
    241     return false;
    242   }
    243 
    244   base::DictionaryValue* local_settings_dict = NULL;
    245   if (!printer->GetDictionary("local_settings", &local_settings_dict)) {
    246     *error_description = "No local_settings found.";
    247     return false;
    248   }
    249 
    250   base::DictionaryValue* current = NULL;
    251   if (!local_settings_dict->GetDictionary("current", &current)) {
    252     *error_description = "No *current* local settings found.";
    253     return false;
    254   }
    255 
    256   LocalSettings::State settings_state;
    257   base::DictionaryValue* pending = NULL;
    258   base::DictionaryValue* settings_to_parse = NULL;
    259   if (local_settings_dict->GetDictionary("pending", &pending)) {
    260     settings_to_parse = pending;
    261     settings_state = LocalSettings::PENDING;
    262   } else {
    263     settings_to_parse = current;
    264     settings_state = LocalSettings::CURRENT;
    265   }
    266 
    267   LocalSettings local_settings;
    268   if (!settings_to_parse->GetBoolean("local_discovery",
    269                                      &local_settings.local_discovery) ||
    270       !settings_to_parse->GetBoolean("access_token_enabled",
    271                                      &local_settings.access_token_enabled) ||
    272       !settings_to_parse->GetBoolean("printer/local_printing_enabled",
    273                                      &local_settings.local_printing_enabled) ||
    274       !settings_to_parse->GetInteger("xmpp_timeout_value",
    275                                      &local_settings.xmpp_timeout_value)) {
    276     *error_description = "Cannot parse local_settings info.";
    277     return false;
    278   }
    279 
    280   *state = settings_state;
    281   *settings = local_settings;
    282   return true;
    283 }
    284 
    285 }  // namespace cloud_print_response_parser
    286 
    287