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 "content/renderer/render_view_impl.h" 6 7 #include <algorithm> 8 #include <cmath> 9 10 #include "base/auto_reset.h" 11 #include "base/bind.h" 12 #include "base/bind_helpers.h" 13 #include "base/command_line.h" 14 #include "base/compiler_specific.h" 15 #include "base/debug/alias.h" 16 #include "base/debug/trace_event.h" 17 #include "base/files/file_path.h" 18 #include "base/i18n/rtl.h" 19 #include "base/json/json_writer.h" 20 #include "base/lazy_instance.h" 21 #include "base/memory/scoped_ptr.h" 22 #include "base/message_loop/message_loop_proxy.h" 23 #include "base/metrics/field_trial.h" 24 #include "base/metrics/histogram.h" 25 #include "base/path_service.h" 26 #include "base/process/kill.h" 27 #include "base/process/process.h" 28 #include "base/strings/string_number_conversions.h" 29 #include "base/strings/string_piece.h" 30 #include "base/strings/string_split.h" 31 #include "base/strings/string_util.h" 32 #include "base/strings/sys_string_conversions.h" 33 #include "base/strings/utf_string_conversions.h" 34 #include "base/time/time.h" 35 #include "cc/base/switches.h" 36 #include "content/child/appcache/appcache_dispatcher.h" 37 #include "content/child/appcache/web_application_cache_host_impl.h" 38 #include "content/child/child_shared_bitmap_manager.h" 39 #include "content/child/child_thread.h" 40 #include "content/child/npapi/webplugin_delegate_impl.h" 41 #include "content/child/request_extra_data.h" 42 #include "content/child/webmessageportchannel_impl.h" 43 #include "content/common/database_messages.h" 44 #include "content/common/dom_storage/dom_storage_types.h" 45 #include "content/common/drag_messages.h" 46 #include "content/common/frame_messages.h" 47 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" 48 #include "content/common/input_messages.h" 49 #include "content/common/pepper_messages.h" 50 #include "content/common/socket_stream_handle_data.h" 51 #include "content/common/ssl_status_serialization.h" 52 #include "content/common/view_messages.h" 53 #include "content/public/common/bindings_policy.h" 54 #include "content/public/common/content_client.h" 55 #include "content/public/common/content_constants.h" 56 #include "content/public/common/content_switches.h" 57 #include "content/public/common/drop_data.h" 58 #include "content/public/common/favicon_url.h" 59 #include "content/public/common/file_chooser_params.h" 60 #include "content/public/common/page_zoom.h" 61 #include "content/public/common/ssl_status.h" 62 #include "content/public/common/three_d_api_types.h" 63 #include "content/public/common/url_constants.h" 64 #include "content/public/common/url_utils.h" 65 #include "content/public/renderer/content_renderer_client.h" 66 #include "content/public/renderer/document_state.h" 67 #include "content/public/renderer/navigation_state.h" 68 #include "content/public/renderer/render_view_observer.h" 69 #include "content/public/renderer/render_view_visitor.h" 70 #include "content/public/renderer/web_preferences.h" 71 #include "content/renderer/accessibility/renderer_accessibility.h" 72 #include "content/renderer/accessibility/renderer_accessibility_complete.h" 73 #include "content/renderer/accessibility/renderer_accessibility_focus_only.h" 74 #include "content/renderer/browser_plugin/browser_plugin.h" 75 #include "content/renderer/browser_plugin/browser_plugin_manager.h" 76 #include "content/renderer/browser_plugin/browser_plugin_manager_impl.h" 77 #include "content/renderer/devtools/devtools_agent.h" 78 #include "content/renderer/disambiguation_popup_helper.h" 79 #include "content/renderer/dom_storage/webstoragenamespace_impl.h" 80 #include "content/renderer/drop_data_builder.h" 81 #include "content/renderer/external_popup_menu.h" 82 #include "content/renderer/gpu/render_widget_compositor.h" 83 #include "content/renderer/history_controller.h" 84 #include "content/renderer/history_serialization.h" 85 #include "content/renderer/idle_user_detector.h" 86 #include "content/renderer/ime_event_guard.h" 87 #include "content/renderer/input/input_handler_manager.h" 88 #include "content/renderer/internal_document_state_data.h" 89 #include "content/renderer/media/audio_device_factory.h" 90 #include "content/renderer/media/media_stream_dispatcher.h" 91 #include "content/renderer/media/video_capture_impl_manager.h" 92 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" 93 #include "content/renderer/memory_benchmarking_extension.h" 94 #include "content/renderer/mhtml_generator.h" 95 #include "content/renderer/push_messaging_dispatcher.h" 96 #include "content/renderer/render_frame_impl.h" 97 #include "content/renderer/render_frame_proxy.h" 98 #include "content/renderer/render_process.h" 99 #include "content/renderer/render_thread_impl.h" 100 #include "content/renderer/render_view_impl_params.h" 101 #include "content/renderer/render_view_mouse_lock_dispatcher.h" 102 #include "content/renderer/render_widget_fullscreen_pepper.h" 103 #include "content/renderer/renderer_webapplicationcachehost_impl.h" 104 #include "content/renderer/resizing_mode_selector.h" 105 #include "content/renderer/savable_resources.h" 106 #include "content/renderer/skia_benchmarking_extension.h" 107 #include "content/renderer/speech_recognition_dispatcher.h" 108 #include "content/renderer/stats_collection_controller.h" 109 #include "content/renderer/stats_collection_observer.h" 110 #include "content/renderer/text_input_client_observer.h" 111 #include "content/renderer/v8_value_converter_impl.h" 112 #include "content/renderer/web_ui_extension.h" 113 #include "content/renderer/web_ui_extension_data.h" 114 #include "content/renderer/web_ui_mojo.h" 115 #include "content/renderer/websharedworker_proxy.h" 116 #include "media/audio/audio_output_device.h" 117 #include "media/base/filter_collection.h" 118 #include "media/base/media_switches.h" 119 #include "media/filters/audio_renderer_impl.h" 120 #include "media/filters/gpu_video_accelerator_factories.h" 121 #include "net/base/data_url.h" 122 #include "net/base/escape.h" 123 #include "net/base/net_errors.h" 124 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 125 #include "net/http/http_util.h" 126 #include "third_party/WebKit/public/platform/WebCString.h" 127 #include "third_party/WebKit/public/platform/WebDragData.h" 128 #include "third_party/WebKit/public/platform/WebHTTPBody.h" 129 #include "third_party/WebKit/public/platform/WebImage.h" 130 #include "third_party/WebKit/public/platform/WebMessagePortChannel.h" 131 #include "third_party/WebKit/public/platform/WebPoint.h" 132 #include "third_party/WebKit/public/platform/WebRect.h" 133 #include "third_party/WebKit/public/platform/WebSize.h" 134 #include "third_party/WebKit/public/platform/WebSocketStreamHandle.h" 135 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h" 136 #include "third_party/WebKit/public/platform/WebString.h" 137 #include "third_party/WebKit/public/platform/WebURL.h" 138 #include "third_party/WebKit/public/platform/WebURLError.h" 139 #include "third_party/WebKit/public/platform/WebURLRequest.h" 140 #include "third_party/WebKit/public/platform/WebURLResponse.h" 141 #include "third_party/WebKit/public/platform/WebVector.h" 142 #include "third_party/WebKit/public/web/WebAXObject.h" 143 #include "third_party/WebKit/public/web/WebColorName.h" 144 #include "third_party/WebKit/public/web/WebColorSuggestion.h" 145 #include "third_party/WebKit/public/web/WebDOMEvent.h" 146 #include "third_party/WebKit/public/web/WebDOMMessageEvent.h" 147 #include "third_party/WebKit/public/web/WebDataSource.h" 148 #include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h" 149 #include "third_party/WebKit/public/web/WebDateTimeChooserParams.h" 150 #include "third_party/WebKit/public/web/WebDevToolsAgent.h" 151 #include "third_party/WebKit/public/web/WebDocument.h" 152 #include "third_party/WebKit/public/web/WebElement.h" 153 #include "third_party/WebKit/public/web/WebFileChooserParams.h" 154 #include "third_party/WebKit/public/web/WebFindOptions.h" 155 #include "third_party/WebKit/public/web/WebFormControlElement.h" 156 #include "third_party/WebKit/public/web/WebFormElement.h" 157 #include "third_party/WebKit/public/web/WebFrame.h" 158 #include "third_party/WebKit/public/web/WebGlyphCache.h" 159 #include "third_party/WebKit/public/web/WebHistoryItem.h" 160 #include "third_party/WebKit/public/web/WebInputElement.h" 161 #include "third_party/WebKit/public/web/WebInputEvent.h" 162 #include "third_party/WebKit/public/web/WebLocalFrame.h" 163 #include "third_party/WebKit/public/web/WebMediaPlayerAction.h" 164 #include "third_party/WebKit/public/web/WebNavigationPolicy.h" 165 #include "third_party/WebKit/public/web/WebNodeList.h" 166 #include "third_party/WebKit/public/web/WebPageSerializer.h" 167 #include "third_party/WebKit/public/web/WebPlugin.h" 168 #include "third_party/WebKit/public/web/WebPluginAction.h" 169 #include "third_party/WebKit/public/web/WebPluginContainer.h" 170 #include "third_party/WebKit/public/web/WebPluginDocument.h" 171 #include "third_party/WebKit/public/web/WebRange.h" 172 #include "third_party/WebKit/public/web/WebScriptSource.h" 173 #include "third_party/WebKit/public/web/WebSearchableFormData.h" 174 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" 175 #include "third_party/WebKit/public/web/WebSecurityPolicy.h" 176 #include "third_party/WebKit/public/web/WebSerializedScriptValue.h" 177 #include "third_party/WebKit/public/web/WebSettings.h" 178 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 179 #include "third_party/WebKit/public/web/WebView.h" 180 #include "third_party/WebKit/public/web/WebWindowFeatures.h" 181 #include "third_party/WebKit/public/web/default/WebRenderTheme.h" 182 #include "ui/base/clipboard/clipboard.h" 183 #include "ui/base/ui_base_switches_util.h" 184 #include "ui/events/latency_info.h" 185 #include "ui/gfx/native_widget_types.h" 186 #include "ui/gfx/point.h" 187 #include "ui/gfx/rect.h" 188 #include "ui/gfx/rect_conversions.h" 189 #include "ui/gfx/size_conversions.h" 190 #include "ui/shell_dialogs/selected_file_info.h" 191 #include "v8/include/v8.h" 192 #include "webkit/child/weburlresponse_extradata_impl.h" 193 194 #if defined(OS_ANDROID) 195 #include <cpu-features.h> 196 197 #include "content/renderer/android/address_detector.h" 198 #include "content/renderer/android/content_detector.h" 199 #include "content/renderer/android/email_detector.h" 200 #include "content/renderer/android/phone_number_detector.h" 201 #include "net/android/network_library.h" 202 #include "skia/ext/platform_canvas.h" 203 #include "third_party/WebKit/public/platform/WebFloatPoint.h" 204 #include "third_party/WebKit/public/platform/WebFloatRect.h" 205 #include "third_party/WebKit/public/web/WebHitTestResult.h" 206 #include "ui/gfx/rect_f.h" 207 208 #elif defined(OS_WIN) 209 // TODO(port): these files are currently Windows only because they concern: 210 // * theming 211 #include "ui/native_theme/native_theme_win.h" 212 #elif defined(USE_X11) 213 #include "ui/native_theme/native_theme.h" 214 #elif defined(OS_MACOSX) 215 #include "skia/ext/skia_utils_mac.h" 216 #endif 217 218 #if defined(ENABLE_PLUGINS) 219 #include "content/renderer/npapi/webplugin_delegate_proxy.h" 220 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" 221 #include "content/renderer/pepper/pepper_plugin_registry.h" 222 #endif 223 224 #if defined(ENABLE_WEBRTC) 225 #include "content/renderer/media/rtc_peer_connection_handler.h" 226 #endif 227 228 using blink::WebAXObject; 229 using blink::WebApplicationCacheHost; 230 using blink::WebApplicationCacheHostClient; 231 using blink::WebCString; 232 using blink::WebColor; 233 using blink::WebColorName; 234 using blink::WebConsoleMessage; 235 using blink::WebData; 236 using blink::WebDataSource; 237 using blink::WebDocument; 238 using blink::WebDOMEvent; 239 using blink::WebDOMMessageEvent; 240 using blink::WebDragData; 241 using blink::WebDragOperation; 242 using blink::WebDragOperationsMask; 243 using blink::WebElement; 244 using blink::WebExternalPopupMenu; 245 using blink::WebExternalPopupMenuClient; 246 using blink::WebFileChooserCompletion; 247 using blink::WebFindOptions; 248 using blink::WebFormControlElement; 249 using blink::WebFormElement; 250 using blink::WebFrame; 251 using blink::WebGestureEvent; 252 using blink::WebHistoryItem; 253 using blink::WebHTTPBody; 254 using blink::WebIconURL; 255 using blink::WebImage; 256 using blink::WebInputElement; 257 using blink::WebInputEvent; 258 using blink::WebLocalFrame; 259 using blink::WebMediaPlayerAction; 260 using blink::WebMouseEvent; 261 using blink::WebNavigationPolicy; 262 using blink::WebNavigationType; 263 using blink::WebNode; 264 using blink::WebPageSerializer; 265 using blink::WebPageSerializerClient; 266 using blink::WebPeerConnection00Handler; 267 using blink::WebPeerConnection00HandlerClient; 268 using blink::WebPeerConnectionHandler; 269 using blink::WebPeerConnectionHandlerClient; 270 using blink::WebPluginAction; 271 using blink::WebPluginContainer; 272 using blink::WebPluginDocument; 273 using blink::WebPoint; 274 using blink::WebPopupMenuInfo; 275 using blink::WebRange; 276 using blink::WebRect; 277 using blink::WebReferrerPolicy; 278 using blink::WebScriptSource; 279 using blink::WebSearchableFormData; 280 using blink::WebSecurityOrigin; 281 using blink::WebSecurityPolicy; 282 using blink::WebSerializedScriptValue; 283 using blink::WebSettings; 284 using blink::WebSize; 285 using blink::WebSocketStreamHandle; 286 using blink::WebStorageNamespace; 287 using blink::WebStorageQuotaCallbacks; 288 using blink::WebStorageQuotaError; 289 using blink::WebStorageQuotaType; 290 using blink::WebString; 291 using blink::WebTextAffinity; 292 using blink::WebTextDirection; 293 using blink::WebTouchEvent; 294 using blink::WebURL; 295 using blink::WebURLError; 296 using blink::WebURLRequest; 297 using blink::WebURLResponse; 298 using blink::WebUserGestureIndicator; 299 using blink::WebVector; 300 using blink::WebView; 301 using blink::WebWidget; 302 using blink::WebWindowFeatures; 303 using base::Time; 304 using base::TimeDelta; 305 using webkit_glue::WebURLResponseExtraDataImpl; 306 307 #if defined(OS_ANDROID) 308 using blink::WebContentDetectionResult; 309 using blink::WebFloatPoint; 310 using blink::WebFloatRect; 311 using blink::WebHitTestResult; 312 #endif 313 314 namespace content { 315 316 //----------------------------------------------------------------------------- 317 318 typedef std::map<blink::WebView*, RenderViewImpl*> ViewMap; 319 static base::LazyInstance<ViewMap> g_view_map = LAZY_INSTANCE_INITIALIZER; 320 typedef std::map<int32, RenderViewImpl*> RoutingIDViewMap; 321 static base::LazyInstance<RoutingIDViewMap> g_routing_id_view_map = 322 LAZY_INSTANCE_INITIALIZER; 323 324 // Time, in seconds, we delay before sending content state changes (such as form 325 // state and scroll position) to the browser. We delay sending changes to avoid 326 // spamming the browser. 327 // To avoid having tab/session restore require sending a message to get the 328 // current content state during tab closing we use a shorter timeout for the 329 // foreground renderer. This means there is a small window of time from which 330 // content state is modified and not sent to session restore, but this is 331 // better than having to wake up all renderers during shutdown. 332 const int kDelaySecondsForContentStateSyncHidden = 5; 333 const int kDelaySecondsForContentStateSync = 1; 334 335 #if defined(OS_ANDROID) 336 // Delay between tapping in content and launching the associated android intent. 337 // Used to allow users see what has been recognized as content. 338 const size_t kContentIntentDelayMilliseconds = 700; 339 #endif 340 341 static RenderViewImpl* (*g_create_render_view_impl)(RenderViewImplParams*) = 342 NULL; 343 344 // static 345 bool RenderViewImpl::IsReload(const FrameMsg_Navigate_Params& params) { 346 return 347 params.navigation_type == FrameMsg_Navigate_Type::RELOAD || 348 params.navigation_type == FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE || 349 params.navigation_type == 350 FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL; 351 } 352 353 // static 354 Referrer RenderViewImpl::GetReferrerFromRequest( 355 WebFrame* frame, 356 const WebURLRequest& request) { 357 return Referrer(GURL(request.httpHeaderField(WebString::fromUTF8("Referer"))), 358 request.referrerPolicy()); 359 } 360 361 // static 362 WindowOpenDisposition RenderViewImpl::NavigationPolicyToDisposition( 363 WebNavigationPolicy policy) { 364 switch (policy) { 365 case blink::WebNavigationPolicyIgnore: 366 return IGNORE_ACTION; 367 case blink::WebNavigationPolicyDownload: 368 return SAVE_TO_DISK; 369 case blink::WebNavigationPolicyCurrentTab: 370 return CURRENT_TAB; 371 case blink::WebNavigationPolicyNewBackgroundTab: 372 return NEW_BACKGROUND_TAB; 373 case blink::WebNavigationPolicyNewForegroundTab: 374 return NEW_FOREGROUND_TAB; 375 case blink::WebNavigationPolicyNewWindow: 376 return NEW_WINDOW; 377 case blink::WebNavigationPolicyNewPopup: 378 return NEW_POPUP; 379 default: 380 NOTREACHED() << "Unexpected WebNavigationPolicy"; 381 return IGNORE_ACTION; 382 } 383 } 384 385 // Returns true if the device scale is high enough that losing subpixel 386 // antialiasing won't have a noticeable effect on text quality. 387 static bool DeviceScaleEnsuresTextQuality(float device_scale_factor) { 388 #if defined(OS_ANDROID) 389 // On Android, we never have subpixel antialiasing. 390 return true; 391 #else 392 return device_scale_factor > 1.5f; 393 #endif 394 395 } 396 397 static bool ShouldUseFixedPositionCompositing(float device_scale_factor) { 398 // Compositing for fixed-position elements is dependent on 399 // device_scale_factor if no flag is set. http://crbug.com/172738 400 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 401 402 if (command_line.HasSwitch(switches::kDisableCompositingForFixedPosition)) 403 return false; 404 405 if (command_line.HasSwitch(switches::kEnableCompositingForFixedPosition)) 406 return true; 407 408 return DeviceScaleEnsuresTextQuality(device_scale_factor); 409 } 410 411 static bool ShouldUseAcceleratedCompositingForOverflowScroll( 412 float device_scale_factor) { 413 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 414 415 if (command_line.HasSwitch(switches::kDisableAcceleratedOverflowScroll)) 416 return false; 417 418 if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll)) 419 return true; 420 421 return DeviceScaleEnsuresTextQuality(device_scale_factor); 422 } 423 424 static bool ShouldUseCompositedScrollingForFrames( 425 float device_scale_factor) { 426 if (RenderThreadImpl::current() && 427 !RenderThreadImpl::current()->is_lcd_text_enabled()) 428 return true; 429 430 return DeviceScaleEnsuresTextQuality(device_scale_factor); 431 } 432 433 static bool ShouldUseTransitionCompositing(float device_scale_factor) { 434 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 435 436 if (command_line.HasSwitch(switches::kDisableCompositingForTransition)) 437 return false; 438 439 if (command_line.HasSwitch(switches::kEnableCompositingForTransition)) 440 return true; 441 442 // TODO(ajuma): Re-enable this by default for high-DPI once the problem 443 // of excessive layer promotion caused by overlap has been addressed. 444 // http://crbug.com/178119. 445 return false; 446 } 447 448 static bool ShouldUseAcceleratedFixedRootBackground(float device_scale_factor) { 449 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 450 451 if (command_line.HasSwitch(switches::kDisableAcceleratedFixedRootBackground)) 452 return false; 453 454 if (command_line.HasSwitch(switches::kEnableAcceleratedFixedRootBackground)) 455 return true; 456 457 return DeviceScaleEnsuresTextQuality(device_scale_factor); 458 } 459 460 static bool ShouldUseExpandedHeuristicsForGpuRasterization() { 461 return base::FieldTrialList::FindFullName( 462 "GpuRasterizationExpandedContentWhitelist") == "Enabled"; 463 } 464 465 static FaviconURL::IconType ToFaviconType(blink::WebIconURL::Type type) { 466 switch (type) { 467 case blink::WebIconURL::TypeFavicon: 468 return FaviconURL::FAVICON; 469 case blink::WebIconURL::TypeTouch: 470 return FaviconURL::TOUCH_ICON; 471 case blink::WebIconURL::TypeTouchPrecomposed: 472 return FaviconURL::TOUCH_PRECOMPOSED_ICON; 473 case blink::WebIconURL::TypeInvalid: 474 return FaviconURL::INVALID_ICON; 475 } 476 return FaviconURL::INVALID_ICON; 477 } 478 479 static void ConvertToFaviconSizes( 480 const blink::WebVector<blink::WebSize>& web_sizes, 481 std::vector<gfx::Size>* sizes) { 482 DCHECK(sizes->empty()); 483 sizes->reserve(web_sizes.size()); 484 for (size_t i = 0; i < web_sizes.size(); ++i) 485 sizes->push_back(gfx::Size(web_sizes[i])); 486 } 487 488 /////////////////////////////////////////////////////////////////////////////// 489 490 struct RenderViewImpl::PendingFileChooser { 491 PendingFileChooser(const FileChooserParams& p, WebFileChooserCompletion* c) 492 : params(p), 493 completion(c) { 494 } 495 FileChooserParams params; 496 WebFileChooserCompletion* completion; // MAY BE NULL to skip callback. 497 }; 498 499 namespace { 500 501 class WebWidgetLockTarget : public MouseLockDispatcher::LockTarget { 502 public: 503 explicit WebWidgetLockTarget(blink::WebWidget* webwidget) 504 : webwidget_(webwidget) {} 505 506 virtual void OnLockMouseACK(bool succeeded) OVERRIDE { 507 if (succeeded) 508 webwidget_->didAcquirePointerLock(); 509 else 510 webwidget_->didNotAcquirePointerLock(); 511 } 512 513 virtual void OnMouseLockLost() OVERRIDE { 514 webwidget_->didLosePointerLock(); 515 } 516 517 virtual bool HandleMouseLockedInputEvent( 518 const blink::WebMouseEvent &event) OVERRIDE { 519 // The WebWidget handles mouse lock in WebKit's handleInputEvent(). 520 return false; 521 } 522 523 private: 524 blink::WebWidget* webwidget_; 525 }; 526 527 bool TouchEnabled() { 528 // Based on the definition of chrome::kEnableTouchIcon. 529 #if defined(OS_ANDROID) 530 return true; 531 #else 532 return false; 533 #endif 534 } 535 536 WebDragData DropDataToWebDragData(const DropData& drop_data) { 537 std::vector<WebDragData::Item> item_list; 538 539 // These fields are currently unused when dragging into WebKit. 540 DCHECK(drop_data.download_metadata.empty()); 541 DCHECK(drop_data.file_contents.empty()); 542 DCHECK(drop_data.file_description_filename.empty()); 543 544 if (!drop_data.text.is_null()) { 545 WebDragData::Item item; 546 item.storageType = WebDragData::Item::StorageTypeString; 547 item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeText); 548 item.stringData = drop_data.text.string(); 549 item_list.push_back(item); 550 } 551 552 // TODO(dcheng): Do we need to distinguish between null and empty URLs? Is it 553 // meaningful to write an empty URL to the clipboard? 554 if (!drop_data.url.is_empty()) { 555 WebDragData::Item item; 556 item.storageType = WebDragData::Item::StorageTypeString; 557 item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeURIList); 558 item.stringData = WebString::fromUTF8(drop_data.url.spec()); 559 item.title = drop_data.url_title; 560 item_list.push_back(item); 561 } 562 563 if (!drop_data.html.is_null()) { 564 WebDragData::Item item; 565 item.storageType = WebDragData::Item::StorageTypeString; 566 item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeHTML); 567 item.stringData = drop_data.html.string(); 568 item.baseURL = drop_data.html_base_url; 569 item_list.push_back(item); 570 } 571 572 for (std::vector<ui::FileInfo>::const_iterator it = 573 drop_data.filenames.begin(); 574 it != drop_data.filenames.end(); 575 ++it) { 576 WebDragData::Item item; 577 item.storageType = WebDragData::Item::StorageTypeFilename; 578 item.filenameData = it->path.AsUTF16Unsafe(); 579 item.displayNameData = it->display_name.AsUTF16Unsafe(); 580 item_list.push_back(item); 581 } 582 583 for (std::vector<DropData::FileSystemFileInfo>::const_iterator it = 584 drop_data.file_system_files.begin(); 585 it != drop_data.file_system_files.end(); 586 ++it) { 587 WebDragData::Item item; 588 item.storageType = WebDragData::Item::StorageTypeFileSystemFile; 589 item.fileSystemURL = it->url; 590 item.fileSystemFileSize = it->size; 591 item_list.push_back(item); 592 } 593 594 for (std::map<base::string16, base::string16>::const_iterator it = 595 drop_data.custom_data.begin(); 596 it != drop_data.custom_data.end(); 597 ++it) { 598 WebDragData::Item item; 599 item.storageType = WebDragData::Item::StorageTypeString; 600 item.stringType = it->first; 601 item.stringData = it->second; 602 item_list.push_back(item); 603 } 604 605 WebDragData result; 606 result.initialize(); 607 result.setItems(item_list); 608 result.setFilesystemId(drop_data.filesystem_id); 609 return result; 610 } 611 612 } // namespace 613 614 RenderViewImpl::RenderViewImpl(RenderViewImplParams* params) 615 : RenderWidget(blink::WebPopupTypeNone, 616 params->screen_info, 617 params->swapped_out, 618 params->hidden, 619 params->never_visible), 620 webkit_preferences_(params->webkit_prefs), 621 send_content_state_immediately_(false), 622 enabled_bindings_(0), 623 send_preferred_size_changes_(false), 624 navigation_gesture_(NavigationGestureUnknown), 625 opened_by_user_gesture_(true), 626 opener_suppressed_(false), 627 suppress_dialogs_until_swap_out_(false), 628 page_id_(-1), 629 last_page_id_sent_to_browser_(-1), 630 next_page_id_(params->next_page_id), 631 history_list_offset_(-1), 632 history_list_length_(0), 633 frames_in_progress_(0), 634 target_url_status_(TARGET_NONE), 635 uses_temporary_zoom_level_(false), 636 #if defined(OS_ANDROID) 637 top_controls_constraints_(cc::BOTH), 638 #endif 639 has_scrolled_focused_editable_node_into_rect_(false), 640 push_messaging_dispatcher_(NULL), 641 speech_recognition_dispatcher_(NULL), 642 media_stream_dispatcher_(NULL), 643 browser_plugin_manager_(NULL), 644 devtools_agent_(NULL), 645 accessibility_mode_(AccessibilityModeOff), 646 renderer_accessibility_(NULL), 647 mouse_lock_dispatcher_(NULL), 648 #if defined(OS_ANDROID) 649 expected_content_intent_id_(0), 650 #endif 651 #if defined(OS_WIN) 652 focused_plugin_id_(-1), 653 #endif 654 #if defined(ENABLE_PLUGINS) 655 plugin_find_handler_(NULL), 656 focused_pepper_plugin_(NULL), 657 pepper_last_mouse_event_target_(NULL), 658 #endif 659 enumeration_completion_id_(0), 660 session_storage_namespace_id_(params->session_storage_namespace_id), 661 next_snapshot_id_(0) { 662 } 663 664 void RenderViewImpl::Initialize(RenderViewImplParams* params) { 665 routing_id_ = params->routing_id; 666 surface_id_ = params->surface_id; 667 if (params->opener_id != MSG_ROUTING_NONE && params->is_renderer_created) 668 opener_id_ = params->opener_id; 669 670 // Ensure we start with a valid next_page_id_ from the browser. 671 DCHECK_GE(next_page_id_, 0); 672 673 main_render_frame_.reset(RenderFrameImpl::Create( 674 this, params->main_frame_routing_id)); 675 // The main frame WebLocalFrame object is closed by 676 // RenderFrameImpl::frameDetached(). 677 WebLocalFrame* web_frame = WebLocalFrame::create(main_render_frame_.get()); 678 main_render_frame_->SetWebFrame(web_frame); 679 680 if (params->proxy_routing_id != MSG_ROUTING_NONE) { 681 CHECK(params->swapped_out); 682 RenderFrameProxy* proxy = 683 RenderFrameProxy::CreateFrameProxy(params->proxy_routing_id, 684 params->main_frame_routing_id); 685 main_render_frame_->set_render_frame_proxy(proxy); 686 } 687 688 webwidget_ = WebView::create(this); 689 webwidget_mouse_lock_target_.reset(new WebWidgetLockTarget(webwidget_)); 690 691 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 692 693 if (command_line.HasSwitch(switches::kStatsCollectionController)) 694 stats_collection_observer_.reset(new StatsCollectionObserver(this)); 695 696 #if defined(OS_ANDROID) 697 const std::string region_code = 698 command_line.HasSwitch(switches::kNetworkCountryIso) 699 ? command_line.GetSwitchValueASCII(switches::kNetworkCountryIso) 700 : net::android::GetTelephonyNetworkOperator(); 701 content_detectors_.push_back(linked_ptr<ContentDetector>( 702 new AddressDetector())); 703 content_detectors_.push_back(linked_ptr<ContentDetector>( 704 new PhoneNumberDetector(region_code))); 705 content_detectors_.push_back(linked_ptr<ContentDetector>( 706 new EmailDetector())); 707 #endif 708 709 RenderThread::Get()->AddRoute(routing_id_, this); 710 // Take a reference on behalf of the RenderThread. This will be balanced 711 // when we receive ViewMsg_ClosePage. 712 AddRef(); 713 if (RenderThreadImpl::current()) { 714 RenderThreadImpl::current()->WidgetCreated(); 715 if (is_hidden_) 716 RenderThreadImpl::current()->WidgetHidden(); 717 } 718 719 // If this is a popup, we must wait for the CreatingNew_ACK message before 720 // completing initialization. Otherwise, we can finish it now. 721 if (opener_id_ == MSG_ROUTING_NONE) { 722 did_show_ = true; 723 CompleteInit(); 724 } 725 726 g_view_map.Get().insert(std::make_pair(webview(), this)); 727 g_routing_id_view_map.Get().insert(std::make_pair(routing_id_, this)); 728 webview()->setDeviceScaleFactor(device_scale_factor_); 729 webview()->settings()->setAcceleratedCompositingForFixedPositionEnabled( 730 ShouldUseFixedPositionCompositing(device_scale_factor_)); 731 webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled( 732 ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_)); 733 webview()->settings()->setAcceleratedCompositingForTransitionEnabled( 734 ShouldUseTransitionCompositing(device_scale_factor_)); 735 webview()->settings()->setAcceleratedCompositingForFixedRootBackgroundEnabled( 736 ShouldUseAcceleratedFixedRootBackground(device_scale_factor_)); 737 webview()->settings()->setCompositedScrollingForFramesEnabled( 738 ShouldUseCompositedScrollingForFrames(device_scale_factor_)); 739 webview()->settings()->setUseExpandedHeuristicsForGpuRasterization( 740 ShouldUseExpandedHeuristicsForGpuRasterization()); 741 742 ApplyWebPreferences(webkit_preferences_, webview()); 743 744 webview()->settings()->setAllowConnectingInsecureWebSocket( 745 command_line.HasSwitch(switches::kAllowInsecureWebSocketFromHttpsOrigin)); 746 747 webview()->setMainFrame(main_render_frame_->GetWebFrame()); 748 main_render_frame_->Initialize(); 749 750 if (switches::IsTouchDragDropEnabled()) 751 webview()->settings()->setTouchDragDropEnabled(true); 752 753 if (switches::IsTouchEditingEnabled()) 754 webview()->settings()->setTouchEditingEnabled(true); 755 756 if (!params->frame_name.empty()) 757 webview()->mainFrame()->setName(params->frame_name); 758 759 // TODO(davidben): Move this state from Blink into content. 760 if (params->window_was_created_with_opener) 761 webview()->setOpenedByDOM(); 762 763 OnSetRendererPrefs(params->renderer_prefs); 764 765 #if defined(ENABLE_WEBRTC) 766 if (!media_stream_dispatcher_) 767 media_stream_dispatcher_ = new MediaStreamDispatcher(this); 768 #endif 769 770 new MHTMLGenerator(this); 771 #if defined(OS_MACOSX) 772 new TextInputClientObserver(this); 773 #endif // defined(OS_MACOSX) 774 775 // The next group of objects all implement RenderViewObserver, so are deleted 776 // along with the RenderView automatically. 777 devtools_agent_ = new DevToolsAgent(this); 778 if (RenderWidgetCompositor* rwc = compositor()) { 779 webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId()); 780 } 781 mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this); 782 783 history_controller_.reset(new HistoryController(this)); 784 785 // Create renderer_accessibility_ if needed. 786 OnSetAccessibilityMode(params->accessibility_mode); 787 788 new IdleUserDetector(this); 789 790 if (command_line.HasSwitch(switches::kDomAutomationController)) 791 enabled_bindings_ |= BINDINGS_POLICY_DOM_AUTOMATION; 792 if (command_line.HasSwitch(switches::kStatsCollectionController)) 793 enabled_bindings_ |= BINDINGS_POLICY_STATS_COLLECTION; 794 795 ProcessViewLayoutFlags(command_line); 796 797 GetContentClient()->renderer()->RenderViewCreated(this); 798 799 // If we have an opener_id but we weren't created by a renderer, then 800 // it's the browser asking us to set our opener to another RenderView. 801 if (params->opener_id != MSG_ROUTING_NONE && !params->is_renderer_created) { 802 RenderViewImpl* opener_view = FromRoutingID(params->opener_id); 803 if (opener_view) 804 webview()->mainFrame()->setOpener(opener_view->webview()->mainFrame()); 805 } 806 807 // If we are initially swapped out, navigate to kSwappedOutURL. 808 // This ensures we are in a unique origin that others cannot script. 809 if (is_swapped_out_) 810 NavigateToSwappedOutURL(webview()->mainFrame()); 811 } 812 813 RenderViewImpl::~RenderViewImpl() { 814 for (BitmapMap::iterator it = disambiguation_bitmaps_.begin(); 815 it != disambiguation_bitmaps_.end(); 816 ++it) 817 delete it->second; 818 history_page_ids_.clear(); 819 820 base::debug::TraceLog::GetInstance()->RemoveProcessLabel(routing_id_); 821 822 // If file chooser is still waiting for answer, dispatch empty answer. 823 while (!file_chooser_completions_.empty()) { 824 if (file_chooser_completions_.front()->completion) { 825 file_chooser_completions_.front()->completion->didChooseFile( 826 WebVector<WebString>()); 827 } 828 file_chooser_completions_.pop_front(); 829 } 830 831 #if defined(OS_ANDROID) 832 // The date/time picker client is both a scoped_ptr member of this class and 833 // a RenderViewObserver. Reset it to prevent double deletion. 834 date_time_picker_client_.reset(); 835 #endif 836 837 #ifndef NDEBUG 838 // Make sure we are no longer referenced by the ViewMap or RoutingIDViewMap. 839 ViewMap* views = g_view_map.Pointer(); 840 for (ViewMap::iterator it = views->begin(); it != views->end(); ++it) 841 DCHECK_NE(this, it->second) << "Failed to call Close?"; 842 RoutingIDViewMap* routing_id_views = g_routing_id_view_map.Pointer(); 843 for (RoutingIDViewMap::iterator it = routing_id_views->begin(); 844 it != routing_id_views->end(); ++it) 845 DCHECK_NE(this, it->second) << "Failed to call Close?"; 846 #endif 847 848 FOR_EACH_OBSERVER(RenderViewObserver, observers_, RenderViewGone()); 849 FOR_EACH_OBSERVER(RenderViewObserver, observers_, OnDestruct()); 850 } 851 852 /*static*/ 853 RenderViewImpl* RenderViewImpl::FromWebView(WebView* webview) { 854 ViewMap* views = g_view_map.Pointer(); 855 ViewMap::iterator it = views->find(webview); 856 return it == views->end() ? NULL : it->second; 857 } 858 859 /*static*/ 860 RenderView* RenderView::FromWebView(blink::WebView* webview) { 861 return RenderViewImpl::FromWebView(webview); 862 } 863 864 /*static*/ 865 RenderViewImpl* RenderViewImpl::FromRoutingID(int32 routing_id) { 866 RoutingIDViewMap* views = g_routing_id_view_map.Pointer(); 867 RoutingIDViewMap::iterator it = views->find(routing_id); 868 return it == views->end() ? NULL : it->second; 869 } 870 871 /*static*/ 872 RenderView* RenderView::FromRoutingID(int routing_id) { 873 return RenderViewImpl::FromRoutingID(routing_id); 874 } 875 876 /* static */ 877 size_t RenderViewImpl::GetRenderViewCount() { 878 return g_view_map.Get().size(); 879 } 880 881 /*static*/ 882 void RenderView::ForEach(RenderViewVisitor* visitor) { 883 ViewMap* views = g_view_map.Pointer(); 884 for (ViewMap::iterator it = views->begin(); it != views->end(); ++it) { 885 if (!visitor->Visit(it->second)) 886 return; 887 } 888 } 889 890 /*static*/ 891 RenderViewImpl* RenderViewImpl::Create( 892 int32 opener_id, 893 bool window_was_created_with_opener, 894 const RendererPreferences& renderer_prefs, 895 const WebPreferences& webkit_prefs, 896 int32 routing_id, 897 int32 main_frame_routing_id, 898 int32 surface_id, 899 int64 session_storage_namespace_id, 900 const base::string16& frame_name, 901 bool is_renderer_created, 902 bool swapped_out, 903 int32 proxy_routing_id, 904 bool hidden, 905 bool never_visible, 906 int32 next_page_id, 907 const blink::WebScreenInfo& screen_info, 908 AccessibilityMode accessibility_mode) { 909 DCHECK(routing_id != MSG_ROUTING_NONE); 910 RenderViewImplParams params(opener_id, 911 window_was_created_with_opener, 912 renderer_prefs, 913 webkit_prefs, 914 routing_id, 915 main_frame_routing_id, 916 surface_id, 917 session_storage_namespace_id, 918 frame_name, 919 is_renderer_created, 920 swapped_out, 921 proxy_routing_id, 922 hidden, 923 never_visible, 924 next_page_id, 925 screen_info, 926 accessibility_mode); 927 RenderViewImpl* render_view = NULL; 928 if (g_create_render_view_impl) 929 render_view = g_create_render_view_impl(¶ms); 930 else 931 render_view = new RenderViewImpl(¶ms); 932 933 render_view->Initialize(¶ms); 934 return render_view; 935 } 936 937 // static 938 void RenderViewImpl::InstallCreateHook( 939 RenderViewImpl* (*create_render_view_impl)(RenderViewImplParams*)) { 940 CHECK(!g_create_render_view_impl); 941 g_create_render_view_impl = create_render_view_impl; 942 } 943 944 void RenderViewImpl::AddObserver(RenderViewObserver* observer) { 945 observers_.AddObserver(observer); 946 } 947 948 void RenderViewImpl::RemoveObserver(RenderViewObserver* observer) { 949 observer->RenderViewGone(); 950 observers_.RemoveObserver(observer); 951 } 952 953 blink::WebView* RenderViewImpl::webview() const { 954 return static_cast<blink::WebView*>(webwidget()); 955 } 956 957 #if defined(ENABLE_PLUGINS) 958 void RenderViewImpl::PepperInstanceCreated( 959 PepperPluginInstanceImpl* instance) { 960 active_pepper_instances_.insert(instance); 961 } 962 963 void RenderViewImpl::PepperInstanceDeleted( 964 PepperPluginInstanceImpl* instance) { 965 active_pepper_instances_.erase(instance); 966 967 if (pepper_last_mouse_event_target_ == instance) 968 pepper_last_mouse_event_target_ = NULL; 969 if (focused_pepper_plugin_ == instance) 970 PepperFocusChanged(instance, false); 971 } 972 973 void RenderViewImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance, 974 bool focused) { 975 if (focused) 976 focused_pepper_plugin_ = instance; 977 else if (focused_pepper_plugin_ == instance) 978 focused_pepper_plugin_ = NULL; 979 980 UpdateTextInputState(NO_SHOW_IME, FROM_NON_IME); 981 UpdateSelectionBounds(); 982 } 983 984 void RenderViewImpl::RegisterPluginDelegate(WebPluginDelegateProxy* delegate) { 985 plugin_delegates_.insert(delegate); 986 // If the renderer is visible, set initial visibility and focus state. 987 if (!is_hidden()) { 988 #if defined(OS_MACOSX) 989 delegate->SetContainerVisibility(true); 990 if (webview() && webview()->isActive()) 991 delegate->SetWindowFocus(true); 992 #endif 993 } 994 // Plugins start assuming the content has focus (so that they work in 995 // environments where RenderView isn't hosting them), so we always have to 996 // set the initial state. See webplugin_delegate_impl.h for details. 997 delegate->SetContentAreaFocus(has_focus()); 998 } 999 1000 void RenderViewImpl::UnregisterPluginDelegate( 1001 WebPluginDelegateProxy* delegate) { 1002 plugin_delegates_.erase(delegate); 1003 } 1004 1005 #if defined(OS_WIN) 1006 void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) { 1007 if (focused) 1008 focused_plugin_id_ = plugin_id; 1009 else 1010 focused_plugin_id_ = -1; 1011 } 1012 #endif 1013 1014 #if defined(OS_MACOSX) 1015 void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) { 1016 Send(new ViewHostMsg_PluginFocusChanged(routing_id(), focused, plugin_id)); 1017 } 1018 1019 void RenderViewImpl::StartPluginIme() { 1020 IPC::Message* msg = new ViewHostMsg_StartPluginIme(routing_id()); 1021 // This message can be sent during event-handling, and needs to be delivered 1022 // within that context. 1023 msg->set_unblock(true); 1024 Send(msg); 1025 } 1026 #endif // defined(OS_MACOSX) 1027 1028 #endif // ENABLE_PLUGINS 1029 1030 void RenderViewImpl::TransferActiveWheelFlingAnimation( 1031 const blink::WebActiveWheelFlingParameters& params) { 1032 if (webview()) 1033 webview()->transferActiveWheelFlingAnimation(params); 1034 } 1035 1036 bool RenderViewImpl::HasIMETextFocus() { 1037 return GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE; 1038 } 1039 1040 bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { 1041 WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL; 1042 if (main_frame) 1043 GetContentClient()->SetActiveURL(main_frame->document().url()); 1044 1045 ObserverListBase<RenderViewObserver>::Iterator it(observers_); 1046 RenderViewObserver* observer; 1047 while ((observer = it.GetNext()) != NULL) 1048 if (observer->OnMessageReceived(message)) 1049 return true; 1050 1051 bool handled = true; 1052 IPC_BEGIN_MESSAGE_MAP(RenderViewImpl, message) 1053 IPC_MESSAGE_HANDLER(InputMsg_ExecuteEditCommand, OnExecuteEditCommand) 1054 IPC_MESSAGE_HANDLER(InputMsg_MoveCaret, OnMoveCaret) 1055 IPC_MESSAGE_HANDLER(InputMsg_ScrollFocusedEditableNodeIntoRect, 1056 OnScrollFocusedEditableNodeIntoRect) 1057 IPC_MESSAGE_HANDLER(InputMsg_SetEditCommandsForNextKeyEvent, 1058 OnSetEditCommandsForNextKeyEvent) 1059 IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop) 1060 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt) 1061 IPC_MESSAGE_HANDLER(ViewMsg_SaveImageAt, OnSaveImageAt) 1062 IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind) 1063 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding) 1064 IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom) 1065 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL, 1066 OnSetZoomLevelForLoadingURL) 1067 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForView, 1068 OnSetZoomLevelForView) 1069 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding) 1070 IPC_MESSAGE_HANDLER(ViewMsg_ResetPageEncodingToDefault, 1071 OnResetPageEncodingToDefault) 1072 IPC_MESSAGE_HANDLER(ViewMsg_PostMessageEvent, OnPostMessageEvent) 1073 IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter) 1074 IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver) 1075 IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave) 1076 IPC_MESSAGE_HANDLER(DragMsg_TargetDrop, OnDragTargetDrop) 1077 IPC_MESSAGE_HANDLER(DragMsg_SourceEnded, OnDragSourceEnded) 1078 IPC_MESSAGE_HANDLER(DragMsg_SourceSystemDragEnded, 1079 OnDragSourceSystemDragEnded) 1080 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings) 1081 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus) 1082 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck) 1083 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences) 1084 IPC_MESSAGE_HANDLER(ViewMsg_EnumerateDirectoryResponse, 1085 OnEnumerateDirectoryResponse) 1086 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse) 1087 IPC_MESSAGE_HANDLER(ViewMsg_SuppressDialogsUntilSwapOut, 1088 OnSuppressDialogsUntilSwapOut) 1089 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage) 1090 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged) 1091 IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted) 1092 IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedElement, OnClearFocusedElement) 1093 IPC_MESSAGE_HANDLER(ViewMsg_SetBackgroundOpaque, OnSetBackgroundOpaque) 1094 IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode, 1095 OnEnablePreferredSizeChangedMode) 1096 IPC_MESSAGE_HANDLER(ViewMsg_EnableAutoResize, OnEnableAutoResize) 1097 IPC_MESSAGE_HANDLER(ViewMsg_DisableAutoResize, OnDisableAutoResize) 1098 IPC_MESSAGE_HANDLER(ViewMsg_DisableScrollbarsForSmallWindows, 1099 OnDisableScrollbarsForSmallWindows) 1100 IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs) 1101 IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt, OnMediaPlayerActionAt) 1102 IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt) 1103 IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive) 1104 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage, 1105 OnGetAllSavableResourceLinksForCurrentPage) 1106 IPC_MESSAGE_HANDLER( 1107 ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks, 1108 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks) 1109 IPC_MESSAGE_HANDLER(ViewMsg_ShowContextMenu, OnShowContextMenu) 1110 // TODO(viettrungluu): Move to a separate message filter. 1111 IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndPrune, 1112 OnSetHistoryLengthAndPrune) 1113 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode) 1114 IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode, OnSetAccessibilityMode) 1115 IPC_MESSAGE_HANDLER(ViewMsg_DisownOpener, OnDisownOpener) 1116 IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupBitmap, 1117 OnReleaseDisambiguationPopupBitmap) 1118 IPC_MESSAGE_HANDLER(ViewMsg_WindowSnapshotCompleted, 1119 OnWindowSnapshotCompleted) 1120 IPC_MESSAGE_HANDLER(ViewMsg_SelectWordAroundCaret, OnSelectWordAroundCaret) 1121 #if defined(OS_ANDROID) 1122 IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult, 1123 OnActivateNearestFindResult) 1124 IPC_MESSAGE_HANDLER(ViewMsg_FindMatchRects, OnFindMatchRects) 1125 IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItems, OnSelectPopupMenuItems) 1126 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState, 1127 OnUpdateTopControlsState) 1128 IPC_MESSAGE_HANDLER(ViewMsg_ExtractSmartClipData, OnExtractSmartClipData) 1129 IPC_MESSAGE_HANDLER(ViewMsg_PauseVideoCaptureStream, 1130 OnPauseVideoCaptureStream) 1131 IPC_MESSAGE_HANDLER(ViewMsg_ResumeVideoCaptureStream, 1132 OnResumeVideoCaptureStream) 1133 #elif defined(OS_MACOSX) 1134 IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted, 1135 OnPluginImeCompositionCompleted) 1136 IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItem, OnSelectPopupMenuItem) 1137 IPC_MESSAGE_HANDLER(ViewMsg_SetInLiveResize, OnSetInLiveResize) 1138 IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility) 1139 IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged) 1140 #endif 1141 // Adding a new message? Add platform independent ones first, then put the 1142 // platform specific ones at the end. 1143 1144 // Have the super handle all other messages. 1145 IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message)) 1146 IPC_END_MESSAGE_MAP() 1147 1148 return handled; 1149 } 1150 1151 void RenderViewImpl::OnSelectWordAroundCaret() { 1152 if (!webview()) 1153 return; 1154 1155 handling_input_event_ = true; 1156 webview()->focusedFrame()->selectWordAroundCaret(); 1157 handling_input_event_ = false; 1158 } 1159 1160 bool RenderViewImpl::IsBackForwardToStaleEntry( 1161 const FrameMsg_Navigate_Params& params, 1162 bool is_reload) { 1163 // Make sure this isn't a back/forward to an entry we have already cropped 1164 // or replaced from our history, before the browser knew about it. If so, 1165 // a new navigation has committed in the mean time, and we can ignore this. 1166 bool is_back_forward = !is_reload && params.page_state.IsValid(); 1167 1168 // Note: if the history_list_length_ is 0 for a back/forward, we must be 1169 // restoring from a previous session. We'll update our state in OnNavigate. 1170 if (!is_back_forward || history_list_length_ <= 0) 1171 return false; 1172 1173 DCHECK_EQ(static_cast<int>(history_page_ids_.size()), history_list_length_); 1174 1175 // Check for whether the forward history has been cropped due to a recent 1176 // navigation the browser didn't know about. 1177 if (params.pending_history_list_offset >= history_list_length_) 1178 return true; 1179 1180 // Check for whether this entry has been replaced with a new one. 1181 int expected_page_id = 1182 history_page_ids_[params.pending_history_list_offset]; 1183 if (expected_page_id > 0 && params.page_id != expected_page_id) { 1184 if (params.page_id < expected_page_id) 1185 return true; 1186 1187 // Otherwise we've removed an earlier entry and should have shifted all 1188 // entries left. For now, it's ok to lazily update the list. 1189 // TODO(creis): Notify all live renderers when we remove entries from 1190 // the front of the list, so that we don't hit this case. 1191 history_page_ids_[params.pending_history_list_offset] = params.page_id; 1192 } 1193 1194 return false; 1195 } 1196 1197 // Stop loading the current page. 1198 void RenderViewImpl::OnStop() { 1199 if (webview()) 1200 webview()->mainFrame()->stopLoading(); 1201 FOR_EACH_OBSERVER(RenderViewObserver, observers_, OnStop()); 1202 main_render_frame_->OnStop(); 1203 } 1204 1205 void RenderViewImpl::OnCopyImageAt(int x, int y) { 1206 webview()->copyImageAt(WebPoint(x, y)); 1207 } 1208 1209 void RenderViewImpl::OnSaveImageAt(int x, int y) { 1210 webview()->saveImageAt(WebPoint(x, y)); 1211 } 1212 1213 void RenderViewImpl::OnUpdateTargetURLAck() { 1214 // Check if there is a targeturl waiting to be sent. 1215 if (target_url_status_ == TARGET_PENDING) { 1216 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, 1217 pending_target_url_)); 1218 } 1219 1220 target_url_status_ = TARGET_NONE; 1221 } 1222 1223 void RenderViewImpl::OnExecuteEditCommand(const std::string& name, 1224 const std::string& value) { 1225 if (!webview() || !webview()->focusedFrame()) 1226 return; 1227 1228 webview()->focusedFrame()->executeCommand( 1229 WebString::fromUTF8(name), WebString::fromUTF8(value)); 1230 } 1231 1232 void RenderViewImpl::OnMoveCaret(const gfx::Point& point) { 1233 if (!webview()) 1234 return; 1235 1236 Send(new ViewHostMsg_MoveCaret_ACK(routing_id_)); 1237 1238 webview()->focusedFrame()->moveCaretSelection(point); 1239 } 1240 1241 void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect( 1242 const gfx::Rect& rect) { 1243 if (has_scrolled_focused_editable_node_into_rect_ && 1244 rect == rect_for_scrolled_focused_editable_node_) { 1245 return; 1246 } 1247 1248 blink::WebElement element = GetFocusedElement(); 1249 if (!element.isNull() && IsEditableNode(element)) { 1250 rect_for_scrolled_focused_editable_node_ = rect; 1251 has_scrolled_focused_editable_node_into_rect_ = true; 1252 webview()->scrollFocusedNodeIntoRect(rect); 1253 } 1254 } 1255 1256 void RenderViewImpl::OnSetEditCommandsForNextKeyEvent( 1257 const EditCommands& edit_commands) { 1258 edit_commands_ = edit_commands; 1259 } 1260 1261 void RenderViewImpl::OnSetHistoryLengthAndPrune(int history_length, 1262 int32 minimum_page_id) { 1263 DCHECK_GE(history_length, 0); 1264 DCHECK(history_list_offset_ == history_list_length_ - 1); 1265 DCHECK_GE(minimum_page_id, -1); 1266 1267 // Generate the new list. 1268 std::vector<int32> new_history_page_ids(history_length, -1); 1269 for (size_t i = 0; i < history_page_ids_.size(); ++i) { 1270 if (minimum_page_id >= 0 && history_page_ids_[i] < minimum_page_id) 1271 continue; 1272 new_history_page_ids.push_back(history_page_ids_[i]); 1273 } 1274 new_history_page_ids.swap(history_page_ids_); 1275 1276 // Update indexes. 1277 history_list_length_ = history_page_ids_.size(); 1278 history_list_offset_ = history_list_length_ - 1; 1279 } 1280 1281 1282 void RenderViewImpl::OnSetInitialFocus(bool reverse) { 1283 if (!webview()) 1284 return; 1285 webview()->setInitialFocus(reverse); 1286 } 1287 1288 #if defined(OS_MACOSX) 1289 void RenderViewImpl::OnSetInLiveResize(bool in_live_resize) { 1290 if (!webview()) 1291 return; 1292 if (in_live_resize) 1293 webview()->willStartLiveResize(); 1294 else 1295 webview()->willEndLiveResize(); 1296 } 1297 #endif 1298 1299 /////////////////////////////////////////////////////////////////////////////// 1300 1301 // Sends the current history state to the browser so it will be saved before we 1302 // navigate to a new page. 1303 void RenderViewImpl::UpdateSessionHistory(WebFrame* frame) { 1304 // If we have a valid page ID at this point, then it corresponds to the page 1305 // we are navigating away from. Otherwise, this is the first navigation, so 1306 // there is no past session history to record. 1307 if (page_id_ == -1) 1308 return; 1309 SendUpdateState(history_controller_->GetCurrentEntry()); 1310 } 1311 1312 void RenderViewImpl::SendUpdateState(HistoryEntry* entry) { 1313 if (!entry) 1314 return; 1315 1316 // Don't send state updates for kSwappedOutURL. 1317 if (entry->root().urlString() == WebString::fromUTF8(kSwappedOutURL)) 1318 return; 1319 1320 Send(new ViewHostMsg_UpdateState( 1321 routing_id_, page_id_, HistoryEntryToPageState(entry))); 1322 } 1323 1324 bool RenderViewImpl::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) { 1325 // Before WebKit asks us to show an alert (etc.), it takes care of doing the 1326 // equivalent of WebView::willEnterModalLoop. In the case of showModalDialog 1327 // it is particularly important that we do not call willEnterModalLoop as 1328 // that would defer resource loads for the dialog itself. 1329 if (RenderThreadImpl::current()) // Will be NULL during unit tests. 1330 RenderThreadImpl::current()->DoNotNotifyWebKitOfModalLoop(); 1331 1332 message->EnableMessagePumping(); // Runs a nested message loop. 1333 return Send(message); 1334 } 1335 1336 void RenderViewImpl::GetWindowSnapshot(const WindowSnapshotCallback& callback) { 1337 int id = next_snapshot_id_++; 1338 pending_snapshots_.insert(std::make_pair(id, callback)); 1339 ui::LatencyInfo latency_info; 1340 latency_info.AddLatencyNumber(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT, 1341 0, 1342 id); 1343 scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor; 1344 if (RenderWidgetCompositor* rwc = compositor()) { 1345 latency_info_swap_promise_monitor = 1346 rwc->CreateLatencyInfoSwapPromiseMonitor(&latency_info).Pass(); 1347 } 1348 ScheduleCompositeWithForcedRedraw(); 1349 } 1350 1351 void RenderViewImpl::OnWindowSnapshotCompleted(const int snapshot_id, 1352 const gfx::Size& size, const std::vector<unsigned char>& png) { 1353 1354 // Any pending snapshots with a lower ID than the one received are considered 1355 // to be implicitly complete, and returned the same snapshot data. 1356 PendingSnapshotMap::iterator it = pending_snapshots_.begin(); 1357 while(it != pending_snapshots_.end()) { 1358 if (it->first <= snapshot_id) { 1359 it->second.Run(size, png); 1360 pending_snapshots_.erase(it++); 1361 } else { 1362 ++it; 1363 } 1364 } 1365 } 1366 1367 // blink::WebViewClient ------------------------------------------------------ 1368 1369 WebView* RenderViewImpl::createView(WebLocalFrame* creator, 1370 const WebURLRequest& request, 1371 const WebWindowFeatures& features, 1372 const WebString& frame_name, 1373 WebNavigationPolicy policy, 1374 bool suppress_opener) { 1375 ViewHostMsg_CreateWindow_Params params; 1376 params.opener_id = routing_id_; 1377 params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture(); 1378 if (GetContentClient()->renderer()->AllowPopup()) 1379 params.user_gesture = true; 1380 params.window_container_type = WindowFeaturesToContainerType(features); 1381 params.session_storage_namespace_id = session_storage_namespace_id_; 1382 if (frame_name != "_blank") 1383 params.frame_name = frame_name; 1384 params.opener_render_frame_id = 1385 RenderFrameImpl::FromWebFrame(creator)->GetRoutingID(); 1386 params.opener_url = creator->document().url(); 1387 params.opener_top_level_frame_url = creator->top()->document().url(); 1388 GURL security_url(creator->document().securityOrigin().toString()); 1389 if (!security_url.is_valid()) 1390 security_url = GURL(); 1391 params.opener_security_origin = security_url; 1392 params.opener_suppressed = suppress_opener; 1393 params.disposition = NavigationPolicyToDisposition(policy); 1394 if (!request.isNull()) { 1395 params.target_url = request.url(); 1396 params.referrer = GetReferrerFromRequest(creator, request); 1397 } 1398 params.features = features; 1399 1400 for (size_t i = 0; i < features.additionalFeatures.size(); ++i) 1401 params.additional_features.push_back(features.additionalFeatures[i]); 1402 1403 int32 routing_id = MSG_ROUTING_NONE; 1404 int32 main_frame_routing_id = MSG_ROUTING_NONE; 1405 int32 surface_id = 0; 1406 int64 cloned_session_storage_namespace_id; 1407 1408 RenderThread::Get()->Send( 1409 new ViewHostMsg_CreateWindow(params, 1410 &routing_id, 1411 &main_frame_routing_id, 1412 &surface_id, 1413 &cloned_session_storage_namespace_id)); 1414 if (routing_id == MSG_ROUTING_NONE) 1415 return NULL; 1416 1417 WebUserGestureIndicator::consumeUserGesture(); 1418 1419 // While this view may be a background extension page, it can spawn a visible 1420 // render view. So we just assume that the new one is not another background 1421 // page instead of passing on our own value. 1422 // TODO(vangelis): Can we tell if the new view will be a background page? 1423 bool never_visible = false; 1424 1425 // The initial hidden state for the RenderViewImpl here has to match what the 1426 // browser will eventually decide for the given disposition. Since we have to 1427 // return from this call synchronously, we just have to make our best guess 1428 // and rely on the browser sending a WasHidden / WasShown message if it 1429 // disagrees. 1430 RenderViewImpl* view = RenderViewImpl::Create( 1431 routing_id_, 1432 true, // window_was_created_with_opener 1433 renderer_preferences_, 1434 webkit_preferences_, 1435 routing_id, 1436 main_frame_routing_id, 1437 surface_id, 1438 cloned_session_storage_namespace_id, 1439 base::string16(), // WebCore will take care of setting the correct name. 1440 true, // is_renderer_created 1441 false, // swapped_out 1442 MSG_ROUTING_NONE, // proxy_routing_id 1443 params.disposition == NEW_BACKGROUND_TAB, // hidden 1444 never_visible, 1445 1, // next_page_id 1446 screen_info_, 1447 accessibility_mode_); 1448 view->opened_by_user_gesture_ = params.user_gesture; 1449 1450 // Record whether the creator frame is trying to suppress the opener field. 1451 view->opener_suppressed_ = params.opener_suppressed; 1452 1453 return view->webview(); 1454 } 1455 1456 WebWidget* RenderViewImpl::createPopupMenu(blink::WebPopupType popup_type) { 1457 RenderWidget* widget = 1458 RenderWidget::Create(routing_id_, popup_type, screen_info_); 1459 if (!widget) 1460 return NULL; 1461 if (screen_metrics_emulator_) { 1462 widget->SetPopupOriginAdjustmentsForEmulation( 1463 screen_metrics_emulator_.get()); 1464 } 1465 return widget->webwidget(); 1466 } 1467 1468 WebExternalPopupMenu* RenderViewImpl::createExternalPopupMenu( 1469 const WebPopupMenuInfo& popup_menu_info, 1470 WebExternalPopupMenuClient* popup_menu_client) { 1471 #if defined(OS_MACOSX) || defined(OS_ANDROID) 1472 // An IPC message is sent to the browser to build and display the actual 1473 // popup. The user could have time to click a different select by the time 1474 // the popup is shown. In that case external_popup_menu_ is non NULL. 1475 // By returning NULL in that case, we instruct WebKit to cancel that new 1476 // popup. So from the user perspective, only the first one will show, and 1477 // will have to close the first one before another one can be shown. 1478 if (external_popup_menu_) 1479 return NULL; 1480 external_popup_menu_.reset( 1481 new ExternalPopupMenu(this, popup_menu_info, popup_menu_client)); 1482 if (screen_metrics_emulator_) { 1483 SetExternalPopupOriginAdjustmentsForEmulation( 1484 external_popup_menu_.get(), screen_metrics_emulator_.get()); 1485 } 1486 return external_popup_menu_.get(); 1487 #else 1488 return NULL; 1489 #endif 1490 } 1491 1492 WebStorageNamespace* RenderViewImpl::createSessionStorageNamespace() { 1493 CHECK(session_storage_namespace_id_ != kInvalidSessionStorageNamespaceId); 1494 return new WebStorageNamespaceImpl(session_storage_namespace_id_); 1495 } 1496 1497 void RenderViewImpl::printPage(WebLocalFrame* frame) { 1498 FOR_EACH_OBSERVER(RenderViewObserver, observers_, 1499 PrintPage(frame, handling_input_event_)); 1500 } 1501 1502 bool RenderViewImpl::enumerateChosenDirectory( 1503 const WebString& path, 1504 WebFileChooserCompletion* chooser_completion) { 1505 int id = enumeration_completion_id_++; 1506 enumeration_completions_[id] = chooser_completion; 1507 return Send(new ViewHostMsg_EnumerateDirectory( 1508 routing_id_, 1509 id, 1510 base::FilePath::FromUTF16Unsafe(path))); 1511 } 1512 1513 void RenderViewImpl::FrameDidStartLoading(WebFrame* frame) { 1514 DCHECK_GE(frames_in_progress_, 0); 1515 if (frames_in_progress_ == 0) 1516 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStartLoading()); 1517 frames_in_progress_++; 1518 } 1519 1520 void RenderViewImpl::FrameDidStopLoading(WebFrame* frame) { 1521 // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes 1522 // calls DidStopLoading() without a matching DidStartLoading(). 1523 if (frames_in_progress_ == 0) 1524 return; 1525 frames_in_progress_--; 1526 if (frames_in_progress_ == 0) { 1527 DidStopLoadingIcons(); 1528 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStopLoading()); 1529 } 1530 } 1531 1532 void RenderViewImpl::didCancelCompositionOnSelectionChange() { 1533 Send(new ViewHostMsg_ImeCancelComposition(routing_id())); 1534 } 1535 1536 bool RenderViewImpl::handleCurrentKeyboardEvent() { 1537 if (edit_commands_.empty()) 1538 return false; 1539 1540 WebFrame* frame = webview()->focusedFrame(); 1541 if (!frame) 1542 return false; 1543 1544 EditCommands::iterator it = edit_commands_.begin(); 1545 EditCommands::iterator end = edit_commands_.end(); 1546 1547 bool did_execute_command = false; 1548 for (; it != end; ++it) { 1549 // In gtk and cocoa, it's possible to bind multiple edit commands to one 1550 // key (but it's the exception). Once one edit command is not executed, it 1551 // seems safest to not execute the rest. 1552 if (!frame->executeCommand(WebString::fromUTF8(it->name), 1553 WebString::fromUTF8(it->value), 1554 GetFocusedElement())) 1555 break; 1556 did_execute_command = true; 1557 } 1558 1559 return did_execute_command; 1560 } 1561 1562 bool RenderViewImpl::runFileChooser( 1563 const blink::WebFileChooserParams& params, 1564 WebFileChooserCompletion* chooser_completion) { 1565 // Do not open the file dialog in a hidden RenderView. 1566 if (is_hidden()) 1567 return false; 1568 FileChooserParams ipc_params; 1569 if (params.directory) 1570 ipc_params.mode = FileChooserParams::UploadFolder; 1571 else if (params.multiSelect) 1572 ipc_params.mode = FileChooserParams::OpenMultiple; 1573 else if (params.saveAs) 1574 ipc_params.mode = FileChooserParams::Save; 1575 else 1576 ipc_params.mode = FileChooserParams::Open; 1577 ipc_params.title = params.title; 1578 ipc_params.default_file_name = 1579 base::FilePath::FromUTF16Unsafe(params.initialValue); 1580 ipc_params.accept_types.reserve(params.acceptTypes.size()); 1581 for (size_t i = 0; i < params.acceptTypes.size(); ++i) 1582 ipc_params.accept_types.push_back(params.acceptTypes[i]); 1583 #if defined(OS_ANDROID) 1584 ipc_params.capture = params.useMediaCapture; 1585 #endif 1586 1587 return ScheduleFileChooser(ipc_params, chooser_completion); 1588 } 1589 1590 void RenderViewImpl::showValidationMessage( 1591 const blink::WebRect& anchor_in_root_view, 1592 const blink::WebString& main_text, 1593 const blink::WebString& sub_text, 1594 blink::WebTextDirection hint) { 1595 base::string16 wrapped_main_text = main_text; 1596 base::string16 wrapped_sub_text = sub_text; 1597 if (hint == blink::WebTextDirectionLeftToRight) { 1598 wrapped_main_text = 1599 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_main_text); 1600 if (!wrapped_sub_text.empty()) { 1601 wrapped_sub_text = 1602 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_sub_text); 1603 } 1604 } else if (hint == blink::WebTextDirectionRightToLeft 1605 && !base::i18n::IsRTL()) { 1606 base::i18n::WrapStringWithRTLFormatting(&wrapped_main_text); 1607 if (!wrapped_sub_text.empty()) { 1608 base::i18n::WrapStringWithRTLFormatting(&wrapped_sub_text); 1609 } 1610 } 1611 Send(new ViewHostMsg_ShowValidationMessage( 1612 routing_id(), anchor_in_root_view, wrapped_main_text, wrapped_sub_text)); 1613 } 1614 1615 void RenderViewImpl::hideValidationMessage() { 1616 Send(new ViewHostMsg_HideValidationMessage(routing_id())); 1617 } 1618 1619 void RenderViewImpl::moveValidationMessage( 1620 const blink::WebRect& anchor_in_root_view) { 1621 Send(new ViewHostMsg_MoveValidationMessage(routing_id(), 1622 anchor_in_root_view)); 1623 } 1624 1625 void RenderViewImpl::setStatusText(const WebString& text) { 1626 } 1627 1628 void RenderViewImpl::UpdateTargetURL(const GURL& url, 1629 const GURL& fallback_url) { 1630 GURL latest_url = url.is_empty() ? fallback_url : url; 1631 if (latest_url == target_url_) 1632 return; 1633 1634 // Tell the browser to display a destination link. 1635 if (target_url_status_ == TARGET_INFLIGHT || 1636 target_url_status_ == TARGET_PENDING) { 1637 // If we have a request in-flight, save the URL to be sent when we 1638 // receive an ACK to the in-flight request. We can happily overwrite 1639 // any existing pending sends. 1640 pending_target_url_ = latest_url; 1641 target_url_status_ = TARGET_PENDING; 1642 } else { 1643 // URLs larger than |MaxURLChars()| cannot be sent through IPC - 1644 // see |ParamTraits<GURL>|. 1645 if (latest_url.possibly_invalid_spec().size() > GetMaxURLChars()) 1646 latest_url = GURL(); 1647 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, latest_url)); 1648 target_url_ = latest_url; 1649 target_url_status_ = TARGET_INFLIGHT; 1650 } 1651 } 1652 1653 gfx::RectF RenderViewImpl::ClientRectToPhysicalWindowRect( 1654 const gfx::RectF& rect) const { 1655 gfx::RectF window_rect = rect; 1656 window_rect.Scale(device_scale_factor_ * webview()->pageScaleFactor()); 1657 return window_rect; 1658 } 1659 1660 void RenderViewImpl::StartNavStateSyncTimerIfNecessary() { 1661 // No need to update state if no page has committed yet. 1662 if (page_id_ == -1) 1663 return; 1664 1665 int delay; 1666 if (send_content_state_immediately_) 1667 delay = 0; 1668 else if (is_hidden()) 1669 delay = kDelaySecondsForContentStateSyncHidden; 1670 else 1671 delay = kDelaySecondsForContentStateSync; 1672 1673 if (nav_state_sync_timer_.IsRunning()) { 1674 // The timer is already running. If the delay of the timer maches the amount 1675 // we want to delay by, then return. Otherwise stop the timer so that it 1676 // gets started with the right delay. 1677 if (nav_state_sync_timer_.GetCurrentDelay().InSeconds() == delay) 1678 return; 1679 nav_state_sync_timer_.Stop(); 1680 } 1681 1682 nav_state_sync_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(delay), this, 1683 &RenderViewImpl::SyncNavigationState); 1684 } 1685 1686 void RenderViewImpl::setMouseOverURL(const WebURL& url) { 1687 mouse_over_url_ = GURL(url); 1688 UpdateTargetURL(mouse_over_url_, focus_url_); 1689 } 1690 1691 void RenderViewImpl::setKeyboardFocusURL(const WebURL& url) { 1692 focus_url_ = GURL(url); 1693 UpdateTargetURL(focus_url_, mouse_over_url_); 1694 } 1695 1696 void RenderViewImpl::startDragging(WebLocalFrame* frame, 1697 const WebDragData& data, 1698 WebDragOperationsMask mask, 1699 const WebImage& image, 1700 const WebPoint& webImageOffset) { 1701 DropData drop_data(DropDataBuilder::Build(data)); 1702 drop_data.referrer_policy = frame->document().referrerPolicy(); 1703 gfx::Vector2d imageOffset(webImageOffset.x, webImageOffset.y); 1704 Send(new DragHostMsg_StartDragging(routing_id_, 1705 drop_data, 1706 mask, 1707 image.getSkBitmap(), 1708 imageOffset, 1709 possible_drag_event_info_)); 1710 } 1711 1712 bool RenderViewImpl::acceptsLoadDrops() { 1713 return renderer_preferences_.can_accept_load_drops; 1714 } 1715 1716 void RenderViewImpl::focusNext() { 1717 Send(new ViewHostMsg_TakeFocus(routing_id_, false)); 1718 } 1719 1720 void RenderViewImpl::focusPrevious() { 1721 Send(new ViewHostMsg_TakeFocus(routing_id_, true)); 1722 } 1723 1724 void RenderViewImpl::focusedNodeChanged(const WebNode& node) { 1725 has_scrolled_focused_editable_node_into_rect_ = false; 1726 1727 Send(new ViewHostMsg_FocusedNodeChanged(routing_id_, IsEditableNode(node))); 1728 1729 FOR_EACH_OBSERVER(RenderViewObserver, observers_, FocusedNodeChanged(node)); 1730 } 1731 1732 void RenderViewImpl::didUpdateLayout() { 1733 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidUpdateLayout()); 1734 1735 // We don't always want to set up a timer, only if we've been put in that 1736 // mode by getting a |ViewMsg_EnablePreferredSizeChangedMode| 1737 // message. 1738 if (!send_preferred_size_changes_ || !webview()) 1739 return; 1740 1741 if (check_preferred_size_timer_.IsRunning()) 1742 return; 1743 check_preferred_size_timer_.Start(FROM_HERE, 1744 TimeDelta::FromMilliseconds(0), this, 1745 &RenderViewImpl::CheckPreferredSize); 1746 } 1747 1748 void RenderViewImpl::navigateBackForwardSoon(int offset) { 1749 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset)); 1750 } 1751 1752 int RenderViewImpl::historyBackListCount() { 1753 return history_list_offset_ < 0 ? 0 : history_list_offset_; 1754 } 1755 1756 int RenderViewImpl::historyForwardListCount() { 1757 return history_list_length_ - historyBackListCount() - 1; 1758 } 1759 1760 void RenderViewImpl::postAccessibilityEvent( 1761 const WebAXObject& obj, blink::WebAXEvent event) { 1762 if (renderer_accessibility_) { 1763 renderer_accessibility_->HandleWebAccessibilityEvent(obj, event); 1764 } 1765 } 1766 1767 void RenderViewImpl::didUpdateInspectorSetting(const WebString& key, 1768 const WebString& value) { 1769 Send(new ViewHostMsg_UpdateInspectorSetting(routing_id_, 1770 key.utf8(), 1771 value.utf8())); 1772 } 1773 1774 // blink::WebWidgetClient ---------------------------------------------------- 1775 1776 void RenderViewImpl::didFocus() { 1777 // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed 1778 // we won't have to test for user gesture anymore and we can 1779 // move that code back to render_widget.cc 1780 if (WebUserGestureIndicator::isProcessingUserGesture() && 1781 !RenderThreadImpl::current()->layout_test_mode()) { 1782 Send(new ViewHostMsg_Focus(routing_id_)); 1783 } 1784 } 1785 1786 void RenderViewImpl::didBlur() { 1787 // TODO(jcivelli): see TODO above in didFocus(). 1788 if (WebUserGestureIndicator::isProcessingUserGesture() && 1789 !RenderThreadImpl::current()->layout_test_mode()) { 1790 Send(new ViewHostMsg_Blur(routing_id_)); 1791 } 1792 } 1793 1794 // We are supposed to get a single call to Show for a newly created RenderView 1795 // that was created via RenderViewImpl::CreateWebView. So, we wait until this 1796 // point to dispatch the ShowView message. 1797 // 1798 // This method provides us with the information about how to display the newly 1799 // created RenderView (i.e., as a blocked popup or as a new tab). 1800 // 1801 void RenderViewImpl::show(WebNavigationPolicy policy) { 1802 if (did_show_) { 1803 // When supports_multiple_windows is disabled, popups are reusing 1804 // the same view. In some scenarios, this makes WebKit to call show() twice. 1805 if (webkit_preferences_.supports_multiple_windows) 1806 NOTREACHED() << "received extraneous Show call"; 1807 return; 1808 } 1809 did_show_ = true; 1810 1811 DCHECK(opener_id_ != MSG_ROUTING_NONE); 1812 1813 // Force new windows to a popup if they were not opened with a user gesture. 1814 if (!opened_by_user_gesture_) { 1815 // We exempt background tabs for compat with older versions of Chrome. 1816 // TODO(darin): This seems bogus. These should have a user gesture, so 1817 // we probably don't need this check. 1818 if (policy != blink::WebNavigationPolicyNewBackgroundTab) 1819 policy = blink::WebNavigationPolicyNewPopup; 1820 } 1821 1822 // NOTE: initial_pos_ may still have its default values at this point, but 1823 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the 1824 // browser process will impose a default position otherwise. 1825 Send(new ViewHostMsg_ShowView(opener_id_, routing_id_, 1826 NavigationPolicyToDisposition(policy), initial_pos_, 1827 opened_by_user_gesture_)); 1828 SetPendingWindowRect(initial_pos_); 1829 } 1830 1831 void RenderViewImpl::runModal() { 1832 DCHECK(did_show_) << "should already have shown the view"; 1833 1834 // Don't allow further dialogs if we are waiting to swap out, since the 1835 // PageGroupLoadDeferrer in our stack prevents it. 1836 if (suppress_dialogs_until_swap_out_) 1837 return; 1838 1839 // We must keep WebKit's shared timer running in this case in order to allow 1840 // showModalDialog to function properly. 1841 // 1842 // TODO(darin): WebKit should really be smarter about suppressing events and 1843 // timers so that we do not need to manage the shared timer in such a heavy 1844 // handed manner. 1845 // 1846 if (RenderThreadImpl::current()) // Will be NULL during unit tests. 1847 RenderThreadImpl::current()->DoNotSuspendWebKitSharedTimer(); 1848 1849 SendAndRunNestedMessageLoop(new ViewHostMsg_RunModal( 1850 routing_id_, opener_id_)); 1851 } 1852 1853 bool RenderViewImpl::enterFullScreen() { 1854 Send(new ViewHostMsg_ToggleFullscreen(routing_id_, true)); 1855 return true; 1856 } 1857 1858 void RenderViewImpl::exitFullScreen() { 1859 Send(new ViewHostMsg_ToggleFullscreen(routing_id_, false)); 1860 } 1861 1862 bool RenderViewImpl::requestPointerLock() { 1863 return mouse_lock_dispatcher_->LockMouse(webwidget_mouse_lock_target_.get()); 1864 } 1865 1866 void RenderViewImpl::requestPointerUnlock() { 1867 mouse_lock_dispatcher_->UnlockMouse(webwidget_mouse_lock_target_.get()); 1868 } 1869 1870 bool RenderViewImpl::isPointerLocked() { 1871 return mouse_lock_dispatcher_->IsMouseLockedTo( 1872 webwidget_mouse_lock_target_.get()); 1873 } 1874 1875 void RenderViewImpl::didHandleGestureEvent( 1876 const WebGestureEvent& event, 1877 bool event_cancelled) { 1878 RenderWidget::didHandleGestureEvent(event, event_cancelled); 1879 1880 if (event.type != blink::WebGestureEvent::GestureTap) 1881 return; 1882 1883 blink::WebTextInputType text_input_type = 1884 GetWebView()->textInputInfo().type; 1885 1886 Send(new ViewHostMsg_FocusedNodeTouched( 1887 routing_id(), text_input_type != blink::WebTextInputTypeNone)); 1888 } 1889 1890 void RenderViewImpl::initializeLayerTreeView() { 1891 RenderWidget::initializeLayerTreeView(); 1892 RenderWidgetCompositor* rwc = compositor(); 1893 if (!rwc) 1894 return; 1895 if (webview() && webview()->devToolsAgent()) 1896 webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId()); 1897 1898 #if !defined(OS_MACOSX) // many events are unhandled - http://crbug.com/138003 1899 RenderThreadImpl* render_thread = RenderThreadImpl::current(); 1900 // render_thread may be NULL in tests. 1901 InputHandlerManager* input_handler_manager = 1902 render_thread ? render_thread->input_handler_manager() : NULL; 1903 if (input_handler_manager) { 1904 input_handler_manager->AddInputHandler( 1905 routing_id_, rwc->GetInputHandler(), AsWeakPtr()); 1906 } 1907 #endif 1908 } 1909 1910 // blink::WebFrameClient ----------------------------------------------------- 1911 1912 void RenderViewImpl::Repaint(const gfx::Size& size) { 1913 OnRepaint(size); 1914 } 1915 1916 void RenderViewImpl::SetEditCommandForNextKeyEvent(const std::string& name, 1917 const std::string& value) { 1918 EditCommands edit_commands; 1919 edit_commands.push_back(EditCommand(name, value)); 1920 OnSetEditCommandsForNextKeyEvent(edit_commands); 1921 } 1922 1923 void RenderViewImpl::ClearEditCommands() { 1924 edit_commands_.clear(); 1925 } 1926 1927 SSLStatus RenderViewImpl::GetSSLStatusOfFrame(blink::WebFrame* frame) const { 1928 std::string security_info; 1929 if (frame && frame->dataSource()) 1930 security_info = frame->dataSource()->response().securityInfo(); 1931 1932 SSLStatus ssl_status; 1933 DeserializeSecurityInfo(security_info, 1934 &ssl_status.cert_id, 1935 &ssl_status.cert_status, 1936 &ssl_status.security_bits, 1937 &ssl_status.connection_status, 1938 &ssl_status.signed_certificate_timestamp_ids); 1939 return ssl_status; 1940 } 1941 1942 const std::string& RenderViewImpl::GetAcceptLanguages() const { 1943 return renderer_preferences_.accept_languages; 1944 } 1945 1946 void RenderViewImpl::didCreateDataSource(WebLocalFrame* frame, 1947 WebDataSource* ds) { 1948 bool content_initiated = !pending_navigation_params_.get(); 1949 1950 // Make sure any previous redirect URLs end up in our new data source. 1951 if (pending_navigation_params_.get()) { 1952 for (std::vector<GURL>::const_iterator i = 1953 pending_navigation_params_->redirects.begin(); 1954 i != pending_navigation_params_->redirects.end(); ++i) { 1955 ds->appendRedirect(*i); 1956 } 1957 } 1958 1959 DocumentState* document_state = DocumentState::FromDataSource(ds); 1960 if (!document_state) { 1961 document_state = new DocumentState; 1962 ds->setExtraData(document_state); 1963 if (!content_initiated) 1964 PopulateDocumentStateFromPending(document_state); 1965 } 1966 1967 // Carry over the user agent override flag, if it exists. 1968 if (content_initiated && webview() && webview()->mainFrame() && 1969 webview()->mainFrame()->dataSource()) { 1970 DocumentState* old_document_state = 1971 DocumentState::FromDataSource(webview()->mainFrame()->dataSource()); 1972 if (old_document_state) { 1973 InternalDocumentStateData* internal_data = 1974 InternalDocumentStateData::FromDocumentState(document_state); 1975 InternalDocumentStateData* old_internal_data = 1976 InternalDocumentStateData::FromDocumentState(old_document_state); 1977 internal_data->set_is_overriding_user_agent( 1978 old_internal_data->is_overriding_user_agent()); 1979 } 1980 } 1981 1982 // The rest of RenderView assumes that a WebDataSource will always have a 1983 // non-null NavigationState. 1984 if (content_initiated) { 1985 document_state->set_navigation_state( 1986 NavigationState::CreateContentInitiated()); 1987 } else { 1988 document_state->set_navigation_state(CreateNavigationStateFromPending()); 1989 pending_navigation_params_.reset(); 1990 } 1991 1992 // DocumentState::referred_by_prefetcher_ is true if we are 1993 // navigating from a page that used prefetching using a link on that 1994 // page. We are early enough in the request process here that we 1995 // can still see the DocumentState of the previous page and set 1996 // this value appropriately. 1997 // TODO(gavinp): catch the important case of navigation in a new 1998 // renderer process. 1999 if (webview()) { 2000 if (WebFrame* old_frame = webview()->mainFrame()) { 2001 const WebURLRequest& original_request = ds->originalRequest(); 2002 const GURL referrer( 2003 original_request.httpHeaderField(WebString::fromUTF8("Referer"))); 2004 if (!referrer.is_empty() && 2005 DocumentState::FromDataSource( 2006 old_frame->dataSource())->was_prefetcher()) { 2007 for (; old_frame; old_frame = old_frame->traverseNext(false)) { 2008 WebDataSource* old_frame_ds = old_frame->dataSource(); 2009 if (old_frame_ds && referrer == GURL(old_frame_ds->request().url())) { 2010 document_state->set_was_referred_by_prefetcher(true); 2011 break; 2012 } 2013 } 2014 } 2015 } 2016 } 2017 2018 if (content_initiated) { 2019 const WebURLRequest& request = ds->request(); 2020 switch (request.cachePolicy()) { 2021 case WebURLRequest::UseProtocolCachePolicy: // normal load. 2022 document_state->set_load_type(DocumentState::LINK_LOAD_NORMAL); 2023 break; 2024 case WebURLRequest::ReloadIgnoringCacheData: // reload. 2025 case WebURLRequest::ReloadBypassingCache: // end-to-end reload. 2026 document_state->set_load_type(DocumentState::LINK_LOAD_RELOAD); 2027 break; 2028 case WebURLRequest::ReturnCacheDataElseLoad: // allow stale data. 2029 document_state->set_load_type( 2030 DocumentState::LINK_LOAD_CACHE_STALE_OK); 2031 break; 2032 case WebURLRequest::ReturnCacheDataDontLoad: // Don't re-post. 2033 document_state->set_load_type(DocumentState::LINK_LOAD_CACHE_ONLY); 2034 break; 2035 default: 2036 NOTREACHED(); 2037 } 2038 } 2039 2040 FOR_EACH_OBSERVER( 2041 RenderViewObserver, observers_, DidCreateDataSource(frame, ds)); 2042 } 2043 2044 void RenderViewImpl::PopulateDocumentStateFromPending( 2045 DocumentState* document_state) { 2046 const FrameMsg_Navigate_Params& params = *pending_navigation_params_.get(); 2047 document_state->set_request_time(params.request_time); 2048 2049 InternalDocumentStateData* internal_data = 2050 InternalDocumentStateData::FromDocumentState(document_state); 2051 2052 if (!params.url.SchemeIs(url::kJavaScriptScheme) && 2053 params.navigation_type == FrameMsg_Navigate_Type::RESTORE) { 2054 // We're doing a load of a page that was restored from the last session. By 2055 // default this prefers the cache over loading (LOAD_PREFERRING_CACHE) which 2056 // can result in stale data for pages that are set to expire. We explicitly 2057 // override that by setting the policy here so that as necessary we load 2058 // from the network. 2059 // 2060 // TODO(davidben): Remove this in favor of passing a cache policy to the 2061 // loadHistoryItem call in OnNavigate. That requires not overloading 2062 // UseProtocolCachePolicy to mean both "normal load" and "determine cache 2063 // policy based on load type, etc". 2064 internal_data->set_cache_policy_override( 2065 WebURLRequest::UseProtocolCachePolicy); 2066 } 2067 2068 if (IsReload(params)) 2069 document_state->set_load_type(DocumentState::RELOAD); 2070 else if (params.page_state.IsValid()) 2071 document_state->set_load_type(DocumentState::HISTORY_LOAD); 2072 else 2073 document_state->set_load_type(DocumentState::NORMAL_LOAD); 2074 2075 internal_data->set_is_overriding_user_agent(params.is_overriding_user_agent); 2076 internal_data->set_must_reset_scroll_and_scale_state( 2077 params.navigation_type == 2078 FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL); 2079 document_state->set_can_load_local_resources(params.can_load_local_resources); 2080 } 2081 2082 NavigationState* RenderViewImpl::CreateNavigationStateFromPending() { 2083 const FrameMsg_Navigate_Params& params = *pending_navigation_params_.get(); 2084 NavigationState* navigation_state = NULL; 2085 2086 // A navigation resulting from loading a javascript URL should not be treated 2087 // as a browser initiated event. Instead, we want it to look as if the page 2088 // initiated any load resulting from JS execution. 2089 if (!params.url.SchemeIs(url::kJavaScriptScheme)) { 2090 navigation_state = NavigationState::CreateBrowserInitiated( 2091 params.page_id, 2092 params.pending_history_list_offset, 2093 params.should_clear_history_list, 2094 params.transition); 2095 navigation_state->set_should_replace_current_entry( 2096 params.should_replace_current_entry); 2097 navigation_state->set_transferred_request_child_id( 2098 params.transferred_request_child_id); 2099 navigation_state->set_transferred_request_request_id( 2100 params.transferred_request_request_id); 2101 navigation_state->set_allow_download(params.allow_download); 2102 navigation_state->set_extra_headers(params.extra_headers); 2103 } else { 2104 navigation_state = NavigationState::CreateContentInitiated(); 2105 } 2106 return navigation_state; 2107 } 2108 2109 void RenderViewImpl::ProcessViewLayoutFlags(const CommandLine& command_line) { 2110 bool enable_viewport = 2111 command_line.HasSwitch(switches::kEnableViewport) || 2112 command_line.HasSwitch(switches::kEnableViewportMeta); 2113 2114 // If viewport tag is enabled, then the WebKit side will take care 2115 // of setting the fixed layout size and page scale limits. 2116 if (enable_viewport) 2117 return; 2118 2119 // When navigating to a new page, reset the page scale factor to be 1.0. 2120 webview()->setInitialPageScaleOverride(1.f); 2121 2122 float maxPageScaleFactor = 2123 command_line.HasSwitch(switches::kEnablePinch) ? 4.f : 1.f ; 2124 webview()->setPageScaleFactorLimits(1, maxPageScaleFactor); 2125 } 2126 2127 void RenderViewImpl::didClearWindowObject(WebLocalFrame* frame) { 2128 FOR_EACH_OBSERVER( 2129 RenderViewObserver, observers_, DidClearWindowObject(frame)); 2130 2131 if (enabled_bindings_& BINDINGS_POLICY_WEB_UI) 2132 WebUIExtension::Install(frame); 2133 2134 if (enabled_bindings_ & BINDINGS_POLICY_STATS_COLLECTION) 2135 StatsCollectionController::Install(frame); 2136 2137 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 2138 2139 if (command_line.HasSwitch(switches::kEnableSkiaBenchmarking)) 2140 SkiaBenchmarking::Install(frame); 2141 2142 if (command_line.HasSwitch(switches::kEnableMemoryBenchmarking)) 2143 MemoryBenchmarkingExtension::Install(frame); 2144 } 2145 2146 void RenderViewImpl::didChangeIcon(WebLocalFrame* frame, 2147 WebIconURL::Type icon_type) { 2148 if (frame->parent()) 2149 return; 2150 2151 if (!TouchEnabled() && icon_type != WebIconURL::TypeFavicon) 2152 return; 2153 2154 WebVector<WebIconURL> icon_urls = frame->iconURLs(icon_type); 2155 std::vector<FaviconURL> urls; 2156 for (size_t i = 0; i < icon_urls.size(); i++) { 2157 std::vector<gfx::Size> sizes; 2158 ConvertToFaviconSizes(icon_urls[i].sizes(), &sizes); 2159 urls.push_back(FaviconURL( 2160 icon_urls[i].iconURL(), ToFaviconType(icon_urls[i].iconType()), sizes)); 2161 } 2162 SendUpdateFaviconURL(urls); 2163 } 2164 2165 void RenderViewImpl::didUpdateCurrentHistoryItem(WebLocalFrame* frame) { 2166 StartNavStateSyncTimerIfNecessary(); 2167 } 2168 2169 void RenderViewImpl::CheckPreferredSize() { 2170 // We don't always want to send the change messages over IPC, only if we've 2171 // been put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode| 2172 // message. 2173 if (!send_preferred_size_changes_ || !webview()) 2174 return; 2175 2176 gfx::Size size = webview()->contentsPreferredMinimumSize(); 2177 2178 // In the presence of zoom, these sizes are still reported as if unzoomed, 2179 // so we need to adjust. 2180 double zoom_factor = ZoomLevelToZoomFactor(webview()->zoomLevel()); 2181 size.set_width(static_cast<int>(size.width() * zoom_factor)); 2182 size.set_height(static_cast<int>(size.height() * zoom_factor)); 2183 2184 if (size == preferred_size_) 2185 return; 2186 2187 preferred_size_ = size; 2188 Send(new ViewHostMsg_DidContentsPreferredSizeChange(routing_id_, 2189 preferred_size_)); 2190 } 2191 2192 BrowserPluginManager* RenderViewImpl::GetBrowserPluginManager() { 2193 if (!browser_plugin_manager_.get()) 2194 browser_plugin_manager_ = BrowserPluginManager::Create(this); 2195 return browser_plugin_manager_.get(); 2196 } 2197 2198 void RenderViewImpl::UpdateScrollState(WebFrame* frame) { 2199 Send(new ViewHostMsg_DidChangeScrollOffset(routing_id_)); 2200 } 2201 2202 void RenderViewImpl::didChangeScrollOffset(WebLocalFrame* frame) { 2203 StartNavStateSyncTimerIfNecessary(); 2204 2205 if (webview()->mainFrame() == frame) 2206 UpdateScrollState(frame); 2207 2208 FOR_EACH_OBSERVER( 2209 RenderViewObserver, observers_, DidChangeScrollOffset(frame)); 2210 } 2211 2212 void RenderViewImpl::SendFindReply(int request_id, 2213 int match_count, 2214 int ordinal, 2215 const WebRect& selection_rect, 2216 bool final_status_update) { 2217 Send(new ViewHostMsg_Find_Reply(routing_id_, 2218 request_id, 2219 match_count, 2220 selection_rect, 2221 ordinal, 2222 final_status_update)); 2223 } 2224 2225 blink::WebString RenderViewImpl::acceptLanguages() { 2226 return WebString::fromUTF8(renderer_preferences_.accept_languages); 2227 } 2228 2229 // blink::WebPageSerializerClient implementation ------------------------------ 2230 2231 void RenderViewImpl::didSerializeDataForFrame( 2232 const WebURL& frame_url, 2233 const WebCString& data, 2234 WebPageSerializerClient::PageSerializationStatus status) { 2235 Send(new ViewHostMsg_SendSerializedHtmlData( 2236 routing_id(), 2237 frame_url, 2238 data.data(), 2239 static_cast<int32>(status))); 2240 } 2241 2242 // RenderView implementation --------------------------------------------------- 2243 2244 bool RenderViewImpl::Send(IPC::Message* message) { 2245 return RenderWidget::Send(message); 2246 } 2247 2248 RenderFrame* RenderViewImpl::GetMainRenderFrame() { 2249 return main_render_frame_.get(); 2250 } 2251 2252 int RenderViewImpl::GetRoutingID() const { 2253 return routing_id_; 2254 } 2255 2256 int RenderViewImpl::GetPageId() const { 2257 return page_id_; 2258 } 2259 2260 gfx::Size RenderViewImpl::GetSize() const { 2261 return size(); 2262 } 2263 2264 WebPreferences& RenderViewImpl::GetWebkitPreferences() { 2265 return webkit_preferences_; 2266 } 2267 2268 void RenderViewImpl::SetWebkitPreferences(const WebPreferences& preferences) { 2269 OnUpdateWebPreferences(preferences); 2270 } 2271 2272 blink::WebView* RenderViewImpl::GetWebView() { 2273 return webview(); 2274 } 2275 2276 blink::WebElement RenderViewImpl::GetFocusedElement() const { 2277 if (!webview()) 2278 return WebElement(); 2279 WebFrame* focused_frame = webview()->focusedFrame(); 2280 if (focused_frame) { 2281 WebDocument doc = focused_frame->document(); 2282 if (!doc.isNull()) 2283 return doc.focusedElement(); 2284 } 2285 2286 return WebElement(); 2287 } 2288 2289 bool RenderViewImpl::IsEditableNode(const WebNode& node) const { 2290 if (node.isNull()) 2291 return false; 2292 2293 if (node.isContentEditable()) 2294 return true; 2295 2296 if (node.isElementNode()) { 2297 const WebElement& element = node.toConst<WebElement>(); 2298 if (element.isTextFormControlElement()) 2299 return true; 2300 2301 // Also return true if it has an ARIA role of 'textbox'. 2302 for (unsigned i = 0; i < element.attributeCount(); ++i) { 2303 if (LowerCaseEqualsASCII(element.attributeLocalName(i), "role")) { 2304 if (LowerCaseEqualsASCII(element.attributeValue(i), "textbox")) 2305 return true; 2306 break; 2307 } 2308 } 2309 } 2310 2311 return false; 2312 } 2313 2314 bool RenderViewImpl::ShouldDisplayScrollbars(int width, int height) const { 2315 return (!send_preferred_size_changes_ || 2316 (disable_scrollbars_size_limit_.width() <= width || 2317 disable_scrollbars_size_limit_.height() <= height)); 2318 } 2319 2320 int RenderViewImpl::GetEnabledBindings() const { 2321 return enabled_bindings_; 2322 } 2323 2324 bool RenderViewImpl::GetContentStateImmediately() const { 2325 return send_content_state_immediately_; 2326 } 2327 2328 blink::WebPageVisibilityState RenderViewImpl::GetVisibilityState() const { 2329 return visibilityState(); 2330 } 2331 2332 void RenderViewImpl::DidStartLoading() { 2333 main_render_frame_->didStartLoading(true); 2334 } 2335 2336 void RenderViewImpl::DidStopLoading() { 2337 main_render_frame_->didStopLoading(); 2338 } 2339 2340 void RenderViewImpl::SyncNavigationState() { 2341 if (!webview()) 2342 return; 2343 SendUpdateState(history_controller_->GetCurrentEntry()); 2344 } 2345 2346 blink::WebPlugin* RenderViewImpl::GetWebPluginForFind() { 2347 if (!webview()) 2348 return NULL; 2349 2350 WebFrame* main_frame = webview()->mainFrame(); 2351 if (main_frame->document().isPluginDocument()) 2352 return webview()->mainFrame()->document().to<WebPluginDocument>().plugin(); 2353 2354 #if defined(ENABLE_PLUGINS) 2355 if (plugin_find_handler_) 2356 return plugin_find_handler_->container()->plugin(); 2357 #endif 2358 2359 return NULL; 2360 } 2361 2362 void RenderViewImpl::OnFind(int request_id, 2363 const base::string16& search_text, 2364 const WebFindOptions& options) { 2365 WebFrame* main_frame = webview()->mainFrame(); 2366 blink::WebPlugin* plugin = GetWebPluginForFind(); 2367 // Check if the plugin still exists in the document. 2368 if (plugin) { 2369 if (options.findNext) { 2370 // Just navigate back/forward. 2371 plugin->selectFindResult(options.forward); 2372 } else { 2373 if (!plugin->startFind( 2374 search_text, options.matchCase, request_id)) { 2375 // Send "no results". 2376 SendFindReply(request_id, 0, 0, gfx::Rect(), true); 2377 } 2378 } 2379 return; 2380 } 2381 2382 WebFrame* frame_after_main = main_frame->traverseNext(true); 2383 WebFrame* focused_frame = webview()->focusedFrame(); 2384 WebFrame* search_frame = focused_frame; // start searching focused frame. 2385 2386 bool multi_frame = (frame_after_main != main_frame); 2387 2388 // If we have multiple frames, we don't want to wrap the search within the 2389 // frame, so we check here if we only have main_frame in the chain. 2390 bool wrap_within_frame = !multi_frame; 2391 2392 WebRect selection_rect; 2393 bool result = false; 2394 2395 // If something is selected when we start searching it means we cannot just 2396 // increment the current match ordinal; we need to re-generate it. 2397 WebRange current_selection = focused_frame->selectionRange(); 2398 2399 do { 2400 result = search_frame->find( 2401 request_id, search_text, options, wrap_within_frame, &selection_rect); 2402 2403 if (!result) { 2404 // don't leave text selected as you move to the next frame. 2405 search_frame->executeCommand(WebString::fromUTF8("Unselect"), 2406 GetFocusedElement()); 2407 2408 // Find the next frame, but skip the invisible ones. 2409 do { 2410 // What is the next frame to search? (we might be going backwards). Note 2411 // that we specify wrap=true so that search_frame never becomes NULL. 2412 search_frame = options.forward ? 2413 search_frame->traverseNext(true) : 2414 search_frame->traversePrevious(true); 2415 } while (!search_frame->hasVisibleContent() && 2416 search_frame != focused_frame); 2417 2418 // Make sure selection doesn't affect the search operation in new frame. 2419 search_frame->executeCommand(WebString::fromUTF8("Unselect"), 2420 GetFocusedElement()); 2421 2422 // If we have multiple frames and we have wrapped back around to the 2423 // focused frame, we need to search it once more allowing wrap within 2424 // the frame, otherwise it will report 'no match' if the focused frame has 2425 // reported matches, but no frames after the focused_frame contain a 2426 // match for the search word(s). 2427 if (multi_frame && search_frame == focused_frame) { 2428 result = search_frame->find( 2429 request_id, search_text, options, true, // Force wrapping. 2430 &selection_rect); 2431 } 2432 } 2433 2434 webview()->setFocusedFrame(search_frame); 2435 } while (!result && search_frame != focused_frame); 2436 2437 if (options.findNext && current_selection.isNull()) { 2438 // Force the main_frame to report the actual count. 2439 main_frame->increaseMatchCount(0, request_id); 2440 } else { 2441 // If nothing is found, set result to "0 of 0", otherwise, set it to 2442 // "-1 of 1" to indicate that we found at least one item, but we don't know 2443 // yet what is active. 2444 int ordinal = result ? -1 : 0; // -1 here means, we might know more later. 2445 int match_count = result ? 1 : 0; // 1 here means possibly more coming. 2446 2447 // If we find no matches then this will be our last status update. 2448 // Otherwise the scoping effort will send more results. 2449 bool final_status_update = !result; 2450 2451 SendFindReply(request_id, match_count, ordinal, selection_rect, 2452 final_status_update); 2453 2454 // Scoping effort begins, starting with the mainframe. 2455 search_frame = main_frame; 2456 2457 main_frame->resetMatchCount(); 2458 2459 do { 2460 // Cancel all old scoping requests before starting a new one. 2461 search_frame->cancelPendingScopingEffort(); 2462 2463 // We don't start another scoping effort unless at least one match has 2464 // been found. 2465 if (result) { 2466 // Start new scoping request. If the scoping function determines that it 2467 // needs to scope, it will defer until later. 2468 search_frame->scopeStringMatches(request_id, 2469 search_text, 2470 options, 2471 true); // reset the tickmarks 2472 } 2473 2474 // Iterate to the next frame. The frame will not necessarily scope, for 2475 // example if it is not visible. 2476 search_frame = search_frame->traverseNext(true); 2477 } while (search_frame != main_frame); 2478 } 2479 } 2480 2481 void RenderViewImpl::OnStopFinding(StopFindAction action) { 2482 WebView* view = webview(); 2483 if (!view) 2484 return; 2485 2486 blink::WebPlugin* plugin = GetWebPluginForFind(); 2487 if (plugin) { 2488 plugin->stopFind(); 2489 return; 2490 } 2491 2492 bool clear_selection = action == STOP_FIND_ACTION_CLEAR_SELECTION; 2493 if (clear_selection) { 2494 view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"), 2495 GetFocusedElement()); 2496 } 2497 2498 WebFrame* frame = view->mainFrame(); 2499 while (frame) { 2500 frame->stopFinding(clear_selection); 2501 frame = frame->traverseNext(false); 2502 } 2503 2504 if (action == STOP_FIND_ACTION_ACTIVATE_SELECTION) { 2505 WebFrame* focused_frame = view->focusedFrame(); 2506 if (focused_frame) { 2507 WebDocument doc = focused_frame->document(); 2508 if (!doc.isNull()) { 2509 WebElement element = doc.focusedElement(); 2510 if (!element.isNull()) 2511 element.simulateClick(); 2512 } 2513 } 2514 } 2515 } 2516 2517 #if defined(OS_ANDROID) 2518 void RenderViewImpl::OnActivateNearestFindResult(int request_id, 2519 float x, float y) { 2520 if (!webview()) 2521 return; 2522 2523 WebFrame* main_frame = webview()->mainFrame(); 2524 WebRect selection_rect; 2525 int ordinal = main_frame->selectNearestFindMatch(WebFloatPoint(x, y), 2526 &selection_rect); 2527 if (ordinal == -1) { 2528 // Something went wrong, so send a no-op reply (force the main_frame to 2529 // report the current match count) in case the host is waiting for a 2530 // response due to rate-limiting). 2531 main_frame->increaseMatchCount(0, request_id); 2532 return; 2533 } 2534 2535 SendFindReply(request_id, 2536 -1 /* number_of_matches */, 2537 ordinal, 2538 selection_rect, 2539 true /* final_update */); 2540 } 2541 2542 void RenderViewImpl::OnFindMatchRects(int current_version) { 2543 if (!webview()) 2544 return; 2545 2546 WebFrame* main_frame = webview()->mainFrame(); 2547 std::vector<gfx::RectF> match_rects; 2548 2549 int rects_version = main_frame->findMatchMarkersVersion(); 2550 if (current_version != rects_version) { 2551 WebVector<WebFloatRect> web_match_rects; 2552 main_frame->findMatchRects(web_match_rects); 2553 match_rects.reserve(web_match_rects.size()); 2554 for (size_t i = 0; i < web_match_rects.size(); ++i) 2555 match_rects.push_back(gfx::RectF(web_match_rects[i])); 2556 } 2557 2558 gfx::RectF active_rect = main_frame->activeFindMatchRect(); 2559 Send(new ViewHostMsg_FindMatchRects_Reply(routing_id_, 2560 rects_version, 2561 match_rects, 2562 active_rect)); 2563 } 2564 #endif 2565 2566 void RenderViewImpl::OnZoom(PageZoom zoom) { 2567 if (!webview()) // Not sure if this can happen, but no harm in being safe. 2568 return; 2569 2570 webview()->hidePopups(); 2571 2572 double old_zoom_level = webview()->zoomLevel(); 2573 double zoom_level; 2574 if (zoom == PAGE_ZOOM_RESET) { 2575 zoom_level = 0; 2576 } else if (static_cast<int>(old_zoom_level) == old_zoom_level) { 2577 // Previous zoom level is a whole number, so just increment/decrement. 2578 zoom_level = old_zoom_level + zoom; 2579 } else { 2580 // Either the user hit the zoom factor limit and thus the zoom level is now 2581 // not a whole number, or a plugin changed it to a custom value. We want 2582 // to go to the next whole number so that the user can always get back to 2583 // 100% with the keyboard/menu. 2584 if ((old_zoom_level > 1 && zoom > 0) || 2585 (old_zoom_level < 1 && zoom < 0)) { 2586 zoom_level = static_cast<int>(old_zoom_level + zoom); 2587 } else { 2588 // We're going towards 100%, so first go to the next whole number. 2589 zoom_level = static_cast<int>(old_zoom_level); 2590 } 2591 } 2592 webview()->setZoomLevel(zoom_level); 2593 zoomLevelChanged(); 2594 } 2595 2596 void RenderViewImpl::OnSetZoomLevelForLoadingURL(const GURL& url, 2597 double zoom_level) { 2598 #if !defined(OS_ANDROID) 2599 // On Android, page zoom isn't used, and in case of WebView, text zoom is used 2600 // for legacy WebView text scaling emulation. Thus, the code that resets 2601 // the zoom level from this map will be effectively resetting text zoom level. 2602 host_zoom_levels_[url] = zoom_level; 2603 #endif 2604 } 2605 2606 void RenderViewImpl::OnSetZoomLevelForView(bool uses_temporary_zoom_level, 2607 double level) { 2608 uses_temporary_zoom_level_ = uses_temporary_zoom_level; 2609 2610 webview()->hidePopups(); 2611 webview()->setZoomLevel(level); 2612 } 2613 2614 void RenderViewImpl::OnSetPageEncoding(const std::string& encoding_name) { 2615 webview()->setPageEncoding(WebString::fromUTF8(encoding_name)); 2616 } 2617 2618 void RenderViewImpl::OnResetPageEncodingToDefault() { 2619 WebString no_encoding; 2620 webview()->setPageEncoding(no_encoding); 2621 } 2622 2623 void RenderViewImpl::OnPostMessageEvent( 2624 const ViewMsg_PostMessage_Params& params) { 2625 // TODO(nasko): Support sending to subframes. 2626 WebFrame* frame = webview()->mainFrame(); 2627 2628 // Find the source frame if it exists. 2629 WebFrame* source_frame = NULL; 2630 if (params.source_routing_id != MSG_ROUTING_NONE) { 2631 RenderViewImpl* source_view = FromRoutingID(params.source_routing_id); 2632 if (source_view) 2633 source_frame = source_view->webview()->mainFrame(); 2634 } 2635 2636 // If the message contained MessagePorts, create the corresponding endpoints. 2637 DCHECK_EQ(params.message_port_ids.size(), params.new_routing_ids.size()); 2638 blink::WebMessagePortChannelArray channels(params.message_port_ids.size()); 2639 for (size_t i = 0; 2640 i < params.message_port_ids.size() && i < params.new_routing_ids.size(); 2641 ++i) { 2642 channels[i] = 2643 new WebMessagePortChannelImpl(params.new_routing_ids[i], 2644 params.message_port_ids[i], 2645 base::MessageLoopProxy::current().get()); 2646 } 2647 2648 // Create an event with the message. The final parameter to initMessageEvent 2649 // is the last event ID, which is not used with postMessage. 2650 WebDOMEvent event = frame->document().createEvent("MessageEvent"); 2651 WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>(); 2652 msg_event.initMessageEvent("message", 2653 // |canBubble| and |cancellable| are always false 2654 false, false, 2655 WebSerializedScriptValue::fromString(params.data), 2656 params.source_origin, source_frame, "", channels); 2657 2658 // We must pass in the target_origin to do the security check on this side, 2659 // since it may have changed since the original postMessage call was made. 2660 WebSecurityOrigin target_origin; 2661 if (!params.target_origin.empty()) { 2662 target_origin = 2663 WebSecurityOrigin::createFromString(WebString(params.target_origin)); 2664 } 2665 frame->dispatchMessageEventWithOriginCheck(target_origin, msg_event); 2666 } 2667 2668 void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags) { 2669 if ((enabled_bindings_flags & BINDINGS_POLICY_WEB_UI) && 2670 !(enabled_bindings_ & BINDINGS_POLICY_WEB_UI)) { 2671 // WebUIExtensionData deletes itself when we're destroyed. 2672 new WebUIExtensionData(this); 2673 // WebUIMojo deletes itself when we're destroyed. 2674 new WebUIMojo(this); 2675 } 2676 2677 enabled_bindings_ |= enabled_bindings_flags; 2678 2679 // Keep track of the total bindings accumulated in this process. 2680 RenderProcess::current()->AddBindings(enabled_bindings_flags); 2681 } 2682 2683 void RenderViewImpl::OnDragTargetDragEnter(const DropData& drop_data, 2684 const gfx::Point& client_point, 2685 const gfx::Point& screen_point, 2686 WebDragOperationsMask ops, 2687 int key_modifiers) { 2688 WebDragOperation operation = webview()->dragTargetDragEnter( 2689 DropDataToWebDragData(drop_data), 2690 client_point, 2691 screen_point, 2692 ops, 2693 key_modifiers); 2694 2695 Send(new DragHostMsg_UpdateDragCursor(routing_id_, operation)); 2696 } 2697 2698 void RenderViewImpl::OnDragTargetDragOver(const gfx::Point& client_point, 2699 const gfx::Point& screen_point, 2700 WebDragOperationsMask ops, 2701 int key_modifiers) { 2702 WebDragOperation operation = webview()->dragTargetDragOver( 2703 client_point, 2704 screen_point, 2705 ops, 2706 key_modifiers); 2707 2708 Send(new DragHostMsg_UpdateDragCursor(routing_id_, operation)); 2709 } 2710 2711 void RenderViewImpl::OnDragTargetDragLeave() { 2712 webview()->dragTargetDragLeave(); 2713 } 2714 2715 void RenderViewImpl::OnDragTargetDrop(const gfx::Point& client_point, 2716 const gfx::Point& screen_point, 2717 int key_modifiers) { 2718 webview()->dragTargetDrop(client_point, screen_point, key_modifiers); 2719 2720 Send(new DragHostMsg_TargetDrop_ACK(routing_id_)); 2721 } 2722 2723 void RenderViewImpl::OnDragSourceEnded(const gfx::Point& client_point, 2724 const gfx::Point& screen_point, 2725 WebDragOperation op) { 2726 webview()->dragSourceEndedAt(client_point, screen_point, op); 2727 } 2728 2729 void RenderViewImpl::OnDragSourceSystemDragEnded() { 2730 webview()->dragSourceSystemDragEnded(); 2731 } 2732 2733 void RenderViewImpl::OnUpdateWebPreferences(const WebPreferences& prefs) { 2734 webkit_preferences_ = prefs; 2735 ApplyWebPreferences(webkit_preferences_, webview()); 2736 } 2737 2738 void RenderViewImpl::OnEnumerateDirectoryResponse( 2739 int id, 2740 const std::vector<base::FilePath>& paths) { 2741 if (!enumeration_completions_[id]) 2742 return; 2743 2744 WebVector<WebString> ws_file_names(paths.size()); 2745 for (size_t i = 0; i < paths.size(); ++i) 2746 ws_file_names[i] = paths[i].AsUTF16Unsafe(); 2747 2748 enumeration_completions_[id]->didChooseFile(ws_file_names); 2749 enumeration_completions_.erase(id); 2750 } 2751 2752 void RenderViewImpl::OnFileChooserResponse( 2753 const std::vector<ui::SelectedFileInfo>& files) { 2754 // This could happen if we navigated to a different page before the user 2755 // closed the chooser. 2756 if (file_chooser_completions_.empty()) 2757 return; 2758 2759 // Convert Chrome's SelectedFileInfo list to WebKit's. 2760 WebVector<WebFileChooserCompletion::SelectedFileInfo> selected_files( 2761 files.size()); 2762 for (size_t i = 0; i < files.size(); ++i) { 2763 WebFileChooserCompletion::SelectedFileInfo selected_file; 2764 selected_file.path = files[i].local_path.AsUTF16Unsafe(); 2765 selected_file.displayName = 2766 base::FilePath(files[i].display_name).AsUTF16Unsafe(); 2767 selected_files[i] = selected_file; 2768 } 2769 2770 if (file_chooser_completions_.front()->completion) 2771 file_chooser_completions_.front()->completion->didChooseFile( 2772 selected_files); 2773 file_chooser_completions_.pop_front(); 2774 2775 // If there are more pending file chooser requests, schedule one now. 2776 if (!file_chooser_completions_.empty()) { 2777 Send(new ViewHostMsg_RunFileChooser(routing_id_, 2778 file_chooser_completions_.front()->params)); 2779 } 2780 } 2781 2782 void RenderViewImpl::OnEnableAutoResize(const gfx::Size& min_size, 2783 const gfx::Size& max_size) { 2784 DCHECK(disable_scrollbars_size_limit_.IsEmpty()); 2785 if (!webview()) 2786 return; 2787 auto_resize_mode_ = true; 2788 webview()->enableAutoResizeMode(min_size, max_size); 2789 } 2790 2791 void RenderViewImpl::OnDisableAutoResize(const gfx::Size& new_size) { 2792 DCHECK(disable_scrollbars_size_limit_.IsEmpty()); 2793 if (!webview()) 2794 return; 2795 auto_resize_mode_ = false; 2796 webview()->disableAutoResizeMode(); 2797 2798 if (!new_size.IsEmpty()) { 2799 Resize(new_size, 2800 physical_backing_size_, 2801 overdraw_bottom_height_, 2802 visible_viewport_size_, 2803 resizer_rect_, 2804 is_fullscreen_, 2805 NO_RESIZE_ACK); 2806 } 2807 } 2808 2809 void RenderViewImpl::OnEnablePreferredSizeChangedMode() { 2810 if (send_preferred_size_changes_) 2811 return; 2812 send_preferred_size_changes_ = true; 2813 2814 // Start off with an initial preferred size notification (in case 2815 // |didUpdateLayout| was already called). 2816 didUpdateLayout(); 2817 } 2818 2819 void RenderViewImpl::OnDisableScrollbarsForSmallWindows( 2820 const gfx::Size& disable_scrollbar_size_limit) { 2821 disable_scrollbars_size_limit_ = disable_scrollbar_size_limit; 2822 } 2823 2824 void RenderViewImpl::OnSetRendererPrefs( 2825 const RendererPreferences& renderer_prefs) { 2826 double old_zoom_level = renderer_preferences_.default_zoom_level; 2827 std::string old_accept_languages = renderer_preferences_.accept_languages; 2828 2829 renderer_preferences_ = renderer_prefs; 2830 UpdateFontRenderingFromRendererPrefs(); 2831 2832 #if defined(USE_DEFAULT_RENDER_THEME) 2833 if (renderer_prefs.use_custom_colors) { 2834 WebColorName name = blink::WebColorWebkitFocusRingColor; 2835 blink::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1); 2836 blink::setCaretBlinkInterval(renderer_prefs.caret_blink_interval); 2837 2838 if (webview()) { 2839 webview()->setSelectionColors( 2840 renderer_prefs.active_selection_bg_color, 2841 renderer_prefs.active_selection_fg_color, 2842 renderer_prefs.inactive_selection_bg_color, 2843 renderer_prefs.inactive_selection_fg_color); 2844 webview()->themeChanged(); 2845 } 2846 } 2847 #endif // defined(USE_DEFAULT_RENDER_THEME) 2848 2849 if (RenderThreadImpl::current()) // Will be NULL during unit tests. 2850 RenderThreadImpl::current()->SetFlingCurveParameters( 2851 renderer_prefs.touchpad_fling_profile, 2852 renderer_prefs.touchscreen_fling_profile); 2853 2854 // If the zoom level for this page matches the old zoom default, and this 2855 // is not a plugin, update the zoom level to match the new default. 2856 if (webview() && !webview()->mainFrame()->document().isPluginDocument() && 2857 !ZoomValuesEqual(old_zoom_level, 2858 renderer_preferences_.default_zoom_level) && 2859 ZoomValuesEqual(webview()->zoomLevel(), old_zoom_level)) { 2860 webview()->setZoomLevel(renderer_preferences_.default_zoom_level); 2861 zoomLevelChanged(); 2862 } 2863 2864 if (webview() && 2865 old_accept_languages != renderer_preferences_.accept_languages) { 2866 webview()->acceptLanguagesChanged(); 2867 } 2868 } 2869 2870 void RenderViewImpl::OnMediaPlayerActionAt(const gfx::Point& location, 2871 const WebMediaPlayerAction& action) { 2872 if (webview()) 2873 webview()->performMediaPlayerAction(action, location); 2874 } 2875 2876 void RenderViewImpl::OnOrientationChange() { 2877 // TODO(mlamouri): consumers of that event should be using DisplayObserver. 2878 FOR_EACH_OBSERVER(RenderViewObserver, 2879 observers_, 2880 OrientationChangeEvent()); 2881 2882 webview()->mainFrame()->sendOrientationChangeEvent(); 2883 } 2884 2885 void RenderViewImpl::OnPluginActionAt(const gfx::Point& location, 2886 const WebPluginAction& action) { 2887 if (webview()) 2888 webview()->performPluginAction(action, location); 2889 } 2890 2891 void RenderViewImpl::OnGetAllSavableResourceLinksForCurrentPage( 2892 const GURL& page_url) { 2893 // Prepare list to storage all savable resource links. 2894 std::vector<GURL> resources_list; 2895 std::vector<GURL> referrer_urls_list; 2896 std::vector<blink::WebReferrerPolicy> referrer_policies_list; 2897 std::vector<GURL> frames_list; 2898 SavableResourcesResult result(&resources_list, 2899 &referrer_urls_list, 2900 &referrer_policies_list, 2901 &frames_list); 2902 2903 // webkit/ doesn't know about Referrer. 2904 if (!GetAllSavableResourceLinksForCurrentPage( 2905 webview(), 2906 page_url, 2907 &result, 2908 const_cast<const char**>(GetSavableSchemes()))) { 2909 // If something is wrong when collecting all savable resource links, 2910 // send empty list to embedder(browser) to tell it failed. 2911 referrer_urls_list.clear(); 2912 referrer_policies_list.clear(); 2913 resources_list.clear(); 2914 frames_list.clear(); 2915 } 2916 2917 std::vector<Referrer> referrers_list; 2918 CHECK_EQ(referrer_urls_list.size(), referrer_policies_list.size()); 2919 for (unsigned i = 0; i < referrer_urls_list.size(); ++i) { 2920 referrers_list.push_back( 2921 Referrer(referrer_urls_list[i], referrer_policies_list[i])); 2922 } 2923 2924 // Send result of all savable resource links to embedder. 2925 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id(), 2926 resources_list, 2927 referrers_list, 2928 frames_list)); 2929 } 2930 2931 void RenderViewImpl::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks( 2932 const std::vector<GURL>& links, 2933 const std::vector<base::FilePath>& local_paths, 2934 const base::FilePath& local_directory_name) { 2935 2936 // Convert std::vector of GURLs to WebVector<WebURL> 2937 WebVector<WebURL> weburl_links(links); 2938 2939 // Convert std::vector of base::FilePath to WebVector<WebString> 2940 WebVector<WebString> webstring_paths(local_paths.size()); 2941 for (size_t i = 0; i < local_paths.size(); i++) 2942 webstring_paths[i] = local_paths[i].AsUTF16Unsafe(); 2943 2944 WebPageSerializer::serialize(webview()->mainFrame()->toWebLocalFrame(), 2945 true, 2946 this, 2947 weburl_links, 2948 webstring_paths, 2949 local_directory_name.AsUTF16Unsafe()); 2950 } 2951 2952 void RenderViewImpl::OnSuppressDialogsUntilSwapOut() { 2953 // Don't show any more dialogs until we finish OnSwapOut. 2954 suppress_dialogs_until_swap_out_ = true; 2955 } 2956 2957 void RenderViewImpl::NavigateToSwappedOutURL(blink::WebFrame* frame) { 2958 // We use loadRequest instead of loadHTMLString because the former commits 2959 // synchronously. Otherwise a new navigation can interrupt the navigation 2960 // to kSwappedOutURL. If that happens to be to the page we had been 2961 // showing, then WebKit will never send a commit and we'll be left spinning. 2962 // TODO(creis): Until we move this to RenderFrame, we may call this from a 2963 // swapped out RenderFrame while our own is_swapped_out_ is false. 2964 RenderFrameImpl* rf = RenderFrameImpl::FromWebFrame(frame); 2965 CHECK(is_swapped_out_ || rf->is_swapped_out()); 2966 GURL swappedOutURL(kSwappedOutURL); 2967 WebURLRequest request(swappedOutURL); 2968 frame->loadRequest(request); 2969 } 2970 2971 void RenderViewImpl::OnClosePage() { 2972 FOR_EACH_OBSERVER(RenderViewObserver, observers_, ClosePage()); 2973 // TODO(creis): We'd rather use webview()->Close() here, but that currently 2974 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs 2975 // in the onunload handler from appearing. For now, we're bypassing that and 2976 // calling the FrameLoader's CloseURL method directly. This should be 2977 // revisited to avoid having two ways to close a page. Having a single way 2978 // to close that can run onunload is also useful for fixing 2979 // http://b/issue?id=753080. 2980 webview()->mainFrame()->dispatchUnloadEvent(); 2981 2982 Send(new ViewHostMsg_ClosePage_ACK(routing_id_)); 2983 } 2984 2985 void RenderViewImpl::OnThemeChanged() { 2986 #if defined(USE_AURA) 2987 // Aura doesn't care if we switch themes. 2988 #elif defined(OS_WIN) 2989 ui::NativeThemeWin::instance()->CloseHandles(); 2990 if (webview()) 2991 webview()->themeChanged(); 2992 #else // defined(OS_WIN) 2993 // TODO(port): we don't support theming on non-Windows platforms yet 2994 NOTIMPLEMENTED(); 2995 #endif 2996 } 2997 2998 void RenderViewImpl::OnMoveOrResizeStarted() { 2999 if (webview()) 3000 webview()->hidePopups(); 3001 } 3002 3003 void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) { 3004 if (webview()) { 3005 webview()->hidePopups(); 3006 if (send_preferred_size_changes_) { 3007 webview()->mainFrame()->setCanHaveScrollbars( 3008 ShouldDisplayScrollbars(params.new_size.width(), 3009 params.new_size.height())); 3010 } 3011 UpdateScrollState(webview()->mainFrame()); 3012 } 3013 3014 gfx::Size old_visible_viewport_size = visible_viewport_size_; 3015 3016 RenderWidget::OnResize(params); 3017 3018 if (old_visible_viewport_size != visible_viewport_size_) 3019 has_scrolled_focused_editable_node_into_rect_ = false; 3020 } 3021 3022 void RenderViewImpl::DidInitiatePaint() { 3023 #if defined(ENABLE_PLUGINS) 3024 // Notify all instances that we painted. The same caveats apply as for 3025 // ViewFlushedPaint regarding instances closing themselves, so we take 3026 // similar precautions. 3027 PepperPluginSet plugins = active_pepper_instances_; 3028 for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) { 3029 if (active_pepper_instances_.find(*i) != active_pepper_instances_.end()) 3030 (*i)->ViewInitiatedPaint(); 3031 } 3032 #endif 3033 } 3034 3035 void RenderViewImpl::DidFlushPaint() { 3036 #if defined(ENABLE_PLUGINS) 3037 // Notify all instances that we flushed. This will call into the plugin, and 3038 // we it may ask to close itself as a result. This will, in turn, modify our 3039 // set, possibly invalidating the iterator. So we iterate on a copy that 3040 // won't change out from under us. 3041 PepperPluginSet plugins = active_pepper_instances_; 3042 for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) { 3043 // The copy above makes sure our iterator is never invalid if some plugins 3044 // are destroyed. But some plugin may decide to close all of its views in 3045 // response to a paint in one of them, so we need to make sure each one is 3046 // still "current" before using it. 3047 // 3048 // It's possible that a plugin was destroyed, but another one was created 3049 // with the same address. In this case, we'll call ViewFlushedPaint on that 3050 // new plugin. But that's OK for this particular case since we're just 3051 // notifying all of our instances that the view flushed, and the new one is 3052 // one of our instances. 3053 // 3054 // What about the case where a new one is created in a callback at a new 3055 // address and we don't issue the callback? We're still OK since this 3056 // callback is used for flush callbacks and we could not have possibly 3057 // started a new paint for the new plugin while processing a previous paint 3058 // for an existing one. 3059 if (active_pepper_instances_.find(*i) != active_pepper_instances_.end()) 3060 (*i)->ViewFlushedPaint(); 3061 } 3062 #endif 3063 3064 // If the RenderWidget is closing down then early-exit, otherwise we'll crash. 3065 // See crbug.com/112921. 3066 if (!webview()) 3067 return; 3068 3069 WebFrame* main_frame = webview()->mainFrame(); 3070 3071 // If we have a provisional frame we are between the start and commit stages 3072 // of loading and we don't want to save stats. 3073 if (!main_frame->provisionalDataSource()) { 3074 WebDataSource* ds = main_frame->dataSource(); 3075 DocumentState* document_state = DocumentState::FromDataSource(ds); 3076 InternalDocumentStateData* data = 3077 InternalDocumentStateData::FromDocumentState(document_state); 3078 if (data->did_first_visually_non_empty_layout() && 3079 !data->did_first_visually_non_empty_paint()) { 3080 data->set_did_first_visually_non_empty_paint(true); 3081 Send(new ViewHostMsg_DidFirstVisuallyNonEmptyPaint(routing_id_)); 3082 } 3083 3084 // TODO(jar): The following code should all be inside a method, probably in 3085 // NavigatorState. 3086 Time now = Time::Now(); 3087 if (document_state->first_paint_time().is_null()) { 3088 document_state->set_first_paint_time(now); 3089 } 3090 if (document_state->first_paint_after_load_time().is_null() && 3091 !document_state->finish_load_time().is_null()) { 3092 document_state->set_first_paint_after_load_time(now); 3093 } 3094 } 3095 } 3096 3097 gfx::Vector2d RenderViewImpl::GetScrollOffset() { 3098 WebSize scroll_offset = webview()->mainFrame()->scrollOffset(); 3099 return gfx::Vector2d(scroll_offset.width, scroll_offset.height); 3100 } 3101 3102 void RenderViewImpl::OnClearFocusedElement() { 3103 if (webview()) 3104 webview()->clearFocusedElement(); 3105 } 3106 3107 void RenderViewImpl::OnSetBackgroundOpaque(bool opaque) { 3108 if (webview()) 3109 webview()->setIsTransparent(!opaque); 3110 if (compositor_) 3111 compositor_->setHasTransparentBackground(!opaque); 3112 } 3113 3114 void RenderViewImpl::OnSetAccessibilityMode(AccessibilityMode new_mode) { 3115 if (accessibility_mode_ == new_mode) 3116 return; 3117 accessibility_mode_ = new_mode; 3118 if (renderer_accessibility_) { 3119 delete renderer_accessibility_; 3120 renderer_accessibility_ = NULL; 3121 } 3122 if (accessibility_mode_ == AccessibilityModeOff) 3123 return; 3124 3125 if (accessibility_mode_ & AccessibilityModeFlagFullTree) 3126 renderer_accessibility_ = new RendererAccessibilityComplete(this); 3127 #if !defined(OS_ANDROID) 3128 else 3129 renderer_accessibility_ = new RendererAccessibilityFocusOnly(this); 3130 #endif 3131 } 3132 3133 void RenderViewImpl::OnSetActive(bool active) { 3134 if (webview()) 3135 webview()->setIsActive(active); 3136 3137 #if defined(ENABLE_PLUGINS) && defined(OS_MACOSX) 3138 std::set<WebPluginDelegateProxy*>::iterator plugin_it; 3139 for (plugin_it = plugin_delegates_.begin(); 3140 plugin_it != plugin_delegates_.end(); ++plugin_it) { 3141 (*plugin_it)->SetWindowFocus(active); 3142 } 3143 #endif 3144 } 3145 3146 #if defined(OS_MACOSX) 3147 void RenderViewImpl::OnSetWindowVisibility(bool visible) { 3148 #if defined(ENABLE_PLUGINS) 3149 // Inform plugins that their container has changed visibility. 3150 std::set<WebPluginDelegateProxy*>::iterator plugin_it; 3151 for (plugin_it = plugin_delegates_.begin(); 3152 plugin_it != plugin_delegates_.end(); ++plugin_it) { 3153 (*plugin_it)->SetContainerVisibility(visible); 3154 } 3155 #endif 3156 } 3157 3158 void RenderViewImpl::OnWindowFrameChanged(const gfx::Rect& window_frame, 3159 const gfx::Rect& view_frame) { 3160 #if defined(ENABLE_PLUGINS) 3161 // Inform plugins that their window's frame has changed. 3162 std::set<WebPluginDelegateProxy*>::iterator plugin_it; 3163 for (plugin_it = plugin_delegates_.begin(); 3164 plugin_it != plugin_delegates_.end(); ++plugin_it) { 3165 (*plugin_it)->WindowFrameChanged(window_frame, view_frame); 3166 } 3167 #endif 3168 } 3169 3170 void RenderViewImpl::OnPluginImeCompositionCompleted(const base::string16& text, 3171 int plugin_id) { 3172 // WebPluginDelegateProxy is responsible for figuring out if this event 3173 // applies to it or not, so inform all the delegates. 3174 std::set<WebPluginDelegateProxy*>::iterator plugin_it; 3175 for (plugin_it = plugin_delegates_.begin(); 3176 plugin_it != plugin_delegates_.end(); ++plugin_it) { 3177 (*plugin_it)->ImeCompositionCompleted(text, plugin_id); 3178 } 3179 } 3180 #endif // OS_MACOSX 3181 3182 void RenderViewImpl::OnClose() { 3183 if (closing_) 3184 RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(routing_id_)); 3185 RenderWidget::OnClose(); 3186 } 3187 3188 void RenderViewImpl::Close() { 3189 // We need to grab a pointer to the doomed WebView before we destroy it. 3190 WebView* doomed = webview(); 3191 RenderWidget::Close(); 3192 g_view_map.Get().erase(doomed); 3193 g_routing_id_view_map.Get().erase(routing_id_); 3194 RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(routing_id_)); 3195 } 3196 3197 void RenderViewImpl::DidHandleKeyEvent() { 3198 ClearEditCommands(); 3199 } 3200 3201 bool RenderViewImpl::WillHandleMouseEvent(const blink::WebMouseEvent& event) { 3202 possible_drag_event_info_.event_source = 3203 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE; 3204 possible_drag_event_info_.event_location = 3205 gfx::Point(event.globalX, event.globalY); 3206 3207 #if defined(ENABLE_PLUGINS) 3208 // This method is called for every mouse event that the render view receives. 3209 // And then the mouse event is forwarded to WebKit, which dispatches it to the 3210 // event target. Potentially a Pepper plugin will receive the event. 3211 // In order to tell whether a plugin gets the last mouse event and which it 3212 // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets 3213 // the event, it will notify us via DidReceiveMouseEvent() and set itself as 3214 // |pepper_last_mouse_event_target_|. 3215 pepper_last_mouse_event_target_ = NULL; 3216 #endif 3217 3218 // If the mouse is locked, only the current owner of the mouse lock can 3219 // process mouse events. 3220 return mouse_lock_dispatcher_->WillHandleMouseEvent(event); 3221 } 3222 3223 bool RenderViewImpl::WillHandleGestureEvent( 3224 const blink::WebGestureEvent& event) { 3225 possible_drag_event_info_.event_source = 3226 ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH; 3227 possible_drag_event_info_.event_location = 3228 gfx::Point(event.globalX, event.globalY); 3229 return false; 3230 } 3231 3232 void RenderViewImpl::DidHandleMouseEvent(const WebMouseEvent& event) { 3233 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidHandleMouseEvent(event)); 3234 } 3235 3236 void RenderViewImpl::DidHandleTouchEvent(const WebTouchEvent& event) { 3237 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidHandleTouchEvent(event)); 3238 } 3239 3240 bool RenderViewImpl::HasTouchEventHandlersAt(const gfx::Point& point) const { 3241 if (!webview()) 3242 return false; 3243 return webview()->hasTouchEventHandlersAt(point); 3244 } 3245 3246 void RenderViewImpl::OnWasHidden() { 3247 RenderWidget::OnWasHidden(); 3248 3249 #if defined(OS_ANDROID) && defined(ENABLE_WEBRTC) 3250 RenderThreadImpl::current()->video_capture_impl_manager()-> 3251 SuspendDevices(true); 3252 if (speech_recognition_dispatcher_) 3253 speech_recognition_dispatcher_->AbortAllRecognitions(); 3254 #endif 3255 3256 if (webview()) 3257 webview()->setVisibilityState(visibilityState(), false); 3258 3259 #if defined(ENABLE_PLUGINS) 3260 for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); 3261 i != active_pepper_instances_.end(); ++i) 3262 (*i)->PageVisibilityChanged(false); 3263 3264 #if defined(OS_MACOSX) 3265 // Inform NPAPI plugins that their container is no longer visible. 3266 std::set<WebPluginDelegateProxy*>::iterator plugin_it; 3267 for (plugin_it = plugin_delegates_.begin(); 3268 plugin_it != plugin_delegates_.end(); ++plugin_it) { 3269 (*plugin_it)->SetContainerVisibility(false); 3270 } 3271 #endif // OS_MACOSX 3272 #endif // ENABLE_PLUGINS 3273 } 3274 3275 void RenderViewImpl::OnWasShown(bool needs_repainting) { 3276 RenderWidget::OnWasShown(needs_repainting); 3277 3278 #if defined(OS_ANDROID) && defined(ENABLE_WEBRTC) 3279 RenderThreadImpl::current()->video_capture_impl_manager()-> 3280 SuspendDevices(false); 3281 #endif 3282 3283 if (webview()) 3284 webview()->setVisibilityState(visibilityState(), false); 3285 3286 #if defined(ENABLE_PLUGINS) 3287 for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); 3288 i != active_pepper_instances_.end(); ++i) 3289 (*i)->PageVisibilityChanged(true); 3290 3291 #if defined(OS_MACOSX) 3292 // Inform NPAPI plugins that their container is now visible. 3293 std::set<WebPluginDelegateProxy*>::iterator plugin_it; 3294 for (plugin_it = plugin_delegates_.begin(); 3295 plugin_it != plugin_delegates_.end(); ++plugin_it) { 3296 (*plugin_it)->SetContainerVisibility(true); 3297 } 3298 #endif // OS_MACOSX 3299 #endif // ENABLE_PLUGINS 3300 } 3301 3302 GURL RenderViewImpl::GetURLForGraphicsContext3D() { 3303 DCHECK(webview()); 3304 if (webview()->mainFrame()) 3305 return GURL(webview()->mainFrame()->document().url()); 3306 else 3307 return GURL("chrome://gpu/RenderViewImpl::CreateGraphicsContext3D"); 3308 } 3309 3310 void RenderViewImpl::OnSetFocus(bool enable) { 3311 RenderWidget::OnSetFocus(enable); 3312 3313 #if defined(ENABLE_PLUGINS) 3314 if (webview() && webview()->isActive()) { 3315 // Notify all NPAPI plugins. 3316 std::set<WebPluginDelegateProxy*>::iterator plugin_it; 3317 for (plugin_it = plugin_delegates_.begin(); 3318 plugin_it != plugin_delegates_.end(); ++plugin_it) { 3319 #if defined(OS_MACOSX) 3320 // RenderWidget's call to setFocus can cause the underlying webview's 3321 // activation state to change just like a call to setIsActive. 3322 if (enable) 3323 (*plugin_it)->SetWindowFocus(true); 3324 #endif 3325 (*plugin_it)->SetContentAreaFocus(enable); 3326 } 3327 } 3328 // Notify all Pepper plugins. 3329 for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); 3330 i != active_pepper_instances_.end(); ++i) 3331 (*i)->SetContentAreaFocus(enable); 3332 #endif 3333 // Notify all BrowserPlugins of the RenderView's focus state. 3334 if (browser_plugin_manager_.get()) 3335 browser_plugin_manager_->UpdateFocusState(); 3336 } 3337 3338 void RenderViewImpl::OnImeSetComposition( 3339 const base::string16& text, 3340 const std::vector<blink::WebCompositionUnderline>& underlines, 3341 int selection_start, 3342 int selection_end) { 3343 #if defined(ENABLE_PLUGINS) 3344 if (focused_pepper_plugin_) { 3345 focused_pepper_plugin_->render_frame()->OnImeSetComposition( 3346 text, underlines, selection_start, selection_end); 3347 return; 3348 } 3349 3350 #if defined(OS_WIN) 3351 // When a plug-in has focus, we create platform-specific IME data used by 3352 // our IME emulator and send it directly to the focused plug-in, i.e. we 3353 // bypass WebKit. (WebPluginDelegate dispatches this IME data only when its 3354 // instance ID is the same one as the specified ID.) 3355 if (focused_plugin_id_ >= 0) { 3356 std::vector<int> clauses; 3357 std::vector<int> target; 3358 for (size_t i = 0; i < underlines.size(); ++i) { 3359 clauses.push_back(underlines[i].startOffset); 3360 clauses.push_back(underlines[i].endOffset); 3361 if (underlines[i].thick) { 3362 target.clear(); 3363 target.push_back(underlines[i].startOffset); 3364 target.push_back(underlines[i].endOffset); 3365 } 3366 } 3367 std::set<WebPluginDelegateProxy*>::iterator it; 3368 for (it = plugin_delegates_.begin(); it != plugin_delegates_.end(); ++it) { 3369 (*it)->ImeCompositionUpdated(text, clauses, target, selection_end, 3370 focused_plugin_id_); 3371 } 3372 return; 3373 } 3374 #endif // OS_WIN 3375 #endif // ENABLE_PLUGINS 3376 RenderWidget::OnImeSetComposition(text, 3377 underlines, 3378 selection_start, 3379 selection_end); 3380 } 3381 3382 void RenderViewImpl::OnImeConfirmComposition( 3383 const base::string16& text, 3384 const gfx::Range& replacement_range, 3385 bool keep_selection) { 3386 #if defined(ENABLE_PLUGINS) 3387 if (focused_pepper_plugin_) { 3388 focused_pepper_plugin_->render_frame()->OnImeConfirmComposition( 3389 text, replacement_range, keep_selection); 3390 return; 3391 } 3392 #if defined(OS_WIN) 3393 // Same as OnImeSetComposition(), we send the text from IMEs directly to 3394 // plug-ins. When we send IME text directly to plug-ins, we should not send 3395 // it to WebKit to prevent WebKit from controlling IMEs. 3396 // TODO(thakis): Honor |replacement_range| for plugins? 3397 if (focused_plugin_id_ >= 0) { 3398 std::set<WebPluginDelegateProxy*>::iterator it; 3399 for (it = plugin_delegates_.begin(); 3400 it != plugin_delegates_.end(); ++it) { 3401 (*it)->ImeCompositionCompleted(text, focused_plugin_id_); 3402 } 3403 return; 3404 } 3405 #endif // OS_WIN 3406 #endif // ENABLE_PLUGINS 3407 if (replacement_range.IsValid() && webview()) { 3408 // Select the text in |replacement_range|, it will then be replaced by 3409 // text added by the call to RenderWidget::OnImeConfirmComposition(). 3410 if (WebLocalFrame* frame = webview()->focusedFrame()->toWebLocalFrame()) { 3411 WebRange webrange = WebRange::fromDocumentRange( 3412 frame, replacement_range.start(), replacement_range.length()); 3413 if (!webrange.isNull()) 3414 frame->selectRange(webrange); 3415 } 3416 } 3417 RenderWidget::OnImeConfirmComposition(text, 3418 replacement_range, 3419 keep_selection); 3420 } 3421 3422 void RenderViewImpl::SetDeviceScaleFactor(float device_scale_factor) { 3423 RenderWidget::SetDeviceScaleFactor(device_scale_factor); 3424 if (webview()) { 3425 webview()->setDeviceScaleFactor(device_scale_factor); 3426 webview()->settings()->setAcceleratedCompositingForFixedPositionEnabled( 3427 ShouldUseFixedPositionCompositing(device_scale_factor_)); 3428 webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled( 3429 ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_)); 3430 webview()->settings()->setAcceleratedCompositingForTransitionEnabled( 3431 ShouldUseTransitionCompositing(device_scale_factor_)); 3432 webview()->settings()-> 3433 setAcceleratedCompositingForFixedRootBackgroundEnabled( 3434 ShouldUseAcceleratedFixedRootBackground(device_scale_factor_)); 3435 webview()->settings()->setCompositedScrollingForFramesEnabled( 3436 ShouldUseCompositedScrollingForFrames(device_scale_factor_)); 3437 } 3438 if (auto_resize_mode_) 3439 AutoResizeCompositor(); 3440 3441 if (browser_plugin_manager_.get()) 3442 browser_plugin_manager_->UpdateDeviceScaleFactor(device_scale_factor_); 3443 } 3444 3445 bool RenderViewImpl::SetDeviceColorProfile( 3446 const std::vector<char>& profile) { 3447 bool changed = RenderWidget::SetDeviceColorProfile(profile); 3448 if (changed && webview()) { 3449 // TODO(noel): notify the webview() of the color profile change so it 3450 // can update and repaint all color profiled page elements. 3451 } 3452 return changed; 3453 } 3454 3455 ui::TextInputType RenderViewImpl::GetTextInputType() { 3456 #if defined(ENABLE_PLUGINS) 3457 if (focused_pepper_plugin_) 3458 return focused_pepper_plugin_->text_input_type(); 3459 #endif 3460 return RenderWidget::GetTextInputType(); 3461 } 3462 3463 void RenderViewImpl::GetSelectionBounds(gfx::Rect* start, gfx::Rect* end) { 3464 #if defined(ENABLE_PLUGINS) 3465 if (focused_pepper_plugin_) { 3466 // TODO(kinaba) http://crbug.com/101101 3467 // Current Pepper IME API does not handle selection bounds. So we simply 3468 // use the caret position as an empty range for now. It will be updated 3469 // after Pepper API equips features related to surrounding text retrieval. 3470 gfx::Rect caret = focused_pepper_plugin_->GetCaretBounds(); 3471 *start = caret; 3472 *end = caret; 3473 return; 3474 } 3475 #endif 3476 RenderWidget::GetSelectionBounds(start, end); 3477 } 3478 3479 #if defined(OS_MACOSX) || defined(USE_AURA) 3480 void RenderViewImpl::GetCompositionCharacterBounds( 3481 std::vector<gfx::Rect>* bounds) { 3482 DCHECK(bounds); 3483 bounds->clear(); 3484 3485 #if defined(ENABLE_PLUGINS) 3486 if (focused_pepper_plugin_) { 3487 return; 3488 } 3489 #endif 3490 3491 if (!webview()) 3492 return; 3493 size_t start_offset = 0; 3494 size_t character_count = 0; 3495 if (!webview()->compositionRange(&start_offset, &character_count)) 3496 return; 3497 if (character_count == 0) 3498 return; 3499 3500 blink::WebFrame* frame = webview()->focusedFrame(); 3501 if (!frame) 3502 return; 3503 3504 bounds->reserve(character_count); 3505 blink::WebRect webrect; 3506 for (size_t i = 0; i < character_count; ++i) { 3507 if (!frame->firstRectForCharacterRange(start_offset + i, 1, webrect)) { 3508 DLOG(ERROR) << "Could not retrieve character rectangle at " << i; 3509 bounds->clear(); 3510 return; 3511 } 3512 bounds->push_back(webrect); 3513 } 3514 } 3515 3516 void RenderViewImpl::GetCompositionRange(gfx::Range* range) { 3517 #if defined(ENABLE_PLUGINS) 3518 if (focused_pepper_plugin_) { 3519 return; 3520 } 3521 #endif 3522 RenderWidget::GetCompositionRange(range); 3523 } 3524 #endif 3525 3526 bool RenderViewImpl::CanComposeInline() { 3527 #if defined(ENABLE_PLUGINS) 3528 if (focused_pepper_plugin_) 3529 return focused_pepper_plugin_->IsPluginAcceptingCompositionEvents(); 3530 #endif 3531 return true; 3532 } 3533 3534 void RenderViewImpl::InstrumentWillBeginFrame(int frame_id) { 3535 if (!webview()) 3536 return; 3537 if (!webview()->devToolsAgent()) 3538 return; 3539 webview()->devToolsAgent()->didBeginFrame(frame_id); 3540 } 3541 3542 void RenderViewImpl::InstrumentDidBeginFrame() { 3543 if (!webview()) 3544 return; 3545 if (!webview()->devToolsAgent()) 3546 return; 3547 // TODO(jamesr/caseq): Decide if this needs to be renamed. 3548 webview()->devToolsAgent()->didComposite(); 3549 } 3550 3551 void RenderViewImpl::InstrumentDidCancelFrame() { 3552 if (!webview()) 3553 return; 3554 if (!webview()->devToolsAgent()) 3555 return; 3556 webview()->devToolsAgent()->didCancelFrame(); 3557 } 3558 3559 void RenderViewImpl::InstrumentWillComposite() { 3560 if (!webview()) 3561 return; 3562 if (!webview()->devToolsAgent()) 3563 return; 3564 webview()->devToolsAgent()->willComposite(); 3565 } 3566 3567 void RenderViewImpl::SetScreenMetricsEmulationParameters( 3568 float device_scale_factor, 3569 const gfx::Point& root_layer_offset, 3570 float root_layer_scale) { 3571 if (webview() && compositor()) { 3572 webview()->setCompositorDeviceScaleFactorOverride(device_scale_factor); 3573 webview()->setRootLayerTransform( 3574 blink::WebSize(root_layer_offset.x(), root_layer_offset.y()), 3575 root_layer_scale); 3576 } 3577 } 3578 3579 bool RenderViewImpl::ScheduleFileChooser( 3580 const FileChooserParams& params, 3581 WebFileChooserCompletion* completion) { 3582 static const size_t kMaximumPendingFileChooseRequests = 4; 3583 if (file_chooser_completions_.size() > kMaximumPendingFileChooseRequests) { 3584 // This sanity check prevents too many file choose requests from getting 3585 // queued which could DoS the user. Getting these is most likely a 3586 // programming error (there are many ways to DoS the user so it's not 3587 // considered a "real" security check), either in JS requesting many file 3588 // choosers to pop up, or in a plugin. 3589 // 3590 // TODO(brettw) we might possibly want to require a user gesture to open 3591 // a file picker, which will address this issue in a better way. 3592 return false; 3593 } 3594 3595 file_chooser_completions_.push_back(linked_ptr<PendingFileChooser>( 3596 new PendingFileChooser(params, completion))); 3597 if (file_chooser_completions_.size() == 1) { 3598 // Actually show the browse dialog when this is the first request. 3599 Send(new ViewHostMsg_RunFileChooser(routing_id_, params)); 3600 } 3601 return true; 3602 } 3603 3604 blink::WebSpeechRecognizer* RenderViewImpl::speechRecognizer() { 3605 if (!speech_recognition_dispatcher_) 3606 speech_recognition_dispatcher_ = new SpeechRecognitionDispatcher(this); 3607 return speech_recognition_dispatcher_; 3608 } 3609 3610 void RenderViewImpl::zoomLimitsChanged(double minimum_level, 3611 double maximum_level) { 3612 int minimum_percent = static_cast<int>( 3613 ZoomLevelToZoomFactor(minimum_level) * 100); 3614 int maximum_percent = static_cast<int>( 3615 ZoomLevelToZoomFactor(maximum_level) * 100); 3616 3617 Send(new ViewHostMsg_UpdateZoomLimits( 3618 routing_id_, minimum_percent, maximum_percent)); 3619 } 3620 3621 void RenderViewImpl::zoomLevelChanged() { 3622 double zoom_level = webview()->zoomLevel(); 3623 3624 FOR_EACH_OBSERVER(RenderViewObserver, observers_, ZoomLevelChanged()); 3625 3626 // Do not send empty URLs to the browser when we are just setting the default 3627 // zoom level (from RendererPreferences) before the first navigation. 3628 if (!webview()->mainFrame()->document().url().isEmpty()) { 3629 // Tell the browser which url got zoomed so it can update the menu and the 3630 // saved values if necessary 3631 Send(new ViewHostMsg_DidZoomURL( 3632 routing_id_, zoom_level, 3633 GURL(webview()->mainFrame()->document().url()))); 3634 } 3635 } 3636 3637 double RenderViewImpl::zoomLevelToZoomFactor(double zoom_level) const { 3638 return ZoomLevelToZoomFactor(zoom_level); 3639 } 3640 3641 double RenderViewImpl::zoomFactorToZoomLevel(double factor) const { 3642 return ZoomFactorToZoomLevel(factor); 3643 } 3644 3645 void RenderViewImpl::registerProtocolHandler(const WebString& scheme, 3646 const WebURL& base_url, 3647 const WebURL& url, 3648 const WebString& title) { 3649 bool user_gesture = WebUserGestureIndicator::isProcessingUserGesture(); 3650 GURL base(base_url); 3651 GURL absolute_url = base.Resolve(base::UTF16ToUTF8(url.string())); 3652 if (base.GetOrigin() != absolute_url.GetOrigin()) { 3653 return; 3654 } 3655 Send(new ViewHostMsg_RegisterProtocolHandler(routing_id_, 3656 base::UTF16ToUTF8(scheme), 3657 absolute_url, 3658 title, 3659 user_gesture)); 3660 } 3661 3662 blink::WebPageVisibilityState RenderViewImpl::visibilityState() const { 3663 blink::WebPageVisibilityState current_state = is_hidden() ? 3664 blink::WebPageVisibilityStateHidden : 3665 blink::WebPageVisibilityStateVisible; 3666 blink::WebPageVisibilityState override_state = current_state; 3667 // TODO(jam): move this method to WebFrameClient. 3668 if (GetContentClient()->renderer()-> 3669 ShouldOverridePageVisibilityState(main_render_frame_.get(), 3670 &override_state)) 3671 return override_state; 3672 return current_state; 3673 } 3674 3675 blink::WebPushClient* RenderViewImpl::webPushClient() { 3676 if (!push_messaging_dispatcher_) 3677 push_messaging_dispatcher_ = new PushMessagingDispatcher(this); 3678 return push_messaging_dispatcher_; 3679 } 3680 3681 void RenderViewImpl::draggableRegionsChanged() { 3682 FOR_EACH_OBSERVER( 3683 RenderViewObserver, 3684 observers_, 3685 DraggableRegionsChanged(webview()->mainFrame())); 3686 } 3687 3688 #if defined(OS_ANDROID) 3689 WebContentDetectionResult RenderViewImpl::detectContentAround( 3690 const WebHitTestResult& touch_hit) { 3691 DCHECK(!touch_hit.isNull()); 3692 DCHECK(!touch_hit.node().isNull()); 3693 DCHECK(touch_hit.node().isTextNode()); 3694 3695 // Process the position with all the registered content detectors until 3696 // a match is found. Priority is provided by their relative order. 3697 for (ContentDetectorList::const_iterator it = content_detectors_.begin(); 3698 it != content_detectors_.end(); ++it) { 3699 ContentDetector::Result content = (*it)->FindTappedContent(touch_hit); 3700 if (content.valid) { 3701 return WebContentDetectionResult(content.content_boundaries, 3702 base::UTF8ToUTF16(content.text), content.intent_url); 3703 } 3704 } 3705 return WebContentDetectionResult(); 3706 } 3707 3708 void RenderViewImpl::scheduleContentIntent(const WebURL& intent) { 3709 // Introduce a short delay so that the user can notice the content. 3710 base::MessageLoop::current()->PostDelayedTask( 3711 FROM_HERE, 3712 base::Bind(&RenderViewImpl::LaunchAndroidContentIntent, 3713 AsWeakPtr(), 3714 intent, 3715 expected_content_intent_id_), 3716 base::TimeDelta::FromMilliseconds(kContentIntentDelayMilliseconds)); 3717 } 3718 3719 void RenderViewImpl::cancelScheduledContentIntents() { 3720 ++expected_content_intent_id_; 3721 } 3722 3723 void RenderViewImpl::LaunchAndroidContentIntent(const GURL& intent, 3724 size_t request_id) { 3725 if (request_id != expected_content_intent_id_) 3726 return; 3727 3728 // Remove the content highlighting if any. 3729 scheduleComposite(); 3730 3731 if (!intent.is_empty()) 3732 Send(new ViewHostMsg_StartContentIntent(routing_id_, intent)); 3733 } 3734 3735 bool RenderViewImpl::openDateTimeChooser( 3736 const blink::WebDateTimeChooserParams& params, 3737 blink::WebDateTimeChooserCompletion* completion) { 3738 // JavaScript may try to open a date time chooser while one is already open. 3739 if (date_time_picker_client_) 3740 return false; 3741 date_time_picker_client_.reset( 3742 new RendererDateTimePicker(this, params, completion)); 3743 return date_time_picker_client_->Open(); 3744 } 3745 3746 void RenderViewImpl::DismissDateTimeDialog() { 3747 DCHECK(date_time_picker_client_); 3748 date_time_picker_client_.reset(NULL); 3749 } 3750 3751 #endif // defined(OS_ANDROID) 3752 3753 #if defined(OS_MACOSX) 3754 void RenderViewImpl::OnSelectPopupMenuItem(int selected_index) { 3755 if (external_popup_menu_ == NULL) 3756 return; 3757 external_popup_menu_->DidSelectItem(selected_index); 3758 external_popup_menu_.reset(); 3759 } 3760 #endif 3761 3762 #if defined(OS_ANDROID) 3763 void RenderViewImpl::OnSelectPopupMenuItems( 3764 bool canceled, 3765 const std::vector<int>& selected_indices) { 3766 // It is possible to receive more than one of these calls if the user presses 3767 // a select faster than it takes for the show-select-popup IPC message to make 3768 // it to the browser UI thread. Ignore the extra-messages. 3769 // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug. 3770 if (!external_popup_menu_) 3771 return; 3772 3773 external_popup_menu_->DidSelectItems(canceled, selected_indices); 3774 external_popup_menu_.reset(); 3775 } 3776 #endif 3777 3778 #if defined(OS_MACOSX) || defined(OS_ANDROID) 3779 void RenderViewImpl::DidHideExternalPopupMenu() { 3780 // We need to clear external_popup_menu_ as soon as ExternalPopupMenu::close 3781 // is called. Otherwise, createExternalPopupMenu() for new popup will fail. 3782 external_popup_menu_.reset(); 3783 } 3784 #endif 3785 3786 void RenderViewImpl::OnShowContextMenu( 3787 ui::MenuSourceType source_type, const gfx::Point& location) { 3788 context_menu_source_type_ = source_type; 3789 has_host_context_menu_location_ = true; 3790 host_context_menu_location_ = location; 3791 if (webview()) 3792 webview()->showContextMenu(); 3793 has_host_context_menu_location_ = false; 3794 } 3795 3796 void RenderViewImpl::OnEnableViewSourceMode() { 3797 if (!webview()) 3798 return; 3799 WebFrame* main_frame = webview()->mainFrame(); 3800 if (!main_frame) 3801 return; 3802 main_frame->enableViewSourceMode(true); 3803 } 3804 3805 void RenderViewImpl::OnDisownOpener() { 3806 if (!webview()) 3807 return; 3808 3809 WebFrame* main_frame = webview()->mainFrame(); 3810 if (main_frame && main_frame->opener()) 3811 main_frame->setOpener(NULL); 3812 } 3813 3814 #if defined(OS_ANDROID) 3815 bool RenderViewImpl::didTapMultipleTargets( 3816 const blink::WebGestureEvent& event, 3817 const WebVector<WebRect>& target_rects) { 3818 // Never show a disambiguation popup when accessibility is enabled, 3819 // as this interferes with "touch exploration". 3820 bool matchesAccessibilityModeComplete = 3821 (accessibility_mode_ & AccessibilityModeComplete) == 3822 AccessibilityModeComplete; 3823 if (matchesAccessibilityModeComplete) 3824 return false; 3825 3826 gfx::Rect finger_rect( 3827 event.x - event.data.tap.width / 2, event.y - event.data.tap.height / 2, 3828 event.data.tap.width, event.data.tap.height); 3829 gfx::Rect zoom_rect; 3830 float new_total_scale = 3831 DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor( 3832 finger_rect, target_rects, GetSize(), 3833 gfx::Rect(webview()->mainFrame()->visibleContentRect()).size(), 3834 device_scale_factor_ * webview()->pageScaleFactor(), &zoom_rect); 3835 if (!new_total_scale) 3836 return false; 3837 3838 bool handled = false; 3839 switch (renderer_preferences_.tap_multiple_targets_strategy) { 3840 case TAP_MULTIPLE_TARGETS_STRATEGY_ZOOM: 3841 handled = webview()->zoomToMultipleTargetsRect(zoom_rect); 3842 break; 3843 case TAP_MULTIPLE_TARGETS_STRATEGY_POPUP: { 3844 gfx::Size canvas_size = 3845 gfx::ToCeiledSize(gfx::ScaleSize(zoom_rect.size(), new_total_scale)); 3846 cc::SharedBitmapManager* manager = 3847 RenderThreadImpl::current()->shared_bitmap_manager(); 3848 scoped_ptr<cc::SharedBitmap> shared_bitmap = 3849 manager->AllocateSharedBitmap(canvas_size); 3850 { 3851 SkBitmap bitmap; 3852 SkImageInfo info = SkImageInfo::MakeN32Premul(canvas_size.width(), 3853 canvas_size.height()); 3854 bitmap.installPixels(info, shared_bitmap->pixels(), info.minRowBytes()); 3855 SkCanvas canvas(bitmap); 3856 3857 // TODO(trchen): Cleanup the device scale factor mess. 3858 // device scale will be applied in WebKit 3859 // --> zoom_rect doesn't include device scale, 3860 // but WebKit will still draw on zoom_rect * device_scale_factor_ 3861 canvas.scale(new_total_scale / device_scale_factor_, 3862 new_total_scale / device_scale_factor_); 3863 canvas.translate(-zoom_rect.x() * device_scale_factor_, 3864 -zoom_rect.y() * device_scale_factor_); 3865 3866 DCHECK(webwidget_->isAcceleratedCompositingActive()); 3867 // TODO(aelias): The disambiguation popup should be composited so we 3868 // don't have to call this method. 3869 webwidget_->paintCompositedDeprecated(&canvas, zoom_rect); 3870 } 3871 3872 gfx::Rect physical_window_zoom_rect = gfx::ToEnclosingRect( 3873 ClientRectToPhysicalWindowRect(gfx::RectF(zoom_rect))); 3874 Send(new ViewHostMsg_ShowDisambiguationPopup(routing_id_, 3875 physical_window_zoom_rect, 3876 canvas_size, 3877 shared_bitmap->id())); 3878 cc::SharedBitmapId id = shared_bitmap->id(); 3879 disambiguation_bitmaps_[id] = shared_bitmap.release(); 3880 handled = true; 3881 break; 3882 } 3883 case TAP_MULTIPLE_TARGETS_STRATEGY_NONE: 3884 // No-op. 3885 break; 3886 } 3887 3888 return handled; 3889 } 3890 #endif 3891 3892 unsigned RenderViewImpl::GetLocalSessionHistoryLengthForTesting() const { 3893 return history_list_length_; 3894 } 3895 3896 void RenderViewImpl::SetFocusAndActivateForTesting(bool enable) { 3897 if (enable) { 3898 if (has_focus()) 3899 return; 3900 OnSetActive(true); 3901 OnSetFocus(true); 3902 } else { 3903 if (!has_focus()) 3904 return; 3905 OnSetFocus(false); 3906 OnSetActive(false); 3907 } 3908 } 3909 3910 void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) { 3911 ViewMsg_Resize_Params params; 3912 params.screen_info = screen_info_; 3913 params.screen_info.deviceScaleFactor = factor; 3914 params.new_size = size(); 3915 params.physical_backing_size = 3916 gfx::ToCeiledSize(gfx::ScaleSize(size(), factor)); 3917 params.overdraw_bottom_height = 0.f; 3918 params.resizer_rect = WebRect(); 3919 params.is_fullscreen = is_fullscreen(); 3920 OnResize(params); 3921 } 3922 3923 void RenderViewImpl::SetScreenOrientationForTesting( 3924 const blink::WebScreenOrientationType& orientation) { 3925 ViewMsg_Resize_Params params; 3926 params.screen_info = screen_info_; 3927 params.screen_info.orientationType = orientation; 3928 // FIXME(ostap): This relationship between orientationType and 3929 // orientationAngle is temporary. The test should be able to specify 3930 // the angle in addition to the orientation type. 3931 switch (orientation) { 3932 case blink::WebScreenOrientationLandscapePrimary: 3933 params.screen_info.orientationAngle = 90; 3934 break; 3935 case blink::WebScreenOrientationLandscapeSecondary: 3936 params.screen_info.orientationAngle = -90; 3937 break; 3938 case blink::WebScreenOrientationPortraitSecondary: 3939 params.screen_info.orientationAngle = 180; 3940 break; 3941 default: 3942 params.screen_info.orientationAngle = 0; 3943 } 3944 params.new_size = size(); 3945 params.physical_backing_size = gfx::ToCeiledSize( 3946 gfx::ScaleSize(size(), params.screen_info.deviceScaleFactor)); 3947 params.overdraw_bottom_height = 0.f; 3948 params.resizer_rect = WebRect(); 3949 params.is_fullscreen = is_fullscreen(); 3950 OnResize(params); 3951 } 3952 3953 void RenderViewImpl::SetDeviceColorProfileForTesting( 3954 const std::vector<char>& color_profile) { 3955 SetDeviceColorProfile(color_profile); 3956 } 3957 3958 void RenderViewImpl::ForceResizeForTesting(const gfx::Size& new_size) { 3959 gfx::Rect new_position(rootWindowRect().x, 3960 rootWindowRect().y, 3961 new_size.width(), 3962 new_size.height()); 3963 ResizeSynchronously(new_position); 3964 } 3965 3966 void RenderViewImpl::UseSynchronousResizeModeForTesting(bool enable) { 3967 resizing_mode_selector_->set_is_synchronous_mode(enable); 3968 } 3969 3970 void RenderViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_size, 3971 const gfx::Size& max_size) { 3972 OnEnableAutoResize(min_size, max_size); 3973 } 3974 3975 void RenderViewImpl::DisableAutoResizeForTesting(const gfx::Size& new_size) { 3976 OnDisableAutoResize(new_size); 3977 } 3978 3979 void RenderViewImpl::OnReleaseDisambiguationPopupBitmap( 3980 const cc::SharedBitmapId& id) { 3981 BitmapMap::iterator it = disambiguation_bitmaps_.find(id); 3982 DCHECK(it != disambiguation_bitmaps_.end()); 3983 delete it->second; 3984 disambiguation_bitmaps_.erase(it); 3985 } 3986 3987 void RenderViewImpl::DidCommitCompositorFrame() { 3988 RenderWidget::DidCommitCompositorFrame(); 3989 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidCommitCompositorFrame()); 3990 } 3991 3992 void RenderViewImpl::SendUpdateFaviconURL(const std::vector<FaviconURL>& urls) { 3993 if (!urls.empty()) 3994 Send(new ViewHostMsg_UpdateFaviconURL(routing_id_, urls)); 3995 } 3996 3997 void RenderViewImpl::DidStopLoadingIcons() { 3998 int icon_types = WebIconURL::TypeFavicon; 3999 if (TouchEnabled()) 4000 icon_types |= WebIconURL::TypeTouchPrecomposed | WebIconURL::TypeTouch; 4001 4002 WebVector<WebIconURL> icon_urls = 4003 webview()->mainFrame()->iconURLs(icon_types); 4004 4005 std::vector<FaviconURL> urls; 4006 for (size_t i = 0; i < icon_urls.size(); i++) { 4007 WebURL url = icon_urls[i].iconURL(); 4008 std::vector<gfx::Size> sizes; 4009 ConvertToFaviconSizes(icon_urls[i].sizes(), &sizes); 4010 if (!url.isEmpty()) 4011 urls.push_back( 4012 FaviconURL(url, ToFaviconType(icon_urls[i].iconType()), sizes)); 4013 } 4014 SendUpdateFaviconURL(urls); 4015 } 4016 4017 } // namespace content 4018