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

Side by Side Diff: chrome/browser/ui/panels/panel.cc

Issue 2263863002: Remove implementation of Panels on OSes other than ChromeOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR feedback Created 4 years, 4 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
« no previous file with comments | « chrome/browser/ui/panels/panel.h ('k') | chrome/browser/ui/panels/panel_bounds_animation.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/panels/panel.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/app/chrome_command_ids.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/devtools/devtools_window.h"
18 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
19 #include "chrome/browser/extensions/api/tabs/tabs_windows_api.h"
20 #include "chrome/browser/extensions/api/tabs/windows_event_router.h"
21 #include "chrome/browser/extensions/extension_service.h"
22 #include "chrome/browser/extensions/extension_tab_util.h"
23 #include "chrome/browser/extensions/window_controller.h"
24 #include "chrome/browser/extensions/window_controller_list.h"
25 #include "chrome/browser/lifetime/application_lifetime.h"
26 #include "chrome/browser/lifetime/keep_alive_types.h"
27 #include "chrome/browser/lifetime/scoped_keep_alive.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/browser/sessions/session_tab_helper.h"
30 #include "chrome/browser/task_manager/web_contents_tags.h"
31 #include "chrome/browser/themes/theme_service.h"
32 #include "chrome/browser/themes/theme_service_factory.h"
33 #include "chrome/browser/ui/panels/native_panel.h"
34 #include "chrome/browser/ui/panels/panel_collection.h"
35 #include "chrome/browser/ui/panels/panel_host.h"
36 #include "chrome/browser/ui/panels/panel_manager.h"
37 #include "chrome/browser/ui/panels/stacked_panel_collection.h"
38 #include "chrome/browser/web_applications/web_app.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/notification_source.h"
41 #include "content/public/browser/notification_types.h"
42 #include "content/public/browser/render_view_host.h"
43 #include "content/public/browser/user_metrics.h"
44 #include "content/public/browser/web_contents.h"
45 #include "extensions/browser/extension_registry.h"
46 #include "extensions/browser/extension_system.h"
47 #include "extensions/browser/image_loader.h"
48 #include "extensions/common/constants.h"
49 #include "extensions/common/extension.h"
50 #include "extensions/common/manifest_handlers/icons_handler.h"
51 #include "ui/gfx/geometry/rect.h"
52 #include "ui/gfx/image/image.h"
53
54 using base::UserMetricsAction;
55 using content::RenderViewHost;
56
57 namespace panel_internal {
58
59 class PanelExtensionWindowController : public extensions::WindowController {
60 public:
61 PanelExtensionWindowController(Panel* panel, Profile* profile);
62 ~PanelExtensionWindowController() override;
63
64 // Overridden from extensions::WindowController.
65 int GetWindowId() const override;
66 std::string GetWindowTypeText() const override;
67 std::unique_ptr<base::DictionaryValue> CreateWindowValueWithTabs(
68 const extensions::Extension* extension) const override;
69 base::DictionaryValue* CreateTabValue(const extensions::Extension* extension,
70 int tab_index) const override;
71 std::unique_ptr<extensions::api::tabs::Tab> CreateTabObject(
72 const extensions::Extension* extension,
73 int tab_index) const override;
74 bool CanClose(Reason* reason) const override;
75 void SetFullscreenMode(bool is_fullscreen,
76 const GURL& extension_url) const override;
77 bool IsVisibleToExtension(
78 const extensions::Extension* extension) const override;
79
80 private:
81 Panel* panel_; // Weak pointer. Owns us.
82 DISALLOW_COPY_AND_ASSIGN(PanelExtensionWindowController);
83 };
84
85 PanelExtensionWindowController::PanelExtensionWindowController(
86 Panel* panel, Profile* profile)
87 : extensions::WindowController(panel, profile),
88 panel_(panel) {
89 extensions::WindowControllerList::GetInstance()->AddExtensionWindow(this);
90 }
91
92 PanelExtensionWindowController::~PanelExtensionWindowController() {
93 extensions::WindowControllerList::GetInstance()->RemoveExtensionWindow(this);
94 }
95
96 int PanelExtensionWindowController::GetWindowId() const {
97 return static_cast<int>(panel_->session_id().id());
98 }
99
100 std::string PanelExtensionWindowController::GetWindowTypeText() const {
101 return extensions::tabs_constants::kWindowTypeValuePanel;
102 }
103
104 std::unique_ptr<base::DictionaryValue>
105 PanelExtensionWindowController::CreateWindowValueWithTabs(
106 const extensions::Extension* extension) const {
107 std::unique_ptr<base::DictionaryValue> result = CreateWindowValue();
108
109 base::DictionaryValue* tab_value = CreateTabValue(extension, 0);
110 if (tab_value) {
111 base::ListValue* tab_list = new base::ListValue();
112 tab_list->Append(tab_value);
113 result->Set(extensions::tabs_constants::kTabsKey, tab_list);
114 }
115 return result;
116 }
117
118 base::DictionaryValue* PanelExtensionWindowController::CreateTabValue(
119 const extensions::Extension* extension, int tab_index) const {
120 return CreateTabObject(extension, tab_index)->ToValue().release();
121 }
122
123 std::unique_ptr<extensions::api::tabs::Tab>
124 PanelExtensionWindowController::CreateTabObject(
125 const extensions::Extension* extension,
126 int tab_index) const {
127 if (tab_index > 0)
128 return nullptr;
129
130 content::WebContents* web_contents = panel_->GetWebContents();
131 if (!web_contents)
132 return nullptr;
133
134 std::unique_ptr<extensions::api::tabs::Tab> tab_object(
135 new extensions::api::tabs::Tab);
136 tab_object->id.reset(new int(SessionTabHelper::IdForTab(web_contents)));
137 tab_object->index = 0;
138 tab_object->window_id =
139 SessionTabHelper::IdForWindowContainingTab(web_contents);
140 tab_object->url.reset(new std::string(web_contents->GetURL().spec()));
141 tab_object->status.reset(
142 new std::string(extensions::ExtensionTabUtil::GetTabStatusText(
143 web_contents->IsLoading())));
144 tab_object->active = panel_->IsActive();
145 tab_object->selected = true;
146 tab_object->highlighted = true;
147 tab_object->pinned = false;
148 tab_object->title.reset(
149 new std::string(base::UTF16ToUTF8(web_contents->GetTitle())));
150 tab_object->incognito = web_contents->GetBrowserContext()->IsOffTheRecord();
151 return tab_object;
152 }
153
154 bool PanelExtensionWindowController::CanClose(Reason* reason) const {
155 return true;
156 }
157
158 void PanelExtensionWindowController::SetFullscreenMode(
159 bool is_fullscreen, const GURL& extension_url) const {
160 // Do nothing. Panels cannot be fullscreen.
161 }
162
163 bool PanelExtensionWindowController::IsVisibleToExtension(
164 const extensions::Extension* extension) const {
165 DCHECK(extension);
166 return extension->id() == panel_->extension_id();
167 }
168
169 } // namespace panel_internal
170
171 Panel::~Panel() {
172 DCHECK(!collection_);
173 }
174
175 PanelManager* Panel::manager() const {
176 return PanelManager::GetInstance();
177 }
178
179 const std::string Panel::extension_id() const {
180 return web_app::GetExtensionIdFromApplicationName(app_name_);
181 }
182
183 CommandUpdater* Panel::command_updater() {
184 return &command_updater_;
185 }
186
187 Profile* Panel::profile() const {
188 return profile_;
189 }
190
191 const extensions::Extension* Panel::GetExtension() const {
192 ExtensionService* extension_service =
193 extensions::ExtensionSystem::Get(profile())->extension_service();
194 if (!extension_service || !extension_service->is_ready())
195 return NULL;
196 return extension_service->GetExtensionById(extension_id(), false);
197 }
198
199 content::WebContents* Panel::GetWebContents() const {
200 return panel_host_.get() ? panel_host_->web_contents() : NULL;
201 }
202
203 void Panel::SetExpansionState(ExpansionState new_state) {
204 if (expansion_state_ == new_state)
205 return;
206 native_panel_->PanelExpansionStateChanging(expansion_state_, new_state);
207 expansion_state_ = new_state;
208
209 manager()->OnPanelExpansionStateChanged(this);
210
211 DCHECK(initialized_ && collection_ != NULL);
212 native_panel_->PreventActivationByOS(collection_->IsPanelMinimized(this));
213 UpdateMinimizeRestoreButtonVisibility();
214
215 content::NotificationService::current()->Notify(
216 chrome::NOTIFICATION_PANEL_CHANGED_EXPANSION_STATE,
217 content::Source<Panel>(this),
218 content::NotificationService::NoDetails());
219 }
220
221 bool Panel::IsDrawingAttention() const {
222 return native_panel_->IsDrawingAttention();
223 }
224
225 void Panel::FullScreenModeChanged(bool is_full_screen) {
226 native_panel_->FullScreenModeChanged(is_full_screen);
227 }
228
229 int Panel::TitleOnlyHeight() const {
230 return native_panel_->TitleOnlyHeight();
231 }
232
233 bool Panel::CanShowMinimizeButton() const {
234 return collection_ && collection_->CanShowMinimizeButton(this);
235 }
236
237 bool Panel::CanShowRestoreButton() const {
238 return collection_ && collection_->CanShowRestoreButton(this);
239 }
240
241 bool Panel::IsActive() const {
242 return native_panel_->IsPanelActive();
243 }
244
245 bool Panel::IsMaximized() const {
246 // Size of panels is managed by PanelManager, they are never 'zoomed'.
247 return false;
248 }
249
250 bool Panel::IsMinimized() const {
251 return !collection_ || collection_->IsPanelMinimized(this);
252 }
253
254 bool Panel::IsFullscreen() const {
255 return false;
256 }
257
258 gfx::NativeWindow Panel::GetNativeWindow() const {
259 return native_panel_->GetNativePanelWindow();
260 }
261
262 gfx::Rect Panel::GetRestoredBounds() const {
263 gfx::Rect bounds = native_panel_->GetPanelBounds();
264 bounds.set_y(bounds.bottom() - full_size_.height());
265 bounds.set_x(bounds.right() - full_size_.width());
266 bounds.set_size(full_size_);
267 return bounds;
268 }
269
270 ui::WindowShowState Panel::GetRestoredState() const {
271 return ui::SHOW_STATE_NORMAL;
272 }
273
274 gfx::Rect Panel::GetBounds() const {
275 return native_panel_->GetPanelBounds();
276 }
277
278 void Panel::Show() {
279 if (manager()->display_settings_provider()->is_full_screen() || !collection_)
280 return;
281
282 native_panel_->ShowPanel();
283 }
284
285 void Panel::Hide() {
286 // Not implemented.
287 }
288
289 void Panel::ShowInactive() {
290 if (manager()->display_settings_provider()->is_full_screen() || !collection_)
291 return;
292
293 native_panel_->ShowPanelInactive();
294 }
295
296 // Close() may be called multiple times if the panel window is not ready to
297 // close on the first attempt.
298 void Panel::Close() {
299 native_panel_->ClosePanel();
300 }
301
302 void Panel::Activate() {
303 if (!collection_)
304 return;
305
306 collection_->ActivatePanel(this);
307 native_panel_->ActivatePanel();
308 }
309
310 void Panel::Deactivate() {
311 native_panel_->DeactivatePanel();
312 }
313
314 void Panel::Maximize() {
315 Restore();
316 }
317
318 void Panel::Minimize() {
319 if (collection_)
320 collection_->MinimizePanel(this);
321 }
322
323 bool Panel::IsMinimizedBySystem() const {
324 return native_panel_->IsPanelMinimizedBySystem();
325 }
326
327 bool Panel::IsShownOnActiveDesktop() const {
328 return native_panel_->IsPanelShownOnActiveDesktop();
329 }
330
331 void Panel::ShowShadow(bool show) {
332 native_panel_->ShowShadow(show);
333 }
334
335 void Panel::Restore() {
336 if (collection_)
337 collection_->RestorePanel(this);
338 }
339
340 void Panel::SetBounds(const gfx::Rect& bounds) {
341 // Ignore bounds position as the panel manager controls all positioning.
342 if (!collection_)
343 return;
344 collection_->ResizePanelWindow(this, bounds.size());
345 SetAutoResizable(false);
346 }
347
348 void Panel::FlashFrame(bool draw_attention) {
349 if (IsDrawingAttention() == draw_attention || !collection_)
350 return;
351
352 // Don't draw attention for an active panel.
353 if (draw_attention && IsActive())
354 return;
355
356 // Invoking native panel to draw attention must be done before informing the
357 // panel collection because it needs to check internal state of the panel to
358 // determine if the panel has been drawing attention.
359 native_panel_->DrawAttention(draw_attention);
360 collection_->OnPanelAttentionStateChanged(this);
361 }
362
363 bool Panel::IsAlwaysOnTop() const {
364 return native_panel_->IsPanelAlwaysOnTop();
365 }
366
367 void Panel::SetAlwaysOnTop(bool on_top) {
368 native_panel_->SetPanelAlwaysOnTop(on_top);
369 }
370
371 void Panel::ExecuteCommandWithDisposition(int id,
372 WindowOpenDisposition disposition) {
373 DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command "
374 << id;
375
376 if (!GetWebContents())
377 return;
378
379 switch (id) {
380 // Navigation
381 case IDC_RELOAD:
382 panel_host_->Reload();
383 break;
384 case IDC_RELOAD_BYPASSING_CACHE:
385 panel_host_->ReloadBypassingCache();
386 break;
387 case IDC_STOP:
388 panel_host_->StopLoading();
389 break;
390
391 // Window management
392 case IDC_CLOSE_WINDOW:
393 content::RecordAction(UserMetricsAction("CloseWindow"));
394 Close();
395 break;
396 case IDC_EXIT:
397 content::RecordAction(UserMetricsAction("Exit"));
398 chrome::AttemptUserExit();
399 break;
400
401 // Clipboard
402 case IDC_COPY:
403 content::RecordAction(UserMetricsAction("Copy"));
404 native_panel_->PanelCopy();
405 break;
406 case IDC_CUT:
407 content::RecordAction(UserMetricsAction("Cut"));
408 native_panel_->PanelCut();
409 break;
410 case IDC_PASTE:
411 content::RecordAction(UserMetricsAction("Paste"));
412 native_panel_->PanelPaste();
413 break;
414
415 // Zoom
416 case IDC_ZOOM_PLUS:
417 panel_host_->Zoom(content::PAGE_ZOOM_IN);
418 break;
419 case IDC_ZOOM_NORMAL:
420 panel_host_->Zoom(content::PAGE_ZOOM_RESET);
421 break;
422 case IDC_ZOOM_MINUS:
423 panel_host_->Zoom(content::PAGE_ZOOM_OUT);
424 break;
425
426 // DevTools
427 case IDC_DEV_TOOLS:
428 content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
429 DevToolsWindow::OpenDevToolsWindow(GetWebContents(),
430 DevToolsToggleAction::Show());
431 break;
432 case IDC_DEV_TOOLS_CONSOLE:
433 content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
434 DevToolsWindow::OpenDevToolsWindow(GetWebContents(),
435 DevToolsToggleAction::ShowConsole());
436 break;
437
438 default:
439 LOG(WARNING) << "Received unimplemented command: " << id;
440 break;
441 }
442 }
443
444 void Panel::Observe(int type,
445 const content::NotificationSource& source,
446 const content::NotificationDetails& details) {
447 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type);
448 Close();
449 }
450
451 void Panel::RenderViewHostChanged(content::RenderViewHost* old_host,
452 content::RenderViewHost* new_host) {
453 ConfigureAutoResize(web_contents());
454 }
455
456 void Panel::OnExtensionUnloaded(
457 content::BrowserContext* browser_context,
458 const extensions::Extension* extension,
459 extensions::UnloadedExtensionInfo::Reason reason) {
460 if (extension->id() == extension_id())
461 Close();
462 }
463 void Panel::OnTitlebarClicked(panel::ClickModifier modifier) {
464 if (collection_)
465 collection_->OnPanelTitlebarClicked(this, modifier);
466
467 // Normally the system activates a window when the titlebar is clicked.
468 // However, we prevent system activation of minimized panels, thus the
469 // activation may not have occurred. Also, some OSes (Windows) will
470 // activate a minimized panel on mouse-down regardless of our attempts to
471 // prevent system activation. Attention state is not cleared in that case.
472 // See Panel::OnActiveStateChanged().
473 // Therefore, we ensure activation and clearing of attention state if the
474 // panel has been expanded. If the panel is in a stack, the titlebar click
475 // might minimize the panel and we do not want to activate it to make it
476 // expand again.
477 // These are no-ops if no changes are needed.
478 if (IsMinimized())
479 return;
480 Activate();
481 FlashFrame(false);
482 }
483
484 void Panel::OnMinimizeButtonClicked(panel::ClickModifier modifier) {
485 if (collection_)
486 collection_->OnMinimizeButtonClicked(this, modifier);
487 }
488
489 void Panel::OnRestoreButtonClicked(panel::ClickModifier modifier) {
490 // Clicking the restore button has the same behavior as clicking the titlebar.
491 OnTitlebarClicked(modifier);
492 }
493
494 void Panel::OnWindowSizeAvailable() {
495 ConfigureAutoResize(GetWebContents());
496 }
497
498 void Panel::OnNativePanelClosed() {
499 // Ensure previously enqueued OnImageLoaded callbacks are ignored.
500 image_loader_ptr_factory_.InvalidateWeakPtrs();
501 registrar_.RemoveAll();
502 extension_registry_->RemoveObserver(this);
503 manager()->OnPanelClosed(this);
504 DCHECK(!collection_);
505 }
506
507 StackedPanelCollection* Panel::stack() const {
508 return collection_ && collection_->type() == PanelCollection::STACKED ?
509 static_cast<StackedPanelCollection*>(collection_) : NULL;
510 }
511
512 panel::Resizability Panel::CanResizeByMouse() const {
513 if (!collection_)
514 return panel::NOT_RESIZABLE;
515
516 return collection_->GetPanelResizability(this);
517 }
518
519 void Panel::Initialize(const GURL& url,
520 content::SiteInstance* source_site_instance,
521 const gfx::Rect& bounds,
522 bool always_on_top) {
523 DCHECK(!initialized_);
524 DCHECK(!collection_); // Cannot be added to a collection until fully created.
525 DCHECK_EQ(EXPANDED, expansion_state_);
526 DCHECK(!bounds.IsEmpty());
527 initialized_ = true;
528 full_size_ = bounds.size();
529 native_panel_ = CreateNativePanel(this, bounds, always_on_top);
530
531 extension_window_controller_.reset(
532 new panel_internal::PanelExtensionWindowController(this, profile_));
533
534 InitCommandState();
535
536 // Set up hosting for web contents.
537 panel_host_.reset(new PanelHost(this, profile_));
538 panel_host_->Init(url, source_site_instance);
539 content::WebContents* web_contents = GetWebContents();
540 // The contents might be NULL for most of our tests.
541 if (web_contents) {
542 native_panel_->AttachWebContents(web_contents);
543
544 // Make the panel show up in the task manager.
545 task_manager::WebContentsTags::CreateForPanel(web_contents, this);
546 }
547
548 // Close when the extension is unloaded or the browser is exiting.
549 extension_registry_->AddObserver(this);
550 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
551 content::NotificationService::AllSources());
552 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
553 content::Source<ThemeService>(
554 ThemeServiceFactory::GetForProfile(profile_)));
555
556 // TODO(dgn): Should keep_alive be always registered regardless of the platform
557 // here? (https://crbug.com/590173)
558 #if !defined(USE_AURA)
559 // Keep alive for AURA has been moved to panel_view.
560 // Prevent the browser process from shutting down while this window is open.
561 keep_alive_.reset(new ScopedKeepAlive(KeepAliveOrigin::PANEL,
562 KeepAliveRestartOption::DISABLED));
563 #endif
564
565 UpdateAppIcon();
566 }
567
568 void Panel::SetPanelBounds(const gfx::Rect& bounds) {
569 if (bounds != native_panel_->GetPanelBounds())
570 native_panel_->SetPanelBounds(bounds);
571 }
572
573 void Panel::SetPanelBoundsInstantly(const gfx::Rect& bounds) {
574 native_panel_->SetPanelBoundsInstantly(bounds);
575 }
576
577 void Panel::LimitSizeToWorkArea(const gfx::Rect& work_area) {
578 int max_width = manager()->GetMaxPanelWidth(work_area);
579 int max_height = manager()->GetMaxPanelHeight(work_area);
580
581 // If the custom max size is used, ensure that it does not exceed the display
582 // area.
583 if (max_size_policy_ == CUSTOM_MAX_SIZE) {
584 int current_max_width = max_size_.width();
585 if (current_max_width > max_width)
586 max_width = std::min(current_max_width, work_area.width());
587 int current_max_height = max_size_.height();
588 if (current_max_height > max_height)
589 max_height = std::min(current_max_height, work_area.height());
590 }
591
592 SetSizeRange(min_size_, gfx::Size(max_width, max_height));
593
594 // Ensure that full size does not exceed max size.
595 full_size_ = ClampSize(full_size_);
596 }
597
598 void Panel::SetAutoResizable(bool resizable) {
599 if (auto_resizable_ == resizable)
600 return;
601
602 auto_resizable_ = resizable;
603 content::WebContents* web_contents = GetWebContents();
604 if (auto_resizable_) {
605 if (web_contents)
606 EnableWebContentsAutoResize(web_contents);
607 } else {
608 if (web_contents) {
609 content::WebContentsObserver::Observe(nullptr);
610
611 // NULL might be returned if the tab has not been added.
612 RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
613 if (render_view_host)
614 render_view_host->DisableAutoResize(full_size_);
615 }
616 }
617 }
618
619 void Panel::EnableWebContentsAutoResize(content::WebContents* web_contents) {
620 DCHECK(web_contents);
621 ConfigureAutoResize(web_contents);
622
623 // We also need to know when the render view host changes in order
624 // to turn on auto-resize notifications in the new render view host.
625 content::WebContentsObserver::Observe(web_contents);
626 }
627
628 void Panel::OnContentsAutoResized(const gfx::Size& new_content_size) {
629 DCHECK(auto_resizable_);
630 if (!collection_)
631 return;
632
633 gfx::Size new_window_size =
634 native_panel_->WindowSizeFromContentSize(new_content_size);
635
636 // Ignore content auto resizes until window frame size is known.
637 // This reduces extra resizes when panel is first shown.
638 // After window frame size is known, it will trigger another content
639 // auto resize.
640 if (new_content_size == new_window_size)
641 return;
642
643 collection_->ResizePanelWindow(this, new_window_size);
644 }
645
646 void Panel::OnWindowResizedByMouse(const gfx::Rect& new_bounds) {
647 if (collection_)
648 collection_->OnPanelResizedByMouse(this, new_bounds);
649 }
650
651 void Panel::SetSizeRange(const gfx::Size& min_size, const gfx::Size& max_size) {
652 if (min_size == min_size_ && max_size == max_size_)
653 return;
654
655 DCHECK(min_size.width() <= max_size.width());
656 DCHECK(min_size.height() <= max_size.height());
657 min_size_ = min_size;
658 max_size_ = max_size;
659
660 ConfigureAutoResize(GetWebContents());
661 }
662
663 void Panel::IncreaseMaxSize(const gfx::Size& desired_panel_size) {
664 gfx::Size new_max_size = max_size_;
665 if (new_max_size.width() < desired_panel_size.width())
666 new_max_size.set_width(desired_panel_size.width());
667 if (new_max_size.height() < desired_panel_size.height())
668 new_max_size.set_height(desired_panel_size.height());
669
670 SetSizeRange(min_size_, new_max_size);
671 }
672
673 void Panel::HandleKeyboardEvent(const content::NativeWebKeyboardEvent& event) {
674 native_panel_->HandlePanelKeyboardEvent(event);
675 }
676
677 void Panel::SetPreviewMode(bool in_preview) {
678 DCHECK_NE(in_preview_mode_, in_preview);
679 in_preview_mode_ = in_preview;
680 }
681
682 void Panel::UpdateMinimizeRestoreButtonVisibility() {
683 native_panel_->UpdatePanelMinimizeRestoreButtonVisibility();
684 }
685
686 gfx::Size Panel::ClampSize(const gfx::Size& size) const {
687 // The panel width:
688 // * cannot grow or shrink to go beyond [min_width, max_width]
689 int new_width = size.width();
690 if (new_width > max_size_.width())
691 new_width = max_size_.width();
692 if (new_width < min_size_.width())
693 new_width = min_size_.width();
694
695 // The panel height:
696 // * cannot grow or shrink to go beyond [min_height, max_height]
697 int new_height = size.height();
698 if (new_height > max_size_.height())
699 new_height = max_size_.height();
700 if (new_height < min_size_.height())
701 new_height = min_size_.height();
702
703 return gfx::Size(new_width, new_height);
704 }
705
706 void Panel::OnActiveStateChanged(bool active) {
707 // Clear attention state when an expanded panel becomes active.
708 // On some systems (e.g. Win), mouse-down activates a panel regardless of
709 // its expansion state. However, we don't want to clear draw attention if
710 // contents are not visible. In that scenario, if the mouse-down results
711 // in a mouse-click, draw attention will be cleared then.
712 // See Panel::OnTitlebarClicked().
713 if (active && IsDrawingAttention() && !IsMinimized())
714 FlashFrame(false);
715
716 if (collection_)
717 collection_->OnPanelActiveStateChanged(this);
718
719 // Send extension event about window changing active state.
720 extensions::TabsWindowsAPI* tabs_windows_api =
721 extensions::TabsWindowsAPI::Get(profile());
722 if (tabs_windows_api) {
723 tabs_windows_api->windows_event_router()->OnActiveWindowChanged(
724 active ? extension_window_controller_.get() : NULL);
725 }
726
727 content::NotificationService::current()->Notify(
728 chrome::NOTIFICATION_PANEL_CHANGED_ACTIVE_STATUS,
729 content::Source<Panel>(this),
730 content::NotificationService::NoDetails());
731 }
732
733 void Panel::OnPanelStartUserResizing() {
734 SetAutoResizable(false);
735 SetPreviewMode(true);
736 max_size_policy_ = CUSTOM_MAX_SIZE;
737 }
738
739 void Panel::OnPanelEndUserResizing() {
740 SetPreviewMode(false);
741 }
742
743 bool Panel::ShouldCloseWindow() {
744 return true;
745 }
746
747 void Panel::OnWindowClosing() {
748 if (GetWebContents()) {
749 native_panel_->DetachWebContents(GetWebContents());
750 panel_host_->DestroyWebContents();
751 }
752 }
753
754 bool Panel::ExecuteCommandIfEnabled(int id) {
755 if (command_updater()->SupportsCommand(id) &&
756 command_updater()->IsCommandEnabled(id)) {
757 ExecuteCommandWithDisposition(id, CURRENT_TAB);
758 return true;
759 }
760 return false;
761 }
762
763 base::string16 Panel::GetWindowTitle() const {
764 content::WebContents* contents = GetWebContents();
765 base::string16 title;
766
767 // |contents| can be NULL during the window's creation.
768 if (contents) {
769 title = contents->GetTitle();
770 FormatTitleForDisplay(&title);
771 }
772
773 if (title.empty())
774 title = base::UTF8ToUTF16(app_name());
775
776 return title;
777 }
778
779 gfx::Image Panel::GetCurrentPageIcon() const {
780 return panel_host_.get() ? panel_host_->GetPageIcon() : gfx::Image();
781 }
782
783 void Panel::UpdateTitleBar() {
784 native_panel_->UpdatePanelTitleBar();
785 }
786
787 void Panel::LoadingStateChanged(bool is_loading) {
788 command_updater_.UpdateCommandEnabled(IDC_STOP, is_loading);
789 native_panel_->UpdatePanelLoadingAnimations(is_loading);
790 UpdateTitleBar();
791 }
792
793 void Panel::MoveByInstantly(const gfx::Vector2d& delta_origin) {
794 gfx::Rect bounds = GetBounds();
795 bounds.Offset(delta_origin);
796 SetPanelBoundsInstantly(bounds);
797 }
798
799 void Panel::SetWindowCornerStyle(panel::CornerStyle corner_style) {
800 native_panel_->SetWindowCornerStyle(corner_style);
801 }
802
803 void Panel::MinimizeBySystem() {
804 native_panel_->MinimizePanelBySystem();
805 }
806
807 Panel::Panel(Profile* profile,
808 const std::string& app_name,
809 const gfx::Size& min_size,
810 const gfx::Size& max_size)
811 : app_name_(app_name),
812 profile_(profile),
813 collection_(NULL),
814 initialized_(false),
815 min_size_(min_size),
816 max_size_(max_size),
817 max_size_policy_(DEFAULT_MAX_SIZE),
818 auto_resizable_(false),
819 in_preview_mode_(false),
820 native_panel_(NULL),
821 attention_mode_(USE_PANEL_ATTENTION),
822 expansion_state_(EXPANDED),
823 command_updater_(this),
824 extension_registry_(extensions::ExtensionRegistry::Get(profile_)),
825 image_loader_ptr_factory_(this) {
826 }
827
828 void Panel::OnImageLoaded(const gfx::Image& image) {
829 if (!image.IsEmpty()) {
830 app_icon_ = image;
831 native_panel_->UpdatePanelTitleBar();
832 }
833
834 content::NotificationService::current()->Notify(
835 chrome::NOTIFICATION_PANEL_APP_ICON_LOADED,
836 content::Source<Panel>(this),
837 content::NotificationService::NoDetails());
838 }
839
840 void Panel::InitCommandState() {
841 // All supported commands whose state isn't set automagically some other way
842 // (like Stop during a page load) must have their state initialized here,
843 // otherwise they will be forever disabled.
844
845 // Navigation commands
846 command_updater_.UpdateCommandEnabled(IDC_RELOAD, true);
847 command_updater_.UpdateCommandEnabled(IDC_RELOAD_BYPASSING_CACHE, true);
848
849 // Window management commands
850 command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true);
851 command_updater_.UpdateCommandEnabled(IDC_EXIT, true);
852
853 // Zoom
854 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MENU, true);
855 command_updater_.UpdateCommandEnabled(IDC_ZOOM_PLUS, true);
856 command_updater_.UpdateCommandEnabled(IDC_ZOOM_NORMAL, true);
857 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MINUS, true);
858
859 // Clipboard
860 command_updater_.UpdateCommandEnabled(IDC_COPY, true);
861 command_updater_.UpdateCommandEnabled(IDC_CUT, true);
862 command_updater_.UpdateCommandEnabled(IDC_PASTE, true);
863
864 // DevTools
865 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS, true);
866 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_CONSOLE, true);
867 }
868
869 void Panel::ConfigureAutoResize(content::WebContents* web_contents) {
870 if (!auto_resizable_ || !web_contents)
871 return;
872
873 // NULL might be returned if the tab has not been added.
874 RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
875 if (!render_view_host)
876 return;
877
878 render_view_host->EnableAutoResize(
879 min_size_,
880 native_panel_->ContentSizeFromWindowSize(max_size_));
881 }
882
883 void Panel::UpdateAppIcon() {
884 const extensions::Extension* extension = GetExtension();
885 if (!extension)
886 return;
887
888 extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile());
889 loader->LoadImageAsync(
890 extension,
891 extensions::IconsInfo::GetIconResource(
892 extension,
893 extension_misc::EXTENSION_ICON_SMALL,
894 ExtensionIconSet::MATCH_BIGGER),
895 gfx::Size(extension_misc::EXTENSION_ICON_SMALL,
896 extension_misc::EXTENSION_ICON_SMALL),
897 base::Bind(&Panel::OnImageLoaded,
898 image_loader_ptr_factory_.GetWeakPtr()));
899 }
900
901 // static
902 void Panel::FormatTitleForDisplay(base::string16* title) {
903 size_t current_index = 0;
904 size_t match_index;
905 while ((match_index = title->find(L'\n', current_index)) !=
906 base::string16::npos) {
907 title->replace(match_index, 1, base::string16());
908 current_index = match_index;
909 }
910 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/panels/panel.h ('k') | chrome/browser/ui/panels/panel_bounds_animation.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698