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