| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/utility/media_router/dial_device_description_parser_impl.h" |
| 6 |
| 7 #include <libxml/parser.h> |
| 8 #include <libxml/tree.h> |
| 9 #include <libxml/xpath.h> |
| 10 #include <utility> |
| 11 |
| 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/strings/stringprintf.h" |
| 14 #include "mojo/public/cpp/bindings/strong_binding.h" |
| 15 #include "third_party/libxml/chromium/libxml_utils.h" |
| 16 |
| 17 namespace { |
| 18 |
| 19 enum ErrorType { |
| 20 NONE, |
| 21 MISSING_UNIQUE_ID, |
| 22 MISSING_FRIENDLY_NAME, |
| 23 }; |
| 24 |
| 25 ErrorType Validate(const chrome::mojom::DialDeviceDescription& description) { |
| 26 if (description.unique_id.empty()) { |
| 27 return ErrorType::MISSING_UNIQUE_ID; |
| 28 } |
| 29 if (description.friendly_name.empty()) { |
| 30 return ErrorType::MISSING_FRIENDLY_NAME; |
| 31 } |
| 32 return ErrorType::NONE; |
| 33 } |
| 34 |
| 35 // If friendly name does not exist, fall back to use model name + last 4 |
| 36 // digits of UUID as friendly name. |
| 37 std::string ComputeFriendlyName(const std::string& unique_id, |
| 38 const std::string& model_name) { |
| 39 if (model_name.empty() || unique_id.length() < 4) |
| 40 return std::string(); |
| 41 |
| 42 std::string trimmed_unique_id = unique_id.substr(unique_id.length() - 4); |
| 43 return base::StringPrintf("%s [%s]", model_name.c_str(), |
| 44 trimmed_unique_id.c_str()); |
| 45 } |
| 46 |
| 47 } // namespace |
| 48 |
| 49 namespace media_router { |
| 50 |
| 51 DialDeviceDescriptionParserImpl::DialDeviceDescriptionParserImpl() = default; |
| 52 DialDeviceDescriptionParserImpl::~DialDeviceDescriptionParserImpl() { |
| 53 DCHECK(thread_checker_.CalledOnValidThread()); |
| 54 } |
| 55 |
| 56 // static |
| 57 void DialDeviceDescriptionParserImpl::Create( |
| 58 chrome::mojom::DialDeviceDescriptionParserRequest request) { |
| 59 mojo::MakeStrongBinding(base::MakeUnique<DialDeviceDescriptionParserImpl>(), |
| 60 std::move(request)); |
| 61 } |
| 62 |
| 63 void DialDeviceDescriptionParserImpl::ParseDialDeviceDescription( |
| 64 const std::string& device_description_xml_data, |
| 65 const ParseDialDeviceDescriptionCallback& callback) { |
| 66 DCHECK(thread_checker_.CalledOnValidThread()); |
| 67 DCHECK(!callback.is_null()); |
| 68 |
| 69 chrome::mojom::DialDeviceDescriptionPtr device_description = |
| 70 Parse(device_description_xml_data); |
| 71 callback.Run(std::move(device_description)); |
| 72 } |
| 73 |
| 74 chrome::mojom::DialDeviceDescriptionPtr DialDeviceDescriptionParserImpl::Parse( |
| 75 const std::string& xml) { |
| 76 XmlReader xml_reader; |
| 77 if (!xml_reader.Load(xml)) |
| 78 return nullptr; |
| 79 |
| 80 chrome::mojom::DialDeviceDescriptionPtr out = |
| 81 chrome::mojom::DialDeviceDescription::New(); |
| 82 |
| 83 while (xml_reader.Read()) { |
| 84 xml_reader.SkipToElement(); |
| 85 std::string node_name(xml_reader.NodeName()); |
| 86 |
| 87 if (node_name == "UDN") { |
| 88 if (!xml_reader.ReadElementContent(&out->unique_id)) |
| 89 return nullptr; |
| 90 } else if (node_name == "friendlyName") { |
| 91 if (!xml_reader.ReadElementContent(&out->friendly_name)) |
| 92 return nullptr; |
| 93 } else if (node_name == "modelName") { |
| 94 if (!xml_reader.ReadElementContent(&out->model_name)) |
| 95 return nullptr; |
| 96 } else if (node_name == "deviceType") { |
| 97 if (!xml_reader.ReadElementContent(&out->device_type)) |
| 98 return nullptr; |
| 99 } |
| 100 } |
| 101 |
| 102 if (out->friendly_name.empty()) |
| 103 out->friendly_name = ComputeFriendlyName(out->unique_id, out->model_name); |
| 104 |
| 105 ErrorType error = Validate(*out); |
| 106 if (error != ErrorType::NONE) { |
| 107 DLOG(WARNING) << "Device description failed to validate: " << error; |
| 108 return nullptr; |
| 109 } |
| 110 |
| 111 return out; |
| 112 } |
| 113 |
| 114 } // namespace media_router |
| OLD | NEW |