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

Side by Side Diff: chrome/browser/ui/extensions/shell_window.cc

Issue 16702003: Move ShellWindow into apps component. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: yar Created 7 years, 5 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/extensions/shell_window.h"
6
7 #include "apps/shell_window_geometry_cache.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/values.h"
10 #include "chrome/browser/extensions/app_window_contents.h"
11 #include "chrome/browser/extensions/extension_process_manager.h"
12 #include "chrome/browser/extensions/extension_system.h"
13 #include "chrome/browser/extensions/image_loader.h"
14 #include "chrome/browser/extensions/shell_window_registry.h"
15 #include "chrome/browser/extensions/suggest_permission_util.h"
16 #include "chrome/browser/favicon/favicon_tab_helper.h"
17 #include "chrome/browser/file_select_helper.h"
18 #include "chrome/browser/lifetime/application_lifetime.h"
19 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
20 #include "chrome/browser/platform_util.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/sessions/session_id.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_dialogs.h"
25 #include "chrome/browser/ui/browser_finder.h"
26 #include "chrome/browser/ui/browser_tabstrip.h"
27 #include "chrome/browser/ui/browser_window.h"
28 #include "chrome/browser/ui/extensions/native_app_window.h"
29 #include "chrome/common/chrome_notification_types.h"
30 #include "chrome/common/extensions/extension.h"
31 #include "chrome/common/extensions/extension_constants.h"
32 #include "chrome/common/extensions/extension_messages.h"
33 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
34 #include "components/web_modal/web_contents_modal_dialog_manager.h"
35 #include "content/public/browser/invalidate_type.h"
36 #include "content/public/browser/navigation_entry.h"
37 #include "content/public/browser/notification_details.h"
38 #include "content/public/browser/notification_service.h"
39 #include "content/public/browser/notification_source.h"
40 #include "content/public/browser/notification_types.h"
41 #include "content/public/browser/render_view_host.h"
42 #include "content/public/browser/resource_dispatcher_host.h"
43 #include "content/public/browser/web_contents.h"
44 #include "content/public/common/media_stream_request.h"
45 #include "extensions/browser/view_type_utils.h"
46 #include "skia/ext/image_operations.h"
47 #include "third_party/skia/include/core/SkRegion.h"
48 #include "ui/gfx/image/image_skia.h"
49 #include "ui/gfx/screen.h"
50
51 #if defined(USE_ASH)
52 #include "ash/launcher/launcher_types.h"
53 #endif
54
55 using content::ConsoleMessageLevel;
56 using content::WebContents;
57 using extensions::APIPermission;
58 using web_modal::WebContentsModalDialogHost;
59 using web_modal::WebContentsModalDialogManager;
60
61 namespace {
62 const int kDefaultWidth = 512;
63 const int kDefaultHeight = 384;
64
65 // The preferred icon size for displaying the app icon.
66 #if defined(USE_ASH)
67 const int kPreferredIconSize = ash::kLauncherPreferredSize;
68 #else
69 const int kPreferredIconSize = extension_misc::EXTENSION_ICON_SMALL;
70 #endif
71
72 static bool disable_external_open_for_testing_ = false;
73
74 class ShellWindowLinkDelegate : public content::WebContentsDelegate {
75 private:
76 virtual content::WebContents* OpenURLFromTab(
77 content::WebContents* source,
78 const content::OpenURLParams& params) OVERRIDE;
79 };
80
81 content::WebContents* ShellWindowLinkDelegate::OpenURLFromTab(
82 content::WebContents* source,
83 const content::OpenURLParams& params) {
84 platform_util::OpenExternal(params.url);
85 delete source;
86 return NULL;
87 }
88
89 } // namespace
90
91 ShellWindow::CreateParams::CreateParams()
92 : window_type(ShellWindow::WINDOW_TYPE_DEFAULT),
93 frame(ShellWindow::FRAME_CHROME),
94 transparent_background(false),
95 bounds(INT_MIN, INT_MIN, 0, 0),
96 creator_process_id(0),
97 state(ui::SHOW_STATE_DEFAULT),
98 hidden(false),
99 resizable(true),
100 focused(true) {
101 }
102
103 ShellWindow::CreateParams::~CreateParams() {
104 }
105
106 ShellWindow* ShellWindow::Create(Profile* profile,
107 const extensions::Extension* extension,
108 const GURL& url,
109 const CreateParams& params) {
110 // This object will delete itself when the window is closed.
111 ShellWindow* window = new ShellWindow(profile, extension);
112 window->Init(url, new AppWindowContents(window), params);
113 extensions::ShellWindowRegistry::Get(profile)->AddShellWindow(window);
114 return window;
115 }
116
117 ShellWindow::ShellWindow(Profile* profile,
118 const extensions::Extension* extension)
119 : profile_(profile),
120 extension_(extension),
121 extension_id_(extension->id()),
122 window_type_(WINDOW_TYPE_DEFAULT),
123 image_loader_ptr_factory_(this),
124 fullscreen_for_window_api_(false),
125 fullscreen_for_tab_(false) {
126 }
127
128 void ShellWindow::Init(const GURL& url,
129 ShellWindowContents* shell_window_contents,
130 const CreateParams& params) {
131 // Initialize the render interface and web contents
132 shell_window_contents_.reset(shell_window_contents);
133 shell_window_contents_->Initialize(profile(), url);
134 WebContents* web_contents = shell_window_contents_->GetWebContents();
135 WebContentsModalDialogManager::CreateForWebContents(web_contents);
136 FaviconTabHelper::CreateForWebContents(web_contents);
137
138 web_contents->SetDelegate(this);
139 WebContentsModalDialogManager::FromWebContents(web_contents)->
140 set_delegate(this);
141 extensions::SetViewType(web_contents, extensions::VIEW_TYPE_APP_SHELL);
142
143 // Initialize the window
144 window_type_ = params.window_type;
145
146 gfx::Rect bounds = params.bounds;
147
148 if (bounds.width() == 0)
149 bounds.set_width(kDefaultWidth);
150 if (bounds.height() == 0)
151 bounds.set_height(kDefaultHeight);
152
153 // If left and top are left undefined, the native shell window will center
154 // the window on the main screen in a platform-defined manner.
155
156 ui::WindowShowState cached_state = ui::SHOW_STATE_DEFAULT;
157 if (!params.window_key.empty()) {
158 window_key_ = params.window_key;
159
160 apps::ShellWindowGeometryCache* cache =
161 apps::ShellWindowGeometryCache::Get(profile());
162
163 gfx::Rect cached_bounds;
164 gfx::Rect cached_screen_bounds;
165 if (cache->GetGeometry(extension()->id(), params.window_key, &cached_bounds,
166 &cached_screen_bounds, &cached_state)) {
167 bounds = cached_bounds;
168 // App window has cached screen bounds, make sure it fits on screen in
169 // case the screen resolution changed.
170 if (!cached_screen_bounds.IsEmpty()) {
171 gfx::Screen* screen = gfx::Screen::GetNativeScreen();
172 gfx::Display display = screen->GetDisplayMatching(cached_bounds);
173 gfx::Rect current_screen_bounds = display.work_area();
174 AdjustBoundsToBeVisibleOnScreen(cached_bounds,
175 cached_screen_bounds,
176 current_screen_bounds,
177 params.minimum_size,
178 &bounds);
179 }
180 }
181 }
182
183 CreateParams new_params = params;
184
185 gfx::Size& minimum_size = new_params.minimum_size;
186 gfx::Size& maximum_size = new_params.maximum_size;
187
188 // In the case that minimum size > maximum size, we consider the minimum
189 // size to be more important.
190 if (maximum_size.width() && maximum_size.width() < minimum_size.width())
191 maximum_size.set_width(minimum_size.width());
192 if (maximum_size.height() && maximum_size.height() < minimum_size.height())
193 maximum_size.set_height(minimum_size.height());
194
195 if (maximum_size.width() && bounds.width() > maximum_size.width())
196 bounds.set_width(maximum_size.width());
197 if (bounds.width() != INT_MIN && bounds.width() < minimum_size.width())
198 bounds.set_width(minimum_size.width());
199
200 if (maximum_size.height() && bounds.height() > maximum_size.height())
201 bounds.set_height(maximum_size.height());
202 if (bounds.height() != INT_MIN && bounds.height() < minimum_size.height())
203 bounds.set_height(minimum_size.height());
204
205 new_params.bounds = bounds;
206
207 if (cached_state != ui::SHOW_STATE_DEFAULT)
208 new_params.state = cached_state;
209
210 native_app_window_.reset(NativeAppWindow::Create(this, new_params));
211
212 if (!new_params.hidden) {
213 if (window_type_is_panel())
214 GetBaseWindow()->ShowInactive(); // Panels are not activated by default.
215 else
216 GetBaseWindow()->Show();
217 }
218
219 if (new_params.state == ui::SHOW_STATE_FULLSCREEN)
220 Fullscreen();
221 else if (new_params.state == ui::SHOW_STATE_MAXIMIZED)
222 Maximize();
223 else if (new_params.state == ui::SHOW_STATE_MINIMIZED)
224 Minimize();
225
226 OnNativeWindowChanged();
227
228 // When the render view host is changed, the native window needs to know
229 // about it in case it has any setup to do to make the renderer appear
230 // properly. In particular, on Windows, the view's clickthrough region needs
231 // to be set.
232 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
233 content::Source<content::NavigationController>(
234 &web_contents->GetController()));
235 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
236 content::Source<Profile>(profile_));
237 // Close when the browser is exiting.
238 // TODO(mihaip): we probably don't want this in the long run (when platform
239 // apps are no longer tied to the browser process).
240 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
241 content::NotificationService::AllSources());
242
243 shell_window_contents_->LoadContents(params.creator_process_id);
244
245 // Prevent the browser process from shutting down while this window is open.
246 chrome::StartKeepAlive();
247
248 UpdateExtensionAppIcon();
249 }
250
251 ShellWindow::~ShellWindow() {
252 // Unregister now to prevent getting NOTIFICATION_APP_TERMINATING if we're the
253 // last window open.
254 registrar_.RemoveAll();
255
256 // Remove shutdown prevention.
257 chrome::EndKeepAlive();
258 }
259
260 void ShellWindow::RequestMediaAccessPermission(
261 content::WebContents* web_contents,
262 const content::MediaStreamRequest& request,
263 const content::MediaResponseCallback& callback) {
264 MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
265 web_contents, request, callback, extension());
266 }
267
268 WebContents* ShellWindow::OpenURLFromTab(WebContents* source,
269 const content::OpenURLParams& params) {
270 // Don't allow the current tab to be navigated. It would be nice to map all
271 // anchor tags (even those without target="_blank") to new tabs, but right
272 // now we can't distinguish between those and <meta> refreshes or window.href
273 // navigations, which we don't want to allow.
274 // TOOD(mihaip): Can we check for user gestures instead?
275 WindowOpenDisposition disposition = params.disposition;
276 if (disposition == CURRENT_TAB) {
277 AddMessageToDevToolsConsole(
278 content::CONSOLE_MESSAGE_LEVEL_ERROR,
279 base::StringPrintf(
280 "Can't open same-window link to \"%s\"; try target=\"_blank\".",
281 params.url.spec().c_str()));
282 return NULL;
283 }
284
285 // These dispositions aren't really navigations.
286 if (disposition == SUPPRESS_OPEN || disposition == SAVE_TO_DISK ||
287 disposition == IGNORE_ACTION) {
288 return NULL;
289 }
290
291 // Force all links to open in a new tab, even if they were trying to open a
292 // window.
293 chrome::NavigateParams new_tab_params(
294 static_cast<Browser*>(NULL), params.url, params.transition);
295 new_tab_params.disposition =
296 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
297 new_tab_params.initiating_profile = profile_;
298 chrome::Navigate(&new_tab_params);
299
300 if (!new_tab_params.target_contents) {
301 AddMessageToDevToolsConsole(
302 content::CONSOLE_MESSAGE_LEVEL_ERROR,
303 base::StringPrintf(
304 "Can't navigate to \"%s\"; apps do not support navigation.",
305 params.url.spec().c_str()));
306 }
307
308 return new_tab_params.target_contents;
309 }
310
311 void ShellWindow::AddNewContents(WebContents* source,
312 WebContents* new_contents,
313 WindowOpenDisposition disposition,
314 const gfx::Rect& initial_pos,
315 bool user_gesture,
316 bool* was_blocked) {
317 DCHECK(Profile::FromBrowserContext(new_contents->GetBrowserContext()) ==
318 profile_);
319 #if defined(OS_MACOSX) || defined(OS_WIN) || \
320 (defined(OS_LINUX) && !defined(OS_CHROMEOS))
321 if (disable_external_open_for_testing_) {
322 Browser* browser =
323 chrome::FindOrCreateTabbedBrowser(profile_, chrome::GetActiveDesktop());
324 // Force all links to open in a new tab, even if they were trying to open a
325 // new window.
326 disposition =
327 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
328 chrome::AddWebContents(browser, NULL, new_contents, disposition,
329 initial_pos, user_gesture, was_blocked);
330 } else {
331 new_contents->SetDelegate(new ShellWindowLinkDelegate());
332 }
333 #else
334 Browser* browser =
335 chrome::FindOrCreateTabbedBrowser(profile_, chrome::GetActiveDesktop());
336 // Force all links to open in a new tab, even if they were trying to open a
337 // new window.
338 disposition =
339 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
340 chrome::AddWebContents(browser, NULL, new_contents, disposition, initial_pos,
341 user_gesture, was_blocked);
342 #endif
343 }
344
345 void ShellWindow::HandleKeyboardEvent(
346 WebContents* source,
347 const content::NativeWebKeyboardEvent& event) {
348 native_app_window_->HandleKeyboardEvent(event);
349 }
350
351 void ShellWindow::RequestToLockMouse(WebContents* web_contents,
352 bool user_gesture,
353 bool last_unlocked_by_target) {
354 bool has_permission = IsExtensionWithPermissionOrSuggestInConsole(
355 APIPermission::kPointerLock,
356 extension_,
357 web_contents->GetRenderViewHost());
358
359 web_contents->GotResponseToLockMouseRequest(has_permission);
360 }
361
362 void ShellWindow::OnNativeClose() {
363 extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
364 if (shell_window_contents_)
365 shell_window_contents_->NativeWindowClosed();
366 delete this;
367 }
368
369 void ShellWindow::OnNativeWindowChanged() {
370 SaveWindowPosition();
371 if (shell_window_contents_ && native_app_window_)
372 shell_window_contents_->NativeWindowChanged(native_app_window_.get());
373 }
374
375 void ShellWindow::OnNativeWindowActivated() {
376 extensions::ShellWindowRegistry::Get(profile_)->ShellWindowActivated(this);
377 }
378
379 scoped_ptr<gfx::Image> ShellWindow::GetAppListIcon() {
380 // TODO(skuhne): We might want to use LoadImages in UpdateExtensionAppIcon
381 // instead to let the extension give us pre-defined icons in the launcher
382 // and the launcher list sizes. Since there is no mock yet, doing this now
383 // seems a bit premature and we scale for the time being.
384 if (app_icon_.IsEmpty())
385 return make_scoped_ptr(new gfx::Image());
386
387 SkBitmap bmp = skia::ImageOperations::Resize(
388 *app_icon_.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST,
389 extension_misc::EXTENSION_ICON_SMALLISH,
390 extension_misc::EXTENSION_ICON_SMALLISH);
391 return make_scoped_ptr(
392 new gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(bmp)));
393 }
394
395 content::WebContents* ShellWindow::web_contents() const {
396 return shell_window_contents_->GetWebContents();
397 }
398
399 NativeAppWindow* ShellWindow::GetBaseWindow() {
400 return native_app_window_.get();
401 }
402
403 gfx::NativeWindow ShellWindow::GetNativeWindow() {
404 return GetBaseWindow()->GetNativeWindow();
405 }
406
407 gfx::Rect ShellWindow::GetClientBounds() const {
408 gfx::Rect bounds = native_app_window_->GetBounds();
409 bounds.Inset(native_app_window_->GetFrameInsets());
410 return bounds;
411 }
412
413 string16 ShellWindow::GetTitle() const {
414 // WebContents::GetTitle() will return the page's URL if there's no <title>
415 // specified. However, we'd prefer to show the name of the extension in that
416 // case, so we directly inspect the NavigationEntry's title.
417 if (!web_contents() ||
418 !web_contents()->GetController().GetActiveEntry() ||
419 web_contents()->GetController().GetActiveEntry()->GetTitle().empty())
420 return UTF8ToUTF16(extension()->name());
421 string16 title = web_contents()->GetTitle();
422 Browser::FormatTitleForDisplay(&title);
423 return title;
424 }
425
426 void ShellWindow::SetAppIconUrl(const GURL& url) {
427 // Avoid using any previous app icons were are being downloaded.
428 image_loader_ptr_factory_.InvalidateWeakPtrs();
429
430 app_icon_url_ = url;
431 web_contents()->DownloadImage(
432 url,
433 true, // is a favicon
434 kPreferredIconSize,
435 0, // no maximum size
436 base::Bind(&ShellWindow::DidDownloadFavicon,
437 image_loader_ptr_factory_.GetWeakPtr()));
438 }
439
440 void ShellWindow::UpdateDraggableRegions(
441 const std::vector<extensions::DraggableRegion>& regions) {
442 native_app_window_->UpdateDraggableRegions(regions);
443 }
444
445 void ShellWindow::UpdateAppIcon(const gfx::Image& image) {
446 if (image.IsEmpty())
447 return;
448 app_icon_ = image;
449 native_app_window_->UpdateWindowIcon();
450 extensions::ShellWindowRegistry::Get(profile_)->ShellWindowIconChanged(this);
451 }
452
453 void ShellWindow::Fullscreen() {
454 fullscreen_for_window_api_ = true;
455 GetBaseWindow()->SetFullscreen(true);
456 }
457
458 void ShellWindow::Maximize() {
459 GetBaseWindow()->Maximize();
460 }
461
462 void ShellWindow::Minimize() {
463 GetBaseWindow()->Minimize();
464 }
465
466 void ShellWindow::Restore() {
467 fullscreen_for_window_api_ = false;
468 fullscreen_for_tab_ = false;
469 if (GetBaseWindow()->IsFullscreenOrPending()) {
470 GetBaseWindow()->SetFullscreen(false);
471 } else {
472 GetBaseWindow()->Restore();
473 }
474 }
475
476 //------------------------------------------------------------------------------
477 // Private methods
478
479 void ShellWindow::OnImageLoaded(const gfx::Image& image) {
480 UpdateAppIcon(image);
481 }
482
483 void ShellWindow::DidDownloadFavicon(int id,
484 int http_status_code,
485 const GURL& image_url,
486 int requested_size,
487 const std::vector<SkBitmap>& bitmaps) {
488 if (image_url != app_icon_url_ || bitmaps.empty())
489 return;
490
491 // Bitmaps are ordered largest to smallest. Choose the smallest bitmap
492 // whose height >= the preferred size.
493 int largest_index = 0;
494 for (size_t i = 1; i < bitmaps.size(); ++i) {
495 if (bitmaps[i].height() < kPreferredIconSize)
496 break;
497 largest_index = i;
498 }
499 const SkBitmap& largest = bitmaps[largest_index];
500 UpdateAppIcon(gfx::Image::CreateFrom1xBitmap(largest));
501 }
502
503 void ShellWindow::UpdateExtensionAppIcon() {
504 // Avoid using any previous app icons were are being downloaded.
505 image_loader_ptr_factory_.InvalidateWeakPtrs();
506
507 // Enqueue OnImageLoaded callback.
508 extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile());
509 loader->LoadImageAsync(
510 extension(),
511 extensions::IconsInfo::GetIconResource(extension(),
512 kPreferredIconSize,
513 ExtensionIconSet::MATCH_BIGGER),
514 gfx::Size(kPreferredIconSize, kPreferredIconSize),
515 base::Bind(&ShellWindow::OnImageLoaded,
516 image_loader_ptr_factory_.GetWeakPtr()));
517 }
518
519 void ShellWindow::CloseContents(WebContents* contents) {
520 native_app_window_->Close();
521 }
522
523 bool ShellWindow::ShouldSuppressDialogs() {
524 return true;
525 }
526
527 content::ColorChooser* ShellWindow::OpenColorChooser(WebContents* web_contents,
528 SkColor initial_color) {
529 return chrome::ShowColorChooser(web_contents, initial_color);
530 }
531
532 void ShellWindow::RunFileChooser(WebContents* tab,
533 const content::FileChooserParams& params) {
534 if (window_type_is_panel()) {
535 // Panels can't host a file dialog, abort. TODO(stevenjb): allow file
536 // dialogs to be unhosted but still close with the owning web contents.
537 // crbug.com/172502.
538 LOG(WARNING) << "File dialog opened by panel.";
539 return;
540 }
541 FileSelectHelper::RunFileChooser(tab, params);
542 }
543
544 bool ShellWindow::IsPopupOrPanel(const WebContents* source) const {
545 return true;
546 }
547
548 void ShellWindow::MoveContents(WebContents* source, const gfx::Rect& pos) {
549 native_app_window_->SetBounds(pos);
550 }
551
552 void ShellWindow::NavigationStateChanged(
553 const content::WebContents* source, unsigned changed_flags) {
554 if (changed_flags & content::INVALIDATE_TYPE_TITLE)
555 native_app_window_->UpdateWindowTitle();
556 else if (changed_flags & content::INVALIDATE_TYPE_TAB)
557 native_app_window_->UpdateWindowIcon();
558 }
559
560 void ShellWindow::ToggleFullscreenModeForTab(content::WebContents* source,
561 bool enter_fullscreen) {
562 if (!IsExtensionWithPermissionOrSuggestInConsole(
563 APIPermission::kFullscreen,
564 extension_,
565 source->GetRenderViewHost())) {
566 return;
567 }
568
569 fullscreen_for_tab_ = enter_fullscreen;
570
571 if (enter_fullscreen) {
572 native_app_window_->SetFullscreen(true);
573 } else if (!fullscreen_for_window_api_) {
574 native_app_window_->SetFullscreen(false);
575 }
576 }
577
578 bool ShellWindow::IsFullscreenForTabOrPending(
579 const content::WebContents* source) const {
580 return fullscreen_for_tab_;
581 }
582
583 void ShellWindow::Observe(int type,
584 const content::NotificationSource& source,
585 const content::NotificationDetails& details) {
586 switch (type) {
587 case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: {
588 // TODO(jianli): once http://crbug.com/123007 is fixed, we'll no longer
589 // need to make the native window (ShellWindowViews specially) update
590 // the clickthrough region for the new RVH.
591 native_app_window_->RenderViewHostChanged();
592 break;
593 }
594 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
595 const extensions::Extension* unloaded_extension =
596 content::Details<extensions::UnloadedExtensionInfo>(
597 details)->extension;
598 if (extension_ == unloaded_extension)
599 native_app_window_->Close();
600 break;
601 }
602 case chrome::NOTIFICATION_APP_TERMINATING:
603 native_app_window_->Close();
604 break;
605 default:
606 NOTREACHED() << "Received unexpected notification";
607 }
608 }
609
610 extensions::ActiveTabPermissionGranter*
611 ShellWindow::GetActiveTabPermissionGranter() {
612 // Shell windows don't support the activeTab permission.
613 return NULL;
614 }
615
616 WebContentsModalDialogHost* ShellWindow::GetWebContentsModalDialogHost() {
617 return native_app_window_.get();
618 }
619
620 void ShellWindow::AddMessageToDevToolsConsole(ConsoleMessageLevel level,
621 const std::string& message) {
622 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
623 rvh->Send(new ExtensionMsg_AddMessageToConsole(
624 rvh->GetRoutingID(), level, message));
625 }
626
627 void ShellWindow::SaveWindowPosition() {
628 if (window_key_.empty())
629 return;
630 if (!native_app_window_)
631 return;
632
633 apps::ShellWindowGeometryCache* cache =
634 apps::ShellWindowGeometryCache::Get(profile());
635
636 gfx::Rect bounds = native_app_window_->GetRestoredBounds();
637 bounds.Inset(native_app_window_->GetFrameInsets());
638 gfx::Rect screen_bounds =
639 gfx::Screen::GetNativeScreen()->GetDisplayMatching(bounds).work_area();
640 ui::WindowShowState window_state = native_app_window_->GetRestoredState();
641 cache->SaveGeometry(extension()->id(),
642 window_key_,
643 bounds,
644 screen_bounds,
645 window_state);
646 }
647
648 void ShellWindow::AdjustBoundsToBeVisibleOnScreen(
649 const gfx::Rect& cached_bounds,
650 const gfx::Rect& cached_screen_bounds,
651 const gfx::Rect& current_screen_bounds,
652 const gfx::Size& minimum_size,
653 gfx::Rect* bounds) const {
654 if (!bounds)
655 return;
656
657 *bounds = cached_bounds;
658
659 // Reposition and resize the bounds if the cached_screen_bounds is different
660 // from the current screen bounds and the current screen bounds doesn't
661 // completely contain the bounds.
662 if (!cached_screen_bounds.IsEmpty() &&
663 cached_screen_bounds != current_screen_bounds &&
664 !current_screen_bounds.Contains(cached_bounds)) {
665 bounds->set_width(
666 std::max(minimum_size.width(),
667 std::min(bounds->width(), current_screen_bounds.width())));
668 bounds->set_height(
669 std::max(minimum_size.height(),
670 std::min(bounds->height(), current_screen_bounds.height())));
671 bounds->set_x(
672 std::max(current_screen_bounds.x(),
673 std::min(bounds->x(),
674 current_screen_bounds.right() - bounds->width())));
675 bounds->set_y(
676 std::max(current_screen_bounds.y(),
677 std::min(bounds->y(),
678 current_screen_bounds.bottom() - bounds->height())));
679 }
680 }
681
682 // static
683 SkRegion* ShellWindow::RawDraggableRegionsToSkRegion(
684 const std::vector<extensions::DraggableRegion>& regions) {
685 SkRegion* sk_region = new SkRegion;
686 for (std::vector<extensions::DraggableRegion>::const_iterator iter =
687 regions.begin();
688 iter != regions.end(); ++iter) {
689 const extensions::DraggableRegion& region = *iter;
690 sk_region->op(
691 region.bounds.x(),
692 region.bounds.y(),
693 region.bounds.right(),
694 region.bounds.bottom(),
695 region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
696 }
697 return sk_region;
698 }
699
700 void ShellWindow::DisableExternalOpenForTesting() {
701 disable_external_open_for_testing_ = true;
702 }
703
OLDNEW
« no previous file with comments | « chrome/browser/ui/extensions/shell_window.h ('k') | chrome/browser/ui/gtk/extensions/native_app_window_gtk.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698