15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_connector.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/md5.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/cloud_print/cloud_print_constants.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/cloud_print/cloud_print_helpers.h"
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_service_helpers.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/mime_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cloud_print {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintConnector::CloudPrintConnector(Client* client,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const ConnectorSettings& settings)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : client_(client),
280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    next_response_handler_(NULL),
290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    stats_ptr_factory_(this) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings_.CopyFrom(settings);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintConnector::InitPrintSystem() {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (print_system_.get())
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  print_system_ = PrintSystem::CreateInstance(
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      settings_.print_system_settings());
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!print_system_.get()) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // No memory.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrintSystem::PrintSystemResult result = print_system_->Init();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.succeeded()) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print_system_ = NULL;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We could not initialize the print system. We need to notify the server.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportUserMessage(kPrintSystemFailedMessageId, result.message());
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CloudPrintConnector::ScheduleStatsReport() {
530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      FROM_HERE,
550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      base::Bind(&CloudPrintConnector::ReportStats,
560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                 stats_ptr_factory_.GetWeakPtr()),
570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      base::TimeDelta::FromHours(1));
580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CloudPrintConnector::ReportStats() {
610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  PrinterJobHandler::ReportsStats();
620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScheduleStatsReport();
630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintConnector::Start() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Starting connector"
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", proxy id: " << settings_.proxy_id();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tasks_.clear();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!InitPrintSystem())
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScheduleStatsReport();
750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start watching for updates from the print system.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_server_watcher_ = print_system_->CreatePrintServerWatcher();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_server_watcher_->StartWatching(this);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get list of registered printers.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPendingAvailableTask();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::Stop() {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Stopping connector"
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", proxy id: " << settings_.proxy_id();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsRunning());
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do uninitialization here.
900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  stats_ptr_factory_.InvalidateWeakPtrs();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tasks_.clear();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_server_watcher_ = NULL;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_ = NULL;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintConnector::IsRunning() {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return print_server_watcher_.get() != NULL;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::GetPrinterIds(std::list<std::string>* printer_ids) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(printer_ids);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_ids->clear();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (JobHandlerMap::const_iterator iter = job_handler_map_.begin();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != job_handler_map_.end(); ++iter) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer_ids->push_back(iter->first);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::RegisterPrinters(
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const printing::PrinterList& printers) {
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsRunning())
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing::PrinterList::const_iterator it;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = printers.begin(); it != printers.end(); ++it) {
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (settings_.ShouldConnect(it->printer_name))
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddPendingRegisterTask(*it);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check for jobs for specific printer
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::CheckForJobs(const std::string& reason,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::string& printer_id) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsRunning())
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!printer_id.empty()) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JobHandlerMap::iterator index = job_handler_map_.find(printer_id);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index != job_handler_map_.end()) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      index->second->CheckForJobs(reason);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string status_message = l10n_util::GetStringUTF8(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          IDS_CLOUD_PRINT_ZOMBIE_PRINTER);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "CP_CONNECTOR: " << status_message <<
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          " Printer_id: " << printer_id;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportUserMessage(kZombiePrinterMessageId, status_message);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (JobHandlerMap::iterator index = job_handler_map_.begin();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         index != job_handler_map_.end(); index++) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      index->second->CheckForJobs(reason);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CloudPrintConnector::UpdatePrinterSettings(const std::string& printer_id) {
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Since connector is managing many printers we need to go through all of them
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // to select the correct settings.
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  GURL printer_list_url = GetUrlForPrinterList(
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      settings_.server_url(), settings_.proxy_id());
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  StartGetRequest(
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      printer_list_url,
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      kCloudPrintRegisterMaxRetryCount,
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      &CloudPrintConnector::HandlePrinterListResponseSettingsUpdate);
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::OnPrinterAdded() {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPendingAvailableTask();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::OnPrinterDeleted(const std::string& printer_id) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPendingDeleteTask(printer_id);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::OnAuthError() {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_->OnAuthFailed();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CloudPrintURLFetcher::Delegate implementation.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintURLFetcher::ResponseAction CloudPrintConnector::HandleRawData(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& data) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this notification came as a result of user message call, stop it.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise proceed continue processing.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (user_message_request_.get() &&
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_message_request_->IsSameRequest(source))
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CloudPrintURLFetcher::STOP_PROCESSING;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CloudPrintURLFetcher::CONTINUE_PROCESSING;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintURLFetcher::ResponseAction CloudPrintConnector::HandleJSONData(
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* json_data,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool succeeded) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsRunning())  // Orphant response. Connector has been stopped already.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CloudPrintURLFetcher::STOP_PROCESSING;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(next_response_handler_);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (this->*next_response_handler_)(source, url, json_data, succeeded);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintURLFetcher::ResponseAction CloudPrintConnector::OnRequestAuthError() {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnAuthError();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CloudPrintURLFetcher::STOP_PROCESSING;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CloudPrintConnector::GetAuthHeader() {
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetCloudPrintAuthHeaderFromStore();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintConnector::~CloudPrintConnector() {}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintURLFetcher::ResponseAction
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintConnector::HandlePrinterListResponse(
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* json_data,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool succeeded) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(succeeded);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!succeeded)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CloudPrintURLFetcher::RETRY_REQUEST;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UpdateSettingsFromPrintersList(json_data);
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now we need to get the list of printers from the print system
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and split printers into 3 categories:
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - existing and registered printers
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - new printers
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - deleted printers
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get list of the printers from the print system.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing::PrinterList local_printers;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrintSystem::PrintSystemResult result =
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print_system_->EnumeratePrinters(&local_printers);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool full_list = result.succeeded();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!full_list) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string message = result.message();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (message.empty())
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message = l10n_util::GetStringFUTF8(IDS_CLOUD_PRINT_ENUM_FAILED,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT));
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There was a failure enumerating printers. Send a message to the server.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportUserMessage(kEnumPrintersFailedMessageId, message);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Go through the list of the cloud printers and init print job handlers.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue* printer_list = NULL;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There may be no "printers" value in the JSON
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (json_data->GetList(kPrinterListValue, &printer_list) && printer_list) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t index = 0; index < printer_list->GetSize(); index++) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DictionaryValue* printer_data = NULL;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (printer_list->GetDictionary(index, &printer_data)) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string printer_name;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer_data->GetString(kNameValue, &printer_name);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string printer_id;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer_data->GetString(kIdValue, &printer_id);
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!settings_.ShouldConnect(printer_name)) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "CP_CONNECTOR: Deleting " << printer_name <<
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              " id: " << printer_id << " as blacklisted";
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AddPendingDeleteTask(printer_id);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (RemovePrinterFromList(printer_name, &local_printers)) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          InitJobHandlerForPrinter(printer_data);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Cloud printer is not found on the local system.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (full_list || settings_.delete_on_enum_fail()) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // Delete if we get the full list of printers or
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // |delete_on_enum_fail_| is set.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            VLOG(1) << "CP_CONNECTOR: Deleting " << printer_name <<
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                " id: " << printer_id <<
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                " full_list: " << full_list <<
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                " delete_on_enum_fail: " << settings_.delete_on_enum_fail();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            AddPendingDeleteTask(printer_id);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            LOG(ERROR) << "CP_CONNECTOR: Printer: " << printer_name <<
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                " id: " << printer_id <<
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                " not found in print system and full printer list was" <<
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                " not received.  Printer will not be able to process" <<
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                " jobs.";
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_ = NULL;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisterPrinters(local_printers);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContinuePendingTaskProcessing();  // Continue processing background tasks.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CloudPrintURLFetcher::STOP_PROCESSING;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintURLFetcher::ResponseAction
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)CloudPrintConnector::HandlePrinterListResponseSettingsUpdate(
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const net::URLFetcher* source,
28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const GURL& url,
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DictionaryValue* json_data,
28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    bool succeeded) {
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(succeeded);
29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!succeeded)
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return CloudPrintURLFetcher::RETRY_REQUEST;
29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UpdateSettingsFromPrintersList(json_data);
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return CloudPrintURLFetcher::STOP_PROCESSING;
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)CloudPrintURLFetcher::ResponseAction
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintConnector::HandlePrinterDeleteResponse(
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* json_data,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool succeeded) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Handler printer delete response"
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", succeeded: " << succeeded
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", url: " << url;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContinuePendingTaskProcessing();  // Continue processing background tasks.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CloudPrintURLFetcher::STOP_PROCESSING;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintURLFetcher::ResponseAction
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintConnector::HandleRegisterPrinterResponse(
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* json_data,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool succeeded) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Handler printer register response"
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", succeeded: " << succeeded
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", url: " << url;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (succeeded) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListValue* printer_list = NULL;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There should be a "printers" value in the JSON
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (json_data->GetList(kPrinterListValue, &printer_list)) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DictionaryValue* printer_data = NULL;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (printer_list->GetDictionary(0, &printer_data))
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        InitJobHandlerForPrinter(printer_data);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContinuePendingTaskProcessing();  // Continue processing background tasks.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CloudPrintURLFetcher::STOP_PROCESSING;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::StartGetRequest(const GURL& url,
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int max_retries,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          ResponseHandler handler) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_response_handler_ = handler;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_ = CloudPrintURLFetcher::Create();
3390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  request_->StartGetRequest(CloudPrintURLFetcher::REQUEST_UPDATE_JOB,
3400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                            url, this, max_retries, std::string());
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CloudPrintConnector::StartPostRequest(
3440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    CloudPrintURLFetcher::RequestType type,
3450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const GURL& url,
3460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int max_retries,
3470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const std::string& mime_type,
3480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const std::string& post_data,
3490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    ResponseHandler handler) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_response_handler_ = handler;
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_ = CloudPrintURLFetcher::Create();
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->StartPostRequest(
3530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      type, url, this, max_retries, mime_type, post_data, std::string());
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::ReportUserMessage(const std::string& message_id,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const std::string& failure_msg) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is a fire and forget type of function.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Result of this request will be ignored.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string mime_boundary;
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateMimeBoundaryForUpload(&mime_boundary);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url = GetUrlForUserMessage(settings_.server_url(), message_id);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string post_data;
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartValueForUpload(kMessageTextValue, failure_msg, mime_boundary,
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                  std::string(), &post_data);
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartFinalDelimiterForUpload(mime_boundary, &post_data);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string mime_type("multipart/form-data; boundary=");
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mime_type += mime_boundary;
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  user_message_request_ = CloudPrintURLFetcher::Create();
3700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  user_message_request_->StartPostRequest(
3710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      CloudPrintURLFetcher::REQUEST_USER_MESSAGE, url, this, 1, mime_type,
3720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      post_data, std::string());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintConnector::RemovePrinterFromList(
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_name,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printing::PrinterList* printer_list) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (printing::PrinterList::iterator index = printer_list->begin();
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       index != printer_list->end(); index++) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsSamePrinter(index->printer_name, printer_name)) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      index = printer_list->erase(index);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::InitJobHandlerForPrinter(
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* printer_data) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(printer_data);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrinterJobHandler::PrinterInfoFromCloud printer_info_cloud;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_data->GetString(kIdValue, &printer_info_cloud.printer_id);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!printer_info_cloud.printer_id.empty());
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Init job handler"
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", printer id: " << printer_info_cloud.printer_id;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JobHandlerMap::iterator index = job_handler_map_.find(
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer_info_cloud.printer_id);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index != job_handler_map_.end())
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Nothing to do if we already have a job handler for this printer.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing::PrinterBasicInfo printer_info;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_data->GetString(kNameValue, &printer_info.printer_name);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!printer_info.printer_name.empty());
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_data->GetString(kPrinterDescValue,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          &printer_info.printer_description);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Printer status is a string value which actually contains an integer.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string printer_status;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (printer_data->GetString(kPrinterStatusValue, &printer_status)) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringToInt(printer_status, &printer_info.printer_status);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer_data->GetString(kPrinterCapsHashValue,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &printer_info_cloud.caps_hash);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue* tags_list = NULL;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (printer_data->GetList(kTagsValue, &tags_list) && tags_list) {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t index = 0; index < tags_list->GetSize(); index++) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string tag;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (tags_list->GetString(index, &tag) &&
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          StartsWithASCII(tag, kCloudPrintServiceTagsHashTagName, false)) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::vector<std::string> tag_parts;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::SplitStringDontTrim(tag, '=', &tag_parts);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(tag_parts.size(), 2U);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (tag_parts.size() == 2)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          printer_info_cloud.tags_hash = tag_parts[1];
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
42768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int xmpp_timeout = 0;
42968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  printer_data->GetInteger(kLocalSettingsPendingXmppValue, &xmpp_timeout);
43068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  printer_info_cloud.current_xmpp_timeout = settings_.xmpp_ping_timeout_sec();
43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  printer_info_cloud.pending_xmpp_timeout = xmpp_timeout;
43268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PrinterJobHandler> job_handler;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job_handler = new PrinterJobHandler(printer_info,
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      printer_info_cloud,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      settings_.server_url(),
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      print_system_.get(),
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      this);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job_handler_map_[printer_info_cloud.printer_id] = job_handler;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job_handler->Initialize();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CloudPrintConnector::UpdateSettingsFromPrintersList(
44468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DictionaryValue* json_data) {
44568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ListValue* printer_list = NULL;
44668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int min_xmpp_timeout = std::numeric_limits<int>::max();
44768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // There may be no "printers" value in the JSON
44868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (json_data->GetList(kPrinterListValue, &printer_list) && printer_list) {
44968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (size_t index = 0; index < printer_list->GetSize(); index++) {
45068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      DictionaryValue* printer_data = NULL;
45168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (printer_list->GetDictionary(index, &printer_data)) {
45268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        int xmpp_timeout = 0;
45368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (printer_data->GetInteger(kLocalSettingsPendingXmppValue,
45468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     &xmpp_timeout)) {
45568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          min_xmpp_timeout = std::min(xmpp_timeout, min_xmpp_timeout);
45668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
45768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
45868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
45968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
46068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
46168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (min_xmpp_timeout != std::numeric_limits<int>::max()) {
46268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(min_xmpp_timeout >= kMinXmppPingTimeoutSecs);
46368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    settings_.SetXmppPingTimeoutSec(min_xmpp_timeout);
46468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    client_->OnXmppPingUpdated(min_xmpp_timeout);
46568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
46668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
46768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
46868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::AddPendingAvailableTask() {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingTask task;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.type = PENDING_PRINTERS_AVAILABLE;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPendingTask(task);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::AddPendingDeleteTask(const std::string& id) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingTask task;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.type = PENDING_PRINTER_DELETE;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.printer_id = id;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPendingTask(task);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::AddPendingRegisterTask(
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const printing::PrinterBasicInfo& info) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingTask task;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.type = PENDING_PRINTER_REGISTER;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.printer_info = info;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPendingTask(task);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::AddPendingTask(const PendingTask& task) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tasks_.push_back(task);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this is the only pending task, we need to start the process.
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_tasks_.size() == 1) {
494a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&CloudPrintConnector::ProcessPendingTask, this));
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::ProcessPendingTask() {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsRunning())
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Orphant call.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_tasks_.size() == 0)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // No peding tasks.
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingTask task = pending_tasks_.front();
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (task.type) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PENDING_PRINTERS_AVAILABLE :
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnPrintersAvailable();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PENDING_PRINTER_REGISTER :
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnPrinterRegister(task.printer_info);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PENDING_PRINTER_DELETE :
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnPrinterDelete(task.printer_id);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::ContinuePendingTaskProcessing() {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_tasks_.size() == 0)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // No pending tasks.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete current task and repost if we have more task available.
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tasks_.pop_front();
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_tasks_.size() != 0) {
529a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&CloudPrintConnector::ProcessPendingTask, this));
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::OnPrintersAvailable() {
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL printer_list_url = GetUrlForPrinterList(
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      settings_.server_url(), settings_.proxy_id());
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartGetRequest(printer_list_url,
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  kCloudPrintRegisterMaxRetryCount,
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  &CloudPrintConnector::HandlePrinterListResponse);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::OnPrinterRegister(
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const printing::PrinterBasicInfo& info) {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (JobHandlerMap::iterator it = job_handler_map_.begin();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != job_handler_map_.end(); ++it) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsSamePrinter(it->second->GetPrinterName(), info.printer_name)) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Printer already registered, continue to the next task.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContinuePendingTaskProcessing();
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Asynchronously fetch the printer caps and defaults. The story will
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // continue in OnReceivePrinterCaps.
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_system_->GetPrinterCapsAndDefaults(
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info.printer_name.c_str(),
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CloudPrintConnector::OnReceivePrinterCaps,
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::OnPrinterDelete(const std::string& printer_id) {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove corresponding printer job handler.
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JobHandlerMap::iterator it = job_handler_map_.find(printer_id);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != job_handler_map_.end()) {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->second->Shutdown();
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    job_handler_map_.erase(it);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(gene): We probably should not try indefinitely here. Just once or
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // twice should be enough.
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Bug: http://code.google.com/p/chromium/issues/detail?id=101850
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url = GetUrlForPrinterDelete(
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      settings_.server_url(), printer_id, "printer_deleted");
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartGetRequest(url,
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  kCloudPrintAPIMaxRetryCount,
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  &CloudPrintConnector::HandlePrinterDeleteResponse);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintConnector::OnReceivePrinterCaps(
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool succeeded,
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_name,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const printing::PrinterCapsAndDefaults& caps_and_defaults) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsRunning())
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Orphant call.
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_tasks_.size() > 0 &&
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         pending_tasks_.front().type == PENDING_PRINTER_REGISTER);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!succeeded) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "CP_CONNECTOR: Failed to get printer info"
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << ", printer name: " << printer_name;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This printer failed to register, notify the server of this failure.
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string16 printer_name_utf16 = UTF8ToUTF16(printer_name);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string status_message = l10n_util::GetStringFUTF8(
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_CLOUD_PRINT_REGISTER_PRINTER_FAILED,
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer_name_utf16,
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT));
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportUserMessage(kGetPrinterCapsFailedMessageId, status_message);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ContinuePendingTaskProcessing();  // Skip this printer registration.
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const printing::PrinterBasicInfo& info = pending_tasks_.front().printer_info;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsSamePrinter(info.printer_name, printer_name));
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string mime_boundary;
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateMimeBoundaryForUpload(&mime_boundary);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string post_data;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
61090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartValueForUpload(kProxyIdValue,
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      settings_.proxy_id(), mime_boundary, std::string(), &post_data);
61290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartValueForUpload(kPrinterNameValue,
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info.printer_name, mime_boundary, std::string(), &post_data);
61490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartValueForUpload(kPrinterDescValue,
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info.printer_description, mime_boundary, std::string(), &post_data);
61690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartValueForUpload(kPrinterStatusValue,
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPrintf("%d", info.printer_status),
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mime_boundary, std::string(), &post_data);
61968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Add local_settings with a current XMPP ping interval.
62068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  net::AddMultipartValueForUpload(kPrinterLocalSettingsValue,
62168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::StringPrintf(kCreateLocalSettingsXmppPingFormat,
62268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          settings_.xmpp_ping_timeout_sec()),
62368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      mime_boundary, std::string(), &post_data);
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  post_data += GetPostDataForPrinterInfo(info, mime_boundary);
62590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartValueForUpload(kPrinterCapsValue,
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      caps_and_defaults.printer_capabilities, mime_boundary,
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      caps_and_defaults.caps_mime_type, &post_data);
62890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartValueForUpload(kPrinterDefaultsValue,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      caps_and_defaults.printer_defaults, mime_boundary,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      caps_and_defaults.defaults_mime_type, &post_data);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send a hash of the printer capabilities to the server. We will use this
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // later to check if the capabilities have changed
63390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartValueForUpload(kPrinterCapsHashValue,
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::MD5String(caps_and_defaults.printer_capabilities),
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mime_boundary, std::string(), &post_data);
63690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  net::AddMultipartFinalDelimiterForUpload(mime_boundary, &post_data);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string mime_type("multipart/form-data; boundary=");
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mime_type += mime_boundary;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL post_url = GetUrlForPrinterRegistration(settings_.server_url());
6410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  StartPostRequest(CloudPrintURLFetcher::REQUEST_REGISTER, post_url,
6420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                   kCloudPrintAPIMaxRetryCount, mime_type, post_data,
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   &CloudPrintConnector::HandleRegisterPrinterResponse);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintConnector::IsSamePrinter(const std::string& name1,
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const std::string& name2) const {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (0 == base::strcasecmp(name1.c_str(), name2.c_str()));
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cloud_print
652