1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "link/ManifestFixer.h"
18
19 #include "test/Test.h"
20
21 using ::android::StringPiece;
22 using ::testing::Eq;
23 using ::testing::Gt;
24 using ::testing::IsNull;
25 using ::testing::Ne;
26 using ::testing::NotNull;
27 using ::testing::StrEq;
28
29 namespace aapt {
30
31 struct ManifestFixerTest : public ::testing::Test {
32 std::unique_ptr<IAaptContext> mContext;
33
SetUpaapt::ManifestFixerTest34 void SetUp() override {
35 mContext =
36 test::ContextBuilder()
37 .SetCompilationPackage("android")
38 .SetPackageId(0x01)
39 .SetNameManglerPolicy(NameManglerPolicy{"android"})
40 .AddSymbolSource(test::StaticSymbolSourceBuilder()
41 .AddSymbol("android:attr/package", ResourceId(0x01010000),
42 test::AttributeBuilder()
43 .SetTypeMask(android::ResTable_map::TYPE_STRING)
44 .Build())
45 .AddSymbol("android:attr/minSdkVersion", ResourceId(0x01010001),
46 test::AttributeBuilder()
47 .SetTypeMask(android::ResTable_map::TYPE_STRING |
48 android::ResTable_map::TYPE_INTEGER)
49 .Build())
50 .AddSymbol("android:attr/targetSdkVersion", ResourceId(0x01010002),
51 test::AttributeBuilder()
52 .SetTypeMask(android::ResTable_map::TYPE_STRING |
53 android::ResTable_map::TYPE_INTEGER)
54 .Build())
55 .AddSymbol("android:string/str", ResourceId(0x01060000))
56 .AddSymbol("android:attr/configChanges", ResourceId(0x01010003),
57 test::AttributeBuilder()
58 .AddItem("testConfigChange1", 1)
59 .AddItem("testConfigChange2", 2)
60 .AddItem("resourcesUnused", 4)
61 .SetTypeMask(android::ResTable_map::TYPE_STRING)
62 .Build())
63 .Build())
64 .Build();
65 }
66
Verifyaapt::ManifestFixerTest67 std::unique_ptr<xml::XmlResource> Verify(StringPiece str) {
68 return VerifyWithOptions(str, {});
69 }
70
VerifyWithOptionsaapt::ManifestFixerTest71 std::unique_ptr<xml::XmlResource> VerifyWithOptions(StringPiece str,
72 const ManifestFixerOptions& options) {
73 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(str);
74 ManifestFixer fixer(options);
75 if (fixer.Consume(mContext.get(), doc.get())) {
76 return doc;
77 }
78 return {};
79 }
80 };
81
TEST_F(ManifestFixerTest,EnsureManifestIsRootTag)82 TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) {
83 EXPECT_THAT(Verify("<other-tag />"), IsNull());
84 EXPECT_THAT(Verify("<ns:manifest xmlns:ns=\"com\" />"), IsNull());
85 EXPECT_THAT(Verify("<manifest package=\"android\"></manifest>"), NotNull());
86 }
87
TEST_F(ManifestFixerTest,EnsureManifestHasPackage)88 TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
89 EXPECT_THAT(Verify("<manifest package=\"android\" />"), NotNull());
90 EXPECT_THAT(Verify("<manifest package=\"com.android\" />"), NotNull());
91 EXPECT_THAT(Verify("<manifest package=\"com.android.google\" />"), NotNull());
92 EXPECT_THAT(Verify("<manifest package=\"com.android.google.Class$1\" />"), IsNull());
93 EXPECT_THAT(Verify("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
94 "android:package=\"com.android\" />"),
95 IsNull());
96 EXPECT_THAT(Verify("<manifest package=\"@string/str\" />"), IsNull());
97 }
98
TEST_F(ManifestFixerTest,AllowMetaData)99 TEST_F(ManifestFixerTest, AllowMetaData) {
100 auto doc = Verify(R"EOF(
101 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
102 package="android">
103 <meta-data />
104 <application>
105 <meta-data />
106 <activity android:name=".Hi"><meta-data /></activity>
107 <activity-alias android:name=".Ho"><meta-data /></activity-alias>
108 <receiver android:name=".OffTo"><meta-data /></receiver>
109 <provider android:name=".Work"><meta-data /></provider>
110 <service android:name=".We"><meta-data /></service>
111 </application>
112 <instrumentation android:name=".Go"><meta-data /></instrumentation>
113 </manifest>)EOF");
114 ASSERT_THAT(doc, NotNull());
115 }
116
117 TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
118 ManifestFixerOptions options;
119 options.min_sdk_version_default = std::string("8");
120 options.target_sdk_version_default = std::string("22");
121
122 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
123 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
124 package="android">
125 <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
126 </manifest>)EOF",
127 options);
128 ASSERT_THAT(doc, NotNull());
129
130 xml::Element* el;
131 xml::Attribute* attr;
132
133 el = doc->root.get();
134 ASSERT_THAT(el, NotNull());
135 el = el->FindChild({}, "uses-sdk");
136 ASSERT_THAT(el, NotNull());
137 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
138 ASSERT_THAT(attr, NotNull());
139 EXPECT_THAT(attr->value, StrEq("7"));
140 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
141 ASSERT_THAT(attr, NotNull());
142 EXPECT_THAT(attr->value, StrEq("21"));
143
144 doc = VerifyWithOptions(R"EOF(
145 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
146 package="android">
147 <uses-sdk android:targetSdkVersion="21" />
148 </manifest>)EOF",
149 options);
150 ASSERT_THAT(doc, NotNull());
151
152 el = doc->root.get();
153 ASSERT_THAT(el, NotNull());
154 el = el->FindChild({}, "uses-sdk");
155 ASSERT_THAT(el, NotNull());
156 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
157 ASSERT_THAT(attr, NotNull());
158 EXPECT_THAT(attr->value, StrEq("8"));
159 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
160 ASSERT_THAT(attr, NotNull());
161 EXPECT_THAT(attr->value, StrEq("21"));
162
163 doc = VerifyWithOptions(R"EOF(
164 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
165 package="android">
166 <uses-sdk />
167 </manifest>)EOF",
168 options);
169 ASSERT_THAT(doc, NotNull());
170
171 el = doc->root.get();
172 ASSERT_THAT(el, NotNull());
173 el = el->FindChild({}, "uses-sdk");
174 ASSERT_THAT(el, NotNull());
175 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
176 ASSERT_THAT(attr, NotNull());
177 EXPECT_THAT(attr->value, StrEq("8"));
178 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
179 ASSERT_THAT(attr, NotNull());
180 EXPECT_THAT(attr->value, StrEq("22"));
181
182 doc = VerifyWithOptions(R"EOF(
183 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
184 package="android" />)EOF",
185 options);
186 ASSERT_THAT(doc, NotNull());
187
188 el = doc->root.get();
189 ASSERT_THAT(el, NotNull());
190 el = el->FindChild({}, "uses-sdk");
191 ASSERT_THAT(el, NotNull());
192 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
193 ASSERT_THAT(attr, NotNull());
194 EXPECT_THAT(attr->value, StrEq("8"));
195 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
196 ASSERT_THAT(attr, NotNull());
197 EXPECT_THAT(attr->value, StrEq("22"));
198 }
199
200 TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) {
201 ManifestFixerOptions options;
202 options.min_sdk_version_default = std::string("8");
203 options.target_sdk_version_default = std::string("22");
204 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
205 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
206 package="android">
207 <application android:name=".MainApplication" />
208 </manifest>)EOF",
209 options);
210 ASSERT_THAT(doc, NotNull());
211
212 xml::Element* manifest_el = doc->root.get();
213 ASSERT_THAT(manifest_el, NotNull());
214 ASSERT_EQ("manifest", manifest_el->name);
215
216 xml::Element* application_el = manifest_el->FindChild("", "application");
217 ASSERT_THAT(application_el, NotNull());
218
219 xml::Element* uses_sdk_el = manifest_el->FindChild("", "uses-sdk");
220 ASSERT_THAT(uses_sdk_el, NotNull());
221
222 // Check that the uses_sdk_el comes before application_el in the children
223 // vector.
224 // Since there are no namespaces here, these children are direct descendants
225 // of manifest.
226 auto uses_sdk_iter =
227 std::find_if(manifest_el->children.begin(), manifest_el->children.end(),
228 [&](const std::unique_ptr<xml::Node>& child) {
229 return child.get() == uses_sdk_el;
230 });
231
232 auto application_iter =
233 std::find_if(manifest_el->children.begin(), manifest_el->children.end(),
234 [&](const std::unique_ptr<xml::Node>& child) {
235 return child.get() == application_el;
236 });
237
238 ASSERT_THAT(uses_sdk_iter, Ne(manifest_el->children.end()));
239 ASSERT_THAT(application_iter, Ne(manifest_el->children.end()));
240
241 // The distance should be positive, meaning uses_sdk_iter comes before
242 // application_iter.
243 EXPECT_THAT(std::distance(uses_sdk_iter, application_iter), Gt(0));
244 }
245
246 TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
247 ManifestFixerOptions options;
248 options.rename_manifest_package = std::string("com.android");
249
250 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
251 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
252 package="android">
253 <uses-split android:name="feature_a" />
254 <application android:name=".MainApplication" text="hello">
255 <activity android:name=".activity.Start" />
256 <receiver android:name="com.google.android.Receiver" />
257 </application>
258 </manifest>)EOF",
259 options);
260 ASSERT_THAT(doc, NotNull());
261
262 xml::Element* manifest_el = doc->root.get();
263 ASSERT_THAT(manifest_el, NotNull());
264
265 xml::Attribute* attr = nullptr;
266
267 attr = manifest_el->FindAttribute({}, "package");
268 ASSERT_THAT(attr, NotNull());
269 EXPECT_THAT(attr->value, StrEq("com.android"));
270
271 xml::Element* uses_split_el = manifest_el->FindChild({}, "uses-split");
272 ASSERT_THAT(uses_split_el, NotNull());
273 attr = uses_split_el->FindAttribute(xml::kSchemaAndroid, "name");
274 ASSERT_THAT(attr, NotNull());
275 // This should NOT have been affected.
276 EXPECT_THAT(attr->value, StrEq("feature_a"));
277
278 xml::Element* application_el = manifest_el->FindChild({}, "application");
279 ASSERT_THAT(application_el, NotNull());
280
281 attr = application_el->FindAttribute(xml::kSchemaAndroid, "name");
282 ASSERT_THAT(attr, NotNull());
283 EXPECT_THAT(attr->value, StrEq("android.MainApplication"));
284
285 attr = application_el->FindAttribute({}, "text");
286 ASSERT_THAT(attr, NotNull());
287 EXPECT_THAT(attr->value, StrEq("hello"));
288
289 xml::Element* el;
290 el = application_el->FindChild({}, "activity");
291 ASSERT_THAT(el, NotNull());
292
293 attr = el->FindAttribute(xml::kSchemaAndroid, "name");
294 ASSERT_THAT(el, NotNull());
295 EXPECT_THAT(attr->value, StrEq("android.activity.Start"));
296
297 el = application_el->FindChild({}, "receiver");
298 ASSERT_THAT(el, NotNull());
299
300 attr = el->FindAttribute(xml::kSchemaAndroid, "name");
301 ASSERT_THAT(el, NotNull());
302 EXPECT_THAT(attr->value, StrEq("com.google.android.Receiver"));
303 }
304
305 TEST_F(ManifestFixerTest,
306 RenameManifestInstrumentationPackageAndFullyQualifyTarget) {
307 ManifestFixerOptions options;
308 options.rename_instrumentation_target_package = std::string("com.android");
309
310 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
311 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
312 package="android">
313 <instrumentation android:name=".TestRunner" android:targetPackage="android" />
314 </manifest>)EOF",
315 options);
316 ASSERT_THAT(doc, NotNull());
317
318 xml::Element* manifest_el = doc->root.get();
319 ASSERT_THAT(manifest_el, NotNull());
320
321 xml::Element* instrumentation_el =
322 manifest_el->FindChild({}, "instrumentation");
323 ASSERT_THAT(instrumentation_el, NotNull());
324
325 xml::Attribute* attr =
326 instrumentation_el->FindAttribute(xml::kSchemaAndroid, "targetPackage");
327 ASSERT_THAT(attr, NotNull());
328 EXPECT_THAT(attr->value, StrEq("com.android"));
329 }
330
331 TEST_F(ManifestFixerTest,
332 RenameManifestOverlayPackageAndFullyQualifyTarget) {
333 ManifestFixerOptions options;
334 options.rename_overlay_target_package = std::string("com.android");
335
336 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
337 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
338 package="android">
339 <overlay android:targetName="Customization" android:targetPackage="android" />
340 </manifest>)EOF",
341 options);
342 ASSERT_THAT(doc, NotNull());
343
344 xml::Element* manifest_el = doc->root.get();
345 ASSERT_THAT(manifest_el, NotNull());
346
347 xml::Element* overlay_el =
348 manifest_el->FindChild({}, "overlay");
349 ASSERT_THAT(overlay_el, NotNull());
350
351 xml::Attribute* attr =
352 overlay_el->FindAttribute(xml::kSchemaAndroid, "targetPackage");
353 ASSERT_THAT(attr, NotNull());
354 EXPECT_THAT(attr->value, StrEq("com.android"));
355 }
356
357 TEST_F(ManifestFixerTest, AddOverlayCategory) {
358 ManifestFixerOptions options;
359 options.rename_overlay_category = std::string("category");
360
361 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
362 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
363 package="android">
364 <overlay android:targetName="Customization" android:targetPackage="android" />
365 </manifest>)EOF",
366 options);
367 ASSERT_THAT(doc, NotNull());
368
369 xml::Element* manifest_el = doc->root.get();
370 ASSERT_THAT(manifest_el, NotNull());
371
372 xml::Element* overlay_el = manifest_el->FindChild({}, "overlay");
373 ASSERT_THAT(overlay_el, NotNull());
374
375 xml::Attribute* attr = overlay_el->FindAttribute(xml::kSchemaAndroid, "category");
376 ASSERT_THAT(attr, NotNull());
377 EXPECT_THAT(attr->value, StrEq("category"));
378 }
379
380 TEST_F(ManifestFixerTest, OverrideOverlayCategory) {
381 ManifestFixerOptions options;
382 options.rename_overlay_category = std::string("category");
383
384 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
385 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
386 package="android">
387 <overlay android:targetName="Customization"
388 android:targetPackage="android"
389 android:category="yrogetac"/>
390 </manifest>)EOF",
391 options);
392 ASSERT_THAT(doc, NotNull());
393
394 xml::Element* manifest_el = doc->root.get();
395 ASSERT_THAT(manifest_el, NotNull());
396
397 xml::Element* overlay_el = manifest_el->FindChild({}, "overlay");
398 ASSERT_THAT(overlay_el, NotNull());
399
400 xml::Attribute* attr = overlay_el->FindAttribute(xml::kSchemaAndroid, "category");
401 ASSERT_THAT(attr, NotNull());
402 EXPECT_THAT(attr->value, StrEq("category"));
403 }
404
405 TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
406 ManifestFixerOptions options;
407 options.version_name_default = std::string("Beta");
408 options.version_code_default = std::string("0x10000000");
409 options.version_code_major_default = std::string("0x20000000");
410
411 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
412 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
413 package="android" />)EOF",
414 options);
415 ASSERT_THAT(doc, NotNull());
416
417 xml::Element* manifest_el = doc->root.get();
418 ASSERT_THAT(manifest_el, NotNull());
419
420 xml::Attribute* attr =
421 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
422 ASSERT_THAT(attr, NotNull());
423 EXPECT_THAT(attr->value, StrEq("Beta"));
424
425 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
426 ASSERT_THAT(attr, NotNull());
427 EXPECT_THAT(attr->value, StrEq("0x10000000"));
428
429 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
430 ASSERT_THAT(attr, NotNull());
431 EXPECT_THAT(attr->value, StrEq("0x20000000"));
432 }
433
434 TEST_F(ManifestFixerTest, DontUseDefaultVersionNameAndCode) {
435 ManifestFixerOptions options;
436 options.version_name_default = std::string("Beta");
437 options.version_code_default = std::string("0x10000000");
438 options.version_code_major_default = std::string("0x20000000");
439
440 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
441 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
442 package="android"
443 android:versionCode="0x00000001"
444 android:versionCodeMajor="0x00000002"
445 android:versionName="Alpha" />)EOF",
446 options);
447 ASSERT_THAT(doc, NotNull());
448
449 xml::Element* manifest_el = doc->root.get();
450 ASSERT_THAT(manifest_el, NotNull());
451
452 xml::Attribute* attr =
453 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
454 ASSERT_THAT(attr, NotNull());
455 EXPECT_THAT(attr->value, StrEq("Alpha"));
456
457 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
458 ASSERT_THAT(attr, NotNull());
459 EXPECT_THAT(attr->value, StrEq("0x00000001"));
460
461 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
462 ASSERT_THAT(attr, NotNull());
463 EXPECT_THAT(attr->value, StrEq("0x00000002"));
464 }
465
466 TEST_F(ManifestFixerTest, ReplaceVersionNameAndCode) {
467 ManifestFixerOptions options;
468 options.replace_version = true;
469 options.version_name_default = std::string("Beta");
470 options.version_code_default = std::string("0x10000000");
471 options.version_code_major_default = std::string("0x20000000");
472
473 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
474 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
475 package="android"
476 android:versionCode="0x00000001"
477 android:versionCodeMajor="0x00000002"
478 android:versionName="Alpha" />)EOF",
479 options);
480 ASSERT_THAT(doc, NotNull());
481
482 xml::Element* manifest_el = doc->root.get();
483 ASSERT_THAT(manifest_el, NotNull());
484
485 xml::Attribute* attr =
486 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
487 ASSERT_THAT(attr, NotNull());
488 EXPECT_THAT(attr->value, StrEq("Beta"));
489
490 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
491 ASSERT_THAT(attr, NotNull());
492 EXPECT_THAT(attr->value, StrEq("0x10000000"));
493
494 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
495 ASSERT_THAT(attr, NotNull());
496 EXPECT_THAT(attr->value, StrEq("0x20000000"));
497 }
498
499 TEST_F(ManifestFixerTest, UseDefaultRevisionCode) {
500 ManifestFixerOptions options;
501 options.revision_code_default = std::string("0x10000000");
502
503 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
504 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
505 package="android"
506 android:versionCode="0x00000001" />)EOF",
507 options);
508 ASSERT_THAT(doc, NotNull());
509
510 xml::Element* manifest_el = doc->root.get();
511 ASSERT_THAT(manifest_el, NotNull());
512
513 xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
514 ASSERT_THAT(attr, NotNull());
515 EXPECT_THAT(attr->value, StrEq("0x10000000"));
516 }
517
518 TEST_F(ManifestFixerTest, DontUseDefaultRevisionCode) {
519 ManifestFixerOptions options;
520 options.revision_code_default = std::string("0x10000000");
521
522 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
523 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
524 package="android"
525 android:versionCode="0x00000001"
526 android:revisionCode="0x00000002" />)EOF",
527 options);
528 ASSERT_THAT(doc, NotNull());
529
530 xml::Element* manifest_el = doc->root.get();
531 ASSERT_THAT(manifest_el, NotNull());
532
533 xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
534 ASSERT_THAT(attr, NotNull());
535 EXPECT_THAT(attr->value, StrEq("0x00000002"));
536 }
537
538 TEST_F(ManifestFixerTest, ReplaceRevisionCode) {
539 ManifestFixerOptions options;
540 options.replace_version = true;
541 options.revision_code_default = std::string("0x10000000");
542
543 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
544 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
545 package="android"
546 android:versionCode="0x00000001"
547 android:revisionCode="0x00000002" />)EOF",
548 options);
549 ASSERT_THAT(doc, NotNull());
550
551 xml::Element* manifest_el = doc->root.get();
552 ASSERT_THAT(manifest_el, NotNull());
553
554 xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
555 ASSERT_THAT(attr, NotNull());
556 EXPECT_THAT(attr->value, StrEq("0x10000000"));
557 }
558
559 TEST_F(ManifestFixerTest, ReplaceVersionName) {
560 ManifestFixerOptions options;
561 options.replace_version = true;
562 options.version_name_default = std::string("Beta");
563
564
565 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
566 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
567 package="android"
568 android:versionCode="0x00000001"
569 android:versionCodeMajor="0x00000002"
570 android:versionName="Alpha" />)EOF",
571 options);
572 ASSERT_THAT(doc, NotNull());
573
574 xml::Element* manifest_el = doc->root.get();
575 ASSERT_THAT(manifest_el, NotNull());
576
577 xml::Attribute* attr =
578 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
579 ASSERT_THAT(attr, NotNull());
580 EXPECT_THAT(attr->value, StrEq("Beta"));
581
582 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
583 ASSERT_THAT(attr, NotNull());
584 EXPECT_THAT(attr->value, StrEq("0x00000001"));
585
586 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
587 ASSERT_THAT(attr, NotNull());
588 EXPECT_THAT(attr->value, StrEq("0x00000002"));
589 }
590
591 TEST_F(ManifestFixerTest, ReplaceVersionCode) {
592 ManifestFixerOptions options;
593 options.replace_version = true;
594 options.version_code_default = std::string("0x10000000");
595
596 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
597 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
598 package="android"
599 android:versionCode="0x00000001"
600 android:versionCodeMajor="0x00000002"
601 android:versionName="Alpha" />)EOF",
602 options);
603 ASSERT_THAT(doc, NotNull());
604
605 xml::Element* manifest_el = doc->root.get();
606 ASSERT_THAT(manifest_el, NotNull());
607
608 xml::Attribute* attr =
609 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
610 ASSERT_THAT(attr, NotNull());
611 EXPECT_THAT(attr->value, StrEq("Alpha"));
612
613 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
614 ASSERT_THAT(attr, NotNull());
615 EXPECT_THAT(attr->value, StrEq("0x10000000"));
616
617 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
618 ASSERT_THAT(attr, NotNull());
619 EXPECT_THAT(attr->value, StrEq("0x00000002"));
620 }
621
622 TEST_F(ManifestFixerTest, ReplaceVersionCodeMajor) {
623 ManifestFixerOptions options;
624 options.replace_version = true;
625 options.version_code_major_default = std::string("0x20000000");
626
627 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
628 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
629 package="android"
630 android:versionCode="0x00000001"
631 android:versionCodeMajor="0x00000002"
632 android:versionName="Alpha" />)EOF",
633 options);
634 ASSERT_THAT(doc, NotNull());
635
636 xml::Element* manifest_el = doc->root.get();
637 ASSERT_THAT(manifest_el, NotNull());
638
639 xml::Attribute* attr =
640 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
641 ASSERT_THAT(attr, NotNull());
642 EXPECT_THAT(attr->value, StrEq("Alpha"));
643
644 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
645 ASSERT_THAT(attr, NotNull());
646 EXPECT_THAT(attr->value, StrEq("0x00000001"));
647
648 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
649 ASSERT_THAT(attr, NotNull());
650 EXPECT_THAT(attr->value, StrEq("0x20000000"));
651 }
652
653 TEST_F(ManifestFixerTest, DontReplaceVersionNameOrCode) {
654 ManifestFixerOptions options;
655 options.replace_version = true;
656
657 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
658 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
659 package="android"
660 android:versionCode="0x00000001"
661 android:versionCodeMajor="0x00000002"
662 android:versionName="Alpha" />)EOF",
663 options);
664 ASSERT_THAT(doc, NotNull());
665
666 xml::Element* manifest_el = doc->root.get();
667 ASSERT_THAT(manifest_el, NotNull());
668
669 xml::Attribute* attr =
670 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
671 ASSERT_THAT(attr, NotNull());
672 EXPECT_THAT(attr->value, StrEq("Alpha"));
673
674 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
675 ASSERT_THAT(attr, NotNull());
676 EXPECT_THAT(attr->value, StrEq("0x00000001"));
677
678 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
679 ASSERT_THAT(attr, NotNull());
680 EXPECT_THAT(attr->value, StrEq("0x00000002"));
681 }
682
683 TEST_F(ManifestFixerTest, MarkNonUpdatableSystem) {
684 ManifestFixerOptions options;
685 options.non_updatable_system = true;
686
687 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
688 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
689 package="android" />)EOF",
690 options);
691 ASSERT_THAT(doc, NotNull());
692
693 xml::Element* manifest_el = doc->root.get();
694 ASSERT_THAT(manifest_el, NotNull());
695
696 xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
697 ASSERT_THAT(attr, NotNull());
698 EXPECT_THAT(attr->value, StrEq("false"));
699 }
700
701 TEST_F(ManifestFixerTest, MarkNonUpdatableSystemOverwritingValue) {
702 ManifestFixerOptions options;
703 options.non_updatable_system = true;
704
705 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
706 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
707 package="android"
708 updatableSystem="true" />)EOF",
709 options);
710 ASSERT_THAT(doc, NotNull());
711
712 xml::Element* manifest_el = doc->root.get();
713 ASSERT_THAT(manifest_el, NotNull());
714
715 xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
716 ASSERT_THAT(attr, NotNull());
717 EXPECT_THAT(attr->value, StrEq("false"));
718 }
719
720 TEST_F(ManifestFixerTest, DontMarkNonUpdatableSystemWhenExplicitVersion) {
721 ManifestFixerOptions options;
722 options.non_updatable_system = true;
723
724 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
725 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
726 package="android"
727 android:versionCode="0x00000001" />)EOF",
728 options);
729 ASSERT_THAT(doc, NotNull());
730
731 xml::Element* manifest_el = doc->root.get();
732 ASSERT_THAT(manifest_el, NotNull());
733
734 xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
735 ASSERT_THAT(attr, IsNull());
736 }
737
738 TEST_F(ManifestFixerTest, DontMarkNonUpdatableSystemWhenAddedVersion) {
739 ManifestFixerOptions options;
740 options.non_updatable_system = true;
741 options.version_code_default = std::string("0x10000000");
742
743 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
744 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
745 package="android" />)EOF",
746 options);
747 ASSERT_THAT(doc, NotNull());
748
749 xml::Element* manifest_el = doc->root.get();
750 ASSERT_THAT(manifest_el, NotNull());
751
752 xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
753 ASSERT_THAT(attr, IsNull());
754
755 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
756 ASSERT_THAT(attr, NotNull());
757 EXPECT_THAT(attr->value, StrEq("0x10000000"));
758 }
759
760 TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
761 EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"hello\" />"), IsNull());
762 EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"1dp\" />"), IsNull());
763
764 std::unique_ptr<xml::XmlResource> doc =
765 Verify("<manifest package=\"android\" coreApp=\"true\" />");
766 ASSERT_THAT(doc, NotNull());
767
768 xml::Element* el = doc->root.get();
769 ASSERT_THAT(el, NotNull());
770
771 EXPECT_THAT(el->name, StrEq("manifest"));
772
773 xml::Attribute* attr = el->FindAttribute("", "coreApp");
774 ASSERT_THAT(attr, NotNull());
775
776 EXPECT_THAT(attr->compiled_value, NotNull());
777 EXPECT_THAT(ValueCast<BinaryPrimitive>(attr->compiled_value.get()), NotNull());
778 }
779
TEST_F(ManifestFixerTest,UsesFeatureMustHaveNameOrGlEsVersion)780 TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
781 std::string input = R"EOF(
782 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
783 package="android">
784 <uses-feature android:name="feature" />
785 <uses-feature android:glEsVersion="1" />
786 <feature-group />
787 <feature-group>
788 <uses-feature android:name="feature_in_group" />
789 <uses-feature android:glEsVersion="2" />
790 </feature-group>
791 </manifest>)EOF";
792 EXPECT_THAT(Verify(input), NotNull());
793
794 input = R"EOF(
795 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
796 package="android">
797 <uses-feature android:name="feature" android:glEsVersion="1" />
798 </manifest>)EOF";
799 EXPECT_THAT(Verify(input), IsNull());
800
801 input = R"EOF(
802 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
803 package="android">
804 <uses-feature />
805 </manifest>)EOF";
806 EXPECT_THAT(Verify(input), IsNull());
807
808 input = R"EOF(
809 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
810 package="android">
811 <feature-group>
812 <uses-feature android:name="feature" android:glEsVersion="1" />
813 </feature-group>
814 </manifest>)EOF";
815 EXPECT_THAT(Verify(input), IsNull());
816
817 input = R"EOF(
818 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
819 package="android">
820 <feature-group>
821 <uses-feature />
822 </feature-group>
823 </manifest>)EOF";
824 EXPECT_THAT(Verify(input), IsNull());
825 }
826
827 TEST_F(ManifestFixerTest, ApplicationInjectDebuggable) {
828 ManifestFixerOptions options;
829 options.debug_mode = true;
830
831 std::string no_d = R"(
832 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
833 package="android">
834 <application>
835 </application>
836 </manifest>)";
837
838 std::string false_d = R"(
839 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
840 package="android">
841 <application android:debuggable="false">
842 </application>
843 </manifest>)";
844
845 std::string true_d = R"(
846 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
847 package="android">
848 <application android:debuggable="true">
849 </application>
850 </manifest>)";
851
852 // Inject the debuggable attribute when the attribute is not present and the
853 // flag is present
854 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(no_d, options);
855 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
856 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
857
858 // Set the debuggable flag to true if the attribute is false and the flag is
859 // present
860 manifest = VerifyWithOptions(false_d, options);
861 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
862 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
863
864 // Keep debuggable flag true if the attribute is true and the flag is present
865 manifest = VerifyWithOptions(true_d, options);
866 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
867 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
868
869 // Do not inject the debuggable attribute when the attribute is not present
870 // and the flag is not present
871 manifest = Verify(no_d);
872 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
873 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
874
875 // Do not set the debuggable flag to true if the attribute is false and the
876 // flag is not present
877 manifest = Verify(false_d);
878 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
879 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
880
881 // Keep debuggable flag true if the attribute is true and the flag is not
882 // present
883 manifest = Verify(true_d);
884 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
885 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
886 }
887
888 TEST_F(ManifestFixerTest, ApplicationProfileable) {
889 std::string shell = R"(
890 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
891 package="android">
892 <application>
893 <profileable android:shell="true"/>
894 </application>
895 </manifest>)";
896 EXPECT_THAT(Verify(shell), NotNull());
897 std::string noshell = R"(
898 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
899 package="android">
900 <application>
901 <profileable/>
902 </application>
903 </manifest>)";
904 EXPECT_THAT(Verify(noshell), NotNull());
905 }
906
907 TEST_F(ManifestFixerTest, IgnoreNamespacedElements) {
908 std::string input = R"EOF(
909 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
910 package="android">
911 <special:tag whoo="true" xmlns:special="http://google.com" />
912 </manifest>)EOF";
913 EXPECT_THAT(Verify(input), NotNull());
914 }
915
916 TEST_F(ManifestFixerTest, DoNotIgnoreNonNamespacedElements) {
917 std::string input = R"EOF(
918 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
919 package="android">
920 <tag whoo="true" />
921 </manifest>)EOF";
922 EXPECT_THAT(Verify(input), IsNull());
923 }
924
925 TEST_F(ManifestFixerTest, SupportKeySets) {
926 std::string input = R"(
927 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
928 package="android">
929 <key-sets>
930 <key-set android:name="old-set">
931 <public-key android:name="old-key" android:value="some+old+key" />
932 </key-set>
933 <key-set android:name="new-set">
934 <public-key android:name="new-key" android:value="some+new+key" />
935 </key-set>
936 <upgrade-key-set android:name="old-set" />
937 <upgrade-key-set android:name="new-set" />
938 </key-sets>
939 </manifest>)";
940 EXPECT_THAT(Verify(input), NotNull());
941 }
942
943 TEST_F(ManifestFixerTest, InsertCompileSdkVersions) {
944 std::string input = R"(<manifest package="com.pkg" />)";
945 ManifestFixerOptions options;
946 options.compile_sdk_version = {"28"};
947 options.compile_sdk_version_codename = {"P"};
948
949 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
950 ASSERT_THAT(manifest, NotNull());
951
952 // There should be a declaration of kSchemaAndroid, even when the input
953 // didn't have one.
954 EXPECT_EQ(manifest->root->namespace_decls.size(), 1);
955 EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
956 EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid);
957
958 xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
959 ASSERT_THAT(attr, NotNull());
960 EXPECT_THAT(attr->value, StrEq("28"));
961
962 attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
963 ASSERT_THAT(attr, NotNull());
964 EXPECT_THAT(attr->value, StrEq("P"));
965
966 attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
967 ASSERT_THAT(attr, NotNull());
968 EXPECT_THAT(attr->value, StrEq("28"));
969
970 attr = manifest->root->FindAttribute("", "platformBuildVersionName");
971 ASSERT_THAT(attr, NotNull());
972 EXPECT_THAT(attr->value, StrEq("P"));
973 }
974
975 TEST_F(ManifestFixerTest, DoNotInsertCompileSdkVersions) {
976 std::string input = R"(<manifest package="com.pkg" />)";
977 ManifestFixerOptions options;
978 options.no_compile_sdk_metadata = true;
979 options.compile_sdk_version = {"28"};
980 options.compile_sdk_version_codename = {"P"};
981
982 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
983 ASSERT_THAT(manifest, NotNull());
984
985 // There should be a declaration of kSchemaAndroid, even when the input
986 // didn't have one.
987 EXPECT_EQ(manifest->root->namespace_decls.size(), 1);
988 EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
989 EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid);
990
991 xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
992 ASSERT_THAT(attr, IsNull());
993
994 attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
995 ASSERT_THAT(attr, IsNull());
996
997 attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
998 ASSERT_THAT(attr, IsNull());
999
1000 attr = manifest->root->FindAttribute("", "platformBuildVersionName");
1001 ASSERT_THAT(attr, IsNull());
1002 }
1003
1004 TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) {
1005 std::string input = R"(
1006 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
1007 compileSdkVersion="27" compileSdkVersionCodename="O"
1008 platformBuildVersionCode="27" platformBuildVersionName="O"/>)";
1009 ManifestFixerOptions options;
1010 options.compile_sdk_version = {"28"};
1011 options.compile_sdk_version_codename = {"P"};
1012
1013 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1014 ASSERT_THAT(manifest, NotNull());
1015
1016 xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
1017 ASSERT_THAT(attr, NotNull());
1018 EXPECT_THAT(attr->value, StrEq("28"));
1019
1020 attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
1021 ASSERT_THAT(attr, NotNull());
1022 EXPECT_THAT(attr->value, StrEq("P"));
1023
1024 attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
1025 ASSERT_THAT(attr, NotNull());
1026 EXPECT_THAT(attr->value, StrEq("28"));
1027
1028 attr = manifest->root->FindAttribute("", "platformBuildVersionName");
1029 ASSERT_THAT(attr, NotNull());
1030 EXPECT_THAT(attr->value, StrEq("P"));
1031 }
1032
1033 TEST_F(ManifestFixerTest, AndroidPrefixAlreadyUsed) {
1034 std::string input =
1035 R"(<manifest package="com.pkg"
1036 xmlns:android="http://schemas.android.com/apk/prv/res/android"
1037 android:private_attr="foo" />)";
1038 ManifestFixerOptions options;
1039 options.compile_sdk_version = {"28"};
1040 options.compile_sdk_version_codename = {"P"};
1041
1042 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1043 ASSERT_THAT(manifest, NotNull());
1044
1045 // Make sure that we don't redefine "android".
1046 EXPECT_EQ(manifest->root->namespace_decls.size(), 2);
1047 EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
1048 EXPECT_EQ(manifest->root->namespace_decls[0].uri,
1049 "http://schemas.android.com/apk/prv/res/android");
1050 EXPECT_EQ(manifest->root->namespace_decls[1].prefix, "android0");
1051 EXPECT_EQ(manifest->root->namespace_decls[1].uri, xml::kSchemaAndroid);
1052 }
1053
TEST_F(ManifestFixerTest,UnexpectedElementsInManifest)1054 TEST_F(ManifestFixerTest, UnexpectedElementsInManifest) {
1055 std::string input = R"(
1056 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1057 package="android">
1058 <beep/>
1059 </manifest>)";
1060 ManifestFixerOptions options;
1061 options.warn_validation = true;
1062
1063 // Unexpected element should result in a warning if the flag is set to 'true'.
1064 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1065 ASSERT_THAT(manifest, NotNull());
1066
1067 // Unexpected element should result in an error if the flag is set to 'false'.
1068 options.warn_validation = false;
1069 manifest = VerifyWithOptions(input, options);
1070 ASSERT_THAT(manifest, IsNull());
1071
1072 // By default the flag should be set to 'false'.
1073 manifest = Verify(input);
1074 ASSERT_THAT(manifest, IsNull());
1075 }
1076
1077 TEST_F(ManifestFixerTest, InsertFingerprintPrefixIfNotExist) {
1078 std::string input = R"(
1079 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1080 package="android">
1081 </manifest>)";
1082 ManifestFixerOptions options;
1083 options.fingerprint_prefixes = {"foo", "bar"};
1084
1085 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1086 ASSERT_THAT(manifest, NotNull());
1087 xml::Element* install_constraints = manifest->root.get()->FindChild({}, "install-constraints");
1088 ASSERT_THAT(install_constraints, NotNull());
1089 std::vector<xml::Element*> fingerprint_prefixes = install_constraints->GetChildElements();
1090 EXPECT_EQ(fingerprint_prefixes.size(), 2);
1091 xml::Attribute* attr;
1092 EXPECT_THAT(fingerprint_prefixes[0]->name, StrEq("fingerprint-prefix"));
1093 attr = fingerprint_prefixes[0]->FindAttribute(xml::kSchemaAndroid, "value");
1094 ASSERT_THAT(attr, NotNull());
1095 EXPECT_THAT(attr->value, StrEq("foo"));
1096 EXPECT_THAT(fingerprint_prefixes[1]->name, StrEq("fingerprint-prefix"));
1097 attr = fingerprint_prefixes[1]->FindAttribute(xml::kSchemaAndroid, "value");
1098 ASSERT_THAT(attr, NotNull());
1099 EXPECT_THAT(attr->value, StrEq("bar"));
1100 }
1101
1102 TEST_F(ManifestFixerTest, AppendFingerprintPrefixIfExists) {
1103 std::string input = R"(
1104 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1105 package="android">
1106 <install-constraints>
1107 <fingerprint-prefix android:value="foo" />
1108 </install-constraints>
1109 </manifest>)";
1110 ManifestFixerOptions options;
1111 options.fingerprint_prefixes = {"bar", "baz"};
1112
1113 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1114 ASSERT_THAT(manifest, NotNull());
1115 xml::Element* install_constraints = manifest->root.get()->FindChild({}, "install-constraints");
1116 ASSERT_THAT(install_constraints, NotNull());
1117 std::vector<xml::Element*> fingerprint_prefixes = install_constraints->GetChildElements();
1118 EXPECT_EQ(fingerprint_prefixes.size(), 3);
1119 xml::Attribute* attr;
1120 EXPECT_THAT(fingerprint_prefixes[0]->name, StrEq("fingerprint-prefix"));
1121 attr = fingerprint_prefixes[0]->FindAttribute(xml::kSchemaAndroid, "value");
1122 ASSERT_THAT(attr, NotNull());
1123 EXPECT_THAT(attr->value, StrEq("foo"));
1124 EXPECT_THAT(fingerprint_prefixes[1]->name, StrEq("fingerprint-prefix"));
1125 attr = fingerprint_prefixes[1]->FindAttribute(xml::kSchemaAndroid, "value");
1126 ASSERT_THAT(attr, NotNull());
1127 EXPECT_THAT(attr->value, StrEq("bar"));
1128 EXPECT_THAT(fingerprint_prefixes[2]->name, StrEq("fingerprint-prefix"));
1129 attr = fingerprint_prefixes[2]->FindAttribute(xml::kSchemaAndroid, "value");
1130 ASSERT_THAT(attr, NotNull());
1131 EXPECT_THAT(attr->value, StrEq("baz"));
1132 }
1133
1134 TEST_F(ManifestFixerTest, UsesLibraryMustHaveNonEmptyName) {
1135 std::string input = R"(
1136 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1137 package="android">
1138 <application>
1139 <uses-library android:name="" />
1140 </application>
1141 </manifest>)";
1142 EXPECT_THAT(Verify(input), IsNull());
1143
1144 input = R"(
1145 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1146 package="android">
1147 <application>
1148 <uses-library />
1149 </application>
1150 </manifest>)";
1151 EXPECT_THAT(Verify(input), IsNull());
1152
1153 input = R"(
1154 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1155 package="android">
1156 <application>
1157 <uses-library android:name="blahhh" />
1158 </application>
1159 </manifest>)";
1160 EXPECT_THAT(Verify(input), NotNull());
1161 }
1162
1163 TEST_F(ManifestFixerTest, ApplicationPropertyAttributeRequired) {
1164 std::string input = R"(
1165 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1166 package="android">
1167 <application>
1168 <property android:name="" />
1169 </application>
1170 </manifest>)";
1171 EXPECT_THAT(Verify(input), IsNull());
1172 }
1173
1174 TEST_F(ManifestFixerTest, ApplicationPropertyOnlyOneAttributeDefined) {
1175 std::string input = R"(
1176 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1177 package="android">
1178 <application>
1179 <property android:name="" android:value="" android:resource="" />
1180 </application>
1181 </manifest>)";
1182 EXPECT_THAT(Verify(input), IsNull());
1183
1184 input = R"(
1185 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1186 package="android">
1187 <application>
1188 <property android:name="" android:resource="" />
1189 </application>
1190 </manifest>)";
1191 EXPECT_THAT(Verify(input), NotNull());
1192
1193 input = R"(
1194 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1195 package="android">
1196 <application>
1197 <property android:name="" android:value="" />
1198 </application>
1199 </manifest>)";
1200 EXPECT_THAT(Verify(input), NotNull());
1201 }
1202
1203 TEST_F(ManifestFixerTest, ComponentPropertyOnlyOneAttributeDefined) {
1204 std::string input = R"(
1205 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1206 package="android">
1207 <application>
1208 <activity android:name=".MyActivity">
1209 <property android:name="" android:value="" android:resource="" />
1210 </activity>
1211 </application>
1212 </manifest>)";
1213 EXPECT_THAT(Verify(input), IsNull());
1214
1215 input = R"(
1216 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1217 package="android">
1218 <application>
1219 <activity android:name=".MyActivity">
1220 <property android:name="" android:value="" />
1221 </activity>
1222 </application>
1223 </manifest>)";
1224 EXPECT_THAT(Verify(input), NotNull());
1225
1226 input = R"(
1227 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1228 package="android">
1229 <application>
1230 <activity android:name=".MyActivity">
1231 <property android:name="" android:resource="" />
1232 </activity>
1233 </application>
1234 </manifest>)";
1235 EXPECT_THAT(Verify(input), NotNull());
1236 }
1237
1238 TEST_F(ManifestFixerTest, IntentFilterActionMustHaveNonEmptyName) {
1239 std::string input = R"(
1240 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1241 package="android">
1242 <application>
1243 <activity android:name=".MainActivity">
1244 <intent-filter>
1245 <action android:name="" />
1246 </intent-filter>
1247 </activity>
1248 </application>
1249 </manifest>)";
1250 EXPECT_THAT(Verify(input), IsNull());
1251
1252 input = R"(
1253 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1254 package="android">
1255 <application>
1256 <activity android:name=".MainActivity">
1257 <intent-filter>
1258 <action />
1259 </intent-filter>
1260 </activity>
1261 </application>
1262 </manifest>)";
1263 EXPECT_THAT(Verify(input), IsNull());
1264
1265 input = R"(
1266 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1267 package="android">
1268 <application>
1269 <activity android:name=".MainActivity">
1270 <intent-filter>
1271 <action android:name="android.intent.action.MAIN" />
1272 </intent-filter>
1273 </activity>
1274 </application>
1275 </manifest>)";
1276 EXPECT_THAT(Verify(input), NotNull());
1277 }
1278
1279 TEST_F(ManifestFixerTest, IntentFilterCategoryMustHaveNonEmptyName) {
1280 std::string input = R"(
1281 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1282 package="android">
1283 <application>
1284 <activity android:name=".MainActivity">
1285 <intent-filter>
1286 <category android:name="" />
1287 </intent-filter>
1288 </activity>
1289 </application>
1290 </manifest>)";
1291 EXPECT_THAT(Verify(input), IsNull());
1292
1293 input = R"(
1294 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1295 package="android">
1296 <application>
1297 <activity android:name=".MainActivity">
1298 <intent-filter>
1299 <category />
1300 </intent-filter>
1301 </activity>
1302 </application>
1303 </manifest>)";
1304 EXPECT_THAT(Verify(input), IsNull());
1305
1306 input = R"(
1307 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1308 package="android">
1309 <application>
1310 <activity android:name=".MainActivity">
1311 <intent-filter>
1312 <category android:name="android.intent.category.LAUNCHER" />
1313 </intent-filter>
1314 </activity>
1315 </application>
1316 </manifest>)";
1317 EXPECT_THAT(Verify(input), NotNull());
1318 }
1319
1320 TEST_F(ManifestFixerTest, IntentFilterPathMustStartWithLeadingSlashOnDeepLinks) {
1321 // No DeepLink.
1322 std::string input = R"(
1323 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1324 package="android">
1325 <application>
1326 <activity android:name=".MainActivity">
1327 <intent-filter>
1328 <data />
1329 </intent-filter>
1330 </activity>
1331 </application>
1332 </manifest>)";
1333 EXPECT_THAT(Verify(input), NotNull());
1334
1335 // No DeepLink, missing ACTION_VIEW.
1336 input = R"(
1337 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1338 package="android">
1339 <application>
1340 <activity android:name=".MainActivity">
1341 <intent-filter>
1342 <category android:name="android.intent.category.DEFAULT" />
1343 <category android:name="android.intent.category.BROWSABLE" />
1344 <data android:scheme="http"
1345 android:host="www.example.com"
1346 android:pathPrefix="pathPattern" />
1347 </intent-filter>
1348 </activity>
1349 </application>
1350 </manifest>)";
1351 EXPECT_THAT(Verify(input), NotNull());
1352
1353 // DeepLink, missing DEFAULT category while DEFAULT is recommended but not required.
1354 input = R"(
1355 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1356 package="android">
1357 <application>
1358 <activity android:name=".MainActivity">
1359 <intent-filter>
1360 <action android:name="android.intent.action.VIEW" />
1361 <category android:name="android.intent.category.BROWSABLE" />
1362 <data android:scheme="http"
1363 android:host="www.example.com"
1364 android:pathPrefix="pathPattern" />
1365 </intent-filter>
1366 </activity>
1367 </application>
1368 </manifest>)";
1369 EXPECT_THAT(Verify(input), IsNull());
1370
1371 // No DeepLink, missing BROWSABLE category.
1372 input = R"(
1373 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1374 package="android">
1375 <application>
1376 <activity android:name=".MainActivity">
1377 <intent-filter>
1378 <action android:name="android.intent.action.VIEW" />
1379 <category android:name="android.intent.category.DEFAULT" />
1380 <data android:scheme="http"
1381 android:host="www.example.com"
1382 android:pathPrefix="pathPattern" />
1383 </intent-filter>
1384 </activity>
1385 </application>
1386 </manifest>)";
1387 EXPECT_THAT(Verify(input), NotNull());
1388
1389 // No DeepLink, missing 'android:scheme' in <data> tag.
1390 input = R"(
1391 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1392 package="android">
1393 <application>
1394 <activity android:name=".MainActivity">
1395 <intent-filter>
1396 <action android:name="android.intent.action.VIEW" />
1397 <category android:name="android.intent.category.DEFAULT" />
1398 <category android:name="android.intent.category.BROWSABLE" />
1399 <data android:host="www.example.com"
1400 android:pathPrefix="pathPattern" />
1401 </intent-filter>
1402 </activity>
1403 </application>
1404 </manifest>)";
1405 EXPECT_THAT(Verify(input), NotNull());
1406
1407 // No DeepLink, <action> is ACTION_MAIN not ACTION_VIEW.
1408 input = R"(
1409 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1410 package="android">
1411 <application>
1412 <activity android:name=".MainActivity">
1413 <intent-filter>
1414 <action android:name="android.intent.action.MAIN" />
1415 <category android:name="android.intent.category.DEFAULT" />
1416 <category android:name="android.intent.category.BROWSABLE" />
1417 <data android:scheme="http"
1418 android:host="www.example.com"
1419 android:pathPrefix="pathPattern" />
1420 </intent-filter>
1421 </activity>
1422 </application>
1423 </manifest>)";
1424 EXPECT_THAT(Verify(input), NotNull());
1425
1426 // DeepLink with no leading slash in android:path.
1427 input = R"(
1428 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1429 package="android">
1430 <application>
1431 <activity android:name=".MainActivity">
1432 <intent-filter>
1433 <action android:name="android.intent.action.VIEW" />
1434 <category android:name="android.intent.category.DEFAULT" />
1435 <category android:name="android.intent.category.BROWSABLE" />
1436 <data android:scheme="http"
1437 android:host="www.example.com"
1438 android:path="path" />
1439 </intent-filter>
1440 </activity>
1441 </application>
1442 </manifest>)";
1443 EXPECT_THAT(Verify(input), IsNull());
1444
1445 // DeepLink with leading slash in android:path.
1446 input = R"(
1447 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1448 package="android">
1449 <application>
1450 <activity android:name=".MainActivity">
1451 <intent-filter>
1452 <action android:name="android.intent.action.VIEW" />
1453 <category android:name="android.intent.category.DEFAULT" />
1454 <category android:name="android.intent.category.BROWSABLE" />
1455 <data android:scheme="http"
1456 android:host="www.example.com"
1457 android:path="/path" />
1458 </intent-filter>
1459 </activity>
1460 </application>
1461 </manifest>)";
1462 EXPECT_THAT(Verify(input), NotNull());
1463
1464 // DeepLink with no leading slash in android:pathPrefix.
1465 input = R"(
1466 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1467 package="android">
1468 <application>
1469 <activity android:name=".MainActivity">
1470 <intent-filter>
1471 <action android:name="android.intent.action.VIEW" />
1472 <category android:name="android.intent.category.DEFAULT" />
1473 <category android:name="android.intent.category.BROWSABLE" />
1474 <data android:scheme="http"
1475 android:host="www.example.com"
1476 android:pathPrefix="pathPrefix" />
1477 </intent-filter>
1478 </activity>
1479 </application>
1480 </manifest>)";
1481 EXPECT_THAT(Verify(input), IsNull());
1482
1483 // DeepLink with leading slash in android:pathPrefix.
1484 input = R"(
1485 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1486 package="android">
1487 <application>
1488 <activity android:name=".MainActivity">
1489 <intent-filter>
1490 <action android:name="android.intent.action.VIEW" />
1491 <category android:name="android.intent.category.DEFAULT" />
1492 <category android:name="android.intent.category.BROWSABLE" />
1493 <data android:scheme="http"
1494 android:host="www.example.com"
1495 android:pathPrefix="/pathPrefix" />
1496 </intent-filter>
1497 </activity>
1498 </application>
1499 </manifest>)";
1500 EXPECT_THAT(Verify(input), NotNull());
1501
1502 // DeepLink with no leading slash in android:pathPattern.
1503 input = R"(
1504 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1505 package="android">
1506 <application>
1507 <activity android:name=".MainActivity">
1508 <intent-filter>
1509 <action android:name="android.intent.action.VIEW" />
1510 <category android:name="android.intent.category.DEFAULT" />
1511 <category android:name="android.intent.category.BROWSABLE" />
1512 <data android:scheme="http"
1513 android:host="www.example.com"
1514 android:pathPattern="pathPattern" />
1515 </intent-filter>
1516 </activity>
1517 </application>
1518 </manifest>)";
1519 EXPECT_THAT(Verify(input), IsNull());
1520
1521 // DeepLink with leading slash in android:pathPattern.
1522 input = R"(
1523 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1524 package="android">
1525 <application>
1526 <activity android:name=".MainActivity">
1527 <intent-filter>
1528 <action android:name="android.intent.action.VIEW" />
1529 <category android:name="android.intent.category.DEFAULT" />
1530 <category android:name="android.intent.category.BROWSABLE" />
1531 <data android:scheme="http"
1532 android:host="www.example.com"
1533 android:pathPattern="/pathPattern" />
1534 </intent-filter>
1535 </activity>
1536 </application>
1537 </manifest>)";
1538 EXPECT_THAT(Verify(input), NotNull());
1539
1540 // DeepLink with '.' start in pathPattern.
1541 input = R"(
1542 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1543 package="android">
1544 <application>
1545 <activity android:name=".MainActivity">
1546 <intent-filter>
1547 <action android:name="android.intent.action.VIEW" />
1548 <category android:name="android.intent.category.DEFAULT" />
1549 <category android:name="android.intent.category.BROWSABLE" />
1550 <data android:scheme="http"
1551 android:host="www.example.com"
1552 android:pathPattern=".*\\.pathPattern" />
1553 </intent-filter>
1554 </activity>
1555 </application>
1556 </manifest>)";
1557 EXPECT_THAT(Verify(input), NotNull());
1558
1559 // DeepLink with '*' start in pathPattern.
1560 input = R"(
1561 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1562 package="android">
1563 <application>
1564 <activity android:name=".MainActivity">
1565 <intent-filter>
1566 <action android:name="android.intent.action.VIEW" />
1567 <category android:name="android.intent.category.DEFAULT" />
1568 <category android:name="android.intent.category.BROWSABLE" />
1569 <data android:scheme="http"
1570 android:host="www.example.com"
1571 android:pathPattern="*" />
1572 </intent-filter>
1573 </activity>
1574 </application>
1575 </manifest>)";
1576 EXPECT_THAT(Verify(input), NotNull());
1577
1578 // DeepLink with string reference as a path.
1579 input = R"(
1580 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1581 package="android">
1582 <application>
1583 <activity android:name=".MainActivity">
1584 <intent-filter>
1585 <action android:name="android.intent.action.VIEW" />
1586 <category android:name="android.intent.category.DEFAULT" />
1587 <category android:name="android.intent.category.BROWSABLE" />
1588 <data android:scheme="http"
1589 android:host="www.example.com"
1590 android:path="@string/startup_uri" />
1591 </intent-filter>
1592 </activity>
1593 </application>
1594 </manifest>)";
1595 EXPECT_THAT(Verify(input), NotNull());
1596 }
1597
1598 TEST_F(ManifestFixerTest, AllKnownNotDeclaredProperly) {
1599 std::string input = R"(
1600 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1601 package="android">
1602 <application>
1603 <activity android:name=".MainActivity"
1604 android:configChanges="allKnown|testConfigChange1">
1605 </activity>
1606 </application>
1607 </manifest>)";
1608 auto doc = Verify(input);
1609 EXPECT_THAT(doc, IsNull());
1610 }
1611
1612 TEST_F(ManifestFixerTest, ModifyAttributeValueForAllKnown) {
1613 std::string input = R"(
1614 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1615 package="android">
1616 <application>
1617 <activity android:name=".MainActivity"
1618 android:configChanges="allKnown">
1619 </activity>
1620 </application>
1621 </manifest>)";
1622 auto doc = Verify(input);
1623 EXPECT_THAT(doc, NotNull());
1624
1625 xml::Element* el;
1626 xml::Attribute* attr;
1627
1628 el = doc->root.get();
1629 ASSERT_THAT(el, NotNull());
1630 el = el->FindChild({}, "application");
1631 ASSERT_THAT(el, NotNull());
1632 el = el->FindChild({}, "activity");
1633 ASSERT_THAT(el, NotNull());
1634
1635 attr = el->FindAttribute(xml::kSchemaAndroid, "configChanges");
1636 ASSERT_THAT(attr->value, "testConfigChange1|testConfigChange2");
1637 }
1638
1639 TEST_F(ManifestFixerTest, DoNothingForOtherConfigChanges) {
1640 std::string input = R"(
1641 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1642 package="android">
1643 <application>
1644 <activity android:name=".MainActivity"
1645 android:configChanges="testConfigChange2">
1646 </activity>
1647 </application>
1648 </manifest>)";
1649 auto doc = Verify(input);
1650 EXPECT_THAT(doc, NotNull());
1651
1652 xml::Element* el;
1653 xml::Attribute* attr;
1654
1655 el = doc->root.get();
1656 ASSERT_THAT(el, NotNull());
1657 el = el->FindChild({}, "application");
1658 ASSERT_THAT(el, NotNull());
1659 el = el->FindChild({}, "activity");
1660 ASSERT_THAT(el, NotNull());
1661
1662 attr = el->FindAttribute(xml::kSchemaAndroid, "configChanges");
1663 ASSERT_THAT(attr->value, "testConfigChange2");
1664 }
1665 } // namespace aapt
1666