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
TEST(ExtensionUpdateManifestTest,TestUpdateManifest)119 TEST(ExtensionUpdateManifestTest, TestUpdateManifest) {
120 UpdateManifest parser;
121
122 // Test parsing of a number of invalid xml cases
123 EXPECT_FALSE(parser.Parse(std::string()));
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