Improve GN templates use of "visibility" and "testonly"

Many spots using forward_variables_from(invoker, "*") were not
allowing these two variables to be set in outer scopes.

* Introduce a helper variable "EXPLICIT_FORWARDS" for use with the
recommended pattern of:
  forward_variables_from(invoker, "*", [ "testonly", "visibility" ])
  forward_variables_from(invoker, [ "testonly", "visibility" ])
* Ensures this pattern is used in android templates, test.gni,
  and BUILDCONFIG.gn
* Documents this pattern in writing_gn_templates.md
* Adds a PRESUBMIT.py for it
* Fixes visibility of a few blink targets now that test()
  respects it.

Bug: 862232
Change-Id: Ib71dbf34be76131fc749c721aea856e1146bc69a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2454427
Commit-Queue: Andrew Grieve <[email protected]>
Reviewed-by: Dirk Pranke <[email protected]>
Cr-Commit-Position: refs/heads/master@{#830678}
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py
index a9b4047..2dfa78a 100755
--- a/PRESUBMIT_test.py
+++ b/PRESUBMIT_test.py
@@ -1824,6 +1824,37 @@
     self.assertEqual(1, len(errors))
 
 
+class GnGlobForwardTest(unittest.TestCase):
+  def testAddBareGlobs(self):
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+      MockAffectedFile('base/stuff.gni', [
+          'forward_variables_from(invoker, "*")']),
+      MockAffectedFile('base/BUILD.gn', [
+          'forward_variables_from(invoker, "*")']),
+    ]
+    warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
+    self.assertEqual(1, len(warnings))
+    msg = '\n'.join(warnings[0].items)
+    self.assertIn('base/stuff.gni', msg)
+    # Should not check .gn files. Local templates don't need to care about
+    # visibility / testonly.
+    self.assertNotIn('base/BUILD.gn', msg)
+
+  def testValidUses(self):
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+      MockAffectedFile('base/stuff.gni', [
+          'forward_variables_from(invoker, "*", [])']),
+      MockAffectedFile('base/stuff2.gni', [
+          'forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)']),
+      MockAffectedFile('base/stuff3.gni', [
+          'forward_variables_from(invoker, [ "testonly" ])']),
+    ]
+    warnings = PRESUBMIT.CheckGnGlobForward(mock_input_api, MockOutputApi())
+    self.assertEqual([], warnings)
+
+
 class NewHeaderWithoutGnChangeTest(unittest.TestCase):
   def testAddHeaderWithoutGn(self):
     mock_input_api = MockInputApi()