diff options
author | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-06 02:42:07 +0000 |
---|---|---|
committer | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-06 02:42:07 +0000 |
commit | e1a31ac75aa84f07134de78fc0cec6a49added50 (patch) | |
tree | e3a3289a65448e8b90244f299340b5b7721d019f /cloud_print/service/service_state.cc | |
parent | 2e2392b161702bd41f3a0058afd3786a912dfd3b (diff) | |
download | chromium_src-e1a31ac75aa84f07134de78fc0cec6a49added50.zip chromium_src-e1a31ac75aa84f07134de78fc0cec6a49added50.tar.gz chromium_src-e1a31ac75aa84f07134de78fc0cec6a49added50.tar.bz2 |
Single binary for unittests.
Root solution for src/cloud_print.
Build cloud_print_unittests on bots.
Added virtual_driver_lib with shared files.
Moved service_state out of win dir as platform independent.
BUG=131058
TEST=unittests
Review URL: https://chromiumcodereview.appspot.com/10505010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@140703 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cloud_print/service/service_state.cc')
-rw-r--r-- | cloud_print/service/service_state.cc | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/cloud_print/service/service_state.cc b/cloud_print/service/service_state.cc new file mode 100644 index 0000000..545210d --- /dev/null +++ b/cloud_print/service/service_state.cc @@ -0,0 +1,211 @@ +// Copyright (c) 2012 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 "cloud_print/service/service_state.h" + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "net/base/escape.h" +#include "net/base/io_buffer.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_builder.h" + +namespace { + +const char kCloudPrintJsonName[] = "cloud_print"; +const char kEnabledOptionName[] = "enabled"; + +const char kEmailOptionName[] = "email"; +const char kPasswordOptionName[] = "password"; +const char kProxyIdOptionName[] = "proxy_id"; +const char kRobotEmailOptionName[] = "robot_email"; +const char kRobotTokenOptionName[] = "robot_refresh_token"; +const char kAuthTokenOptionName[] = "auth_token"; +const char kXmppAuthTokenOptionName[] = "xmpp_auth_token"; + +const char kClientLoginUrl[] = "https://www.google.com/accounts/ClientLogin"; + +const int64 kRequestTimeoutMs = 10 * 1000; + +class ServiceStateURLRequestDelegate : public net::URLRequest::Delegate { + public: + virtual void OnResponseStarted(net::URLRequest* request) { + if (request->GetResponseCode() == 200) { + Read(request); + if (request->status().is_io_pending()) + return; + } + request->Cancel(); + }; + + virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) { + Read(request); + if (!request->status().is_io_pending()) + MessageLoop::current()->Quit(); + }; + + const std::string& data() const { + return data_; + } + + private: + void Read(net::URLRequest* request) { + // Read as many bytes as are available synchronously. + const int kBufSize = 100000; + scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufSize)); + int num_bytes = 0; + while (request->Read(buf, kBufSize, &num_bytes)) { + data_.append(buf->data(), buf->data() + num_bytes); + } + } + std::string data_; +}; + + +void SetNotEmptyJsonString(base::DictionaryValue* dictionary, + const std::string& name, + const std::string& value) { + if (!value.empty()) + dictionary->SetString(name, value); +} + +} // namespace + +ServiceState::ServiceState() { + Reset(); +} + +ServiceState::~ServiceState() { +} + +void ServiceState::Reset() { + email_.clear(); + proxy_id_.clear(); + robot_email_.clear(); + robot_token_.clear(); + auth_token_.clear(); + xmpp_auth_token_.clear(); +} + +bool ServiceState::FromString(const std::string& json) { + Reset(); + scoped_ptr<base::Value> data(base::JSONReader::Read(json)); + if (!data.get()) + return false; + + const base::DictionaryValue* services = NULL; + if (!data->GetAsDictionary(&services)) + return false; + + base::DictionaryValue* cloud_print = NULL; + if (!services->GetDictionary(kCloudPrintJsonName, &cloud_print)) + return false; + + bool valid_file = true; + // Don't exit on fail. Collect all data for re-use by user later. + if (!cloud_print->GetBoolean(kEnabledOptionName, &valid_file)) + valid_file = false; + + cloud_print->GetString(kEmailOptionName, &email_); + cloud_print->GetString(kProxyIdOptionName, &proxy_id_); + cloud_print->GetString(kRobotEmailOptionName, &robot_email_); + cloud_print->GetString(kRobotTokenOptionName, &robot_token_); + cloud_print->GetString(kAuthTokenOptionName, &auth_token_); + cloud_print->GetString(kXmppAuthTokenOptionName, &xmpp_auth_token_); + + return valid_file && IsValid(); +} + +bool ServiceState::IsValid() const { + if (email_.empty() || proxy_id_.empty()) + return false; + bool valid_robot = !robot_email_.empty() && !robot_token_.empty(); + bool valid_auth = !auth_token_.empty() && !xmpp_auth_token_.empty(); + return valid_robot || valid_auth; +} + +std::string ServiceState::ToString() { + scoped_ptr<base::DictionaryValue> services(new DictionaryValue()); + + scoped_ptr<base::DictionaryValue> cloud_print(new DictionaryValue()); + cloud_print->SetBoolean(kEnabledOptionName, true); + + SetNotEmptyJsonString(cloud_print.get(), kEmailOptionName, email_); + SetNotEmptyJsonString(cloud_print.get(), kProxyIdOptionName, proxy_id_); + SetNotEmptyJsonString(cloud_print.get(), kRobotEmailOptionName, robot_email_); + SetNotEmptyJsonString(cloud_print.get(), kRobotTokenOptionName, robot_token_); + SetNotEmptyJsonString(cloud_print.get(), kAuthTokenOptionName, auth_token_); + SetNotEmptyJsonString(cloud_print.get(), kXmppAuthTokenOptionName, + xmpp_auth_token_); + + services->Set(kCloudPrintJsonName, cloud_print.release()); + + std::string json; + base::JSONWriter::WriteWithOptions(services.get(), + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &json); + return json; +} + +std::string ServiceState::LoginToGoogle(const std::string& service, + const std::string& email, + const std::string& password) { + MessageLoop loop(MessageLoop::TYPE_IO); + + net::URLRequestContextBuilder builder; + scoped_ptr<net::URLRequestContext> context(builder.Build()); + + ServiceStateURLRequestDelegate fetcher_delegate; + GURL url(kClientLoginUrl); + + std::string post_body; + post_body += "accountType=GOOGLE"; + post_body += "&Email=" + net::EscapeUrlEncodedData(email, true); + post_body += "&Passwd=" + net::EscapeUrlEncodedData(password, true); + post_body += "&source=" + net::EscapeUrlEncodedData("CP-Service", true); + post_body += "&service=" + net::EscapeUrlEncodedData(service, true); + + net::URLRequest request(url, &fetcher_delegate); + + request.AppendBytesToUpload(post_body.c_str(), post_body.size()); + request.SetExtraRequestHeaderByName( + "Content-Type", "application/x-www-form-urlencoded", true); + request.set_context(context.get()); + request.set_method("POST"); + request.Start(); + + MessageLoop::current()->PostDelayedTask( + FROM_HERE, MessageLoop::QuitClosure(), kRequestTimeoutMs); + + MessageLoop::current()->Run(); + + const char kAuthStart[] = "Auth="; + std::vector<std::string> lines; + Tokenize(fetcher_delegate.data(), "\r\n", &lines); + for (size_t i = 0; i < lines.size(); ++i) { + std::vector<std::string> tokens; + if (StartsWithASCII(lines[i], kAuthStart, false)) + return lines[i].substr(arraysize(kAuthStart) - 1); + } + + return std::string(); +} + +bool ServiceState::Configure(const std::string& email, + const std::string& password, + const std::string& proxy_id) { + robot_token_.clear(); + robot_email_.clear(); + email_ = email; + proxy_id_ = proxy_id; + auth_token_ = LoginToGoogle("cloudprint", email_, password); + xmpp_auth_token_ = LoginToGoogle("chromiumsync", email_, password); + return IsValid(); +} + |