1 // Copyright (c) 2011 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/common/extensions/update_manifest.h" 7 #include "testing/gtest/include/gtest/gtest.h" 8 #include "libxml/globals.h" 9 10 static const char* kValidXml = 11 "<?xml version='1.0' encoding='UTF-8'?>" 12 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>" 13 " <app appid='12345'>" 14 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'" 15 " version='1.2.3.4' prodversionmin='2.0.143.0' />" 16 " </app>" 17 "</gupdate>"; 18 19 const char *valid_xml_with_hash = 20 "<?xml version='1.0' encoding='UTF-8'?>" 21 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>" 22 " <app appid='12345'>" 23 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'" 24 " version='1.2.3.4' prodversionmin='2.0.143.0' " 25 " hash='1234'/>" 26 " </app>" 27 "</gupdate>"; 28 29 static const char* kMissingAppId = 30 "<?xml version='1.0'?>" 31 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>" 32 " <app>" 33 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'" 34 " version='1.2.3.4' />" 35 " </app>" 36 "</gupdate>"; 37 38 static const char* kInvalidCodebase = 39 "<?xml version='1.0'?>" 40 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>" 41 " <app appid='12345' status='ok'>" 42 " <updatecheck codebase='example.com/extension_1.2.3.4.crx'" 43 " version='1.2.3.4' />" 44 " </app>" 45 "</gupdate>"; 46 47 static const char* kMissingVersion = 48 "<?xml version='1.0'?>" 49 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>" 50 " <app appid='12345' status='ok'>" 51 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx' />" 52 " </app>" 53 "</gupdate>"; 54 55 static const char* kInvalidVersion = 56 "<?xml version='1.0'?>" 57 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>" 58 " <app appid='12345' status='ok'>" 59 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx' " 60 " version='1.2.3.a'/>" 61 " </app>" 62 "</gupdate>"; 63 64 static const char* kUsesNamespacePrefix = 65 "<?xml version='1.0' encoding='UTF-8'?>" 66 "<g:gupdate xmlns:g='http://www.google.com/update2/response' protocol='2.0'>" 67 " <g:app appid='12345'>" 68 " <g:updatecheck codebase='http://example.com/extension_1.2.3.4.crx'" 69 " version='1.2.3.4' prodversionmin='2.0.143.0' />" 70 " </g:app>" 71 "</g:gupdate>"; 72 73 // Includes unrelated <app> tags from other xml namespaces - this should 74 // not cause problems. 75 static const char* kSimilarTagnames = 76 "<?xml version='1.0' encoding='UTF-8'?>" 77 "<gupdate xmlns='http://www.google.com/update2/response'" 78 " xmlns:a='http://a' protocol='2.0'>" 79 " <a:app/>" 80 " <b:app xmlns:b='http://b' />" 81 " <app appid='12345'>" 82 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'" 83 " version='1.2.3.4' prodversionmin='2.0.143.0' />" 84 " </app>" 85 "</gupdate>"; 86 87 // Includes a <daystart> tag. 88 static const char* kWithDaystart = 89 "<?xml version='1.0' encoding='UTF-8'?>" 90 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>" 91 " <daystart elapsed_seconds='456' />" 92 " <app appid='12345'>" 93 " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'" 94 " version='1.2.3.4' prodversionmin='2.0.143.0' />" 95 " </app>" 96 "</gupdate>"; 97 98 // Indicates no updates available - this should not be a parse error. 99 static const char* kNoUpdate = 100 "<?xml version='1.0' encoding='UTF-8'?>" 101 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>" 102 " <app appid='12345'>" 103 " <updatecheck status='noupdate' />" 104 " </app>" 105 "</gupdate>"; 106 107 // Includes two <app> tags, one with an error. 108 static const char* kTwoAppsOneError = 109 "<?xml version='1.0' encoding='UTF-8'?>" 110 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>" 111 " <app appid='aaaaaaaa' status='error-unknownApplication'>" 112 " <updatecheck status='error-unknownapplication'/>" 113 " </app>" 114 " <app appid='bbbbbbbb'>" 115 " <updatecheck codebase='http://example.com/b_3.1.crx' version='3.1'/>" 116 " </app>" 117 "</gupdate>"; 118 119 TEST(ExtensionUpdateManifestTest, TestUpdateManifest) { 120 UpdateManifest parser; 121 122 // Test parsing of a number of invalid xml cases 123 EXPECT_FALSE(parser.Parse("")); 124 EXPECT_FALSE(parser.errors().empty()); 125 126 EXPECT_TRUE(parser.Parse(kMissingAppId)); 127 EXPECT_TRUE(parser.results().list.empty()); 128 EXPECT_FALSE(parser.errors().empty()); 129 130 EXPECT_TRUE(parser.Parse(kInvalidCodebase)); 131 EXPECT_TRUE(parser.results().list.empty()); 132 EXPECT_FALSE(parser.errors().empty()); 133 134 EXPECT_TRUE(parser.Parse(kMissingVersion)); 135 EXPECT_TRUE(parser.results().list.empty()); 136 EXPECT_FALSE(parser.errors().empty()); 137 138 EXPECT_TRUE(parser.Parse(kInvalidVersion)); 139 EXPECT_TRUE(parser.results().list.empty()); 140 EXPECT_FALSE(parser.errors().empty()); 141 142 // Parse some valid XML, and check that all params came out as expected 143 EXPECT_TRUE(parser.Parse(kValidXml)); 144 EXPECT_TRUE(parser.errors().empty()); 145 EXPECT_FALSE(parser.results().list.empty()); 146 const UpdateManifest::Result* firstResult = &parser.results().list.at(0); 147 EXPECT_EQ(GURL("http://example.com/extension_1.2.3.4.crx"), 148 firstResult->crx_url); 149 150 EXPECT_EQ("1.2.3.4", firstResult->version); 151 EXPECT_EQ("2.0.143.0", firstResult->browser_min_version); 152 153 // Parse some xml that uses namespace prefixes. 154 EXPECT_TRUE(parser.Parse(kUsesNamespacePrefix)); 155 EXPECT_TRUE(parser.errors().empty()); 156 EXPECT_TRUE(parser.Parse(kSimilarTagnames)); 157 EXPECT_TRUE(parser.errors().empty()); 158 xmlCleanupGlobals(); 159 160 // Parse xml with hash value 161 EXPECT_TRUE(parser.Parse(valid_xml_with_hash)); 162 EXPECT_TRUE(parser.errors().empty()); 163 EXPECT_FALSE(parser.results().list.empty()); 164 firstResult = &parser.results().list.at(0); 165 EXPECT_EQ("1234", firstResult->package_hash); 166 167 // Parse xml with a <daystart> element. 168 EXPECT_TRUE(parser.Parse(kWithDaystart)); 169 EXPECT_TRUE(parser.errors().empty()); 170 EXPECT_FALSE(parser.results().list.empty()); 171 EXPECT_EQ(parser.results().daystart_elapsed_seconds, 456); 172 173 // Parse a no-update response. 174 EXPECT_TRUE(parser.Parse(kNoUpdate)); 175 EXPECT_TRUE(parser.errors().empty()); 176 EXPECT_FALSE(parser.results().list.empty()); 177 firstResult = &parser.results().list.at(0); 178 EXPECT_EQ(firstResult->extension_id, "12345"); 179 EXPECT_EQ(firstResult->version, ""); 180 181 // Parse xml with one error and one success <app> tag. 182 EXPECT_TRUE(parser.Parse(kTwoAppsOneError)); 183 EXPECT_FALSE(parser.errors().empty()); 184 EXPECT_EQ(1u, parser.results().list.size()); 185 firstResult = &parser.results().list.at(0); 186 EXPECT_EQ(firstResult->extension_id, "bbbbbbbb"); 187 } 188