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