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

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: Feedback 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_MACOSX) || defined(OS_WIN) || \
306 (defined(OS_LINUX) && !defined(OS_CHROMEOS))
307 if (disable_external_open_for_testing_) {
308 Browser* browser =
309 chrome::FindOrCreateTabbedBrowser(profile_, chrome::GetActiveDesktop());
310 // Force all links to open in a new tab, even if they were trying to open a
311 // new window.
312 disposition =
313 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
314 chrome::AddWebContents(browser, NULL, new_contents, disposition,
315 initial_pos, user_gesture, was_blocked);
316 } else {
317 new_contents->SetDelegate(new ShellWindowLinkDelegate());
318 }
319 #else
320 Browser* browser =
321 chrome::FindOrCreateTabbedBrowser(profile_, chrome::GetActiveDesktop());
322 // Force all links to open in a new tab, even if they were trying to open a
323 // new window.
324 disposition =
325 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
326 chrome::AddWebContents(browser, NULL, new_contents, disposition, initial_pos,
327 user_gesture, was_blocked);
328 #endif
329 }
330
331 void ShellWindow::HandleKeyboardEvent(
332 WebContents* source,
333 const content::NativeWebKeyboardEvent& event) {
334 native_app_window_->HandleKeyboardEvent(event);
335 }
336
337 void ShellWindow::RequestToLockMouse(WebContents* web_contents,
338 bool user_gesture,
339 bool last_unlocked_by_target) {
340 bool has_permission = IsExtensionWithPermissionOrSuggestInConsole(
341 APIPermission::kPointerLock,
342 extension_,
343 web_contents->GetRenderViewHost());
344
345 web_contents->GotResponseToLockMouseRequest(has_permission);
346 }
347
348 void ShellWindow::OnNativeClose() {
349 extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
350 if (shell_window_contents_)
351 shell_window_contents_->NativeWindowClosed();
352 delete this;
353 }
354
355 void ShellWindow::OnNativeWindowChanged() {
356 SaveWindowPosition();
357 if (shell_window_contents_ && native_app_window_)
358 shell_window_contents_->NativeWindowChanged(native_app_window_.get());
359 }
360
361 void ShellWindow::OnNativeWindowActivated() {
362 extensions::ShellWindowRegistry::Get(profile_)->ShellWindowActivated(this);
363 }
364
365 scoped_ptr<gfx::Image> ShellWindow::GetAppListIcon() {
366 // TODO(skuhne): We might want to use LoadImages in UpdateExtensionAppIcon
367 // instead to let the extension give us pre-defined icons in the launcher
368 // and the launcher list sizes. Since there is no mock yet, doing this now
369 // seems a bit premature and we scale for the time being.
370 if (app_icon_.IsEmpty())
371 return make_scoped_ptr(new gfx::Image());
372
373 SkBitmap bmp = skia::ImageOperations::Resize(
374 *app_icon_.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST,
375 extension_misc::EXTENSION_ICON_SMALLISH,
376 extension_misc::EXTENSION_ICON_SMALLISH);
377 return make_scoped_ptr(
378 new gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(bmp)));
379 }
380
381 content::WebContents* ShellWindow::web_contents() const {
382 return shell_window_contents_->GetWebContents();
383 }
384
385 NativeAppWindow* ShellWindow::GetBaseWindow() {
386 return native_app_window_.get();
387 }
388
389 gfx::NativeWindow ShellWindow::GetNativeWindow() {
390 return GetBaseWindow()->GetNativeWindow();
391 }
392
393 gfx::Rect ShellWindow::GetClientBounds() const {
394 gfx::Rect bounds = native_app_window_->GetBounds();
395 bounds.Inset(native_app_window_->GetFrameInsets());
396 return bounds;
397 }
398
399 string16 ShellWindow::GetTitle() const {
400 // WebContents::GetTitle() will return the page's URL if there's no <title>
401 // specified. However, we'd prefer to show the name of the extension in that
402 // case, so we directly inspect the NavigationEntry's title.
403 if (!web_contents() ||
404 !web_contents()->GetController().GetActiveEntry() ||
405 web_contents()->GetController().GetActiveEntry()->GetTitle().empty())
406 return UTF8ToUTF16(extension()->name());
407 string16 title = web_contents()->GetTitle();
408 Browser::FormatTitleForDisplay(&title);
409 return title;
410 }
411
412 void ShellWindow::SetAppIconUrl(const GURL& url) {
413 // Avoid using any previous app icons were are being downloaded.
414 image_loader_ptr_factory_.InvalidateWeakPtrs();
415
416 app_icon_url_ = url;
417 web_contents()->DownloadImage(
418 url, true, kPreferredIconSize,
419 base::Bind(&ShellWindow::DidDownloadFavicon,
420 image_loader_ptr_factory_.GetWeakPtr()));
421 }
422
423 void ShellWindow::UpdateDraggableRegions(
424 const std::vector<extensions::DraggableRegion>& regions) {
425 native_app_window_->UpdateDraggableRegions(regions);
426 }
427
428 void ShellWindow::UpdateAppIcon(const gfx::Image& image) {
429 if (image.IsEmpty())
430 return;
431 app_icon_ = image;
432 native_app_window_->UpdateWindowIcon();
433 extensions::ShellWindowRegistry::Get(profile_)->ShellWindowIconChanged(this);
434 }
435
436 void ShellWindow::Fullscreen() {
437 fullscreen_for_window_api_ = true;
438 GetBaseWindow()->SetFullscreen(true);
439 }
440
441 void ShellWindow::Maximize() {
442 GetBaseWindow()->Maximize();
443 }
444
445 void ShellWindow::Minimize() {
446 GetBaseWindow()->Minimize();
447 }
448
449 void ShellWindow::Restore() {
450 fullscreen_for_window_api_ = false;
451 fullscreen_for_tab_ = false;
452 if (GetBaseWindow()->IsFullscreenOrPending()) {
453 GetBaseWindow()->SetFullscreen(false);
454 } else {
455 GetBaseWindow()->Restore();
456 }
457 }
458
459 //------------------------------------------------------------------------------
460 // Private methods
461
462 void ShellWindow::OnImageLoaded(const gfx::Image& image) {
463 UpdateAppIcon(image);
464 }
465
466 void ShellWindow::DidDownloadFavicon(int id,
467 int http_status_code,
468 const GURL& image_url,
469 int requested_size,
470 const std::vector<SkBitmap>& bitmaps) {
471 if (image_url != app_icon_url_ || bitmaps.empty())
472 return;
473
474 // Bitmaps are ordered largest to smallest. Choose the smallest bitmap
475 // whose height >= the preferred size.
476 int largest_index = 0;
477 for (size_t i = 1; i < bitmaps.size(); ++i) {
478 if (bitmaps[i].height() < kPreferredIconSize)
479 break;
480 largest_index = i;
481 }
482 const SkBitmap& largest = bitmaps[largest_index];
483 UpdateAppIcon(gfx::Image::CreateFrom1xBitmap(largest));
484 }
485
486 void ShellWindow::UpdateExtensionAppIcon() {
487 // Avoid using any previous app icons were are being downloaded.
488 image_loader_ptr_factory_.InvalidateWeakPtrs();
489
490 // Enqueue OnImageLoaded callback.
491 extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile());
492 loader->LoadImageAsync(
493 extension(),
494 extensions::IconsInfo::GetIconResource(extension(),
495 kPreferredIconSize,
496 ExtensionIconSet::MATCH_BIGGER),
497 gfx::Size(kPreferredIconSize, kPreferredIconSize),
498 base::Bind(&ShellWindow::OnImageLoaded,
499 image_loader_ptr_factory_.GetWeakPtr()));
500 }
501
502 void ShellWindow::CloseContents(WebContents* contents) {
503 native_app_window_->Close();
504 }
505
506 bool ShellWindow::ShouldSuppressDialogs() {
507 return true;
508 }
509
510 content::ColorChooser* ShellWindow::OpenColorChooser(WebContents* web_contents,
511 SkColor initial_color) {
512 return chrome::ShowColorChooser(web_contents, initial_color);
513 }
514
515 void ShellWindow::RunFileChooser(WebContents* tab,
516 const content::FileChooserParams& params) {
517 if (window_type_is_panel()) {
518 // Panels can't host a file dialog, abort. TODO(stevenjb): allow file
519 // dialogs to be unhosted but still close with the owning web contents.
520 // crbug.com/172502.
521 LOG(WARNING) << "File dialog opened by panel.";
522 return;
523 }
524 FileSelectHelper::RunFileChooser(tab, params);
525 }
526
527 bool ShellWindow::IsPopupOrPanel(const WebContents* source) const {
528 return true;
529 }
530
531 void ShellWindow::MoveContents(WebContents* source, const gfx::Rect& pos) {
532 native_app_window_->SetBounds(pos);
533 }
534
535 void ShellWindow::NavigationStateChanged(
536 const content::WebContents* source, unsigned changed_flags) {
537 if (changed_flags & content::INVALIDATE_TYPE_TITLE)
538 native_app_window_->UpdateWindowTitle();
539 else if (changed_flags & content::INVALIDATE_TYPE_TAB)
540 native_app_window_->UpdateWindowIcon();
541 }
542
543 void ShellWindow::ToggleFullscreenModeForTab(content::WebContents* source,
544 bool enter_fullscreen) {
545 if (!IsExtensionWithPermissionOrSuggestInConsole(
546 APIPermission::kFullscreen,
547 extension_,
548 source->GetRenderViewHost())) {
549 return;
550 }
551
552 fullscreen_for_tab_ = enter_fullscreen;
553
554 if (enter_fullscreen) {
555 native_app_window_->SetFullscreen(true);
556 } else if (!fullscreen_for_window_api_) {
557 native_app_window_->SetFullscreen(false);
558 }
559 }
560
561 bool ShellWindow::IsFullscreenForTabOrPending(
562 const content::WebContents* source) const {
563 return fullscreen_for_tab_;
564 }
565
566 void ShellWindow::Observe(int type,
567 const content::NotificationSource& source,
568 const content::NotificationDetails& details) {
569 switch (type) {
570 case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: {
571 // TODO(jianli): once http://crbug.com/123007 is fixed, we'll no longer
572 // need to make the native window (ShellWindowViews specially) update
573 // the clickthrough region for the new RVH.
574 native_app_window_->RenderViewHostChanged();
575 break;
576 }
577 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
578 const extensions::Extension* unloaded_extension =
579 content::Details<extensions::UnloadedExtensionInfo>(
580 details)->extension;
581 if (extension_ == unloaded_extension)
582 native_app_window_->Close();
583 break;
584 }
585 case chrome::NOTIFICATION_APP_TERMINATING:
586 native_app_window_->Close();
587 break;
588 default:
589 NOTREACHED() << "Received unexpected notification";
590 }
591 }
592
593 extensions::ActiveTabPermissionGranter*
594 ShellWindow::GetActiveTabPermissionGranter() {
595 // Shell windows don't support the activeTab permission.
596 return NULL;
597 }
598
599 WebContentsModalDialogHost* ShellWindow::GetWebContentsModalDialogHost() {
600 return native_app_window_.get();
601 }
602
603 void ShellWindow::AddMessageToDevToolsConsole(ConsoleMessageLevel level,
604 const std::string& message) {
605 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
606 rvh->Send(new ExtensionMsg_AddMessageToConsole(
607 rvh->GetRoutingID(), level, message));
608 }
609
610 void ShellWindow::SaveWindowPosition() {
611 if (window_key_.empty())
612 return;
613 if (!native_app_window_)
614 return;
615
616 apps::ShellWindowGeometryCache* cache =
617 apps::ShellWindowGeometryCache::Get(profile());
618
619 gfx::Rect bounds = native_app_window_->GetRestoredBounds();
620 bounds.Inset(native_app_window_->GetFrameInsets());
621 ui::WindowShowState window_state = native_app_window_->GetRestoredState();
622 cache->SaveGeometry(extension()->id(), window_key_, bounds, window_state);
623 }
624
625 // static
626 SkRegion* ShellWindow::RawDraggableRegionsToSkRegion(
627 const std::vector<extensions::DraggableRegion>& regions) {
628 SkRegion* sk_region = new SkRegion;
629 for (std::vector<extensions::DraggableRegion>::const_iterator iter =
630 regions.begin();
631 iter != regions.end(); ++iter) {
632 const extensions::DraggableRegion& region = *iter;
633 sk_region->op(
634 region.bounds.x(),
635 region.bounds.y(),
636 region.bounds.right(),
637 region.bounds.bottom(),
638 region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
639 }
640 return sk_region;
641 }
642
643 void ShellWindow::DisableExternalOpenForTesting() {
644 disable_external_open_for_testing_ = true;
645 }
646
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698