15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/ui/views/extensions/extension_popup.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h" 89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/devtools/devtools_window.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/extensions/extension_view_host.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/extensions/extension_view_host_factory.h" 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/browser/devtools_agent_host.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/browser/render_view_host.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/insets.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/fill_layout.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/wm/core/window_animations.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/wm/core/window_util.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/wm/public/activation_client.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExtensionViewViews* GetExtensionView(extensions::ExtensionViewHost* host) { 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return static_cast<ExtensionViewViews*>(host->view()); 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The minimum/maximum dimensions of the popup. 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The minimum is just a little larger than the size of the button itself. 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The maximum is an arbitrary number that should be smaller than most screens. 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int ExtensionPopup::kMinWidth = 25; 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int ExtensionPopup::kMinHeight = 25; 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const int ExtensionPopup::kMaxWidth = 800; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int ExtensionPopup::kMaxHeight = 600; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ExtensionPopup::ExtensionPopup(extensions::ExtensionViewHost* host, 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View* anchor_view, 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::BubbleBorder::Arrow arrow, 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ShowAction show_action) 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : BubbleDelegateView(anchor_view, arrow), 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci host_(host), 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci devtools_callback_(base::Bind( 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &ExtensionPopup::OnDevToolsStateChanged, base::Unretained(this))), 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci widget_initialized_(false) { 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) inspect_with_devtools_ = show_action == SHOW_AND_INSPECT; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Adjust the margin so that contents fit better. 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int margin = views::BubbleBorder::GetCornerRadius() / 2; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_margins(gfx::Insets(margin, margin, margin, margin)); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetLayoutManager(new views::FillLayout()); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(GetExtensionView(host)); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetExtensionView(host)->set_container(this); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ExtensionPopup closes itself on very specific de-activation conditions. 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_close_on_deactivate(false); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Wait to show the popup until the contained host finishes loading. 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<content::WebContents>(host->host_contents())); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Listen for the containing view calling window.close(); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Add( 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<content::BrowserContext>(host->browser_context())); 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) content::DevToolsAgentHost::AddAgentStateCallback(devtools_callback_); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetExtensionView(host)->GetBrowser()->tab_strip_model()->AddObserver(this); 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciExtensionPopup::~ExtensionPopup() { 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::DevToolsAgentHost::RemoveAgentStateCallback(devtools_callback_); 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetExtensionView( 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci host_.get())->GetBrowser()->tab_strip_model()->RemoveObserver(this); 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionPopup::Observe(int type, 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const content::NotificationSource& source, 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const content::NotificationDetails& details) { 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci switch (type) { 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(host()->host_contents(), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<content::WebContents>(source).ptr()); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Show when the content finishes loading and its width is computed. 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ShowBubble(); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we aren't the host of the popup, then disregard the notification. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (content::Details<extensions::ExtensionHost>(host()) == details) 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) GetWidget()->Close(); 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << L"Received unexpected notification"; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionPopup::OnDevToolsStateChanged( 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::DevToolsAgentHost* agent_host, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool attached) { 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // First check that the devtools are being opened on this popup. 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (host()->host_contents() != agent_host->GetWebContents()) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached) { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set inspect_with_devtools_ so the popup will be kept open while 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the devtools are open. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inspect_with_devtools_ = true; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Widget::Close posts a task, which should give the devtools window a 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chance to finish detaching from the inspected RenderViewHost. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWidget()->Close(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionPopup::OnExtensionSizeChanged(ExtensionViewViews* view) { 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SizeToContents(); 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)gfx::Size ExtensionPopup::GetPreferredSize() const { 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Constrain the size to popup min/max. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size sz = views::View::GetPreferredSize(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sz.set_width(std::max(kMinWidth, std::min(kMaxWidth, sz.width()))); 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sz.set_height(std::max(kMinHeight, std::min(kMaxHeight, sz.height()))); 13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return sz; 13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionPopup::ViewHierarchyChanged( 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ViewHierarchyChangedDetails& details) { 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(msw): Find any remaining crashes related to http://crbug.com/327776 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // No view hierarchy changes are expected if the widget no longer exists. 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) widget_initialized_ |= details.child == this && details.is_add && GetWidget(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(GetWidget() || !widget_initialized_); 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionPopup::OnWidgetDestroying(views::Widget* widget) { 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BubbleDelegateView::OnWidgetDestroying(widget); 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window* bubble_window = GetWidget()->GetNativeWindow(); 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::client::ActivationClient* activation_client = 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::client::GetActivationClient(bubble_window->GetRootWindow()); 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the popup was being inspected with devtools and the browser window was 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // closed, then the root window and activation client are already destroyed. 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (activation_client) 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci activation_client->RemoveObserver(this); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionPopup::OnWidgetActivationChanged(views::Widget* widget, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool active) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(msw): Find any remaining crashes related to http://crbug.com/327776 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No calls are expected if the widget isn't initialized or no longer exists. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(widget_initialized_); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(GetWidget()); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close on anchor window activation (ie. user clicked the browser window). 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!inspect_with_devtools_ && widget && active && 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) widget->GetNativeWindow() == anchor_widget()->GetNativeWindow()) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWidget()->Close(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionPopup::OnWindowActivated(aura::Window* gained_active, 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window* lost_active) { 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(msw): Find any remaining crashes related to http://crbug.com/327776 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // No calls are expected if the widget isn't initialized or no longer exists. 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(widget_initialized_); 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(GetWidget()); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Close on anchor window activation (ie. user clicked the browser window). 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DesktopNativeWidgetAura does not trigger the expected browser widget 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // [de]activation events when activating widgets in its own root window. 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // This additional check handles those cases. See: http://crbug.com/320889 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!inspect_with_devtools_ && 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gained_active == anchor_widget()->GetNativeWindow()) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWidget()->Close(); 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionPopup::ActiveTabChanged(content::WebContents* old_contents, 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::WebContents* new_contents, 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int index, 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int reason) { 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetWidget()->Close(); 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionPopup* ExtensionPopup::ShowPopup(const GURL& url, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* anchor_view, 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) views::BubbleBorder::Arrow arrow, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShowAction show_action) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionViewHost* host = 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionViewHostFactory::CreatePopupHost(url, browser); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionPopup* popup = new ExtensionPopup(host, anchor_view, arrow, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_action); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::BubbleDelegateView::CreateBubble(popup); 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::NativeView native_view = popup->GetWidget()->GetNativeView(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wm::SetWindowVisibilityAnimationType( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) native_view, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wm::SetWindowVisibilityAnimationVerticalPosition(native_view, -3.0f); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the host had somehow finished loading, then we'd miss the notification 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and not show. This seems to happen in single-process mode. 207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (host->did_stop_loading()) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup->ShowBubble(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window* bubble_window = popup->GetWidget()->GetNativeWindow(); 211 aura::client::ActivationClient* activation_client = 212 aura::client::GetActivationClient(bubble_window->GetRootWindow()); 213 activation_client->AddObserver(popup); 214 215 return popup; 216} 217 218void ExtensionPopup::ShowBubble() { 219 GetWidget()->Show(); 220 221 // Focus on the host contents when the bubble is first shown. 222 host()->host_contents()->Focus(); 223 224 if (inspect_with_devtools_) { 225 DevToolsWindow::OpenDevToolsWindow(host()->host_contents(), 226 DevToolsToggleAction::ShowConsole()); 227 } 228} 229