diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
index 691087a..3eacfd0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -553,37 +553,26 @@
     }
 
     /**
-     * Updates notifications for a given list of downloads. Should not be called from UI thread.
+     * Updates notifications for a given list of downloads.
      * @param progresses A list of notifications to update.
-     * @return A List of failed downloads.
      */
-    private List<DownloadItem> updateAllNotifications(List<DownloadProgress> progresses) {
-        assert !ThreadUtils.runningOnUiThread();
-        List<DownloadItem> downloadItems = new ArrayList<DownloadItem>();
+    private void updateAllNotifications(List<DownloadProgress> progresses) {
+        assert ThreadUtils.runningOnUiThread();
         for (int i = 0; i < progresses.size(); ++i) {
             DownloadProgress progress = progresses.get(i);
             DownloadItem item = progress.mDownloadItem;
             DownloadInfo info = item.getDownloadInfo();
+            boolean notificationUpdateScheduled = true;
+            boolean removeFromDownloadProgressMap = true;
             switch (progress.mDownloadStatus) {
                 case DOWNLOAD_STATUS_COMPLETE:
-                    boolean success = addCompletedDownload(item);
-                    if (success) {
-                        boolean canResolve = isOMADownloadDescription(info)
-                                || canResolveDownloadItem(
-                                        mContext, item, progress.mIsSupportedMimeType);
-                        long systemDownloadId = item.getSystemDownloadId();
-                        mDownloadNotifier.notifyDownloadSuccessful(
-                                info, systemDownloadId, canResolve, progress.mIsSupportedMimeType);
-                        broadcastDownloadSuccessful(info);
-                    } else {
-                        downloadItems.add(item);
-                        mDownloadNotifier.notifyDownloadFailed(info);
-                    }
+                    notificationUpdateScheduled = updateDownloadSuccessNotification(progress);
+                    removeFromDownloadProgressMap = notificationUpdateScheduled;
                     break;
                 case DOWNLOAD_STATUS_FAILED:
-                    downloadItems.add(item);
                     mDownloadNotifier.notifyDownloadFailed(info);
                     Log.w(TAG, "Download failed: " + info.getFilePath());
+                    onDownloadFailed(info.getFileName(), DownloadManager.ERROR_UNKNOWN);
                     break;
                 case DOWNLOAD_STATUS_IN_PROGRESS:
                     if (info.isPaused()) {
@@ -592,6 +581,7 @@
                     } else {
                         mDownloadNotifier.notifyDownloadProgress(info,
                                 progress.mStartTimeInMillis, progress.mCanDownloadWhileMetered);
+                        removeFromDownloadProgressMap = false;
                     }
                     break;
                 case DOWNLOAD_STATUS_CANCELLED:
@@ -599,13 +589,61 @@
                     break;
                 case DOWNLOAD_STATUS_INTERRUPTED:
                     mDownloadNotifier.notifyDownloadInterrupted(info, progress.mIsAutoResumable);
+                    removeFromDownloadProgressMap = !progress.mIsAutoResumable;
                     break;
                 default:
                     assert false;
                     break;
             }
+            if (notificationUpdateScheduled) {
+                progress.mIsUpdated = false;
+            }
+            if (removeFromDownloadProgressMap) {
+                mDownloadProgressMap.remove(item.getId());
+            }
         }
-        return downloadItems;
+    }
+
+    /**
+     * Helper method to schedule a task to update the download success notification.
+     * @param progresses Download progress to update.
+     * @return True if the task can be scheduled, or false otherwise.
+     */
+    private boolean updateDownloadSuccessNotification(DownloadProgress progress) {
+        final boolean isSupportedMimeType = progress.mIsSupportedMimeType;
+        final DownloadItem item = progress.mDownloadItem;
+        AsyncTask<Void, Void, Pair<Long, Boolean>> task =
+                new AsyncTask<Void, Void, Pair<Long, Boolean>>() {
+            @Override
+            public Pair<Long, Boolean> doInBackground(Void... params) {
+                boolean success = addCompletedDownload(item);
+                boolean canResolve = success ? (isOMADownloadDescription(item.getDownloadInfo())
+                        || canResolveDownloadItem(mContext, item, isSupportedMimeType)) : false;
+                return Pair.create(item.getSystemDownloadId(), canResolve);
+            }
+
+            @Override
+            protected void onPostExecute(Pair<Long, Boolean> result) {
+                DownloadInfo info = item.getDownloadInfo();
+                if (result.first != DownloadItem.INVALID_DOWNLOAD_ID) {
+                    mDownloadNotifier.notifyDownloadSuccessful(
+                            info, result.first, result.second, isSupportedMimeType);
+                    broadcastDownloadSuccessful(info);
+                } else {
+                    mDownloadNotifier.notifyDownloadFailed(info);
+                    // TODO(qinmin): get the failure message from native.
+                    onDownloadFailed(info.getFileName(), DownloadManager.ERROR_UNKNOWN);
+                }
+            }
+        };
+        try {
+            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+            return true;
+        } catch (RejectedExecutionException e) {
+            // Reaching thread limit, update will be reschduled for the next run.
+            Log.e(TAG, "Thread limit reached, reschedule notification update later.");
+            return false;
+        }
     }
 
     /**
@@ -615,6 +653,7 @@
      * @return true if the download is added to the DownloadManager, or false otherwise.
      */
     protected boolean addCompletedDownload(DownloadItem downloadItem) {
+        assert !ThreadUtils.runningOnUiThread();
         DownloadInfo downloadInfo = downloadItem.getDownloadInfo();
         String description = downloadInfo.getDescription();
         if (TextUtils.isEmpty(description)) description = downloadInfo.getFileName();
@@ -658,7 +697,8 @@
     /**
      * Schedule an update if there is no update scheduled.
      */
-    private void scheduleUpdateIfNeeded() {
+    @VisibleForTesting
+    protected void scheduleUpdateIfNeeded() {
         if (mIsUIUpdateScheduled) return;
 
         mIsUIUpdateScheduled = true;
@@ -674,45 +714,7 @@
             mIsUIUpdateScheduled = false;
             return;
         }
-        // Make a copy of the |progressUpdated|, so that we can update the notification on another
-        // thread without worrying about concurrent modifications.
-        final List<DownloadProgress> progressToUpdate = new ArrayList<DownloadProgress>();
-        for (int i = 0; i < progressPendingUpdate.size(); ++i) {
-            progressToUpdate.add(new DownloadProgress(progressPendingUpdate.get(i)));
-        }
-        AsyncTask<Void, Void, List<DownloadItem>> task =
-                new AsyncTask<Void, Void, List<DownloadItem>>() {
-            @Override
-            public List<DownloadItem> doInBackground(Void... params) {
-                return updateAllNotifications(progressToUpdate);
-            }
-
-            @Override
-            protected void onPostExecute(List<DownloadItem> result) {
-                for (int i = 0; i < result.size(); ++i) {
-                    // TODO(qinmin): get the failure message from native.
-                    onDownloadFailed(result.get(i).getDownloadInfo().getFileName(),
-                            DownloadManager.ERROR_UNKNOWN);
-                }
-            }
-        };
-        try {
-            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-            for (int i = 0; i < progressPendingUpdate.size(); ++i) {
-                DownloadProgress progress = progressPendingUpdate.get(i);
-                progress.mIsUpdated = false;
-                // Remove progress entry from  mDownloadProgressMap if they are no longer needed.
-                if ((progress.mDownloadStatus != DOWNLOAD_STATUS_IN_PROGRESS
-                        || progress.mDownloadItem.getDownloadInfo().isPaused())
-                        && (progress.mDownloadStatus != DOWNLOAD_STATUS_INTERRUPTED
-                                || !progress.mIsAutoResumable)) {
-                    mDownloadProgressMap.remove(progress.mDownloadItem.getId());
-                }
-            }
-        } catch (RejectedExecutionException e) {
-            // Reaching thread limit, update will be reschduled for the next run.
-            Log.e(TAG, "reaching thread limit, reschedule notification update later.");
-        }
+        updateAllNotifications(progressPendingUpdate);
 
         Runnable scheduleNextUpdateTask = new Runnable(){
             @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java
index de1d292..5b6a2766 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java
@@ -111,7 +111,7 @@
     void handlePendingNotifications() {
         if (mPendingNotifications.isEmpty()) return;
         for (PendingNotificationInfo info : mPendingNotifications) {
-            updateDownloadNotificationOnUiThread(info);
+            updateDownloadNotification(info);
         }
         mPendingNotifications.clear();
     }
@@ -227,25 +227,12 @@
     }
 
     /**
-     * Helper method to schedule download notification updates, can be called on any thread.
+     * Helper method to schedule download notification updates.
      * @param info Pending notification information to be handled.
      */
-    private void updateDownloadNotification(final PendingNotificationInfo notificationInfo) {
-        ThreadUtils.postOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                updateDownloadNotificationOnUiThread(notificationInfo);
-            }
-        });
-    }
-
-    /**
-     * Updates the download notification on UI thread if the notification service is started.
-     * Otherwise, wait for the notification service to become ready.
-     * @param info Pending notification information to be handled.
-     */
-    private void updateDownloadNotificationOnUiThread(
-            final PendingNotificationInfo notificationInfo) {
+    @VisibleForTesting
+    void updateDownloadNotification(final PendingNotificationInfo notificationInfo) {
+        assert ThreadUtils.runningOnUiThread();
         startAndBindToServiceIfNeeded();
         final DownloadInfo info = notificationInfo.downloadInfo;
         if (notificationInfo.type == DOWNLOAD_NOTIFICATION_TYPE_PROGRESS) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java
index 1193695..bc487aa 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java
@@ -306,6 +306,16 @@
         public void resumeDownload(DownloadItem item, boolean hasUserGesture) {
             mResumed = true;
         }
+
+        @Override
+        protected void scheduleUpdateIfNeeded() {
+            ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+                @Override
+                public void run() {
+                    DownloadManagerServiceForTest.super.scheduleUpdateIfNeeded();
+                }
+            });
+        }
     }
 
     @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java
