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 "extensions/common/update_manifest.h"
7#include "libxml/globals.h"
8#include "testing/gtest/include/gtest/gtest.h"
9
10static 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
19const 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
29static 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
38static 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
47static 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
55static 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
64static 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.
75static 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.
88static 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.
99static 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.
108static 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
119TEST(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