diff options
author | noamsml@chromium.org <noamsml@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-06 20:29:47 +0000 |
---|---|---|
committer | noamsml@chromium.org <noamsml@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-06 20:29:47 +0000 |
commit | b69ac914734e86e9a5cf8740539db18e49c7b7ea (patch) | |
tree | 3cabc33c054b5f33589292b033c6192380d4101d | |
parent | 6da4ffab43cdc0143fff609692e4238529b16e02 (diff) | |
download | chromium_src-b69ac914734e86e9a5cf8740539db18e49c7b7ea.zip chromium_src-b69ac914734e86e9a5cf8740539db18e49c7b7ea.tar.gz chromium_src-b69ac914734e86e9a5cf8740539db18e49c7b7ea.tar.bz2 |
Class to list only printers that support local printing
An adapter for PrivetDeviceLister that checks /privet/info and outputs only
devices that support /privet/printer/submitdoc.
BUG=311390
Review URL: https://codereview.chromium.org/48113019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233340 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/local_discovery/privet_constants.cc | 11 | ||||
-rw-r--r-- | chrome/browser/local_discovery/privet_constants.h | 7 | ||||
-rw-r--r-- | chrome/browser/local_discovery/privet_http_impl.cc | 8 | ||||
-rw-r--r-- | chrome/browser/local_discovery/privet_local_printer_lister.cc | 130 | ||||
-rw-r--r-- | chrome/browser/local_discovery/privet_local_printer_lister.h | 71 | ||||
-rw-r--r-- | chrome/browser/local_discovery/privet_local_printer_lister_unittest.cc | 208 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 4 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests_unit.gypi | 9 |
9 files changed, 438 insertions, 12 deletions
diff --git a/chrome/browser/local_discovery/privet_constants.cc b/chrome/browser/local_discovery/privet_constants.cc index 4d586cc..6561e8b 100644 --- a/chrome/browser/local_discovery/privet_constants.cc +++ b/chrome/browser/local_discovery/privet_constants.cc @@ -17,6 +17,12 @@ const char kPrivetKeyTimeout[] = "timeout"; const char kPrivetActionNameInfo[] = "info"; +const char kPrivetInfoPath[] = "/privet/info"; +const char kPrivetRegisterPath[] = "/privet/register"; +const char kPrivetCapabilitiesPath[] = "/privet/capabilities"; +const char kPrivetSubmitdocPath[] = "/privet/printer/submitdoc"; +const char kPrivetCreatejobPath[] = "/privet/printer/createjob"; + const char kPrivetErrorDeviceBusy[] = "device_busy"; const char kPrivetErrorPendingUserAction[] = "pending_user_action"; const char kPrivetErrorInvalidXPrivetToken[] = "invalid_x_privet_token"; @@ -28,8 +34,9 @@ const char kPrivetActionGetClaimToken[] = "getClaimToken"; const char kPrivetActionComplete[] = "complete"; const char kPrivetActionCancel[] = "cancel"; -extern const char kPrivetDefaultDeviceType[] = "_privet._tcp.local"; -extern const char kPrivetSubtypeTemplate[] = "%s._sub._privet._tcp.local"; +const char kPrivetDefaultDeviceType[] = "_privet._tcp.local"; +const char kPrivetSubtypeTemplate[] = "%s._sub._privet._tcp.local"; +const char kPrivetSubtypePrinter[] = "_printer"; const char kPrivetTxtKeyName[] = "ty"; const char kPrivetTxtKeyDescription[] = "note"; diff --git a/chrome/browser/local_discovery/privet_constants.h b/chrome/browser/local_discovery/privet_constants.h index 9166ad7..9333839 100644 --- a/chrome/browser/local_discovery/privet_constants.h +++ b/chrome/browser/local_discovery/privet_constants.h @@ -18,6 +18,12 @@ extern const char kPrivetKeyTimeout[]; extern const char kPrivetActionNameInfo[]; +extern const char kPrivetInfoPath[]; +extern const char kPrivetRegisterPath[]; +extern const char kPrivetCapabilitiesPath[]; +extern const char kPrivetSubmitdocPath[]; +extern const char kPrivetCreatejobPath[]; + extern const char kPrivetErrorDeviceBusy[]; extern const char kPrivetErrorPendingUserAction[]; extern const char kPrivetErrorInvalidXPrivetToken[]; @@ -31,6 +37,7 @@ extern const char kPrivetActionCancel[]; extern const char kPrivetDefaultDeviceType[]; extern const char kPrivetSubtypeTemplate[]; +extern const char kPrivetSubtypePrinter[]; const double kPrivetMaximumTimeScaling = 1.2; diff --git a/chrome/browser/local_discovery/privet_http_impl.cc b/chrome/browser/local_discovery/privet_http_impl.cc index c236255..28575a36 100644 --- a/chrome/browser/local_discovery/privet_http_impl.cc +++ b/chrome/browser/local_discovery/privet_http_impl.cc @@ -18,12 +18,6 @@ const char kUrlPlaceHolder[] = "http://host/"; const char kPrivetRegisterActionArgName[] = "action"; const char kPrivetRegisterUserArgName[] = "user"; -const char kPrivetInfoPath[] = "/privet/info"; -const char kPrivetRegisterPath[] = "/privet/register"; -const char kPrivetCapabilitiesPath[] = "/privet/capabilities"; -const char kPrivetSubmitdocPath[] = "/privet/printer/submitdoc"; -const char kPrivetCreatejobPath[] = "/privet/printer/createjob"; - const char kPrivetURLKeyUser[] = "user"; const char kPrivetURLKeyJobname[] = "jobname"; const char kPrivetURLKeyOffline[] = "offline"; @@ -241,7 +235,7 @@ void PrivetRegisterOperationImpl::OnPrivetInfoDone( PrivetInfoOperation* operation, int http_code, const base::DictionaryValue* value) { - // TODO (noamsml): Simplify error case. + // TODO(noamsml): Simplify error case. if (!value) { delegate_->OnPrivetRegisterError(this, kPrivetActionNameInfo, diff --git a/chrome/browser/local_discovery/privet_local_printer_lister.cc b/chrome/browser/local_discovery/privet_local_printer_lister.cc new file mode 100644 index 0000000..7104107 --- /dev/null +++ b/chrome/browser/local_discovery/privet_local_printer_lister.cc @@ -0,0 +1,130 @@ +// 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 "chrome/browser/local_discovery/privet_local_printer_lister.h" + +#include <string> + +#include "chrome/browser/local_discovery/privet_constants.h" +#include "chrome/browser/local_discovery/privet_device_lister_impl.h" +#include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h" + +namespace local_discovery { + +struct PrivetLocalPrinterLister::DeviceContext { + public: + DeviceContext() { + } + + ~DeviceContext() { + } + + scoped_ptr<PrivetHTTPResolution> privet_resolution; + scoped_ptr<PrivetHTTPClient> privet_client; + scoped_ptr<PrivetInfoOperation> info_operation; + DeviceDescription description; + + bool has_local_printing; +}; + +PrivetLocalPrinterLister::PrivetLocalPrinterLister( + ServiceDiscoveryClient* service_discovery_client, + net::URLRequestContextGetter* request_context, + Delegate* delegate) : delegate_(delegate) { + privet_lister_.reset(new PrivetDeviceListerImpl(service_discovery_client, + this, + kPrivetSubtypePrinter)); + privet_http_factory_ = PrivetHTTPAsynchronousFactory::CreateInstance( + service_discovery_client, + request_context); +} + +PrivetLocalPrinterLister::~PrivetLocalPrinterLister() { +} + +void PrivetLocalPrinterLister::Start() { + privet_lister_->Start(); + privet_lister_->DiscoverNewDevices(false); +} + +void PrivetLocalPrinterLister::DeviceChanged( + bool added, + const std::string& name, + const DeviceDescription& description) { + DeviceContextMap::iterator i = device_contexts_.find(name); + + if (i != device_contexts_.end()) { + if (i->second->has_local_printing) { + // This line helps with the edge case of a device description changing + // during the /privet/info call. + i->second->description = description; + delegate_->LocalPrinterChanged(added, name, description); + } + } else { + linked_ptr<DeviceContext> context(new DeviceContext); + context->has_local_printing = false; + context->description = description; + context->privet_resolution = privet_http_factory_->CreatePrivetHTTP( + name, + description.address, + base::Bind(&PrivetLocalPrinterLister::OnPrivetResolved, + base::Unretained(this))); + + device_contexts_[name] = context; + context->privet_resolution->Start(); + } +} + +void PrivetLocalPrinterLister::DeviceCacheFlushed() { + device_contexts_.clear(); + delegate_->LocalPrinterCacheFlushed(); +} + +void PrivetLocalPrinterLister::OnPrivetResolved( + scoped_ptr<PrivetHTTPClient> http_client) { + DeviceContextMap::iterator i = device_contexts_.find(http_client->GetName()); + DCHECK(i != device_contexts_.end()); + + i->second->info_operation = http_client->CreateInfoOperation(this); + i->second->privet_client = http_client.Pass(); + i->second->info_operation->Start(); +} + +void PrivetLocalPrinterLister::OnPrivetInfoDone( + PrivetInfoOperation* operation, + int http_code, + const base::DictionaryValue* json_value) { + bool has_local_printing = false; + const base::ListValue* api_list = NULL; + if (json_value && json_value->GetList(kPrivetInfoKeyAPIList, &api_list)) { + for (size_t i = 0; i < api_list->GetSize(); i++) { + std::string api; + api_list->GetString(i, &api); + if (api == kPrivetSubmitdocPath) { + has_local_printing = true; + } + } + } + + std::string name = operation->GetHTTPClient()->GetName(); + DeviceContextMap::iterator i = device_contexts_.find(name); + DCHECK(i != device_contexts_.end()); + i->second->has_local_printing = has_local_printing; + if (has_local_printing) { + delegate_->LocalPrinterChanged(true, name, i->second->description); + } +} + +void PrivetLocalPrinterLister::DeviceRemoved(const std::string& device_name) { + DeviceContextMap::iterator i = device_contexts_.find(device_name); + if (i != device_contexts_.end()) { + bool has_local_printing = i->second->has_local_printing; + device_contexts_.erase(i); + if (has_local_printing) { + delegate_->LocalPrinterRemoved(device_name); + } + } +} + +} // namespace local_discovery diff --git a/chrome/browser/local_discovery/privet_local_printer_lister.h b/chrome/browser/local_discovery/privet_local_printer_lister.h new file mode 100644 index 0000000..85f7358 --- /dev/null +++ b/chrome/browser/local_discovery/privet_local_printer_lister.h @@ -0,0 +1,71 @@ +// 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_PRIVET_LOCAL_PRINTER_LISTER_H_ +#define CHROME_BROWSER_LOCAL_DISCOVERY_PRIVET_LOCAL_PRINTER_LISTER_H_ + +#include <map> +#include <string> + +#include "base/memory/linked_ptr.h" +#include "chrome/browser/local_discovery/privet_device_lister.h" +#include "chrome/browser/local_discovery/privet_http.h" +#include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h" +#include "chrome/common/local_discovery/service_discovery_client.h" +#include "net/url_request/url_request_context.h" + +namespace local_discovery { + +// This is an adapter to PrivetDeviceLister that finds printers and checks if +// they support Privet local printing. +class PrivetLocalPrinterLister : PrivetDeviceLister::Delegate, + PrivetInfoOperation::Delegate { + public: + class Delegate { + public: + virtual ~Delegate() {} + virtual void LocalPrinterChanged(bool added, + const std::string& name, + const DeviceDescription& description) = 0; + virtual void LocalPrinterRemoved(const std::string& name) = 0; + virtual void LocalPrinterCacheFlushed() = 0; + }; + + PrivetLocalPrinterLister(ServiceDiscoveryClient* service_discovery_client, + net::URLRequestContextGetter* request_context, + Delegate* delegate); + virtual ~PrivetLocalPrinterLister(); + + void Start(); + + // PrivetDeviceLister::Delegate implementation. + virtual void DeviceChanged(bool added, + const std::string& name, + const DeviceDescription& description) OVERRIDE; + virtual void DeviceRemoved(const std::string& name) OVERRIDE; + virtual void DeviceCacheFlushed() OVERRIDE; + + // PrivetInfoOperation::Delegate implementation. + virtual void OnPrivetInfoDone( + PrivetInfoOperation* operation, + int http_code, + const base::DictionaryValue* json_value) OVERRIDE; + + private: + struct DeviceContext; + + void OnPrivetResolved(scoped_ptr<PrivetHTTPClient> http_client); + + typedef std::map<std::string, linked_ptr<DeviceContext> > DeviceContextMap; + + scoped_ptr<PrivetHTTPAsynchronousFactory> privet_http_factory_; + DeviceContextMap device_contexts_; + Delegate* delegate_; + + scoped_ptr<PrivetDeviceLister> privet_lister_; +}; + +} // namespace local_discovery + +#endif // CHROME_BROWSER_LOCAL_DISCOVERY_PRIVET_LOCAL_PRINTER_LISTER_H_ diff --git a/chrome/browser/local_discovery/privet_local_printer_lister_unittest.cc b/chrome/browser/local_discovery/privet_local_printer_lister_unittest.cc new file mode 100644 index 0000000..4480295 --- /dev/null +++ b/chrome/browser/local_discovery/privet_local_printer_lister_unittest.cc @@ -0,0 +1,208 @@ +// 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 "base/message_loop/message_loop.h" +#include "chrome/browser/local_discovery/privet_local_printer_lister.h" +#include "chrome/browser/local_discovery/test_service_discovery_client.h" +#include "net/url_request/test_url_fetcher_factory.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::StrictMock; +using testing::_; + +namespace local_discovery { + +namespace { + +const uint8 kAnnouncePacket[] = { + // Header + 0x00, 0x00, // ID is zeroed out + 0x80, 0x00, // Standard query response, no error + 0x00, 0x00, // No questions (for simplicity) + 0x00, 0x05, // 5 RR (answers) + 0x00, 0x00, // 0 authority RRs + 0x00, 0x00, // 0 additional RRs + + 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r', + 0x04, '_', 's', 'u', 'b', + 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', + 0x04, '_', 't', 'c', 'p', + 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + 0x00, 0x0c, // TYPE is PTR. + 0x00, 0x01, // CLASS is IN. + 0x00, 0x00, // TTL (4 bytes) is 32768 second. + 0x10, 0x00, + 0x00, 0x0c, // RDLENGTH is 12 bytes. + 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', + 0xc0, 0x0c, + + 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', + 0xc0, 0x0c, + 0x00, 0x10, // TYPE is TXT. + 0x00, 0x01, // CLASS is IN. + 0x00, 0x00, // TTL (4 bytes) is 32768 seconds. + 0x01, 0x00, + 0x00, 0x37, // RDLENGTH is 55 bytes. + 0x06, 'i', 'd', '=', 'r', 'e', 'g', + 0x10, 't', 'y', '=', 'S', 'a', 'm', 'p', 'l', 'e', ' ', + 'd', 'e', 'v', 'i', 'c', 'e', + 0x1e, 'n', 'o', 't', 'e', '=', + 'S', 'a', 'm', 'p', 'l', 'e', ' ', 'd', 'e', 'v', 'i', 'c', 'e', ' ', + 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', + + 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', + 0xc0, 0x0c, + 0x00, 0x21, // Type is SRV + 0x00, 0x01, // CLASS is IN + 0x00, 0x00, // TTL (4 bytes) is 32768 second. + 0x10, 0x00, + 0x00, 0x17, // RDLENGTH is 23 + 0x00, 0x00, + 0x00, 0x00, + 0x22, 0xb8, // port 8888 + 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', + 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + + 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', + 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + 0x00, 0x01, // Type is A + 0x00, 0x01, // CLASS is IN + 0x00, 0x00, // TTL (4 bytes) is 32768 second. + 0x10, 0x00, + 0x00, 0x04, // RDLENGTH is 4 + 0x01, 0x02, 0x03, 0x04, // 1.2.3.4 + + 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', + 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + 0x00, 0x1C, // Type is AAAA + 0x00, 0x01, // CLASS is IN + 0x00, 0x00, // TTL (4 bytes) is 32768 second. + 0x10, 0x00, + 0x00, 0x10, // RDLENGTH is 16 + 0x01, 0x02, 0x03, 0x04, // 1.2.3.4 + 0x01, 0x02, 0x03, 0x04, + 0x01, 0x02, 0x03, 0x04, + 0x01, 0x02, 0x03, 0x04, +}; + +const char kInfoIsLocalPrinter[] = "{" + "\"api\" : [ \"/privet/printer/submitdoc\" ]," + "\"x-privet-token\" : \"sample\"" + "}"; + +const char kInfoIsNotLocalPrinter[] = "{" + "\"api\" : [ \"/privet/register\" ]," + "\"x-privet-token\" : \"sample\"" + "}"; + + +class MockLocalPrinterListerDelegate + : public PrivetLocalPrinterLister::Delegate { + public: + MockLocalPrinterListerDelegate() { + } + + virtual ~MockLocalPrinterListerDelegate() { + } + + MOCK_METHOD3(LocalPrinterChanged, void(bool added, + const std::string& name, + const DeviceDescription& description)); + + MOCK_METHOD1(LocalPrinterRemoved, void(const std::string& name)); + + MOCK_METHOD0(LocalPrinterCacheFlushed, void()); +}; + +class PrivetLocalPrinterListerTest : public testing::Test { + public: + PrivetLocalPrinterListerTest() { + test_service_discovery_client_ = new TestServiceDiscoveryClient(); + test_service_discovery_client_->Start(); + url_request_context_ = new net::TestURLRequestContextGetter( + base::MessageLoopProxy::current()); + local_printer_lister_.reset(new PrivetLocalPrinterLister( + test_service_discovery_client_.get(), + url_request_context_.get(), + &delegate_)); + } + + ~PrivetLocalPrinterListerTest() { + } + + bool SuccessfulResponseToURL(const GURL& url, + const std::string& response) { + net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); + EXPECT_TRUE(fetcher); + EXPECT_EQ(url, fetcher->GetOriginalURL()); + + if (!fetcher || url != fetcher->GetOriginalURL()) + return false; + + fetcher->SetResponseString(response); + fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, + net::OK)); + fetcher->set_response_code(200); + fetcher->delegate()->OnURLFetchComplete(fetcher); + return true; + } + + void SimulateReceive(const uint8* packet, size_t size) { + test_service_discovery_client_->SimulateReceive(packet, size); + message_loop_.RunUntilIdle(); + } + + void ExpectAnyPacket() { + EXPECT_CALL(*test_service_discovery_client_, OnSendTo(_)) + .Times(2); + } + + protected: + base::MessageLoop message_loop_; + scoped_refptr<TestServiceDiscoveryClient> test_service_discovery_client_; + scoped_refptr<net::TestURLRequestContextGetter> url_request_context_; + scoped_ptr<PrivetLocalPrinterLister> local_printer_lister_; + net::TestURLFetcherFactory fetcher_factory_; + StrictMock<MockLocalPrinterListerDelegate> delegate_; +}; + +TEST_F(PrivetLocalPrinterListerTest, PrinterAddedTest) { + ExpectAnyPacket(); + + local_printer_lister_->Start(); + + SimulateReceive(kAnnouncePacket, sizeof(kAnnouncePacket)); + + EXPECT_CALL(delegate_, LocalPrinterChanged( + true, + "myService._printer._sub._privet._tcp.local", + _)); + + EXPECT_TRUE(SuccessfulResponseToURL( + GURL("http://1.2.3.4:8888/privet/info"), + std::string(kInfoIsLocalPrinter))); +}; + +TEST_F(PrivetLocalPrinterListerTest, NonPrinterAddedTest) { + ExpectAnyPacket(); + + local_printer_lister_->Start(); + + SimulateReceive(kAnnouncePacket, sizeof(kAnnouncePacket)); + + EXPECT_TRUE(SuccessfulResponseToURL( + GURL("http://1.2.3.4:8888/privet/info"), + std::string(kInfoIsNotLocalPrinter))); +}; + +} // namespace + +} // namespace local_discovery diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 1736036..58ad06a 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -963,6 +963,8 @@ 'browser/local_discovery/privet_http.h', 'browser/local_discovery/privet_http_impl.cc', 'browser/local_discovery/privet_http_impl.h', + 'browser/local_discovery/privet_local_printer_lister.h', + 'browser/local_discovery/privet_local_printer_lister.cc', 'browser/local_discovery/privet_url_fetcher.cc', 'browser/local_discovery/privet_url_fetcher.h', 'browser/local_discovery/service_discovery_client_mac.h', @@ -3534,6 +3536,8 @@ 'browser/local_discovery/service_discovery_client_mdns.h', 'browser/local_discovery/service_discovery_host_client.cc', 'browser/local_discovery/service_discovery_host_client.h', + 'browser/local_discovery/privet_local_printer_lister.h', + 'browser/local_discovery/privet_local_printer_lister.cc' ] }] ], diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index e20d77e..ae26530 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -2015,8 +2015,6 @@ }], ['enable_mdns==1', { 'sources' : [ - 'browser/local_discovery/test_service_discovery_client.cc', - 'browser/local_discovery/test_service_discovery_client.h', 'browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc', ] }], diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 87bf1be..10e178f 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -411,6 +411,12 @@ '../components/components.gyp:breakpad_stubs', ], }], + ['enable_mdns == 1', { + 'sources': [ + 'browser/local_discovery/test_service_discovery_client.cc', + 'browser/local_discovery/test_service_discovery_client.h', + ] + }], ], }, { @@ -2216,7 +2222,8 @@ 'utility/local_discovery/local_domain_resolver_unittest.cc', 'utility/local_discovery/service_discovery_client_unittest.cc', 'browser/local_discovery/privet_device_lister_unittest.cc', - 'browser/local_discovery/privet_notifications_unittest.cc' + 'browser/local_discovery/privet_notifications_unittest.cc', + 'browser/local_discovery/privet_local_printer_lister_unittest.cc', ] }], ['configuration_policy==0', { |