index f2a27bb..1504637 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java
@@ -46,6 +46,16 @@
                 final SystemDownloadNotifier.PendingNotificationInfo notificationInfo,
                 final int notificationId) {
         }
+
+        @Override
+        void updateDownloadNotification(final PendingNotificationInfo notificationInfo) {
+            ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+                @Override
+                public void run() {
+                    MockSystemDownloadNotifier.super.updateDownloadNotification(notificationInfo);
+                }
+            });
+        }
     }
 
     @Override
diff --git a/third_party/WebKit/LayoutTests/inspector/components/viewport-datagrid.html b/third_party/WebKit/LayoutTests/inspector/components/viewport-datagrid.html
index 29aeb990..98202d4 100644
--- a/third_party/WebKit/LayoutTests/inspector/components/viewport-datagrid.html
+++ b/third_party/WebKit/LayoutTests/inspector/components/viewport-datagrid.html
@@ -62,9 +62,7 @@
 
     var root = dataGrid.rootNode();
 
-    var dialog = new UI.Dialog();
-    dialog.show();
-    var containerElement = dialog.element;
+    var containerElement = document.body.createChild('div');
     containerElement.style.position = "absolute";
     containerElement.style.width = "300px";
     containerElement.style.height = "300px";
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index 37721b4..edda862d 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -605,6 +605,7 @@
   "front_end/ui/FilterBar.js",
   "front_end/ui/ForwardedInputEventHandler.js",
   "front_end/ui/Geometry.js",
