diff options
author | noamsml@chromium.org <noamsml@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-14 19:55:59 +0000 |
---|---|---|
committer | noamsml@chromium.org <noamsml@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-14 19:55:59 +0000 |
commit | 1862693823dcdcef50caf63325b5b9dbcbc75516 (patch) | |
tree | 5d9e92e08de34afc51467b7e15ae91687d6a088a | |
parent | 9d20d7d94e5e3ee442be84c3ed7290e57bcba75e (diff) | |
download | chromium_src-1862693823dcdcef50caf63325b5b9dbcbc75516.zip chromium_src-1862693823dcdcef50caf63325b5b9dbcbc75516.tar.gz chromium_src-1862693823dcdcef50caf63325b5b9dbcbc75516.tar.bz2 |
Implementation for gcdPrivate.getCloudDeviceList plus tests.
Get cloud device list from Javascript API.
BUG=
Review URL: https://codereview.chromium.org/332483006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277258 0039d316-1c4b-4281-b951-d872f2087c98
10 files changed, 327 insertions, 5 deletions
diff --git a/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc b/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc index 38ddcb8..b17b984 100644 --- a/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc +++ b/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc @@ -6,14 +6,53 @@ #include "base/lazy_instance.h" #include "base/memory/scoped_ptr.h" +#include "chrome/browser/local_discovery/cloud_device_list.h" +#include "chrome/browser/local_discovery/cloud_print_printer_list.h" +#include "chrome/browser/local_discovery/gcd_constants.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "components/signin/core/browser/profile_oauth2_token_service.h" +#include "components/signin/core/browser/signin_manager.h" +#include "components/signin/core/browser/signin_manager_base.h" namespace extensions { +using extensions::api::gcd_private::GCDDevice; + namespace { + +const int kNumRequestsNeeded = 2; + +const char kIDPrefixCloudPrinter[] = "cloudprint:"; +const char kIDPrefixGcd[] = "gcd:"; + +GcdPrivateAPI::GCDApiFlowFactoryForTests* g_gcd_api_flow_factory = NULL; + base::LazyInstance<BrowserContextKeyedAPIFactory<GcdPrivateAPI> > g_factory = LAZY_INSTANCE_INITIALIZER; + +scoped_ptr<local_discovery::GCDApiFlow> MakeGCDApiFlow(Profile* profile) { + if (g_gcd_api_flow_factory) { + return g_gcd_api_flow_factory->CreateGCDApiFlow(); + } + + ProfileOAuth2TokenService* token_service = + ProfileOAuth2TokenServiceFactory::GetForProfile(profile); + if (!token_service) + return scoped_ptr<local_discovery::GCDApiFlow>(); + SigninManagerBase* signin_manager = + SigninManagerFactory::GetInstance()->GetForProfile(profile); + if (!signin_manager) + return scoped_ptr<local_discovery::GCDApiFlow>(); + return local_discovery::GCDApiFlow::Create( + profile->GetRequestContext(), + token_service, + signin_manager->GetAuthenticatedAccountId()); } +} // namespace + GcdPrivateAPI::GcdPrivateAPI(content::BrowserContext* context) : browser_context_(context) { } @@ -27,12 +66,86 @@ GcdPrivateAPI::GetFactoryInstance() { return g_factory.Pointer(); } +// static +void GcdPrivateAPI::SetGCDApiFlowFactoryForTests( + GCDApiFlowFactoryForTests* factory) { + g_gcd_api_flow_factory = factory; +} + +GcdPrivateGetCloudDeviceListFunction::GcdPrivateGetCloudDeviceListFunction() { +} +GcdPrivateGetCloudDeviceListFunction::~GcdPrivateGetCloudDeviceListFunction() { +} + bool GcdPrivateGetCloudDeviceListFunction::RunAsync() { - results_.reset(new base::ListValue); - results_->Append(new base::ListValue); + requests_succeeded_ = 0; + requests_failed_ = 0; + + printer_list_ = MakeGCDApiFlow(GetProfile()); + device_list_ = MakeGCDApiFlow(GetProfile()); + + if (!printer_list_ || !device_list_) + return false; + + // Balanced in CheckListingDone() + AddRef(); + + printer_list_->Start(make_scoped_ptr<local_discovery::GCDApiFlow::Request>( + new local_discovery::CloudPrintPrinterList(this))); + device_list_->Start(make_scoped_ptr<local_discovery::GCDApiFlow::Request>( + new local_discovery::CloudDeviceList(this))); - SendResponse(true); return true; } +void GcdPrivateGetCloudDeviceListFunction::OnDeviceListReady( + const DeviceList& devices) { + requests_succeeded_++; + + devices_.insert(devices_.end(), devices.begin(), devices.end()); + + CheckListingDone(); +} + +void GcdPrivateGetCloudDeviceListFunction::OnDeviceListUnavailable() { + requests_failed_++; + + CheckListingDone(); +} + +void GcdPrivateGetCloudDeviceListFunction::CheckListingDone() { + if (requests_failed_ + requests_succeeded_ != kNumRequestsNeeded) + return; + + if (requests_succeeded_ == 0) { + SendResponse(false); + return; + } + + std::vector<linked_ptr<GCDDevice> > devices; + + for (DeviceList::iterator i = devices_.begin(); i != devices_.end(); i++) { + linked_ptr<GCDDevice> device(new GCDDevice); + device->setup_type = extensions::api::gcd_private::SETUP_TYPE_CLOUD; + if (i->type == local_discovery::kGCDTypePrinter) { + device->id_string = kIDPrefixCloudPrinter + i->id; + } else { + device->id_string = kIDPrefixGcd + i->id; + } + + device->cloud_id.reset(new std::string(i->id)); + device->device_type = i->type; + device->device_name = i->display_name; + device->device_description = i->description; + + devices.push_back(device); + } + + results_ = extensions::api::gcd_private::GetCloudDeviceList::Results::Create( + devices); + + SendResponse(true); + Release(); +} + } // namespace extensions diff --git a/chrome/browser/extensions/api/gcd_private/gcd_private_api.h b/chrome/browser/extensions/api/gcd_private/gcd_private_api.h index dc7b680..d8c6f46 100644 --- a/chrome/browser/extensions/api/gcd_private/gcd_private_api.h +++ b/chrome/browser/extensions/api/gcd_private/gcd_private_api.h @@ -5,7 +5,10 @@ #ifndef CHROME_BROWSER_EXTENSIONS_API_GCD_PRIVATE_GCD_PRIVATE_API_H_ #define CHROME_BROWSER_EXTENSIONS_API_GCD_PRIVATE_GCD_PRIVATE_API_H_ +#include "base/memory/scoped_ptr.h" #include "chrome/browser/extensions/chrome_extension_function.h" +#include "chrome/browser/local_discovery/cloud_device_list_delegate.h" +#include "chrome/browser/local_discovery/gcd_api_flow.h" #include "chrome/common/extensions/api/gcd_private.h" #include "extensions/browser/browser_context_keyed_api_factory.h" @@ -13,9 +16,18 @@ namespace extensions { class GcdPrivateAPI : public BrowserContextKeyedAPI { public: + class GCDApiFlowFactoryForTests { + public: + virtual ~GCDApiFlowFactoryForTests() {} + + virtual scoped_ptr<local_discovery::GCDApiFlow> CreateGCDApiFlow() = 0; + }; + explicit GcdPrivateAPI(content::BrowserContext* context); virtual ~GcdPrivateAPI(); + static void SetGCDApiFlowFactoryForTests(GCDApiFlowFactoryForTests* factory); + // BrowserContextKeyedAPI implementation. static BrowserContextKeyedAPIFactory<GcdPrivateAPI>* GetFactoryInstance(); @@ -29,16 +41,33 @@ class GcdPrivateAPI : public BrowserContextKeyedAPI { }; class GcdPrivateGetCloudDeviceListFunction - : public ChromeAsyncExtensionFunction { + : public ChromeAsyncExtensionFunction, + public local_discovery::CloudDeviceListDelegate { public: DECLARE_EXTENSION_FUNCTION("gcdPrivate.getCloudDeviceList", FEEDBACKPRIVATE_GETSTRINGS) + GcdPrivateGetCloudDeviceListFunction(); + protected: - virtual ~GcdPrivateGetCloudDeviceListFunction() {} + virtual ~GcdPrivateGetCloudDeviceListFunction(); // SyncExtensionFunction overrides. virtual bool RunAsync() OVERRIDE; + + private: + // CloudDeviceListDelegate implementation + virtual void OnDeviceListReady(const DeviceList& devices) OVERRIDE; + virtual void OnDeviceListUnavailable() OVERRIDE; + + void CheckListingDone(); + + int requests_succeeded_; + int requests_failed_; + DeviceList devices_; + + scoped_ptr<local_discovery::GCDApiFlow> printer_list_; + scoped_ptr<local_discovery::GCDApiFlow> device_list_; }; } // namespace extensions diff --git a/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc b/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc new file mode 100644 index 0000000..7e6ae8b --- /dev/null +++ b/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc @@ -0,0 +1,124 @@ +// Copyright 2014 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 "base/command_line.h" +#include "base/json/json_reader.h" +#include "chrome/browser/extensions/api/gcd_private/gcd_private_api.h" +#include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/common/extensions/api/mdns.h" +#include "extensions/common/switches.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace api = extensions::api; + +namespace { + +const char kCloudPrintResponse[] = + "{" + " \"success\": true," + " \"printers\": [" + " {\"id\" : \"someCloudPrintID\"," + " \"displayName\": \"someCloudPrintDisplayName\"," + " \"description\": \"someCloudPrintDescription\"}" + " ]" + "}"; + +const char kGCDResponse[] = + "{" + "\"kind\": \"clouddevices#devicesListResponse\"," + "\"devices\": [{" + " \"kind\": \"clouddevices#device\"," + " \"id\": \"someGCDID\"," + " \"deviceKind\": \"someType\"," + " \"creationTimeMs\": \"123\"," + " \"systemName\": \"someGCDDisplayName\"," + " \"owner\": \"user@domain.com\"," + " \"description\": \"someGCDDescription\"," + " \"state\": {" + " \"base\": {" + " \"connectionStatus\": \"offline\"" + " }" + " }," + " \"channel\": {" + " \"supportedType\": \"xmpp\"" + " }," + " \"personalizedInfo\": {" + " \"maxRole\": \"owner\"" + " }}]}"; + +// Sentinel value to signify the request should fail. +const char kResponseValueFailure[] = "FAILURE"; + +class FakeGCDApiFlowFactory + : public extensions::GcdPrivateAPI::GCDApiFlowFactoryForTests { + public: + FakeGCDApiFlowFactory() { + extensions::GcdPrivateAPI::SetGCDApiFlowFactoryForTests(this); + } + + virtual ~FakeGCDApiFlowFactory() { + extensions::GcdPrivateAPI::SetGCDApiFlowFactoryForTests(NULL); + } + + virtual scoped_ptr<local_discovery::GCDApiFlow> CreateGCDApiFlow() OVERRIDE { + return scoped_ptr<local_discovery::GCDApiFlow>(new FakeGCDApiFlow(this)); + } + + void SetResponse(const GURL& url, const std::string& response) { + responses_[url] = response; + } + + private: + class FakeGCDApiFlow : public local_discovery::GCDApiFlow { + public: + explicit FakeGCDApiFlow(FakeGCDApiFlowFactory* factory) + : factory_(factory) {} + + virtual ~FakeGCDApiFlow() {} + + virtual void Start(scoped_ptr<Request> request) OVERRIDE { + std::string response_str = factory_->responses_[request->GetURL()]; + + if (response_str == kResponseValueFailure) { + request->OnGCDAPIFlowError( + local_discovery::GCDApiFlow::ERROR_MALFORMED_RESPONSE); + return; + } + + scoped_ptr<base::Value> response(base::JSONReader::Read(response_str)); + ASSERT_TRUE(response); + + base::DictionaryValue* response_dict; + ASSERT_TRUE(response->GetAsDictionary(&response_dict)); + + request->OnGCDAPIFlowComplete(*response_dict); + } + + private: + FakeGCDApiFlowFactory* factory_; + }; + + std::map<GURL /*request url*/, std::string /*response json*/> responses_; +}; + +class GcdPrivateAPITest : public ExtensionApiTest { + public: + GcdPrivateAPITest() {} + + protected: + FakeGCDApiFlowFactory api_flow_factory_; +}; + +IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, GetCloudList) { + api_flow_factory_.SetResponse( + GURL("https://www.google.com/cloudprint/search"), kCloudPrintResponse); + + api_flow_factory_.SetResponse( + GURL("https://www.googleapis.com/clouddevices/v1/devices"), kGCDResponse); + + EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "get_cloud_list.html")); +} + +} // namespace diff --git a/chrome/browser/local_discovery/gcd_constants.cc b/chrome/browser/local_discovery/gcd_constants.cc index b5b63cc..9c7e050 100644 --- a/chrome/browser/local_discovery/gcd_constants.cc +++ b/chrome/browser/local_discovery/gcd_constants.cc @@ -7,5 +7,6 @@ namespace local_discovery { const char kGCDKeyKind[] = "kind"; +const char kGCDTypePrinter[] = "printer"; } // namespace local_discovery diff --git a/chrome/browser/local_discovery/gcd_constants.h b/chrome/browser/local_discovery/gcd_constants.h index c51d15e..542a0b7 100644 --- a/chrome/browser/local_discovery/gcd_constants.h +++ b/chrome/browser/local_discovery/gcd_constants.h @@ -8,6 +8,7 @@ namespace local_discovery { extern const char kGCDKeyKind[]; +extern const char kGCDTypePrinter[]; } // namespace local_discovery diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 7ebd5e0..6f7c7f8 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1089,6 +1089,7 @@ 'browser/extensions/api/file_system/file_system_apitest_chromeos.cc', 'browser/extensions/api/font_settings/font_settings_apitest.cc', 'browser/extensions/api/gcm/gcm_apitest.cc', + 'browser/extensions/api/gcd_private/gcd_private_apitest.cc', 'browser/extensions/api/history/history_apitest.cc', 'browser/extensions/api/hotword_private/hotword_private_apitest.cc', 'browser/extensions/api/i18n/i18n_apitest.cc', diff --git a/chrome/test/data/extensions/api_test/gcd_private/api/get_cloud_list.html b/chrome/test/data/extensions/api_test/gcd_private/api/get_cloud_list.html new file mode 100644 index 0000000..c658bdd --- /dev/null +++ b/chrome/test/data/extensions/api_test/gcd_private/api/get_cloud_list.html @@ -0,0 +1 @@ +<script src="get_cloud_list.js"></script> diff --git a/chrome/test/data/extensions/api_test/gcd_private/api/get_cloud_list.js b/chrome/test/data/extensions/api_test/gcd_private/api/get_cloud_list.js new file mode 100644 index 0000000..0ea069c --- /dev/null +++ b/chrome/test/data/extensions/api_test/gcd_private/api/get_cloud_list.js @@ -0,0 +1,37 @@ +// Copyright 2014 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. + +onload = function() { + chrome.test.runTests([ + function getCloudList() { + chrome.gcdPrivate.getCloudDeviceList(function(services) { + // Sort to avoid order dependence + services.sort(function(a,b) { + return a.idString.localeCompare(b.idString); + }); + + chrome.test.assertEq(2, services.length); + + chrome.test.assertEq(services[0].setupType, "cloud"); + chrome.test.assertEq(services[0].idString, + "cloudprint:someCloudPrintID"); + chrome.test.assertEq(services[0].cloudId, "someCloudPrintID"); + chrome.test.assertEq(services[0].deviceType, "printer"); + chrome.test.assertEq(services[0].deviceName, + "someCloudPrintDisplayName"); + chrome.test.assertEq(services[0].deviceDescription, + "someCloudPrintDescription"); + + chrome.test.assertEq(services[1].setupType, "cloud"); + chrome.test.assertEq(services[1].idString, "gcd:someGCDID"); + chrome.test.assertEq(services[1].cloudId, "someGCDID"); + chrome.test.assertEq(services[1].deviceType, "someType"); + chrome.test.assertEq(services[1].deviceName, "someGCDDisplayName"); + chrome.test.assertEq(services[1].deviceDescription, + "someGCDDescription"); + + chrome.test.notifyPass(); + }) + }]); +}; diff --git a/chrome/test/data/extensions/api_test/gcd_private/api/manifest.json b/chrome/test/data/extensions/api_test/gcd_private/api/manifest.json new file mode 100644 index 0000000..9ada54d --- /dev/null +++ b/chrome/test/data/extensions/api_test/gcd_private/api/manifest.json @@ -0,0 +1,7 @@ + { + "manifest_version": 2, + "name": "GCD Extension", + "version": "1.0", + "description": "Test GCD Extension", + "permissions": ["gcdPrivate"] +} diff --git a/chrome/test/data/extensions/api_test/gcd_private/api/trun b/chrome/test/data/extensions/api_test/gcd_private/api/trun new file mode 100644 index 0000000..96cfbed --- /dev/null +++ b/chrome/test/data/extensions/api_test/gcd_private/api/trun @@ -0,0 +1,8 @@ + { + "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8xv6iO+j4kzj1HiBL93+XVJH/CRyAQMUHS/Z0l8nCAzaAFkW/JsNwxJqQhrZspnxLqbQxNncXs6g6bsXAwKHiEs+LSs+bIv0Gc/2ycZdhXJ8GhEsSMakog5dpQd1681c2gLK/8CrAoewE/0GIKhaFcp7a2iZlGh4Am6fgMKy0iQIDAQAB", + "manifest_version": 2, + "name": "MDNS Extension", + "version": "1.0", + "description": "Test MDNS Extension", + "permissions": ["mdns"] +} |