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

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

Powered by Google App Engine
This is Rietveld 408576698