+  "front_end/ui/glassPane.css",
   "front_end/ui/GlassPane.js",
   "front_end/ui/HistoryInput.js",
   "front_end/ui/Icon.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/dom_extension/DOMExtension.js b/third_party/WebKit/Source/devtools/front_end/dom_extension/DOMExtension.js
index e073412..dd12c01 100644
--- a/third_party/WebKit/Source/devtools/front_end/dom_extension/DOMExtension.js
+++ b/third_party/WebKit/Source/devtools/front_end/dom_extension/DOMExtension.js
@@ -758,9 +758,15 @@
  * @return {?Node}
  */
 Document.prototype.deepElementFromPoint = function(x, y) {
-  var node = this.elementFromPoint(x, y);
-  while (node && node.shadowRoot)
-    node = node.shadowRoot.elementFromPoint(x, y);
+  var container = this;
+  var node = null;
+  while (container) {
+    var innerNode = container.elementFromPoint(x, y);
+    if (!innerNode)
+      break;
+    node = innerNode;
+    container = node.shadowRoot;
+  }
   return node;
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index 22e209dc..d4d3ecb9 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -871,11 +871,11 @@
    */
   static show(reason) {
     var dialog = new UI.Dialog();
-    dialog.setWrapsContent(true);
+    dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
     dialog.addCloseButton();
     dialog.setDimmed(true);
-    new Main.RemoteDebuggingTerminatedScreen(reason).show(dialog.element);
-    dialog.show();
+    new Main.RemoteDebuggingTerminatedScreen(reason).show(dialog.contentElement);
+    dialog.showDialog();
   }
 };
 
