| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/extensions/shell_window.h" | 5 #include "chrome/browser/ui/extensions/shell_window.h" |
| 6 | 6 |
| 7 #include "base/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
| 8 #include "chrome/browser/extensions/extension_process_manager.h" | 8 #include "chrome/browser/extensions/extension_process_manager.h" |
| 9 #include "chrome/browser/extensions/extension_system.h" | 9 #include "chrome/browser/extensions/extension_system.h" |
| 10 #include "chrome/browser/extensions/shell_window_geometry_cache.h" | 10 #include "chrome/browser/extensions/shell_window_geometry_cache.h" |
| 11 #include "chrome/browser/extensions/shell_window_registry.h" | 11 #include "chrome/browser/extensions/shell_window_registry.h" |
| 12 #include "chrome/browser/extensions/tab_helper.h" | 12 #include "chrome/browser/extensions/tab_helper.h" |
| 13 #include "chrome/browser/favicon/favicon_tab_helper.h" | 13 #include "chrome/browser/favicon/favicon_tab_helper.h" |
| 14 #include "chrome/browser/file_select_helper.h" | 14 #include "chrome/browser/file_select_helper.h" |
| 15 #include "chrome/browser/intents/web_intents_util.h" | 15 #include "chrome/browser/intents/web_intents_util.h" |
| 16 #include "chrome/browser/lifetime/application_lifetime.h" | 16 #include "chrome/browser/lifetime/application_lifetime.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/sessions/session_id.h" | 18 #include "chrome/browser/sessions/session_id.h" |
| 19 #include "chrome/browser/ui/browser.h" | 19 #include "chrome/browser/ui/browser.h" |
| 20 #include "chrome/browser/ui/browser_finder.h" | 20 #include "chrome/browser/ui/browser_finder.h" |
| 21 #include "chrome/browser/ui/browser_tabstrip.h" | 21 #include "chrome/browser/ui/browser_tabstrip.h" |
| 22 #include "chrome/browser/ui/browser_window.h" | 22 #include "chrome/browser/ui/browser_window.h" |
| 23 #include "chrome/browser/ui/constrained_window_tab_helper.h" | 23 #include "chrome/browser/ui/constrained_window_tab_helper.h" |
| 24 #include "chrome/browser/ui/extensions/native_shell_window.h" | 24 #include "chrome/browser/ui/extensions/app_base_window.h" |
| 25 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | 25 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" |
| 26 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 26 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 27 #include "chrome/browser/view_type_utils.h" | 27 #include "chrome/browser/view_type_utils.h" |
| 28 #include "chrome/common/chrome_notification_types.h" | 28 #include "chrome/common/chrome_notification_types.h" |
| 29 #include "chrome/common/extensions/api/app_window.h" | 29 #include "chrome/common/extensions/api/app_window.h" |
| 30 #include "chrome/common/extensions/extension.h" | 30 #include "chrome/common/extensions/extension.h" |
| 31 #include "chrome/common/extensions/extension_messages.h" | 31 #include "chrome/common/extensions/extension_messages.h" |
| 32 #include "chrome/common/extensions/request_media_access_permission_helper.h" | 32 #include "chrome/common/extensions/request_media_access_permission_helper.h" |
| 33 #include "content/public/browser/browser_thread.h" | 33 #include "content/public/browser/browser_thread.h" |
| 34 #include "content/public/browser/invalidate_type.h" | 34 #include "content/public/browser/invalidate_type.h" |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 shell_window_geometry_cache(); | 135 shell_window_geometry_cache(); |
| 136 gfx::Rect cached_bounds; | 136 gfx::Rect cached_bounds; |
| 137 if (cache->GetGeometry(extension()->id(), params.window_key, | 137 if (cache->GetGeometry(extension()->id(), params.window_key, |
| 138 &cached_bounds)) | 138 &cached_bounds)) |
| 139 bounds = cached_bounds; | 139 bounds = cached_bounds; |
| 140 } | 140 } |
| 141 | 141 |
| 142 ShellWindow::CreateParams new_params = params; | 142 ShellWindow::CreateParams new_params = params; |
| 143 new_params.bounds = bounds; | 143 new_params.bounds = bounds; |
| 144 | 144 |
| 145 native_window_.reset(NativeShellWindow::Create(this, new_params)); | 145 app_window_.reset(AppBaseWindow::Create(this, new_params)); |
| 146 SaveWindowPosition(); | 146 SaveWindowPosition(); |
| 147 | 147 |
| 148 if (!params.hidden) | 148 if (!params.hidden) |
| 149 GetBaseWindow()->Show(); | 149 GetBaseWindow()->Show(); |
| 150 | 150 |
| 151 // If the new view is in the same process as the creator, block the created | 151 // If the new view is in the same process as the creator, block the created |
| 152 // RVH from loading anything until the background page has had a chance to do | 152 // RVH from loading anything until the background page has had a chance to do |
| 153 // any initialization it wants. If it's a different process, the new RVH | 153 // any initialization it wants. If it's a different process, the new RVH |
| 154 // shouldn't communicate with the background page anyway (e.g. sandboxed). | 154 // shouldn't communicate with the background page anyway (e.g. sandboxed). |
| 155 if (web_contents_->GetRenderViewHost()->GetProcess()->GetID() == | 155 if (web_contents_->GetRenderViewHost()->GetProcess()->GetID() == |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 disposition = | 270 disposition = |
| 271 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB; | 271 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB; |
| 272 chrome::AddWebContents(browser, NULL, new_contents, disposition, initial_pos, | 272 chrome::AddWebContents(browser, NULL, new_contents, disposition, initial_pos, |
| 273 user_gesture, was_blocked); | 273 user_gesture, was_blocked); |
| 274 } | 274 } |
| 275 | 275 |
| 276 void ShellWindow::HandleKeyboardEvent( | 276 void ShellWindow::HandleKeyboardEvent( |
| 277 WebContents* source, | 277 WebContents* source, |
| 278 const content::NativeWebKeyboardEvent& event) { | 278 const content::NativeWebKeyboardEvent& event) { |
| 279 DCHECK_EQ(source, web_contents_); | 279 DCHECK_EQ(source, web_contents_); |
| 280 native_window_->HandleKeyboardEvent(event); | 280 app_window_->HandleKeyboardEvent(event); |
| 281 } | 281 } |
| 282 | 282 |
| 283 void ShellWindow::OnNativeClose() { | 283 void ShellWindow::OnNativeClose() { |
| 284 extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this); | 284 extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this); |
| 285 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); | 285 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); |
| 286 rvh->Send(new ExtensionMsg_AppWindowClosed(rvh->GetRoutingID())); | 286 rvh->Send(new ExtensionMsg_AppWindowClosed(rvh->GetRoutingID())); |
| 287 delete this; | 287 delete this; |
| 288 } | 288 } |
| 289 | 289 |
| 290 BaseWindow* ShellWindow::GetBaseWindow() { | 290 BaseWindow* ShellWindow::GetBaseWindow() { |
| 291 return native_window_.get(); | 291 return app_window_.get(); |
| 292 } | 292 } |
| 293 | 293 |
| 294 string16 ShellWindow::GetTitle() const { | 294 string16 ShellWindow::GetTitle() const { |
| 295 // WebContents::GetTitle() will return the page's URL if there's no <title> | 295 // WebContents::GetTitle() will return the page's URL if there's no <title> |
| 296 // specified. However, we'd prefer to show the name of the extension in that | 296 // specified. However, we'd prefer to show the name of the extension in that |
| 297 // case, so we directly inspect the NavigationEntry's title. | 297 // case, so we directly inspect the NavigationEntry's title. |
| 298 if (!web_contents()->GetController().GetActiveEntry() || | 298 if (!web_contents()->GetController().GetActiveEntry() || |
| 299 web_contents()->GetController().GetActiveEntry()->GetTitle().empty()) | 299 web_contents()->GetController().GetActiveEntry()->GetTitle().empty()) |
| 300 return UTF8ToUTF16(extension()->name()); | 300 return UTF8ToUTF16(extension()->name()); |
| 301 string16 title = web_contents()->GetTitle(); | 301 string16 title = web_contents()->GetTitle(); |
| 302 Browser::FormatTitleForDisplay(&title); | 302 Browser::FormatTitleForDisplay(&title); |
| 303 return title; | 303 return title; |
| 304 } | 304 } |
| 305 | 305 |
| 306 bool ShellWindow::OnMessageReceived(const IPC::Message& message) { | 306 bool ShellWindow::OnMessageReceived(const IPC::Message& message) { |
| 307 bool handled = true; | 307 bool handled = true; |
| 308 IPC_BEGIN_MESSAGE_MAP(ShellWindow, message) | 308 IPC_BEGIN_MESSAGE_MAP(ShellWindow, message) |
| 309 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) | 309 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) |
| 310 IPC_MESSAGE_HANDLER(ExtensionHostMsg_UpdateDraggableRegions, | 310 IPC_MESSAGE_HANDLER(ExtensionHostMsg_UpdateDraggableRegions, |
| 311 UpdateDraggableRegions) | 311 UpdateDraggableRegions) |
| 312 IPC_MESSAGE_UNHANDLED(handled = false) | 312 IPC_MESSAGE_UNHANDLED(handled = false) |
| 313 IPC_END_MESSAGE_MAP() | 313 IPC_END_MESSAGE_MAP() |
| 314 return handled; | 314 return handled; |
| 315 } | 315 } |
| 316 | 316 |
| 317 void ShellWindow::UpdateDraggableRegions( | 317 void ShellWindow::UpdateDraggableRegions( |
| 318 const std::vector<extensions::DraggableRegion>& regions) { | 318 const std::vector<extensions::DraggableRegion>& regions) { |
| 319 native_window_->UpdateDraggableRegions(regions); | 319 app_window_->UpdateDraggableRegions(regions); |
| 320 } | 320 } |
| 321 | 321 |
| 322 void ShellWindow::OnImageLoaded(const gfx::Image& image, | 322 void ShellWindow::OnImageLoaded(const gfx::Image& image, |
| 323 const std::string& extension_id, | 323 const std::string& extension_id, |
| 324 int index) { | 324 int index) { |
| 325 if (!image.IsEmpty()) { | 325 if (!image.IsEmpty()) { |
| 326 app_icon_ = image; | 326 app_icon_ = image; |
| 327 native_window_->UpdateWindowIcon(); | 327 app_window_->UpdateWindowIcon(); |
| 328 } | 328 } |
| 329 app_icon_loader_.reset(); | 329 app_icon_loader_.reset(); |
| 330 } | 330 } |
| 331 | 331 |
| 332 void ShellWindow::UpdateExtensionAppIcon() { | 332 void ShellWindow::UpdateExtensionAppIcon() { |
| 333 app_icon_loader_.reset(new ImageLoadingTracker(this)); | 333 app_icon_loader_.reset(new ImageLoadingTracker(this)); |
| 334 app_icon_loader_->LoadImage( | 334 app_icon_loader_->LoadImage( |
| 335 extension(), | 335 extension(), |
| 336 extension()->GetIconResource(extension_misc::EXTENSION_ICON_SMALL, | 336 extension()->GetIconResource(extension_misc::EXTENSION_ICON_SMALL, |
| 337 ExtensionIconSet::MATCH_BIGGER), | 337 ExtensionIconSet::MATCH_BIGGER), |
| 338 gfx::Size(extension_misc::EXTENSION_ICON_SMALL, | 338 gfx::Size(extension_misc::EXTENSION_ICON_SMALL, |
| 339 extension_misc::EXTENSION_ICON_SMALL), | 339 extension_misc::EXTENSION_ICON_SMALL), |
| 340 ImageLoadingTracker::CACHE); | 340 ImageLoadingTracker::CACHE); |
| 341 } | 341 } |
| 342 | 342 |
| 343 void ShellWindow::CloseContents(WebContents* contents) { | 343 void ShellWindow::CloseContents(WebContents* contents) { |
| 344 DCHECK(contents == web_contents_); | 344 DCHECK(contents == web_contents_); |
| 345 native_window_->Close(); | 345 app_window_->Close(); |
| 346 } | 346 } |
| 347 | 347 |
| 348 bool ShellWindow::ShouldSuppressDialogs() { | 348 bool ShellWindow::ShouldSuppressDialogs() { |
| 349 return true; | 349 return true; |
| 350 } | 350 } |
| 351 | 351 |
| 352 void ShellWindow::WebIntentDispatch( | 352 void ShellWindow::WebIntentDispatch( |
| 353 content::WebContents* web_contents, | 353 content::WebContents* web_contents, |
| 354 content::WebIntentsDispatcher* intents_dispatcher) { | 354 content::WebIntentsDispatcher* intents_dispatcher) { |
| 355 if (!web_intents::IsWebIntentsEnabledForProfile(profile_)) | 355 if (!web_intents::IsWebIntentsEnabledForProfile(profile_)) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 368 FileSelectHelper::RunFileChooser(tab, params); | 368 FileSelectHelper::RunFileChooser(tab, params); |
| 369 } | 369 } |
| 370 | 370 |
| 371 bool ShellWindow::IsPopupOrPanel(const WebContents* source) const { | 371 bool ShellWindow::IsPopupOrPanel(const WebContents* source) const { |
| 372 DCHECK(source == web_contents_.get()); | 372 DCHECK(source == web_contents_.get()); |
| 373 return true; | 373 return true; |
| 374 } | 374 } |
| 375 | 375 |
| 376 void ShellWindow::MoveContents(WebContents* source, const gfx::Rect& pos) { | 376 void ShellWindow::MoveContents(WebContents* source, const gfx::Rect& pos) { |
| 377 DCHECK(source == web_contents_.get()); | 377 DCHECK(source == web_contents_.get()); |
| 378 native_window_->SetBounds(pos); | 378 app_window_->SetBounds(pos); |
| 379 } | 379 } |
| 380 | 380 |
| 381 void ShellWindow::NavigationStateChanged( | 381 void ShellWindow::NavigationStateChanged( |
| 382 const content::WebContents* source, unsigned changed_flags) { | 382 const content::WebContents* source, unsigned changed_flags) { |
| 383 DCHECK(source == web_contents_.get()); | 383 DCHECK(source == web_contents_.get()); |
| 384 if (changed_flags & content::INVALIDATE_TYPE_TITLE) | 384 if (changed_flags & content::INVALIDATE_TYPE_TITLE) |
| 385 native_window_->UpdateWindowTitle(); | 385 app_window_->UpdateWindowTitle(); |
| 386 else if (changed_flags & content::INVALIDATE_TYPE_TAB) | 386 else if (changed_flags & content::INVALIDATE_TYPE_TAB) |
| 387 native_window_->UpdateWindowIcon(); | 387 app_window_->UpdateWindowIcon(); |
| 388 } | 388 } |
| 389 | 389 |
| 390 void ShellWindow::ToggleFullscreenModeForTab(content::WebContents* source, | 390 void ShellWindow::ToggleFullscreenModeForTab(content::WebContents* source, |
| 391 bool enter_fullscreen) { | 391 bool enter_fullscreen) { |
| 392 DCHECK(source == web_contents_.get()); | 392 DCHECK(source == web_contents_.get()); |
| 393 native_window_->SetFullscreen(enter_fullscreen); | 393 app_window_->SetFullscreen(enter_fullscreen); |
| 394 } | 394 } |
| 395 | 395 |
| 396 bool ShellWindow::IsFullscreenForTabOrPending( | 396 bool ShellWindow::IsFullscreenForTabOrPending( |
| 397 const content::WebContents* source) const { | 397 const content::WebContents* source) const { |
| 398 DCHECK(source == web_contents_.get()); | 398 DCHECK(source == web_contents_.get()); |
| 399 return native_window_->IsFullscreenOrPending(); | 399 return app_window_->IsFullscreenOrPending(); |
| 400 } | 400 } |
| 401 | 401 |
| 402 void ShellWindow::Observe(int type, | 402 void ShellWindow::Observe(int type, |
| 403 const content::NotificationSource& source, | 403 const content::NotificationSource& source, |
| 404 const content::NotificationDetails& details) { | 404 const content::NotificationDetails& details) { |
| 405 switch (type) { | 405 switch (type) { |
| 406 case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: { | 406 case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: { |
| 407 // TODO(jeremya): once http://crbug.com/123007 is fixed, we'll no longer | 407 // TODO(jeremya): once http://crbug.com/123007 is fixed, we'll no longer |
| 408 // need to suspend resource requests here (the call in the constructor | 408 // need to suspend resource requests here (the call in the constructor |
| 409 // should be enough). | 409 // should be enough). |
| 410 content::Details<std::pair<RenderViewHost*, RenderViewHost*> > | 410 content::Details<std::pair<RenderViewHost*, RenderViewHost*> > |
| 411 host_details(details); | 411 host_details(details); |
| 412 if (host_details->first) | 412 if (host_details->first) |
| 413 SuspendRenderViewHost(host_details->second); | 413 SuspendRenderViewHost(host_details->second); |
| 414 // TODO(jianli): once http://crbug.com/123007 is fixed, we'll no longer | 414 // TODO(jianli): once http://crbug.com/123007 is fixed, we'll no longer |
| 415 // need to make the native window (ShellWindowViews specially) update | 415 // need to make the native window (ShellWindowViews specially) update |
| 416 // the clickthrough region for the new RVH. | 416 // the clickthrough region for the new RVH. |
| 417 native_window_->RenderViewHostChanged(); | 417 app_window_->RenderViewHostChanged(); |
| 418 break; | 418 break; |
| 419 } | 419 } |
| 420 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | 420 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
| 421 const extensions::Extension* unloaded_extension = | 421 const extensions::Extension* unloaded_extension = |
| 422 content::Details<extensions::UnloadedExtensionInfo>( | 422 content::Details<extensions::UnloadedExtensionInfo>( |
| 423 details)->extension; | 423 details)->extension; |
| 424 if (extension_ == unloaded_extension) | 424 if (extension_ == unloaded_extension) |
| 425 native_window_->Close(); | 425 app_window_->Close(); |
| 426 break; | 426 break; |
| 427 } | 427 } |
| 428 case chrome::NOTIFICATION_APP_TERMINATING: | 428 case chrome::NOTIFICATION_APP_TERMINATING: |
| 429 native_window_->Close(); | 429 app_window_->Close(); |
| 430 break; | 430 break; |
| 431 default: | 431 default: |
| 432 NOTREACHED() << "Received unexpected notification"; | 432 NOTREACHED() << "Received unexpected notification"; |
| 433 } | 433 } |
| 434 } | 434 } |
| 435 | 435 |
| 436 extensions::WindowController* | 436 extensions::WindowController* |
| 437 ShellWindow::GetExtensionWindowController() const { | 437 ShellWindow::GetExtensionWindowController() const { |
| 438 return NULL; | 438 return NULL; |
| 439 } | 439 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 454 } | 454 } |
| 455 | 455 |
| 456 void ShellWindow::AddMessageToDevToolsConsole(ConsoleMessageLevel level, | 456 void ShellWindow::AddMessageToDevToolsConsole(ConsoleMessageLevel level, |
| 457 const std::string& message) { | 457 const std::string& message) { |
| 458 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); | 458 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); |
| 459 rvh->Send(new ExtensionMsg_AddMessageToConsole( | 459 rvh->Send(new ExtensionMsg_AddMessageToConsole( |
| 460 rvh->GetRoutingID(), level, message)); | 460 rvh->GetRoutingID(), level, message)); |
| 461 } | 461 } |
| 462 | 462 |
| 463 void ShellWindow::SendBoundsUpdate() { | 463 void ShellWindow::SendBoundsUpdate() { |
| 464 if (!native_window_ || !web_contents_) | 464 if (!app_window_ || !web_contents_) |
| 465 return; | 465 return; |
| 466 gfx::Rect bounds = native_window_->GetBounds(); | 466 gfx::Rect bounds = app_window_->GetBounds(); |
| 467 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); | 467 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); |
| 468 ListValue args; | 468 ListValue args; |
| 469 app_window::Bounds update; | 469 app_window::Bounds update; |
| 470 update.left.reset(new int(bounds.x())); | 470 update.left.reset(new int(bounds.x())); |
| 471 update.top.reset(new int(bounds.y())); | 471 update.top.reset(new int(bounds.y())); |
| 472 update.width.reset(new int(bounds.width())); | 472 update.width.reset(new int(bounds.width())); |
| 473 update.height.reset(new int(bounds.height())); | 473 update.height.reset(new int(bounds.height())); |
| 474 args.Append(update.ToValue().release()); | 474 args.Append(update.ToValue().release()); |
| 475 rvh->Send(new ExtensionMsg_MessageInvoke(rvh->GetRoutingID(), | 475 rvh->Send(new ExtensionMsg_MessageInvoke(rvh->GetRoutingID(), |
| 476 extension_->id(), | 476 extension_->id(), |
| 477 "updateAppWindowBounds", | 477 "updateAppWindowBounds", |
| 478 args, | 478 args, |
| 479 GURL(), | 479 GURL(), |
| 480 false)); | 480 false)); |
| 481 } | 481 } |
| 482 | 482 |
| 483 void ShellWindow::SaveWindowPosition() { | 483 void ShellWindow::SaveWindowPosition() { |
| 484 SendBoundsUpdate(); | 484 SendBoundsUpdate(); |
| 485 if (window_key_.empty()) | 485 if (window_key_.empty()) |
| 486 return; | 486 return; |
| 487 if (!native_window_) | 487 if (!app_window_) |
| 488 return; | 488 return; |
| 489 | 489 |
| 490 extensions::ShellWindowGeometryCache* cache = | 490 extensions::ShellWindowGeometryCache* cache = |
| 491 extensions::ExtensionSystem::Get(profile())-> | 491 extensions::ExtensionSystem::Get(profile())-> |
| 492 shell_window_geometry_cache(); | 492 shell_window_geometry_cache(); |
| 493 | 493 |
| 494 gfx::Rect bounds = native_window_->GetBounds(); | 494 gfx::Rect bounds = app_window_->GetBounds(); |
| 495 cache->SaveGeometry(extension()->id(), window_key_, bounds); | 495 cache->SaveGeometry(extension()->id(), window_key_, bounds); |
| 496 } | 496 } |
| 497 | 497 |
| 498 // static | 498 // static |
| 499 SkRegion* ShellWindow::RawDraggableRegionsToSkRegion( | 499 SkRegion* ShellWindow::RawDraggableRegionsToSkRegion( |
| 500 const std::vector<extensions::DraggableRegion>& regions) { | 500 const std::vector<extensions::DraggableRegion>& regions) { |
| 501 SkRegion* sk_region = new SkRegion; | 501 SkRegion* sk_region = new SkRegion; |
| 502 for (std::vector<extensions::DraggableRegion>::const_iterator iter = | 502 for (std::vector<extensions::DraggableRegion>::const_iterator iter = |
| 503 regions.begin(); | 503 regions.begin(); |
| 504 iter != regions.end(); ++iter) { | 504 iter != regions.end(); ++iter) { |
| 505 const extensions::DraggableRegion& region = *iter; | 505 const extensions::DraggableRegion& region = *iter; |
| 506 sk_region->op( | 506 sk_region->op( |
| 507 region.bounds.x(), | 507 region.bounds.x(), |
| 508 region.bounds.y(), | 508 region.bounds.y(), |
| 509 region.bounds.right(), | 509 region.bounds.right(), |
| 510 region.bounds.bottom(), | 510 region.bounds.bottom(), |
| 511 region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op); | 511 region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op); |
| 512 } | 512 } |
| 513 return sk_region; | 513 return sk_region; |
| 514 } | 514 } |
| OLD | NEW |