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",