@@ -902,14 +902,14 @@
    */
   static show(debuggerModel) {
     var dialog = new UI.Dialog();
-    dialog.setWrapsContent(true);
+    dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
     dialog.addCloseButton();
     dialog.setDimmed(true);
-    var hideBound = dialog.detach.bind(dialog, false);
+    var hideBound = dialog.hideDialog.bind(dialog);
     debuggerModel.addEventListener(SDK.DebuggerModel.Events.GlobalObjectCleared, hideBound);
 
-    new Main.TargetCrashedScreen(onHide).show(dialog.element);
-    dialog.show();
+    new Main.TargetCrashedScreen(onHide).show(dialog.contentElement);
+    dialog.showDialog();
 
     function onHide() {
       debuggerModel.removeEventListener(SDK.DebuggerModel.Events.GlobalObjectCleared, hideBound);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
index a775c8d..0f9428c 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
@@ -444,9 +444,9 @@
         customHeaders, headerTitle => !!this._addCustomHeader(headerTitle), this._changeCustomHeader.bind(this),
         this._removeCustomHeader.bind(this));
     var dialog = new UI.Dialog();
-    manageCustomHeaders.show(dialog.element);
-    dialog.setWrapsContent(true);
-    dialog.show();
+    manageCustomHeaders.show(dialog.contentElement);
+    dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
+    dialog.showDialog(this._networkLogView.element);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/FilmStripView.js b/third_party/WebKit/Source/devtools/front_end/perf_ui/FilmStripView.js
index 34d53ca..6e822193 100644
--- a/third_party/WebKit/Source/devtools/front_end/perf_ui/FilmStripView.js
+++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/FilmStripView.js
@@ -240,11 +240,10 @@
   _resize() {
     if (!this._dialog) {
       this._dialog = new UI.Dialog();
-      this.show(this._dialog.element);
-      this._dialog.setWrapsContent(true);
-      this._dialog.show();
+      this.show(this._dialog.contentElement);
+      this._dialog.showDialog();
     }
-    this._dialog.contentResized();
+    this._dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js b/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js
index bcca3fc..d9717f4f 100644
--- a/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js
@@ -118,11 +118,11 @@
 
   showAsDialog() {
     this._dialog = new UI.Dialog();
-    this._dialog.setMaxSize(new UI.Size(504, 340));
-    this._dialog.setFixedHeight(false);
-    this._dialog.setPosition(null, 22);
-    this.show(this._dialog.element);
-    this._dialog.show();
+    this._dialog.setMaxContentSize(new UI.Size(504, 340));
+    this._dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.SetMaxHeight);
+    this._dialog.setContentPosition(null, 22);
+    this.show(this._dialog.contentElement);
+    this._dialog.showDialog();
     this._updateShowMatchingItems();
   }
 
@@ -160,7 +160,7 @@
 
     // Detach dialog before allowing delegate to override focus.
     if (this._dialog)
-      this._dialog.detach();
+      this._dialog.hideDialog();
     this._selectItemWithQuery(selectedIndexInDelegate, this._value());
   }
 
@@ -191,7 +191,7 @@
       event.consume(true);
       // Detach dialog before allowing delegate to override focus.
       if (this._dialog)
-        this._dialog.detach();
+        this._dialog.hideDialog();
       this._selectItemWithQuery(item, this._value());
     }, false);
     return itemElement;
@@ -364,10 +364,12 @@
     delete this._refreshListWithCurrentResult;
     filteredItems = [].concat(bestItems, overflowItems, filteredItems);
     this._updateNotFoundMessage(!!filteredItems.length);
+    var oldHeight = this._list.element.offsetHeight;
     this._list.replaceAllItems(filteredItems);
     if (filteredItems.length)
       this._list.selectItem(filteredItems[0]);
