Commit d3f434f7 authored by noamsml@chromium.org's avatar noamsml@chromium.org

Printer list for Google Cloud Print

Retrieves list of printers for Google Cloud Print. Lets users look up printers
by ID or iterate over all printers.

BUG=286157

Review URL: https://chromiumcodereview.appspot.com/23658020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221733 0039d316-1c4b-4281-b951-d872f2087c98
parent 193912d1
...@@ -77,8 +77,11 @@ class CloudPrintBaseApiFlow : public net::URLFetcherDelegate, ...@@ -77,8 +77,11 @@ class CloudPrintBaseApiFlow : public net::URLFetcherDelegate,
virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) OVERRIDE; const GoogleServiceAuthError& error) OVERRIDE;
// Return the user index or kAccountIndexUseOAuth2 if none is available.
int user_index() { return user_index_; }
private: private:
bool UseOAuth2() { return token_service_ != NULL; } bool UseOAuth2() { return user_index_ == kAccountIndexUseOAuth2; }
void CreateRequest(const GURL& url); void CreateRequest(const GURL& url);
......
// Copyright 2013 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 <utility>
#include "base/strings/stringprintf.h"
#include "chrome/browser/local_discovery/cloud_print_printer_list.h"
#include "chrome/common/cloud_print/cloud_print_constants.h"
namespace local_discovery {
namespace {
const char kPrinterListURLFormat[] = "%s/search";
}
CloudPrintPrinterList::CloudPrintPrinterList(
net::URLRequestContextGetter* request_context,
const std::string& cloud_print_url,
OAuth2TokenService* token_service,
Delegate* delegate)
: request_context_(request_context),
url_(base::StringPrintf(kPrinterListURLFormat, cloud_print_url.c_str())),
delegate_(delegate),
api_flow_(request_context_,
token_service,
url_,
this) {
}
CloudPrintPrinterList::~CloudPrintPrinterList() {
}
void CloudPrintPrinterList::Start() {
api_flow_.Start();
}
const CloudPrintPrinterList::PrinterDetails*
CloudPrintPrinterList::GetDetailsFor(const std::string& id) {
PrinterIDMap::iterator found = printer_id_map_.find(id);
if (found != printer_id_map_.end()) {
return &printer_list_[found->second];
}
return NULL;
}
void CloudPrintPrinterList::OnCloudPrintAPIFlowError(
CloudPrintBaseApiFlow* flow,
CloudPrintBaseApiFlow::Status status) {
delegate_->OnCloudPrintPrinterListUnavailable();
}
void CloudPrintPrinterList::OnCloudPrintAPIFlowComplete(
CloudPrintBaseApiFlow* flow,
const base::DictionaryValue* value) {
const base::ListValue* printers;
if (!value->GetList(cloud_print::kPrinterListValue, &printers)) {
delegate_->OnCloudPrintPrinterListUnavailable();
return;
}
for (base::ListValue::const_iterator i = printers->begin();
i != printers->end();
i++) {
base::DictionaryValue* printer;
PrinterDetails printer_details;
if (!(*i)->GetAsDictionary(&printer))
continue;
if (!FillPrinterDetails(printer, &printer_details)) continue;
std::pair<PrinterIDMap::iterator, bool> inserted =
printer_id_map_.insert(
make_pair(printer_details.id, printer_list_.size()) );
if (inserted.second) { // ID is new.
printer_list_.push_back(printer_details);
}
}
delegate_->OnCloudPrintPrinterListReady();
}
bool CloudPrintPrinterList::FillPrinterDetails(
const base::DictionaryValue* printer_value,
PrinterDetails* printer_details) {
if (!printer_value->GetString(cloud_print::kIdValue, &printer_details->id))
return false;
if (!printer_value->GetString(cloud_print::kDisplayNameValue,
&printer_details->display_name)) {
return false;
}
// Non-essential.
printer_value->GetString(cloud_print::kPrinterDescValue,
&printer_details->description);
return true;
}
CloudPrintPrinterList::PrinterDetails::PrinterDetails() {
}
CloudPrintPrinterList::PrinterDetails::~PrinterDetails() {
}
} // namespace local_discovery
// Copyright 2013 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.
#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_CLOUD_PRINT_PRINTER_LIST_H_
#define CHROME_BROWSER_LOCAL_DISCOVERY_CLOUD_PRINT_PRINTER_LIST_H_
#include <map>
#include <string>
#include <vector>
#include "chrome/browser/local_discovery/cloud_print_base_api_flow.h"
namespace local_discovery {
class CloudPrintPrinterList : public CloudPrintBaseApiFlow::Delegate {
public:
class Delegate {
public:
~Delegate() {}
virtual void OnCloudPrintPrinterListReady() = 0;
virtual void OnCloudPrintPrinterListUnavailable() = 0;
};
struct PrinterDetails {
PrinterDetails();
~PrinterDetails();
std::string id;
std::string display_name;
std::string description;
// TODO(noamsml): std::string user;
};
typedef std::vector<PrinterDetails> PrinterList;
typedef PrinterList::const_iterator iterator;
CloudPrintPrinterList(net::URLRequestContextGetter* request_context,
const std::string& cloud_print_url,
OAuth2TokenService* token_service,
Delegate* delegate);
virtual ~CloudPrintPrinterList();
void Start();
virtual void OnCloudPrintAPIFlowError(
CloudPrintBaseApiFlow* flow,
CloudPrintBaseApiFlow::Status status) OVERRIDE;
virtual void OnCloudPrintAPIFlowComplete(
CloudPrintBaseApiFlow* flow,
const base::DictionaryValue* value) OVERRIDE;
const PrinterDetails* GetDetailsFor(const std::string& id);
iterator begin() { return printer_list_.begin(); }
iterator end() { return printer_list_.end(); }
CloudPrintBaseApiFlow* GetOAuth2ApiFlowForTests() {
return &api_flow_;
}
private:
typedef std::map<std::string /*ID*/, int /* index in printer_list_ */>
PrinterIDMap;
bool FillPrinterDetails(const base::DictionaryValue* printer_value,
PrinterDetails* printer_details);
scoped_refptr<net::URLRequestContextGetter> request_context_;
GURL url_;
PrinterIDMap printer_id_map_;
PrinterList printer_list_;
Delegate* delegate_;
CloudPrintBaseApiFlow api_flow_;
};
} // namespace local_discovery
#endif // CHROME_BROWSER_LOCAL_DISCOVERY_CLOUD_PRINT_PRINTER_LIST_H_
// Copyright 2013 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 <set>
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/local_discovery/cloud_print_printer_list.h"
#include "content/public/test/test_browser_thread.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher_impl.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::NiceMock;
using testing::StrictMock;
using testing::Mock;
namespace local_discovery {
namespace {
const char kSampleSuccessResponseOAuth[] = "{"
" \"success\": true,"
" \"printers\": ["
" {\"id\" : \"someID\","
" \"displayName\": \"someDisplayName\","
" \"description\": \"someDescription\"}"
" ]"
"}";
class TestOAuth2TokenService : public OAuth2TokenService {
public:
explicit TestOAuth2TokenService(net::URLRequestContextGetter* request_context)
: request_context_(request_context) {
}
protected:
virtual std::string GetRefreshToken() OVERRIDE {
return "SampleToken";
}
virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE {
return request_context_.get();
}
private:
scoped_refptr<net::URLRequestContextGetter> request_context_;
};
class MockDelegate : public CloudPrintPrinterList::Delegate {
public:
MOCK_METHOD0(OnCloudPrintPrinterListUnavailable, void());
MOCK_METHOD0(OnCloudPrintPrinterListReady, void());
};
class CloudPrintPrinterListTest : public testing::Test {
public:
CloudPrintPrinterListTest()
: ui_thread_(content::BrowserThread::UI,
&loop_),
request_context_(new net::TestURLRequestContextGetter(
base::MessageLoopProxy::current())),
token_service_(request_context_.get()) {
ui_thread_.Stop(); // HACK: Fake being on the UI thread
printer_list_.reset(
new CloudPrintPrinterList(request_context_.get(),
"http://SoMeUrL.com/cloudprint",
&token_service_,
&delegate_));
fallback_fetcher_factory_.reset(new net::TestURLFetcherFactory());
net::URLFetcherImpl::set_factory(NULL);
fetcher_factory_.reset(new net::FakeURLFetcherFactory(
fallback_fetcher_factory_.get()));
}
virtual ~CloudPrintPrinterListTest() {
fetcher_factory_.reset();
net::URLFetcherImpl::set_factory(fallback_fetcher_factory_.get());
fallback_fetcher_factory_.reset();
}
protected:
base::MessageLoopForUI loop_;
content::TestBrowserThread ui_thread_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
// Use a test factory as a fallback so we don't have to deal with OAuth2
// requests.
scoped_ptr<net::TestURLFetcherFactory> fallback_fetcher_factory_;
scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory_;
TestOAuth2TokenService token_service_;
StrictMock<MockDelegate> delegate_;
scoped_ptr<CloudPrintPrinterList> printer_list_;
};
TEST_F(CloudPrintPrinterListTest, SuccessOAuth2) {
fetcher_factory_->SetFakeResponse("http://SoMeUrL.com/cloudprint/search",
kSampleSuccessResponseOAuth,
true);
CloudPrintBaseApiFlow* cloudprint_flow =
printer_list_->GetOAuth2ApiFlowForTests();
printer_list_->Start();
cloudprint_flow->OnGetTokenSuccess(NULL, "SomeToken", base::Time());
EXPECT_CALL(delegate_, OnCloudPrintPrinterListReady());
base::MessageLoop::current()->RunUntilIdle();
Mock::VerifyAndClear(&delegate_);
std::set<std::string> ids_found;
std::set<std::string> ids_expected;
ids_expected.insert("someID");
int length = 0;
for (CloudPrintPrinterList::iterator i = printer_list_->begin();
i != printer_list_->end(); i++, length++) {
ids_found.insert(i->id);
}
EXPECT_EQ(ids_expected, ids_found);
EXPECT_EQ(1, length);
const CloudPrintPrinterList::PrinterDetails* found =
printer_list_->GetDetailsFor("someID");
ASSERT_TRUE(found != NULL);
EXPECT_EQ("someID", found->id);
EXPECT_EQ("someDisplayName", found->display_name);
EXPECT_EQ("someDescription", found->description);
}
} // namespace
} // namespace local_discovery
...@@ -929,6 +929,8 @@ ...@@ -929,6 +929,8 @@
'browser/local_discovery/cloud_print_account_manager.h', 'browser/local_discovery/cloud_print_account_manager.h',
'browser/local_discovery/cloud_print_base_api_flow.cc', 'browser/local_discovery/cloud_print_base_api_flow.cc',
'browser/local_discovery/cloud_print_base_api_flow.h', 'browser/local_discovery/cloud_print_base_api_flow.h',
'browser/local_discovery/cloud_print_printer_list.h',
'browser/local_discovery/cloud_print_printer_list.cc',
'browser/local_discovery/privet_confirm_api_flow.cc', 'browser/local_discovery/privet_confirm_api_flow.cc',
'browser/local_discovery/privet_confirm_api_flow.h', 'browser/local_discovery/privet_confirm_api_flow.h',
'browser/local_discovery/privet_constants.h', 'browser/local_discovery/privet_constants.h',
......
...@@ -959,6 +959,7 @@ ...@@ -959,6 +959,7 @@
'browser/local_discovery/privet_http_unittest.cc', 'browser/local_discovery/privet_http_unittest.cc',
'browser/local_discovery/privet_url_fetcher_unittest.cc', 'browser/local_discovery/privet_url_fetcher_unittest.cc',
'browser/local_discovery/cloud_print_account_manager_unittest.cc', 'browser/local_discovery/cloud_print_account_manager_unittest.cc',
'browser/local_discovery/cloud_print_printer_list_unittest.cc',
'browser/mac/keystone_glue_unittest.mm', 'browser/mac/keystone_glue_unittest.mm',
'browser/managed_mode/managed_mode_url_filter_unittest.cc', 'browser/managed_mode/managed_mode_url_filter_unittest.cc',
'browser/managed_mode/managed_user_service_unittest.cc', 'browser/managed_mode/managed_user_service_unittest.cc',
......
...@@ -29,6 +29,7 @@ const char kZombiePrinterMessageId[] = "zombieprinter"; ...@@ -29,6 +29,7 @@ const char kZombiePrinterMessageId[] = "zombieprinter";
const char kSuccessValue[] = "success"; const char kSuccessValue[] = "success";
const char kNameValue[] = "name"; const char kNameValue[] = "name";
const char kDisplayNameValue[] = "displayName";
const char kIdValue[] = "id"; const char kIdValue[] = "id";
const char kTicketUrlValue[] = "ticketUrl"; const char kTicketUrlValue[] = "ticketUrl";
const char kFileUrlValue[] = "fileUrl"; const char kFileUrlValue[] = "fileUrl";
...@@ -41,6 +42,8 @@ const char kXMPPJidValue[] = "xmpp_jid"; ...@@ -41,6 +42,8 @@ const char kXMPPJidValue[] = "xmpp_jid";
const char kOAuthCodeValue[] = "authorization_code"; const char kOAuthCodeValue[] = "authorization_code";
const char kCreateTimeValue[] = "createTime"; const char kCreateTimeValue[] = "createTime";
const char kPrinterTypeValue[] = "type"; const char kPrinterTypeValue[] = "type";
const char kUserValue[] = "request.user";
const char kUsersValue[] = "request.users";
const char kChromeVersionTagName[] = "chrome_version"; const char kChromeVersionTagName[] = "chrome_version";
const char kSystemNameTagName[] = "system_name"; const char kSystemNameTagName[] = "system_name";
......
...@@ -39,6 +39,7 @@ extern const char kZombiePrinterMessageId[]; ...@@ -39,6 +39,7 @@ extern const char kZombiePrinterMessageId[];
// Values in the respone JSON from the cloud print server. // Values in the respone JSON from the cloud print server.
extern const char kSuccessValue[]; extern const char kSuccessValue[];
extern const char kNameValue[]; extern const char kNameValue[];
extern const char kDisplayNameValue[];
extern const char kIdValue[]; extern const char kIdValue[];
extern const char kTicketUrlValue[]; extern const char kTicketUrlValue[];
extern const char kFileUrlValue[]; extern const char kFileUrlValue[];
...@@ -51,6 +52,8 @@ extern const char kXMPPJidValue[]; ...@@ -51,6 +52,8 @@ extern const char kXMPPJidValue[];
extern const char kOAuthCodeValue[]; extern const char kOAuthCodeValue[];
extern const char kCreateTimeValue[]; extern const char kCreateTimeValue[];
extern const char kPrinterTypeValue[]; extern const char kPrinterTypeValue[];
extern const char kUserValue[];
extern const char kUsersValue[];
// Printer tag names. Don't need prefixes. They will be added on submit. // Printer tag names. Don't need prefixes. They will be added on submit.
extern const char kChromeVersionTagName[]; extern const char kChromeVersionTagName[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment