Add a button to chart-title to populate the test-picker.

https://dev-benjhayden-7b9c4420-dot-chromeperf.appspot.com/report?sid=ca6c52111f8337a0f6478573cd639ed39dbd8eb82d903d8c3932651f452b9fb9

http://i.imgur.com/BAFCy8r.png

BUG=catapult:#2641

Review-Url: https://codereview.chromium.org/2881193003
diff --git a/dashboard/dashboard/elements/chart-title.html b/dashboard/dashboard/elements/chart-title.html
index ea3f783..a45e325 100644
--- a/dashboard/dashboard/elements/chart-title.html
+++ b/dashboard/dashboard/elements/chart-title.html
@@ -23,8 +23,22 @@
         text-decoration: none;
         cursor: default;
       }
+      paper-button {
+        color: white;
+        font-weight: bold;
+        min-width: initial;
+        padding: 5px;
+        margin: 0;
+        background: #4285f4;
+        font-size: 18px;
+      }
+      h3 {
+        display: inline-block;
+      }
     </style>
 
+    <paper-button raised on-click="populateTestPicker_">&#8632;</paper-button>
+
     <h3>
       <template is="dom-repeat" items="{{titleParts}}">
         <a class="title disabled" href="javascript:void(0);"
@@ -97,6 +111,21 @@
         this.suiteDescriptions = this.getSuitesAndDescriptions();
       },
 
+      populateTestPicker_(event) {
+        // chart-title's testPaths have a different structure from test-picker's
+        // testPaths.
+        let testPath = [];
+        for (const part of this.titleParts) {
+          testPath.push.apply(testPath, part.split('/'));
+        }
+
+        // chart-title's testPaths are in a different order from test-picker's
+        // testPaths.
+        testPath = [testPath[2], testPath[1]].concat(testPath.slice(3));
+
+        this.fire('populateTestPicker', {testPath});
+      },
+
       onClicked(event) {
         const index = event.model.index;
         if (index == this.currentIndex) {
diff --git a/dashboard/dashboard/elements/report-page.html b/dashboard/dashboard/elements/report-page.html
index f32edfa..f9cbdce 100644
--- a/dashboard/dashboard/elements/report-page.html
+++ b/dashboard/dashboard/elements/report-page.html
@@ -41,8 +41,12 @@
   <script>
     'use strict';
     Polymer({
-
       is: 'report-page',
+
+      listeners: {
+        populateTestPicker: 'populateTestPicker_',
+      },
+
       properties: {
         charts: {
           type: Array,
@@ -121,6 +125,11 @@
         this.uriController.load();
       },
 
+      async populateTestPicker_(event) {
+        this.testPicker.scrollIntoViewIfNeeded();
+        await this.testPicker.setCurrentSelectedPath(event.detail.testPath);
+      },
+
       /**
        * On 'uriload' event, adds charts from the current query parameters.
        * @param {Object} event Event object.
diff --git a/dashboard/dashboard/elements/test-picker.html b/dashboard/dashboard/elements/test-picker.html
index 11f2751..dbcc1d6 100644
--- a/dashboard/dashboard/elements/test-picker.html
+++ b/dashboard/dashboard/elements/test-picker.html
@@ -482,6 +482,36 @@
         return this.currentSelectedPath_;
       },
 
+      async setCurrentSelectedPath(testPath) {
+        this.updatingSubtestMenus = true;
+        for (let boxIndex = 0; boxIndex < testPath.length; ++boxIndex) {
+          const menu = this.getSelectionMenu(boxIndex);
+          const name = testPath[boxIndex];
+          let found = false;
+
+          for (const menuItem of menu.items) {
+            if (menuItem.name === name) {
+              found = true;
+              menu.selectedItem = menuItem;
+              break;
+            }
+          }
+
+          if (!found) {
+            this.updatingSubtestMenus = false;
+            throw new Error(`Invalid testPath ${testPath} @ ${boxIndex}`);
+          }
+
+          if (boxIndex == 0) {
+            this.updateTestSuiteDescription();
+            await this.updateBotMenu();
+          } else {
+            await this.updateSubtestMenus(boxIndex + 1);
+          }
+        }
+        this.updatingSubtestMenus = false;
+      },
+
       getCurrentUnselected() {
         return this.currentUnselectedTests_;
       },