-    this._list.viewportResized();
+    if (this._list.element.offsetHeight !== oldHeight)
+      this._list.viewportResized();
     this._itemsFilteredForTest();
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js
index 79978b43..c6f2a1a 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js
@@ -71,7 +71,7 @@
 
   _deleteDatabase() {
     UI.ConfirmDialog.show(
-        Common.UIString('Are you sure you want to delete "%s"?', this._database.databaseId.name),
+        this.element, Common.UIString('Are you sure you want to delete "%s"?', this._database.databaseId.name),
         () => this._model.deleteDatabase(this._database.databaseId));
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
index 40e4ff4..8ced0ffc0 100644
--- a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
+++ b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
@@ -71,8 +71,8 @@
       return;
     var dialog = new UI.Dialog();
     dialog.addCloseButton();
-    settingsScreen.show(dialog.element);
-    dialog.show();
+    settingsScreen.show(dialog.contentElement);
+    dialog.showDialog();
     settingsScreen._selectTab(name || 'preferences');
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/AddSourceMapURLDialog.js b/third_party/WebKit/Source/devtools/front_end/sources/AddSourceMapURLDialog.js
index 6b683ad0..47ef0408 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/AddSourceMapURLDialog.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/AddSourceMapURLDialog.js
@@ -32,15 +32,15 @@
   static show(callback) {
     var dialog = new UI.Dialog();
     var addSourceMapURLDialog = new Sources.AddSourceMapURLDialog(done);
-    addSourceMapURLDialog.show(dialog.element);
-    dialog.setWrapsContent(true);
-    dialog.show();
+    addSourceMapURLDialog.show(dialog.contentElement);
+    dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
+    dialog.showDialog();
 
     /**
      * @param {string} value
      */
     function done(value) {
-      dialog.detach();
+      dialog.hideDialog();
       callback(value);
     }
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js b/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js
index 664f820..e47c1e9 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js
@@ -28,30 +28,22 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/**
- * @unrestricted
- */
-UI.Dialog = class extends UI.Widget {
+UI.Dialog = class extends UI.GlassPane {
   constructor() {
-    super(true);
-    this.markAsRoot();
+    super();
     this.registerRequiredCSS('ui/dialog.css');
-
-    this.contentElement.createChild('content');
     this.contentElement.tabIndex = 0;
     this.contentElement.addEventListener('focus', this.focus.bind(this), false);
     this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this), false);
-    this._dimmed = false;
-    this._wrapsContent = false;
-    this._maxSize = null;
-    /** @type {?number} */
-    this._positionX = null;
-    /** @type {?number} */
-    this._positionY = null;
-    this._fixedHeight = true;
-
+    this.setBlockPointerEvents(true);
+    this.setSetOutsideClickCallback(event => {
+      this.hideDialog();
+      event.consume(true);
+    });
     /** @type {!Map<!HTMLElement, number>} */
     this._tabIndexMap = new Map();
+    /** @type {?UI.WidgetFocusRestorer} */
+    this._focusRestorer = null;
   }
 
   /**
@@ -62,41 +54,23 @@
   }
 
   /**
-   * @override
-   * @suppressGlobalPropertiesCheck
-   * TODO(dgozman): pass document in constructor.
+   * @param {!Document|!Element=} where
    */
-  show() {
+  showDialog(where) {
+    var document = /** @type {!Document} */ (
+        where instanceof Document ? where : (where || UI.inspectorView.element).ownerDocument);
     if (UI.Dialog._instance)
       UI.Dialog._instance.detach();
     UI.Dialog._instance = this;
-
     this._disableTabIndexOnElements(document);
-
-    this._glassPane = new UI.GlassPane(document, this._dimmed, true /* blockPointerEvents*/, event => {
-      this.detach();
-      event.consume(true);
-    });
-    this._glassPane.setFixedHeight(this._fixedHeight);
-    this._glassPane.show();
-    super.show(this._glassPane.contentElement);
-    this._glassPane.setContentPosition(this._positionX, this._positionY);
-    this._glassPane.setMaxContentSize(this._effectiveMaxSize());
+    this.showGlassPane(document);
     this._focusRestorer = new UI.WidgetFocusRestorer(this);
   }
 
-  /**
-   * @override
-   */
-  detach() {
+  hideDialog() {
     this._focusRestorer.restore();
-
-    super.detach();
-    this._glassPane.hide();
-    delete this._glassPane;
-
+    this.hideGlassPane();
     this._restoreTabIndexOnElements();
-
     delete UI.Dialog._instance;
   }
 
@@ -107,59 +81,6 @@
   }
 
   /**
-   * @param {?number} positionX
-   * @param {?number} positionY
-   */
-  setPosition(positionX, positionY) {
-    this._positionX = positionX;
-    this._positionY = positionY;
-  }
-
-  /**
-   * @param {!UI.Size} size
-   */
-  setMaxSize(size) {
-    this._maxSize = size;
-  }
-
-  /**
-   * @param {boolean} fixedHeight
-   */
-  setFixedHeight(fixedHeight) {
-    this._fixedHeight = fixedHeight;
-  }
-
-  /**
-   * @return {?UI.Size}
-   */
-  _effectiveMaxSize() {
-    if (!this._wrapsContent)
-      return this._maxSize;
-    return new UI.Size(this.contentElement.offsetWidth, this.contentElement.offsetHeight).clipTo(this._maxSize);
-  }
-
-  /**
-   * @param {boolean} wraps
-   */
-  setWrapsContent(wraps) {
-    this._wrapsContent = wraps;
-    this.element.classList.toggle('wraps-content', wraps);
-  }
-
-  /**
-   * @param {boolean} dimmed
-   */
-  setDimmed(dimmed) {
-    this._dimmed = dimmed;
-  }
-
-  contentResized() {
-    if (!this._wrapsContent || !this._glassPane)
-      return;
-    this._glassPane.setMaxContentSize(this._effectiveMaxSize());
-  }
-
-  /**
    * @param {!Document} document
    */
   _disableTabIndexOnElements(document) {
@@ -188,7 +109,7 @@
   _onKeyDown(event) {
     if (event.keyCode === UI.KeyboardShortcut.Keys.Esc.code) {
       event.consume(true);
-      this.detach();
+      this.hideDialog();
     }
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js b/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
index 2d365cf..58ef0d0e 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
@@ -2,26 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-UI.GlassPane = class {
-  /**
-   * @param {!Document} document
-   * @param {boolean} dimmed
-   * @param {boolean} blockPointerEvents
-   * @param {function(!Event)} onClickOutside
-   */
-  constructor(document, dimmed, blockPointerEvents, onClickOutside) {
-    this._element = createElementWithClass('div', 'glass-pane');
-    this._element.style.backgroundColor = dimmed ? 'rgba(255, 255, 255, 0.5)' : 'transparent';
-    if (!blockPointerEvents)
-      this._element.style.pointerEvents = 'none';
-    this._onMouseDown = event => {
-      if (!this.contentElement.isSelfOrAncestor(/** @type {?Node} */ (event.target)))
-        onClickOutside.call(null, event);
-    };
-
-    this.contentElement = this._element.createChild('div', 'glass-pane-content');
-    this._document = document;
-    this._visible = false;
+UI.GlassPane = class extends UI.Widget {
+  constructor() {
+    super(true);
+    this.markAsRoot();
+    this.registerRequiredCSS('ui/glassPane.css');
+    this.element.classList.add('no-pointer-events');
+    this._onMouseDownBound = this._onMouseDown.bind(this);
+    /** @type {?function(!Event)} */
+    this._onClickOutsideCallback = null;
     /** @type {?UI.Size} */
     this._maxSize = null;
     /** @type {?number} */
@@ -31,7 +20,28 @@
     /** @type {?AnchorBox} */
     this._anchorBox = null;
     this._anchorBehavior = UI.GlassPane.AnchorBehavior.PreferTop;
-    this._fixedHeight = true;
+    this._sizeBehavior = UI.GlassPane.SizeBehavior.SetHeight;
+  }
+
+  /**
+   * @param {boolean} dimmed
+   */
+  setDimmed(dimmed) {
+    this.element.classList.toggle('dimmed-pane', dimmed);
+  }
+
+  /**
+   * @param {boolean} blockPointerEvents
+   */
+  setBlockPointerEvents(blockPointerEvents) {
+    this.element.classList.toggle('no-pointer-events', !blockPointerEvents);
+  }
+
+  /**
+   * @param {?function(!Event)} callback
+   */
+  setSetOutsideClickCallback(callback) {
+    this._onClickOutsideCallback = callback;
   }
 
   /**
@@ -43,10 +53,11 @@
   }
 
   /**
-   * @param {boolean} fixedHeight
+   * @param {!UI.GlassPane.SizeBehavior} sizeBehavior
    */
-  setFixedHeight(fixedHeight) {
-    this._fixedHeight = fixedHeight;
+  setSizeBehavior(sizeBehavior) {
+    this._sizeBehavior = sizeBehavior;
+    this._positionContent();
   }
 
   /**
@@ -76,39 +87,52 @@
     this._anchorBehavior = behavior;
   }
 
-  show() {
-    if (this._visible)
+  /**
+   * @param {!Document} document
+   */
+  showGlassPane(document) {
+    if (this.isShowing())
       return;
-    this._visible = true;
     // Deliberately starts with 3000 to hide other z-indexed elements below.
-    this._element.style.zIndex = 3000 + 1000 * UI.GlassPane._panes.size;
-    this._document.body.appendChild(this._element);
-    this._document.body.addEventListener('mousedown', this._onMouseDown, true);
+    this.element.style.zIndex = 3000 + 1000 * UI.GlassPane._panes.size;
+    document.body.addEventListener('mousedown', this._onMouseDownBound, true);
+    this.show(document.body);
     UI.GlassPane._panes.add(this);
+    this._positionContent();
   }
 
-  hide() {
-    if (!this._visible)
+  hideGlassPane() {
+    if (!this.isShowing())
       return;
     UI.GlassPane._panes.delete(this);
-    this._document.body.removeEventListener('mousedown', this._onMouseDown, true);
-    this._document.body.removeChild(this._element);
-    this._visible = false;
+    this.element.ownerDocument.body.removeEventListener('mousedown', this._onMouseDownBound, true);
+    this.detach();
   }
 
   /**
-   * @return {boolean}
+   * @param {!Event} event
    */
-  visible() {
-    return this._visible;
+  _onMouseDown(event) {
+    if (!this._onClickOutsideCallback)
+      return;
+    if (this.contentElement.isSelfOrAncestor(/** @type {?Node} */ (event.deepElementFromPoint())))
+      return;
+    this._onClickOutsideCallback.call(null, event);
   }
 
   _positionContent() {
-    if (!this._visible)
+    if (!this.isShowing())
       return;
 
     var gutterSize = 5;
-    var container = UI.GlassPane._containers.get(this._document);
+    var container = UI.GlassPane._containers.get(/** @type {!Document} */ (this.element.ownerDocument));
+    if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
+      this.contentElement.positionAt(0, 0);
+      this.contentElement.style.width = '';
+      this.contentElement.style.height = '';
+      this.contentElement.style.maxHeight = '';
+    }
+
     var containerWidth = container.offsetWidth;
     var containerHeight = container.offsetHeight;
 
@@ -122,6 +146,11 @@
       height = Math.min(height, this._maxSize.height);
     }
 
+    if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
+      width = Math.min(width, this.contentElement.offsetWidth);
+      height = Math.min(height, this.contentElement.offsetHeight);
+    }
+
     if (this._anchorBox) {
       var anchorBox = this._anchorBox.relativeToElement(container);
       var behavior = this._anchorBehavior;
@@ -169,10 +198,10 @@
     }
 
     this.contentElement.style.width = width + 'px';
-    if (this._fixedHeight)
-      this.contentElement.style.height = height + 'px';
-    else
+    if (this._sizeBehavior === UI.GlassPane.SizeBehavior.SetMaxHeight)
       this.contentElement.style.maxHeight = height + 'px';
+    else
+      this.contentElement.style.height = height + 'px';
     this.contentElement.positionAt(positionX, positionY, container);
   }
 
@@ -197,8 +226,10 @@
    */
   static containerMoved(element) {
     for (var pane of UI.GlassPane._panes) {
-      if (pane._document === element.ownerDocument)
+      if (pane.isShowing() && pane.element.ownerDocument === element.ownerDocument) {
         pane._positionContent();
+        pane.doResize();
+      }
     }
   }
 };
@@ -213,6 +244,15 @@
   PreferRight: Symbol('PreferRight'),
 };
 
+/**
+ * @enum {symbol}
+ */
+UI.GlassPane.SizeBehavior = {
+  SetHeight: Symbol('SetHeight'),
+  SetMaxHeight: Symbol('SetMaxHeight'),
+  MeasureContent: Symbol('MeasureContent')
+};
+
 /** @type {!Map<!Document, !Element>} */
 UI.GlassPane._containers = new Map();
 /** @type {!Set<!UI.GlassPane>} */
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
index e74c807..73d2908 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
@@ -53,7 +53,6 @@
    * @param {!UI.SuggestBoxDelegate} suggestBoxDelegate
    * @param {number=} maxItemsHeight
    * @param {boolean=} captureEnter
-   * @suppressGlobalPropertiesCheck
    */
   constructor(suggestBoxDelegate, maxItemsHeight, captureEnter) {
     this._suggestBoxDelegate = suggestBoxDelegate;
@@ -71,10 +70,9 @@
     this._element.classList.add('suggest-box');
     this._element.addEventListener('mousedown', event => event.preventDefault(), true);
 
-    // TODO(dgozman): take document in constructor.
-    this._glassPane =
-        new UI.GlassPane(document, false /* dimmed */, false /* blockPointerEvents */, this.hide.bind(this));
+    this._glassPane = new UI.GlassPane();
     this._glassPane.setAnchorBehavior(UI.GlassPane.AnchorBehavior.PreferBottom);
+    this._glassPane.setSetOutsideClickCallback(this.hide.bind(this));
     var shadowRoot = UI.createShadowRootWithCoreStyles(this._glassPane.contentElement, 'ui/suggestBox.css');
     shadowRoot.appendChild(this._element);
   }
@@ -83,7 +81,7 @@
    * @return {boolean}
    */
   visible() {
-    return this._glassPane.visible();
+    return this._glassPane.isShowing();
   }
 
   /**
@@ -124,10 +122,14 @@
     return Math.min(kMaxWidth, UI.measurePreferredSize(element, this._element).width);
   }
 
+  /**
+   * @suppressGlobalPropertiesCheck
+   */
   _show() {
     if (this.visible())
       return;
-    this._glassPane.show();
+    // TODO(dgozman): take document as a parameter.
+    this._glassPane.showGlassPane(document);
     this._rowHeight =
         UI.measurePreferredSize(this.createElementForItem({text: '1', subtitle: '12'}), this._element).height;
   }
@@ -136,7 +138,7 @@
     if (!this.visible())
       return;
     this._userInteracted = false;
-    this._glassPane.hide();
+    this._glassPane.hideGlassPane();
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
index e0dfe62..983ceeb 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
@@ -123,8 +123,9 @@
       var document = button.element.ownerDocument;
       document.documentElement.addEventListener('mouseup', mouseUp, false);
 
-      var optionsGlassPane = new UI.GlassPane(document, false /* dimmed */, true /* blockPointerEvents */, event => {});
-      optionsGlassPane.show();
+      var optionsGlassPane = new UI.GlassPane();
+      optionsGlassPane.setBlockPointerEvents(true);
+      optionsGlassPane.showGlassPane(document);
       var optionsBar = new UI.Toolbar('fill', optionsGlassPane.contentElement);
       optionsBar._contentElement.classList.add('floating');
       const buttonHeight = 26;
@@ -168,7 +169,7 @@
       function mouseUp(e) {
         if (e.which !== 1)
           return;
-        optionsGlassPane.hide();
+        optionsGlassPane.hideGlassPane();
         document.documentElement.removeEventListener('mouseup', mouseUp, false);
 
         for (var i = 0; i < buttons.length; ++i) {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
index f999a81..64d4636 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -95,9 +95,9 @@
   _createGlassPane() {
     this._glassPaneInUse = true;
     if (!UI.DragHandler._glassPaneUsageCount++) {
-      UI.DragHandler._glassPane = new UI.GlassPane(
-          UI.DragHandler._documentForMouseOut, false /* dimmed */, true /* blockPointerEvents */, event => {});
-      UI.DragHandler._glassPane.show();
+      UI.DragHandler._glassPane = new UI.GlassPane();
+      UI.DragHandler._glassPane.setBlockPointerEvents(true);
+      UI.DragHandler._glassPane.showGlassPane(UI.DragHandler._documentForMouseOut);
     }
   }
 
@@ -107,7 +107,7 @@
     this._glassPaneInUse = false;
     if (--UI.DragHandler._glassPaneUsageCount)
       return;
-    UI.DragHandler._glassPane.hide();
+    UI.DragHandler._glassPane.hideGlassPane();
     delete UI.DragHandler._glassPane;
     delete UI.DragHandler._documentForMouseOut;
   }
@@ -2037,24 +2037,25 @@
  */
 UI.ConfirmDialog = class extends UI.VBox {
   /**
+   * @param {!Document|!Element} where
    * @param {string} message
    * @param {!Function} callback
    */
-  static show(message, callback) {
+  static show(where, message, callback) {
     var dialog = new UI.Dialog();
-    dialog.setWrapsContent(true);
+    dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
     dialog.addCloseButton();
     dialog.setDimmed(true);
     new UI
         .ConfirmDialog(
             message,
             () => {
-              dialog.detach();
+              dialog.hideDialog();
               callback();
             },
-            () => dialog.detach())
-        .show(dialog.element);
-    dialog.show();
+            () => dialog.hideDialog())
+        .show(dialog.contentElement);
+    dialog.showDialog(where);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/dialog.css b/third_party/WebKit/Source/devtools/front_end/ui/dialog.css
index 730596e..8f0f06f 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/dialog.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/dialog.css
@@ -4,32 +4,17 @@
  * found in the LICENSE file.
  */
 
-:host {
+.widget {
     box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 2px 4px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0, 0, 0, 0.1);
     background: white;
     justify-content: flex-start;
     align-items: stretch;
-}
-
-.widget {
     display: flex;
-    flex: auto;
-    justify-content: flex-start;
-    align-items: stretch;
-}
-
-:host-context(.wraps-content) {
-    align-items: flex-start;
-    overflow: hidden;
-}
-
-:host-context(.wraps-content) .widget {
-    flex: none !important;
-    align-items: center;
 }
 
 .dialog-close-button {
     position: absolute;
     right: 9px;
     top: 9px;
+    z-index: 1;
 }
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/glassPane.css b/third_party/WebKit/Source/devtools/front_end/ui/glassPane.css
new file mode 100644
index 0000000..190979b
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/ui/glassPane.css
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+:host {
+    position: absolute !important;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    overflow: hidden;
+    contain: strict;
+    background-color: transparent;
+}
+
+:host-context(.dimmed-pane) {
+    background-color: rgba(255, 255, 255, 0.5);
+}
+
+:host-context(.no-pointer-events) {
+    pointer-events: none;
+}
+
+.widget {
+    display: flex;
+    background-color: transparent;
+    pointer-events: auto;
+    flex: none;
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css b/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css
index 3c8faf08..d7b2f886 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css
@@ -387,17 +387,3 @@
     background: unset;
     background-color: white;
 }
-
-.glass-pane {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    overflow: hidden;
-    contain: strict;
-}
-
-.glass-pane-content {
-    display: flex;
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/module.json b/third_party/WebKit/Source/devtools/front_end/ui/module.json
index 42a2f375..8a498d9 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/ui/module.json
@@ -14,6 +14,7 @@
         "ShortcutRegistry.js",
         "Context.js",
         "ContextMenu.js",
+        "GlassPane.js",
         "Dialog.js",
         "SyntaxHighlighter.js",
         "DropDownMenu.js",
@@ -29,7 +30,6 @@
         "KeyboardShortcut.js",
         "ListControl.js",
         "ListWidget.js",
-        "GlassPane.js",
         "Panel.js",
         "Popover.js",
         "ProgressIndicator.js",
@@ -61,6 +61,7 @@
         "dropTarget.css",
         "emptyWidget.css",
         "filter.css",
+        "glassPane.css",
         "infobar.css",
         "inspectorCommon.css",
         "inspectorStyle.css",