1 // Copyright 2013 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 "base/memory/scoped_vector.h" 6 #include "chrome/browser/component_updater/update_response.h" 7 #include "libxml/globals.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 namespace component_updater { 11 12 const char* kValidXml = 13 "<?xml version='1.0' encoding='UTF-8'?>" 14 "<response protocol='3.0'>" 15 " <app appid='12345'>" 16 " <updatecheck status='ok'>" 17 " <urls>" 18 " <url codebase='http://example.com/'/>" 19 " <url codebasediff='http://diff.example.com/'/>" 20 " </urls>" 21 " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" 22 " <packages>" 23 " <package name='extension_1_2_3_4.crx'/>" 24 " </packages>" 25 " </manifest>" 26 " </updatecheck>" 27 " </app>" 28 "</response>"; 29 30 const char* valid_xml_with_hash = 31 "<?xml version='1.0' encoding='UTF-8'?>" 32 "<response protocol='3.0'>" 33 " <app appid='12345'>" 34 " <updatecheck status='ok'>" 35 " <urls>" 36 " <url codebase='http://example.com/'/>" 37 " </urls>" 38 " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" 39 " <packages>" 40 " <package name='extension_1_2_3_4.crx' hash_sha256='1234'/>" 41 " </packages>" 42 " </manifest>" 43 " </updatecheck>" 44 " </app>" 45 "</response>"; 46 47 const char* valid_xml_with_invalid_sizes = 48 "<?xml version='1.0' encoding='UTF-8'?>" 49 "<response protocol='3.0'>" 50 " <app appid='12345'>" 51 " <updatecheck status='ok'>" 52 " <urls>" 53 " <url codebase='http://example.com/'/>" 54 " </urls>" 55 " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" 56 " <packages>" 57 " <package name='1' size='1234'/>" 58 " <package name='2' size='-1234'/>" 59 " <package name='3' />" 60 " <package name='4' size='-a'/>" 61 " <package name='5' size='-123467890123456789'/>" 62 " <package name='6' size='123467890123456789'/>" 63 " </packages>" 64 " </manifest>" 65 " </updatecheck>" 66 " </app>" 67 "</response>"; 68 69 const char* kInvalidValidXmlMissingCodebase = 70 "<?xml version='1.0' encoding='UTF-8'?>" 71 "<response protocol='3.0'>" 72 " <app appid='12345'>" 73 " <updatecheck status='ok'>" 74 " <urls>" 75 " <url codebasediff='http://diff.example.com/'/>" 76 " </urls>" 77 " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" 78 " <packages>" 79 " <package namediff='extension_1_2_3_4.crx'/>" 80 " </packages>" 81 " </manifest>" 82 " </updatecheck>" 83 " </app>" 84 "</response>"; 85 86 const char* kMissingAppId = 87 "<?xml version='1.0'?>" 88 "<response protocol='3.0'>" 89 " <app>" 90 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'" 91 " version='1.2.3.4' />" 92 " </app>" 93 "</response>"; 94 95 const char* kInvalidCodebase = 96 "<?xml version='1.0'?>" 97 "<response protocol='3.0'>" 98 " <app appid='12345' status='ok'>" 99 " <updatecheck codebase='example.com/extension_1.2.3.4.crx'" 100 " version='1.2.3.4' />" 101 " </app>" 102 "</response>"; 103 104 const char* kMissingVersion = 105 "<?xml version='1.0'?>" 106 "<response protocol='3.0'>" 107 " <app appid='12345' status='ok'>" 108 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx' />" 109 " </app>" 110 "</response>"; 111 112 const char* kInvalidVersion = 113 "<?xml version='1.0'?>" 114 "<response protocol='3.0'>" 115 " <app appid='12345' status='ok'>" 116 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx' " 117 " version='1.2.3.a'/>" 118 " </app>" 119 "</response>"; 120 121 // The v3 version of the protocol is not using namespaces. However, the parser 122 // must be able to parse responses that include namespaces. 123 const char* kUsesNamespacePrefix = 124 "<?xml version='1.0' encoding='UTF-8'?>" 125 "<g:response xmlns='http://www.google.com/update2/response' protocol='3.0'>" 126 " <g:app appid='12345'>" 127 " <g:updatecheck status='ok'>" 128 " <g:urls>" 129 " <g:url codebase='http://example.com/'/>" 130 " </g:urls>" 131 " <g:manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" 132 " <g:packages>" 133 " <g:package name='extension_1_2_3_4.crx'/>" 134 " </g:packages>" 135 " </g:manifest>" 136 " </g:updatecheck>" 137 " </g:app>" 138 "</g:response>"; 139 140 // Includes unrelated <app> tags from other xml namespaces - this should 141 // not cause problems. 142 const char* kSimilarTagnames = 143 "<?xml version='1.0' encoding='UTF-8'?>" 144 "<response xmlns:a='http://a' protocol='3.0'>" 145 " <a:app appid='12345'>" 146 " <updatecheck status='ok'>" 147 " <urls>" 148 " <url codebase='http://example.com/'/>" 149 " </urls>" 150 " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" 151 " <packages>" 152 " <package name='extension_1_2_3_4.crx'/>" 153 " </packages>" 154 " </manifest>" 155 " </updatecheck>" 156 " </a:app>" 157 " <b:app appid='xyz' xmlns:b='http://b'>" 158 " <updatecheck status='noupdate'/>" 159 " </b:app>" 160 "</response>"; 161 162 // Includes a <daystart> tag. 163 const char* kWithDaystart = 164 "<?xml version='1.0' encoding='UTF-8'?>" 165 "<response protocol='3.0'>" 166 " <daystart elapsed_seconds='456' />" 167 " <app appid='12345'>" 168 " <updatecheck status='ok'>" 169 " <urls>" 170 " <url codebase='http://example.com/'/>" 171 " </urls>" 172 " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" 173 " <packages>" 174 " <package name='extension_1_2_3_4.crx'/>" 175 " </packages>" 176 " </manifest>" 177 " </updatecheck>" 178 " </app>" 179 "</response>"; 180 181 // Indicates no updates available - this should not be a parse error. 182 const char* kNoUpdate = 183 "<?xml version='1.0' encoding='UTF-8'?>" 184 "<response protocol='3.0'>" 185 " <app appid='12345'>" 186 " <updatecheck status='noupdate' />" 187 " </app>" 188 "</response>"; 189 190 // Includes two <app> tags, one with an error. 191 const char* kTwoAppsOneError = 192 "<?xml version='1.0' encoding='UTF-8'?>" 193 "<response protocol='3.0'>" 194 " <app appid='aaaaaaaa' status='error-unknownApplication'>" 195 " <updatecheck status='error-unknownapplication'/>" 196 " </app>" 197 " <app appid='bbbbbbbb'>" 198 " <updatecheck status='ok'>" 199 " <urls>" 200 " <url codebase='http://example.com/'/>" 201 " </urls>" 202 " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" 203 " <packages>" 204 " <package name='extension_1_2_3_4.crx'/>" 205 " </packages>" 206 " </manifest>" 207 " </updatecheck>" 208 " </app>" 209 "</response>"; 210 211 TEST(ComponentUpdaterUpdateResponseTest, TestParser) { 212 UpdateResponse parser; 213 214 // Test parsing of a number of invalid xml cases 215 EXPECT_FALSE(parser.Parse(std::string())); 216 EXPECT_FALSE(parser.errors().empty()); 217 218 EXPECT_TRUE(parser.Parse(kMissingAppId)); 219 EXPECT_TRUE(parser.results().list.empty()); 220 EXPECT_FALSE(parser.errors().empty()); 221 222 EXPECT_TRUE(parser.Parse(kInvalidCodebase)); 223 EXPECT_TRUE(parser.results().list.empty()); 224 EXPECT_FALSE(parser.errors().empty()); 225 226 EXPECT_TRUE(parser.Parse(kMissingVersion)); 227 EXPECT_TRUE(parser.results().list.empty()); 228 EXPECT_FALSE(parser.errors().empty()); 229 230 EXPECT_TRUE(parser.Parse(kInvalidVersion)); 231 EXPECT_TRUE(parser.results().list.empty()); 232 EXPECT_FALSE(parser.errors().empty()); 233 234 EXPECT_TRUE(parser.Parse(kInvalidValidXmlMissingCodebase)); 235 EXPECT_TRUE(parser.results().list.empty()); 236 EXPECT_FALSE(parser.errors().empty()); 237 238 // Parse some valid XML, and check that all params came out as expected 239 EXPECT_TRUE(parser.Parse(kValidXml)); 240 EXPECT_TRUE(parser.errors().empty()); 241 EXPECT_EQ(1u, parser.results().list.size()); 242 const UpdateResponse::Result* firstResult = &parser.results().list[0]; 243 EXPECT_EQ(1u, firstResult->crx_urls.size()); 244 EXPECT_EQ(GURL("http://example.com/"), firstResult->crx_urls[0]); 245 EXPECT_EQ(GURL("http://diff.example.com/"), firstResult->crx_diffurls[0]); 246 EXPECT_EQ("1.2.3.4", firstResult->manifest.version); 247 EXPECT_EQ("2.0.143.0", firstResult->manifest.browser_min_version); 248 EXPECT_EQ(1u, firstResult->manifest.packages.size()); 249 EXPECT_EQ("extension_1_2_3_4.crx", firstResult->manifest.packages[0].name); 250 251 // Parse some xml that uses namespace prefixes. 252 EXPECT_TRUE(parser.Parse(kUsesNamespacePrefix)); 253 EXPECT_TRUE(parser.errors().empty()); 254 EXPECT_TRUE(parser.Parse(kSimilarTagnames)); 255 EXPECT_TRUE(parser.errors().empty()); 256 xmlCleanupGlobals(); 257 258 // Parse xml with hash value 259 EXPECT_TRUE(parser.Parse(valid_xml_with_hash)); 260 EXPECT_TRUE(parser.errors().empty()); 261 EXPECT_FALSE(parser.results().list.empty()); 262 firstResult = &parser.results().list[0]; 263 EXPECT_FALSE(firstResult->manifest.packages.empty()); 264 EXPECT_EQ("1234", firstResult->manifest.packages[0].hash_sha256); 265 266 // Parse xml with package size value 267 EXPECT_TRUE(parser.Parse(valid_xml_with_invalid_sizes)); 268 EXPECT_TRUE(parser.errors().empty()); 269 EXPECT_FALSE(parser.results().list.empty()); 270 firstResult = &parser.results().list[0]; 271 EXPECT_FALSE(firstResult->manifest.packages.empty()); 272 EXPECT_EQ(1234, firstResult->manifest.packages[0].size); 273 EXPECT_EQ(-1234, firstResult->manifest.packages[1].size); 274 EXPECT_EQ(0, firstResult->manifest.packages[2].size); 275 EXPECT_EQ(0, firstResult->manifest.packages[3].size); 276 EXPECT_EQ(0, firstResult->manifest.packages[4].size); 277 EXPECT_EQ(0, firstResult->manifest.packages[5].size); 278 279 // Parse xml with a <daystart> element. 280 EXPECT_TRUE(parser.Parse(kWithDaystart)); 281 EXPECT_TRUE(parser.errors().empty()); 282 EXPECT_FALSE(parser.results().list.empty()); 283 EXPECT_EQ(parser.results().daystart_elapsed_seconds, 456); 284 285 // Parse a no-update response. 286 EXPECT_TRUE(parser.Parse(kNoUpdate)); 287 EXPECT_TRUE(parser.errors().empty()); 288 EXPECT_FALSE(parser.results().list.empty()); 289 firstResult = &parser.results().list[0]; 290 EXPECT_EQ(firstResult->extension_id, "12345"); 291 EXPECT_EQ(firstResult->manifest.version, ""); 292 293 // Parse xml with one error and one success <app> tag. 294 EXPECT_TRUE(parser.Parse(kTwoAppsOneError)); 295 EXPECT_FALSE(parser.errors().empty()); 296 EXPECT_EQ(1u, parser.results().list.size()); 297 firstResult = &parser.results().list[0]; 298 EXPECT_EQ(firstResult->extension_id, "bbbbbbbb"); 299 } 300 301 } // namespace component_updater 302