Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: chrome/browser/ui/gtk/extensions/extension_popup_gtk.cc

Issue 231733005: Delete the GTK+ port of Chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remerge to ToT Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/gtk/extensions/extension_popup_gtk.h"
6
7 #include <gtk/gtk.h>
8
9 #include <algorithm>
10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/callback.h"
14 #include "base/i18n/rtl.h"
15 #include "base/message_loop/message_loop.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/devtools/devtools_window.h"
18 #include "chrome/browser/extensions/extension_view_host.h"
19 #include "chrome/browser/extensions/extension_view_host_factory.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_window.h"
23 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
24 #include "content/public/browser/devtools_agent_host.h"
25 #include "content/public/browser/devtools_manager.h"
26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_source.h"
28 #include "content/public/browser/render_view_host.h"
29 #include "content/public/browser/render_widget_host_view.h"
30 #include "url/gurl.h"
31
32 using content::BrowserContext;
33 using content::RenderViewHost;
34
35 ExtensionPopupGtk* ExtensionPopupGtk::current_extension_popup_ = NULL;
36
37 // The minimum/maximum dimensions of the extension popup.
38 // The minimum is just a little larger than the size of a browser action button.
39 // The maximum is an arbitrary number that should be smaller than most screens.
40 const int ExtensionPopupGtk::kMinWidth = 25;
41 const int ExtensionPopupGtk::kMinHeight = 25;
42 const int ExtensionPopupGtk::kMaxWidth = 800;
43 const int ExtensionPopupGtk::kMaxHeight = 600;
44
45 ExtensionPopupGtk::ExtensionPopupGtk(Browser* browser,
46 extensions::ExtensionViewHost* host,
47 GtkWidget* anchor,
48 ShowAction show_action)
49 : browser_(browser),
50 bubble_(NULL),
51 host_(host),
52 anchor_(anchor),
53 devtools_callback_(base::Bind(
54 &ExtensionPopupGtk::OnDevToolsStateChanged, base::Unretained(this))),
55 weak_factory_(this) {
56 host_->view()->SetContainer(this);
57 being_inspected_ = show_action == SHOW_AND_INSPECT;
58
59 // If the host had somehow finished loading, then we'd miss the notification
60 // and not show. This seems to happen in single-process mode.
61 if (host->did_stop_loading()) {
62 ShowPopup();
63 } else {
64 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
65 content::Source<BrowserContext>(host->browser_context()));
66 }
67
68 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
69 content::Source<BrowserContext>(host->browser_context()));
70 content::DevToolsManager::GetInstance()->AddAgentStateCallback(
71 devtools_callback_);
72 }
73
74 ExtensionPopupGtk::~ExtensionPopupGtk() {
75 content::DevToolsManager::GetInstance()->RemoveAgentStateCallback(
76 devtools_callback_);
77 }
78
79 // static
80 void ExtensionPopupGtk::Show(const GURL& url, Browser* browser,
81 GtkWidget* anchor, ShowAction show_action) {
82 extensions::ExtensionViewHost* host =
83 extensions::ExtensionViewHostFactory::CreatePopupHost(url, browser);
84 // This object will delete itself when the bubble is closed.
85 new ExtensionPopupGtk(browser, host, anchor, show_action);
86 }
87
88 void ExtensionPopupGtk::Observe(int type,
89 const content::NotificationSource& source,
90 const content::NotificationDetails& details) {
91 switch (type) {
92 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING:
93 if (content::Details<extensions::ExtensionHost>(host_.get()) == details)
94 ShowPopup();
95 break;
96 case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE:
97 if (content::Details<extensions::ExtensionHost>(host_.get()) == details)
98 DestroyPopup();
99 break;
100 default:
101 NOTREACHED() << "Received unexpected notification";
102 }
103 }
104
105 void ExtensionPopupGtk::OnDevToolsStateChanged(
106 content::DevToolsAgentHost* agent_host, bool attached) {
107 // Make sure it's the devtools window that is inspecting our popup.
108 if (host_->render_view_host() != agent_host->GetRenderViewHost())
109 return;
110 if (attached) {
111 // Make sure that the popup won't go away when the inspector is activated.
112 if (bubble_)
113 bubble_->StopGrabbingInput();
114
115 being_inspected_ = true;
116 } else {
117 // If the devtools window is closing, we post a task to ourselves to
118 // close the popup. This gives the devtools window a chance to finish
119 // detaching from the inspected RenderViewHost.
120 base::MessageLoop::current()->PostTask(
121 FROM_HERE,
122 base::Bind(&ExtensionPopupGtk::DestroyPopupWithoutResult,
123 weak_factory_.GetWeakPtr()));
124 }
125 }
126
127 void ExtensionPopupGtk::BubbleClosing(BubbleGtk* bubble,
128 bool closed_by_escape) {
129 current_extension_popup_ = NULL;
130 delete this;
131 }
132
133 void ExtensionPopupGtk::OnExtensionSizeChanged(
134 ExtensionViewGtk* view,
135 const gfx::Size& new_size) {
136 int width = std::max(kMinWidth, std::min(kMaxWidth, new_size.width()));
137 int height = std::max(kMinHeight, std::min(kMaxHeight, new_size.height()));
138
139 view->render_view_host()->GetView()->SetSize(gfx::Size(width, height));
140 gtk_widget_set_size_request(view->native_view(), width, height);
141 }
142
143 bool ExtensionPopupGtk::DestroyPopup() {
144 if (!bubble_) {
145 NOTREACHED();
146 return false;
147 }
148
149 bubble_->Close();
150 return true;
151 }
152
153 void ExtensionPopupGtk::ShowPopup() {
154 if (bubble_) {
155 NOTREACHED();
156 return;
157 }
158
159 if (being_inspected_)
160 DevToolsWindow::OpenDevToolsWindow(host_->render_view_host());
161
162 // Only one instance should be showing at a time. Get rid of the old one, if
163 // any. Typically, |current_extension_popup_| will be NULL, but it can be
164 // non-NULL if a browser action button is clicked while another extension
165 // popup's extension host is still loading.
166 if (current_extension_popup_)
167 current_extension_popup_->DestroyPopup();
168 current_extension_popup_ = this;
169
170 GtkWidget* border_box = gtk_alignment_new(0, 0, 1.0, 1.0);
171 // This border is necessary so the bubble's corners do not get cut off by the
172 // render view.
173 gtk_container_set_border_width(GTK_CONTAINER(border_box), 2);
174 gtk_container_add(GTK_CONTAINER(border_box), host_->view()->native_view());
175
176 // We'll be in the upper-right corner of the window for LTR languages, so we
177 // want to put the arrow at the upper-right corner of the bubble to match the
178 // page and app menus.
179 bubble_ = BubbleGtk::Show(anchor_,
180 NULL,
181 border_box,
182 BubbleGtk::ANCHOR_TOP_RIGHT,
183 being_inspected_ ? 0 :
184 BubbleGtk::POPUP_WINDOW | BubbleGtk::GRAB_INPUT,
185 GtkThemeService::GetFrom(browser_->profile()),
186 this);
187 }
188
189 void ExtensionPopupGtk::DestroyPopupWithoutResult() {
190 DestroyPopup();
191 }
192
193 gfx::Rect ExtensionPopupGtk::GetViewBounds() {
194 GtkAllocation allocation;
195 gtk_widget_get_allocation(host_->view()->native_view(), &allocation);
196 return gfx::Rect(allocation);
197 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698