Home | History | Annotate | Download | only in renderer
      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/json/json_writer.h"
     19 #include "base/lazy_instance.h"
     20 #include "base/memory/scoped_ptr.h"
     21 #include "base/message_loop/message_loop_proxy.h"
     22 #include "base/metrics/histogram.h"
     23 #include "base/path_service.h"
     24 #include "base/process/kill.h"
     25 #include "base/strings/string_number_conversions.h"
     26 #include "base/strings/string_piece.h"
     27 #include "base/strings/string_split.h"
     28 #include "base/strings/string_util.h"
     29 #include "base/strings/sys_string_conversions.h"
     30 #include "base/strings/utf_string_conversions.h"
     31 #include "base/time/time.h"
     32 #include "content/child/appcache/appcache_dispatcher.h"
     33 #include "content/child/appcache/web_application_cache_host_impl.h"
     34 #include "content/child/child_thread.h"
     35 #include "content/child/fileapi/file_system_dispatcher.h"
     36 #include "content/child/fileapi/webfilesystem_callback_adapters.h"
     37 #include "content/child/npapi/webplugin_delegate_impl.h"
     38 #include "content/child/quota_dispatcher.h"
     39 #include "content/child/request_extra_data.h"
     40 #include "content/child/webmessageportchannel_impl.h"
     41 #include "content/common/clipboard_messages.h"
     42 #include "content/common/database_messages.h"
     43 #include "content/common/dom_storage/dom_storage_types.h"
     44 #include "content/common/drag_messages.h"
     45 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
     46 #include "content/common/input_messages.h"
     47 #include "content/common/java_bridge_messages.h"
     48 #include "content/common/pepper_messages.h"
     49 #include "content/common/socket_stream_handle_data.h"
     50 #include "content/common/ssl_status_serialization.h"
     51 #include "content/common/view_messages.h"
     52 #include "content/public/common/bindings_policy.h"
     53 #include "content/public/common/content_client.h"
     54 #include "content/public/common/content_constants.h"
     55 #include "content/public/common/content_switches.h"
     56 #include "content/public/common/context_menu_params.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/context_menu_client.h"
     67 #include "content/public/renderer/document_state.h"
     68 #include "content/public/renderer/history_item_serialization.h"
     69 #include "content/public/renderer/navigation_state.h"
     70 #include "content/public/renderer/password_form_conversion_utils.h"
     71 #include "content/public/renderer/render_view_observer.h"
     72 #include "content/public/renderer/render_view_visitor.h"
     73 #include "content/renderer/accessibility/renderer_accessibility.h"
     74 #include "content/renderer/accessibility/renderer_accessibility_complete.h"
     75 #include "content/renderer/accessibility/renderer_accessibility_focus_only.h"
     76 #include "content/renderer/browser_plugin/browser_plugin.h"
     77 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
     78 #include "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
     79 #include "content/renderer/context_menu_params_builder.h"
     80 #include "content/renderer/device_orientation_dispatcher.h"
     81 #include "content/renderer/devtools/devtools_agent.h"
     82 #include "content/renderer/disambiguation_popup_helper.h"
     83 #include "content/renderer/dom_automation_controller.h"
     84 #include "content/renderer/dom_storage/webstoragenamespace_impl.h"
     85 #include "content/renderer/drop_data_builder.h"
     86 #include "content/renderer/external_popup_menu.h"
     87 #include "content/renderer/fetchers/alt_error_page_resource_fetcher.h"
     88 #include "content/renderer/geolocation_dispatcher.h"
     89 #include "content/renderer/gpu/input_handler_manager.h"
     90 #include "content/renderer/gpu/render_widget_compositor.h"
     91 #include "content/renderer/idle_user_detector.h"
     92 #include "content/renderer/image_loading_helper.h"
     93 #include "content/renderer/ime_event_guard.h"
     94 #include "content/renderer/input_tag_speech_dispatcher.h"
     95 #include "content/renderer/internal_document_state_data.h"
     96 #include "content/renderer/java/java_bridge_dispatcher.h"
     97 #include "content/renderer/load_progress_tracker.h"
     98 #include "content/renderer/media/audio_device_factory.h"
     99 #include "content/renderer/media/audio_renderer_mixer_manager.h"
    100 #include "content/renderer/media/media_stream_dependency_factory.h"
    101 #include "content/renderer/media/media_stream_dispatcher.h"
    102 #include "content/renderer/media/media_stream_impl.h"
    103 #include "content/renderer/media/midi_dispatcher.h"
    104 #include "content/renderer/media/render_media_log.h"
    105 #include "content/renderer/media/rtc_peer_connection_handler.h"
    106 #include "content/renderer/media/video_capture_impl_manager.h"
    107 #include "content/renderer/media/webmediaplayer_impl.h"
    108 #include "content/renderer/media/webmediaplayer_ms.h"
    109 #include "content/renderer/media/webmediaplayer_params.h"
    110 #include "content/renderer/mhtml_generator.h"
    111 #include "content/renderer/notification_provider.h"
    112 #include "content/renderer/render_frame_impl.h"
    113 #include "content/renderer/render_process.h"
    114 #include "content/renderer/render_thread_impl.h"
    115 #include "content/renderer/render_view_impl_params.h"
    116 #include "content/renderer/render_view_mouse_lock_dispatcher.h"
    117 #include "content/renderer/render_widget_fullscreen_pepper.h"
    118 #include "content/renderer/renderer_date_time_picker.h"
    119 #include "content/renderer/renderer_webapplicationcachehost_impl.h"
    120 #include "content/renderer/renderer_webcolorchooser_impl.h"
    121 #include "content/renderer/savable_resources.h"
    122 #include "content/renderer/speech_recognition_dispatcher.h"
    123 #include "content/renderer/stats_collection_controller.h"
    124 #include "content/renderer/stats_collection_observer.h"
    125 #include "content/renderer/text_input_client_observer.h"
    126 #include "content/renderer/v8_value_converter_impl.h"
    127 #include "content/renderer/web_ui_extension.h"
    128 #include "content/renderer/web_ui_extension_data.h"
    129 #include "content/renderer/websharedworker_proxy.h"
    130 #include "media/audio/audio_output_device.h"
    131 #include "media/base/audio_renderer_mixer_input.h"
    132 #include "media/base/filter_collection.h"
    133 #include "media/base/media_switches.h"
    134 #include "media/filters/audio_renderer_impl.h"
    135 #include "media/filters/gpu_video_decoder_factories.h"
    136 #include "net/base/data_url.h"
    137 #include "net/base/escape.h"
    138 #include "net/base/net_errors.h"
    139 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
    140 #include "net/http/http_util.h"
    141 #include "third_party/WebKit/public/platform/WebCString.h"
    142 #include "third_party/WebKit/public/platform/WebDragData.h"
    143 #include "third_party/WebKit/public/platform/WebFileSystemType.h"
    144 #include "third_party/WebKit/public/platform/WebHTTPBody.h"
    145 #include "third_party/WebKit/public/platform/WebImage.h"
    146 #include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
    147 #include "third_party/WebKit/public/platform/WebPoint.h"
    148 #include "third_party/WebKit/public/platform/WebRect.h"
    149 #include "third_party/WebKit/public/platform/WebSize.h"
    150 #include "third_party/WebKit/public/platform/WebSocketStreamHandle.h"
    151 #include "third_party/WebKit/public/platform/WebString.h"
    152 #include "third_party/WebKit/public/platform/WebURL.h"
    153 #include "third_party/WebKit/public/platform/WebURLError.h"
    154 #include "third_party/WebKit/public/platform/WebURLRequest.h"
    155 #include "third_party/WebKit/public/platform/WebURLResponse.h"
    156 #include "third_party/WebKit/public/platform/WebVector.h"
    157 #include "third_party/WebKit/public/web/WebAccessibilityObject.h"
    158 #include "third_party/WebKit/public/web/WebColorName.h"
    159 #include "third_party/WebKit/public/web/WebDOMEvent.h"
    160 #include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
    161 #include "third_party/WebKit/public/web/WebDataSource.h"
    162 #include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h"
    163 #include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
    164 #include "third_party/WebKit/public/web/WebDevToolsAgent.h"
    165 #include "third_party/WebKit/public/web/WebDocument.h"
    166 #include "third_party/WebKit/public/web/WebElement.h"
    167 #include "third_party/WebKit/public/web/WebFileChooserParams.h"
    168 #include "third_party/WebKit/public/web/WebFileSystemCallbacks.h"
    169 #include "third_party/WebKit/public/web/WebFindOptions.h"
    170 #include "third_party/WebKit/public/web/WebFormControlElement.h"
    171 #include "third_party/WebKit/public/web/WebFormElement.h"
    172 #include "third_party/WebKit/public/web/WebFrame.h"
    173 #include "third_party/WebKit/public/web/WebGlyphCache.h"
    174 #include "third_party/WebKit/public/web/WebHelperPlugin.h"
    175 #include "third_party/WebKit/public/web/WebHistoryItem.h"
    176 #include "third_party/WebKit/public/web/WebInputElement.h"
    177 #include "third_party/WebKit/public/web/WebInputEvent.h"
    178 #include "third_party/WebKit/public/web/WebMediaPlayerAction.h"
    179 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
    180 #include "third_party/WebKit/public/web/WebNodeList.h"
    181 #include "third_party/WebKit/public/web/WebPageSerializer.h"
    182 #include "third_party/WebKit/public/web/WebPlugin.h"
    183 #include "third_party/WebKit/public/web/WebPluginAction.h"
    184 #include "third_party/WebKit/public/web/WebPluginContainer.h"
    185 #include "third_party/WebKit/public/web/WebPluginDocument.h"
    186 #include "third_party/WebKit/public/web/WebPluginParams.h"
    187 #include "third_party/WebKit/public/web/WebRange.h"
    188 #include "third_party/WebKit/public/web/WebScriptSource.h"
    189 #include "third_party/WebKit/public/web/WebSearchableFormData.h"
    190 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
    191 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
    192 #include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
    193 #include "third_party/WebKit/public/web/WebSettings.h"
    194 #include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h"
    195 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
    196 #include "third_party/WebKit/public/web/WebUserMediaClient.h"
    197 #include "third_party/WebKit/public/web/WebView.h"
    198 #include "third_party/WebKit/public/web/WebWindowFeatures.h"
    199 #include "third_party/WebKit/public/web/default/WebRenderTheme.h"
    200 #include "ui/base/ui_base_switches_util.h"
    201 #include "ui/gfx/native_widget_types.h"
    202 #include "ui/gfx/point.h"
    203 #include "ui/gfx/rect.h"
    204 #include "ui/gfx/rect_conversions.h"
    205 #include "ui/gfx/size_conversions.h"
    206 #include "ui/shell_dialogs/selected_file_info.h"
    207 #include "v8/include/v8.h"
    208 #include "webkit/child/weburlresponse_extradata_impl.h"
    209 #include "webkit/renderer/webpreferences_renderer.h"
    210 
    211 #if defined(OS_ANDROID)
    212 #include <cpu-features.h>
    213 
    214 #include "content/common/android/device_telephony_info.h"
    215 #include "content/common/gpu/client/context_provider_command_buffer.h"
    216 #include "content/renderer/android/address_detector.h"
    217 #include "content/renderer/android/content_detector.h"
    218 #include "content/renderer/android/email_detector.h"
    219 #include "content/renderer/android/phone_number_detector.h"
    220 #include "content/renderer/android/synchronous_compositor_factory.h"
    221 #include "content/renderer/media/android/renderer_media_player_manager.h"
    222 #include "content/renderer/media/android/stream_texture_factory_android_impl.h"
    223 #include "content/renderer/media/android/webmediaplayer_android.h"
    224 #include "content/renderer/media/android/webmediaplayer_proxy_android.h"
    225 #include "skia/ext/platform_canvas.h"
    226 #include "third_party/WebKit/public/platform/WebFloatPoint.h"
    227 #include "third_party/WebKit/public/platform/WebFloatRect.h"
    228 #include "third_party/WebKit/public/web/WebHitTestResult.h"
    229 #include "ui/gfx/rect_f.h"
    230 
    231 #if defined(GOOGLE_TV)
    232 #include "content/renderer/media/rtc_video_decoder_bridge_tv.h"
    233 #include "content/renderer/media/rtc_video_decoder_factory_tv.h"
    234 #endif
    235 
    236 #elif defined(OS_WIN)
    237 // TODO(port): these files are currently Windows only because they concern:
    238 //   * theming
    239 #include "ui/native_theme/native_theme_win.h"
    240 #elif defined(USE_X11)
    241 #include "ui/native_theme/native_theme.h"
    242 #elif defined(OS_MACOSX)
    243 #include "skia/ext/skia_utils_mac.h"
    244 #endif
    245 
    246 #if defined(ENABLE_PLUGINS)
    247 #include "content/renderer/npapi/webplugin_delegate_proxy.h"
    248 #include "content/renderer/npapi/webplugin_impl.h"
    249 #include "content/renderer/pepper/pepper_browser_connection.h"
    250 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
    251 #include "content/renderer/pepper/pepper_plugin_registry.h"
    252 #include "content/renderer/pepper/pepper_webplugin_impl.h"
    253 #include "content/renderer/pepper/plugin_module.h"
    254 #endif
    255 
    256 using WebKit::WebAccessibilityNotification;
    257 using WebKit::WebAccessibilityObject;
    258 using WebKit::WebApplicationCacheHost;
    259 using WebKit::WebApplicationCacheHostClient;
    260 using WebKit::WebCString;
    261 using WebKit::WebColor;
    262 using WebKit::WebColorName;
    263 using WebKit::WebConsoleMessage;
    264 using WebKit::WebContextMenuData;
    265 using WebKit::WebCookieJar;
    266 using WebKit::WebData;
    267 using WebKit::WebDataSource;
    268 using WebKit::WebDocument;
    269 using WebKit::WebDOMEvent;
    270 using WebKit::WebDOMMessageEvent;
    271 using WebKit::WebDragData;
    272 using WebKit::WebDragOperation;
    273 using WebKit::WebDragOperationsMask;
    274 using WebKit::WebEditingAction;
    275 using WebKit::WebElement;
    276 using WebKit::WebExternalPopupMenu;
    277 using WebKit::WebExternalPopupMenuClient;
    278 using WebKit::WebFileChooserCompletion;
    279 using WebKit::WebFileSystem;
    280 using WebKit::WebFileSystemCallbacks;
    281 using WebKit::WebFindOptions;
    282 using WebKit::WebFormControlElement;
    283 using WebKit::WebFormElement;
    284 using WebKit::WebFrame;
    285 using WebKit::WebGestureEvent;
    286 using WebKit::WebHistoryItem;
    287 using WebKit::WebHTTPBody;
    288 using WebKit::WebIconURL;
    289 using WebKit::WebImage;
    290 using WebKit::WebInputElement;
    291 using WebKit::WebInputEvent;
    292 using WebKit::WebMediaPlayer;
    293 using WebKit::WebMediaPlayerAction;
    294 using WebKit::WebMediaPlayerClient;
    295 using WebKit::WebMouseEvent;
    296 using WebKit::WebNavigationPolicy;
    297 using WebKit::WebNavigationType;
    298 using WebKit::WebNode;
    299 using WebKit::WebPageSerializer;
    300 using WebKit::WebPageSerializerClient;
    301 using WebKit::WebPeerConnection00Handler;
    302 using WebKit::WebPeerConnection00HandlerClient;
    303 using WebKit::WebPeerConnectionHandler;
    304 using WebKit::WebPeerConnectionHandlerClient;
    305 using WebKit::WebPluginAction;
    306 using WebKit::WebPluginContainer;
    307 using WebKit::WebPluginDocument;
    308 using WebKit::WebPluginParams;
    309 using WebKit::WebPoint;
    310 using WebKit::WebPopupMenuInfo;
    311 using WebKit::WebRange;
    312 using WebKit::WebRect;
    313 using WebKit::WebReferrerPolicy;
    314 using WebKit::WebScriptSource;
    315 using WebKit::WebSearchableFormData;
    316 using WebKit::WebSecurityOrigin;
    317 using WebKit::WebSecurityPolicy;
    318 using WebKit::WebSerializedScriptValue;
    319 using WebKit::WebSettings;
    320 using WebKit::WebSharedWorker;
    321 using WebKit::WebSize;
    322 using WebKit::WebSocketStreamHandle;
    323 using WebKit::WebStorageNamespace;
    324 using WebKit::WebStorageQuotaCallbacks;
    325 using WebKit::WebStorageQuotaError;
    326 using WebKit::WebStorageQuotaType;
    327 using WebKit::WebString;
    328 using WebKit::WebTextAffinity;
    329 using WebKit::WebTextDirection;
    330 using WebKit::WebTouchEvent;
    331 using WebKit::WebURL;
    332 using WebKit::WebURLError;
    333 using WebKit::WebURLRequest;
    334 using WebKit::WebURLResponse;
    335 using WebKit::WebUserGestureIndicator;
    336 using WebKit::WebVector;
    337 using WebKit::WebView;
    338 using WebKit::WebWidget;
    339 using WebKit::WebWindowFeatures;
    340 using base::Time;
    341 using base::TimeDelta;
    342 using webkit_glue::WebURLResponseExtraDataImpl;
    343 
    344 #if defined(OS_ANDROID)
    345 using WebKit::WebContentDetectionResult;
    346 using WebKit::WebFloatPoint;
    347 using WebKit::WebFloatRect;
    348 using WebKit::WebHitTestResult;
    349 #endif
    350 
    351 namespace content {
    352 
    353 //-----------------------------------------------------------------------------
    354 
    355 typedef std::map<WebKit::WebView*, RenderViewImpl*> ViewMap;
    356 static base::LazyInstance<ViewMap> g_view_map = LAZY_INSTANCE_INITIALIZER;
    357 typedef std::map<int32, RenderViewImpl*> RoutingIDViewMap;
    358 static base::LazyInstance<RoutingIDViewMap> g_routing_id_view_map =
    359     LAZY_INSTANCE_INITIALIZER;
    360 
    361 // Time, in seconds, we delay before sending content state changes (such as form
    362 // state and scroll position) to the browser. We delay sending changes to avoid
    363 // spamming the browser.
    364 // To avoid having tab/session restore require sending a message to get the
    365 // current content state during tab closing we use a shorter timeout for the
    366 // foreground renderer. This means there is a small window of time from which
    367 // content state is modified and not sent to session restore, but this is
    368 // better than having to wake up all renderers during shutdown.
    369 static const int kDelaySecondsForContentStateSyncHidden = 5;
    370 static const int kDelaySecondsForContentStateSync = 1;
    371 
    372 static const size_t kExtraCharsBeforeAndAfterSelection = 100;
    373 
    374 // The maximum number of popups that can be spawned from one page.
    375 static const int kMaximumNumberOfUnacknowledgedPopups = 25;
    376 
    377 static const float kScalingIncrement = 0.1f;
    378 
    379 static const float kScalingIncrementForGesture = 0.01f;
    380 
    381 #if defined(OS_ANDROID)
    382 // Delay between tapping in content and launching the associated android intent.
    383 // Used to allow users see what has been recognized as content.
    384 static const size_t kContentIntentDelayMilliseconds = 700;
    385 #endif
    386 
    387 static RenderViewImpl* (*g_create_render_view_impl)(RenderViewImplParams*) =
    388     NULL;
    389 
    390 static void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
    391   // Replace any occurrences of swappedout:// with about:blank.
    392   const WebURL& blank_url = GURL(kAboutBlankURL);
    393   WebVector<WebURL> urls;
    394   ds->redirectChain(urls);
    395   result->reserve(urls.size());
    396   for (size_t i = 0; i < urls.size(); ++i) {
    397     if (urls[i] != GURL(kSwappedOutURL))
    398       result->push_back(urls[i]);
    399     else
    400       result->push_back(blank_url);
    401   }
    402 }
    403 
    404 // If |data_source| is non-null and has an InternalDocumentStateData associated
    405 // with it, the AltErrorPageResourceFetcher is reset.
    406 static void StopAltErrorPageFetcher(WebDataSource* data_source) {
    407   if (data_source) {
    408     InternalDocumentStateData* internal_data =
    409         InternalDocumentStateData::FromDataSource(data_source);
    410     if (internal_data)
    411       internal_data->set_alt_error_page_fetcher(NULL);
    412   }
    413 }
    414 
    415 static bool IsReload(const ViewMsg_Navigate_Params& params) {
    416   return
    417       params.navigation_type == ViewMsg_Navigate_Type::RELOAD ||
    418       params.navigation_type == ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE ||
    419       params.navigation_type ==
    420           ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
    421 }
    422 
    423 // static
    424 WebReferrerPolicy RenderViewImpl::GetReferrerPolicyFromRequest(
    425     WebFrame* frame,
    426     const WebURLRequest& request) {
    427   return request.extraData() ?
    428       static_cast<RequestExtraData*>(request.extraData())->referrer_policy() :
    429       frame->document().referrerPolicy();
    430 }
    431 
    432 // static
    433 Referrer RenderViewImpl::GetReferrerFromRequest(
    434     WebFrame* frame,
    435     const WebURLRequest& request) {
    436   return Referrer(GURL(request.httpHeaderField(WebString::fromUTF8("Referer"))),
    437                   GetReferrerPolicyFromRequest(frame, request));
    438 }
    439 
    440 // static
    441 WebURLResponseExtraDataImpl* RenderViewImpl::GetExtraDataFromResponse(
    442     const WebURLResponse& response) {
    443   return static_cast<WebURLResponseExtraDataImpl*>(
    444       response.extraData());
    445 }
    446 
    447 NOINLINE static void CrashIntentionally() {
    448   // NOTE(shess): Crash directly rather than using NOTREACHED() so
    449   // that the signature is easier to triage in crash reports.
    450   volatile int* zero = NULL;
    451   *zero = 0;
    452 }
    453 
    454 #if defined(ADDRESS_SANITIZER)
    455 NOINLINE static void MaybeTriggerAsanError(const GURL& url) {
    456   // NOTE(rogerm): We intentionally perform an invalid heap access here in
    457   //     order to trigger an Address Sanitizer (ASAN) error report.
    458   static const char kCrashDomain[] = "crash";
    459   static const char kHeapOverflow[] = "/heap-overflow";
    460   static const char kHeapUnderflow[] = "/heap-underflow";
    461   static const char kUseAfterFree[] = "/use-after-free";
    462   static const int kArraySize = 5;
    463 
    464   if (!url.DomainIs(kCrashDomain, sizeof(kCrashDomain) - 1))
    465     return;
    466 
    467   if (!url.has_path())
    468     return;
    469 
    470   scoped_ptr<int[]> array(new int[kArraySize]);
    471   std::string crash_type(url.path());
    472   int dummy = 0;
    473   if (crash_type == kHeapOverflow) {
    474     dummy = array[kArraySize];
    475   } else if (crash_type == kHeapUnderflow ) {
    476     dummy = array[-1];
    477   } else if (crash_type == kUseAfterFree) {
    478     int* dangling = array.get();
    479     array.reset();
    480     dummy = dangling[kArraySize / 2];
    481   }
    482 
    483   // Make sure the assignments to the dummy value aren't optimized away.
    484   base::debug::Alias(&dummy);
    485 }
    486 #endif  // ADDRESS_SANITIZER
    487 
    488 static void MaybeHandleDebugURL(const GURL& url) {
    489   if (!url.SchemeIs(chrome::kChromeUIScheme))
    490     return;
    491   if (url == GURL(kChromeUICrashURL)) {
    492     CrashIntentionally();
    493   } else if (url == GURL(kChromeUIKillURL)) {
    494     base::KillProcess(base::GetCurrentProcessHandle(), 1, false);
    495   } else if (url == GURL(kChromeUIHangURL)) {
    496     for (;;) {
    497       base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
    498     }
    499   } else if (url == GURL(kChromeUIShorthangURL)) {
    500     base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
    501   }
    502 
    503 #if defined(ADDRESS_SANITIZER)
    504   MaybeTriggerAsanError(url);
    505 #endif  // ADDRESS_SANITIZER
    506 }
    507 
    508 // Returns false unless this is a top-level navigation.
    509 static bool IsTopLevelNavigation(WebFrame* frame) {
    510   return frame->parent() == NULL;
    511 }
    512 
    513 // Returns false unless this is a top-level navigation that crosses origins.
    514 static bool IsNonLocalTopLevelNavigation(const GURL& url,
    515                                          WebFrame* frame,
    516                                          WebNavigationType type,
    517                                          bool is_form_post) {
    518   if (!IsTopLevelNavigation(frame))
    519     return false;
    520 
    521   // Navigations initiated within Webkit are not sent out to the external host
    522   // in the following cases.
    523   // 1. The url scheme is not http/https
    524   // 2. The origin of the url and the opener is the same in which case the
    525   //    opener relationship is maintained.
    526   // 3. Reloads/form submits/back forward navigations
    527   if (!url.SchemeIs(chrome::kHttpScheme) && !url.SchemeIs(chrome::kHttpsScheme))
    528     return false;
    529 
    530   if (type != WebKit::WebNavigationTypeReload &&
    531       type != WebKit::WebNavigationTypeBackForward && !is_form_post) {
    532     // The opener relationship between the new window and the parent allows the
    533     // new window to script the parent and vice versa. This is not allowed if
    534     // the origins of the two domains are different. This can be treated as a
    535     // top level navigation and routed back to the host.
    536     WebKit::WebFrame* opener = frame->opener();
    537     if (!opener)
    538       return true;
    539 
    540     if (url.GetOrigin() != GURL(opener->document().url()).GetOrigin())
    541       return true;
    542   }
    543   return false;
    544 }
    545 
    546 static void NotifyTimezoneChange(WebKit::WebFrame* frame) {
    547   v8::HandleScope handle_scope;
    548   v8::Context::Scope context_scope(frame->mainWorldScriptContext());
    549   v8::Date::DateTimeConfigurationChangeNotification();
    550   WebKit::WebFrame* child = frame->firstChild();
    551   for (; child; child = child->nextSibling())
    552     NotifyTimezoneChange(child);
    553 }
    554 
    555 static WindowOpenDisposition NavigationPolicyToDisposition(
    556     WebNavigationPolicy policy) {
    557   switch (policy) {
    558     case WebKit::WebNavigationPolicyIgnore:
    559       return IGNORE_ACTION;
    560     case WebKit::WebNavigationPolicyDownload:
    561       return SAVE_TO_DISK;
    562     case WebKit::WebNavigationPolicyCurrentTab:
    563       return CURRENT_TAB;
    564     case WebKit::WebNavigationPolicyNewBackgroundTab:
    565       return NEW_BACKGROUND_TAB;
    566     case WebKit::WebNavigationPolicyNewForegroundTab:
    567       return NEW_FOREGROUND_TAB;
    568     case WebKit::WebNavigationPolicyNewWindow:
    569       return NEW_WINDOW;
    570     case WebKit::WebNavigationPolicyNewPopup:
    571       return NEW_POPUP;
    572   default:
    573     NOTREACHED() << "Unexpected WebNavigationPolicy";
    574     return IGNORE_ACTION;
    575   }
    576 }
    577 
    578 // Returns true if the device scale is high enough that losing subpixel
    579 // antialiasing won't have a noticeable effect on text quality.
    580 static bool DeviceScaleEnsuresTextQuality(float device_scale_factor) {
    581 #if defined(OS_ANDROID)
    582   // On Android, we never have subpixel antialiasing.
    583   return true;
    584 #else
    585   return device_scale_factor > 1.5f;
    586 #endif
    587 
    588 }
    589 
    590 static bool ShouldUseFixedPositionCompositing(float device_scale_factor) {
    591   // Compositing for fixed-position elements is dependent on
    592   // device_scale_factor if no flag is set. http://crbug.com/172738
    593   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    594 
    595   if (command_line.HasSwitch(switches::kDisableCompositingForFixedPosition))
    596     return false;
    597 
    598   if (command_line.HasSwitch(switches::kEnableCompositingForFixedPosition))
    599     return true;
    600 
    601   return DeviceScaleEnsuresTextQuality(device_scale_factor);
    602 }
    603 
    604 static bool ShouldUseAcceleratedCompositingForOverflowScroll(
    605     float device_scale_factor) {
    606   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    607 
    608   if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll))
    609     return true;
    610 
    611   return DeviceScaleEnsuresTextQuality(device_scale_factor);
    612 }
    613 
    614 static bool ShouldUseTransitionCompositing(float device_scale_factor) {
    615   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    616 
    617   if (command_line.HasSwitch(switches::kDisableCompositingForTransition))
    618     return false;
    619 
    620   if (command_line.HasSwitch(switches::kEnableCompositingForTransition))
    621     return true;
    622 
    623   // TODO(ajuma): Re-enable this by default for high-DPI once the problem
    624   // of excessive layer promotion caused by overlap has been addressed.
    625   // http://crbug.com/178119.
    626   return false;
    627 }
    628 
    629 static bool ShouldUseAcceleratedFixedRootBackground(float device_scale_factor) {
    630   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    631 
    632   if (command_line.HasSwitch(switches::kDisableAcceleratedFixedRootBackground))
    633     return false;
    634 
    635   if (command_line.HasSwitch(switches::kEnableAcceleratedFixedRootBackground))
    636     return true;
    637 
    638   return DeviceScaleEnsuresTextQuality(device_scale_factor);
    639 }
    640 
    641 static FaviconURL::IconType ToFaviconType(WebKit::WebIconURL::Type type) {
    642   switch (type) {
    643     case WebKit::WebIconURL::TypeFavicon:
    644       return FaviconURL::FAVICON;
    645     case WebKit::WebIconURL::TypeTouch:
    646       return FaviconURL::TOUCH_ICON;
    647     case WebKit::WebIconURL::TypeTouchPrecomposed:
    648       return FaviconURL::TOUCH_PRECOMPOSED_ICON;
    649     case WebKit::WebIconURL::TypeInvalid:
    650       return FaviconURL::INVALID_ICON;
    651   }
    652   return FaviconURL::INVALID_ICON;
    653 }
    654 
    655 ///////////////////////////////////////////////////////////////////////////////
    656 
    657 struct RenderViewImpl::PendingFileChooser {
    658   PendingFileChooser(const FileChooserParams& p, WebFileChooserCompletion* c)
    659       : params(p),
    660         completion(c) {
    661   }
    662   FileChooserParams params;
    663   WebFileChooserCompletion* completion;  // MAY BE NULL to skip callback.
    664 };
    665 
    666 namespace {
    667 
    668 class WebWidgetLockTarget : public MouseLockDispatcher::LockTarget {
    669  public:
    670   explicit WebWidgetLockTarget(WebKit::WebWidget* webwidget)
    671       : webwidget_(webwidget) {}
    672 
    673   virtual void OnLockMouseACK(bool succeeded) OVERRIDE {
    674     if (succeeded)
    675       webwidget_->didAcquirePointerLock();
    676     else
    677       webwidget_->didNotAcquirePointerLock();
    678   }
    679 
    680   virtual void OnMouseLockLost() OVERRIDE {
    681     webwidget_->didLosePointerLock();
    682   }
    683 
    684   virtual bool HandleMouseLockedInputEvent(
    685       const WebKit::WebMouseEvent &event) OVERRIDE {
    686     // The WebWidget handles mouse lock in WebKit's handleInputEvent().
    687     return false;
    688   }
    689 
    690  private:
    691   WebKit::WebWidget* webwidget_;
    692 };
    693 
    694 int64 ExtractPostId(const WebHistoryItem& item) {
    695   if (item.isNull())
    696     return -1;
    697 
    698   if (item.httpBody().isNull())
    699     return -1;
    700 
    701   return item.httpBody().identifier();
    702 }
    703 
    704 bool TouchEnabled() {
    705 // Based on the definition of chrome::kEnableTouchIcon.
    706 #if defined(OS_ANDROID)
    707   return true;
    708 #else
    709   return false;
    710 #endif
    711 }
    712 
    713 WebDragData DropDataToWebDragData(const DropData& drop_data) {
    714   std::vector<WebDragData::Item> item_list;
    715 
    716   // These fields are currently unused when dragging into WebKit.
    717   DCHECK(drop_data.download_metadata.empty());
    718   DCHECK(drop_data.file_contents.empty());
    719   DCHECK(drop_data.file_description_filename.empty());
    720 
    721   if (!drop_data.text.is_null()) {
    722     WebDragData::Item item;
    723     item.storageType = WebDragData::Item::StorageTypeString;
    724     item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeText);
    725     item.stringData = drop_data.text.string();
    726     item_list.push_back(item);
    727   }
    728 
    729   // TODO(dcheng): Do we need to distinguish between null and empty URLs? Is it
    730   // meaningful to write an empty URL to the clipboard?
    731   if (!drop_data.url.is_empty()) {
    732     WebDragData::Item item;
    733     item.storageType = WebDragData::Item::StorageTypeString;
    734     item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeURIList);
    735     item.stringData = WebString::fromUTF8(drop_data.url.spec());
    736     item.title = drop_data.url_title;
    737     item_list.push_back(item);
    738   }
    739 
    740   if (!drop_data.html.is_null()) {
    741     WebDragData::Item item;
    742     item.storageType = WebDragData::Item::StorageTypeString;
    743     item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeHTML);
    744     item.stringData = drop_data.html.string();
    745     item.baseURL = drop_data.html_base_url;
    746     item_list.push_back(item);
    747   }
    748 
    749   for (std::vector<DropData::FileInfo>::const_iterator it =
    750            drop_data.filenames.begin();
    751        it != drop_data.filenames.end();
    752        ++it) {
    753     WebDragData::Item item;
    754     item.storageType = WebDragData::Item::StorageTypeFilename;
    755     item.filenameData = it->path;
    756     item.displayNameData = it->display_name;
    757     item_list.push_back(item);
    758   }
    759 
    760   for (std::map<base::string16, base::string16>::const_iterator it =
    761            drop_data.custom_data.begin();
    762        it != drop_data.custom_data.end();
    763        ++it) {
    764     WebDragData::Item item;
    765     item.storageType = WebDragData::Item::StorageTypeString;
    766     item.stringType = it->first;
    767     item.stringData = it->second;
    768     item_list.push_back(item);
    769   }
    770 
    771   WebDragData result;
    772   result.initialize();
    773   result.setItems(item_list);
    774   result.setFilesystemId(drop_data.filesystem_id);
    775   return result;
    776 }
    777 
    778 }  // namespace
    779 
    780 RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
    781     : RenderWidget(WebKit::WebPopupTypeNone,
    782                    params->screen_info,
    783                    params->swapped_out),
    784       webkit_preferences_(params->webkit_prefs),
    785       send_content_state_immediately_(false),
    786       enabled_bindings_(0),
    787       send_preferred_size_changes_(false),
    788       is_loading_(false),
    789       navigation_gesture_(NavigationGestureUnknown),
    790       opened_by_user_gesture_(true),
    791       opener_suppressed_(false),
    792       page_id_(-1),
    793       last_page_id_sent_to_browser_(-1),
    794       next_page_id_(params->next_page_id),
    795       history_list_offset_(-1),
    796       history_list_length_(0),
    797       target_url_status_(TARGET_NONE),
    798       selection_text_offset_(0),
    799       selection_range_(ui::Range::InvalidRange()),
    800 #if defined(OS_ANDROID)
    801       top_controls_constraints_(cc::BOTH),
    802 #endif
    803       cached_is_main_frame_pinned_to_left_(false),
    804       cached_is_main_frame_pinned_to_right_(false),
    805       cached_has_main_frame_horizontal_scrollbar_(false),
    806       cached_has_main_frame_vertical_scrollbar_(false),
    807       cookie_jar_(this),
    808       notification_provider_(NULL),
    809       geolocation_dispatcher_(NULL),
    810       input_tag_speech_dispatcher_(NULL),
    811       speech_recognition_dispatcher_(NULL),
    812       device_orientation_dispatcher_(NULL),
    813       media_stream_dispatcher_(NULL),
    814       browser_plugin_manager_(NULL),
    815       media_stream_client_(NULL),
    816       web_user_media_client_(NULL),
    817       midi_dispatcher_(NULL),
    818       devtools_agent_(NULL),
    819       accessibility_mode_(AccessibilityModeOff),
    820       renderer_accessibility_(NULL),
    821       java_bridge_dispatcher_(NULL),
    822       mouse_lock_dispatcher_(NULL),
    823 #if defined(OS_ANDROID)
    824       body_background_color_(SK_ColorWHITE),
    825       expected_content_intent_id_(0),
    826       media_player_proxy_(NULL),
    827 #endif
    828 #if defined(OS_WIN)
    829       focused_plugin_id_(-1),
    830 #endif
    831 #if defined(ENABLE_PLUGINS)
    832       focused_pepper_plugin_(NULL),
    833       pepper_last_mouse_event_target_(NULL),
    834 #endif
    835       enumeration_completion_id_(0),
    836 #if defined(OS_ANDROID)
    837       load_progress_tracker_(new LoadProgressTracker(this)),
    838 #endif
    839       session_storage_namespace_id_(params->session_storage_namespace_id),
    840       decrement_shared_popup_at_destruction_(false),
    841       handling_select_range_(false),
    842       next_snapshot_id_(0),
    843       allow_partial_swap_(params->allow_partial_swap),
    844       context_menu_source_type_(ui::MENU_SOURCE_MOUSE) {
    845 }
    846 
    847 void RenderViewImpl::Initialize(RenderViewImplParams* params) {
    848   RenderFrameImpl* main_frame = RenderFrameImpl::Create(
    849       this, params->main_frame_routing_id);
    850   main_render_frame_.reset(main_frame);
    851   routing_id_ = params->routing_id;
    852   surface_id_ = params->surface_id;
    853   if (params->opener_id != MSG_ROUTING_NONE && params->is_renderer_created)
    854     opener_id_ = params->opener_id;
    855 
    856   // Ensure we start with a valid next_page_id_ from the browser.
    857   DCHECK_GE(next_page_id_, 0);
    858 
    859 #if defined(ENABLE_NOTIFICATIONS)
    860   notification_provider_ = new NotificationProvider(this);
    861 #else
    862   notification_provider_ = NULL;
    863 #endif
    864 
    865   webwidget_ = WebView::create(this);
    866   webwidget_mouse_lock_target_.reset(new WebWidgetLockTarget(webwidget_));
    867 
    868   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    869 
    870   if (command_line.HasSwitch(switches::kStatsCollectionController))
    871     stats_collection_observer_.reset(new StatsCollectionObserver(this));
    872 
    873 #if defined(OS_ANDROID)
    874   content::DeviceTelephonyInfo device_info;
    875 
    876   const std::string region_code =
    877       command_line.HasSwitch(switches::kNetworkCountryIso)
    878           ? command_line.GetSwitchValueASCII(switches::kNetworkCountryIso)
    879           : device_info.GetNetworkCountryIso();
    880   content_detectors_.push_back(linked_ptr<ContentDetector>(
    881       new AddressDetector()));
    882   content_detectors_.push_back(linked_ptr<ContentDetector>(
    883       new PhoneNumberDetector(region_code)));
    884   content_detectors_.push_back(linked_ptr<ContentDetector>(
    885       new EmailDetector()));
    886 #endif
    887 
    888   if (params->counter) {
    889     shared_popup_counter_ = params->counter;
    890     // Only count this if it isn't swapped out upon creation.
    891     if (!params->swapped_out)
    892       shared_popup_counter_->data++;
    893     decrement_shared_popup_at_destruction_ = true;
    894   } else {
    895     shared_popup_counter_ = new SharedRenderViewCounter(0);
    896     decrement_shared_popup_at_destruction_ = false;
    897   }
    898 
    899   RenderThread::Get()->AddRoute(routing_id_, this);
    900   // Take a reference on behalf of the RenderThread.  This will be balanced
    901   // when we receive ViewMsg_ClosePage.
    902   AddRef();
    903 
    904   // If this is a popup, we must wait for the CreatingNew_ACK message before
    905   // completing initialization.  Otherwise, we can finish it now.
    906   if (opener_id_ == MSG_ROUTING_NONE) {
    907     did_show_ = true;
    908     CompleteInit();
    909   }
    910 
    911   g_view_map.Get().insert(std::make_pair(webview(), this));
    912   g_routing_id_view_map.Get().insert(std::make_pair(routing_id_, this));
    913   webview()->setDeviceScaleFactor(device_scale_factor_);
    914   webview()->settings()->setAcceleratedCompositingForFixedPositionEnabled(
    915       ShouldUseFixedPositionCompositing(device_scale_factor_));
    916   webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled(
    917       ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_));
    918   webview()->settings()->setAcceleratedCompositingForTransitionEnabled(
    919       ShouldUseTransitionCompositing(device_scale_factor_));
    920   webview()->settings()->setAcceleratedCompositingForFixedRootBackgroundEnabled(
    921       ShouldUseAcceleratedFixedRootBackground(device_scale_factor_));
    922 
    923   webkit_glue::ApplyWebPreferences(webkit_preferences_, webview());
    924   webview()->initializeMainFrame(main_render_frame_.get());
    925 
    926   if (switches::IsTouchDragDropEnabled())
    927     webview()->settings()->setTouchDragDropEnabled(true);
    928 
    929   if (switches::IsTouchEditingEnabled())
    930     webview()->settings()->setTouchEditingEnabled(true);
    931 
    932   if (!params->frame_name.empty())
    933     webview()->mainFrame()->setName(params->frame_name);
    934 
    935   OnSetRendererPrefs(params->renderer_prefs);
    936 
    937 #if defined(ENABLE_WEBRTC)
    938   if (!media_stream_dispatcher_)
    939     media_stream_dispatcher_ = new MediaStreamDispatcher(this);
    940 #endif
    941 
    942   new MHTMLGenerator(this);
    943 #if defined(OS_MACOSX)
    944   new TextInputClientObserver(this);
    945 #endif  // defined(OS_MACOSX)
    946 
    947 #if defined(OS_ANDROID)
    948   media_player_manager_.reset(new RendererMediaPlayerManager());
    949 #endif
    950 
    951   // The next group of objects all implement RenderViewObserver, so are deleted
    952   // along with the RenderView automatically.
    953   devtools_agent_ = new DevToolsAgent(this);
    954   if (RenderWidgetCompositor* rwc = compositor()) {
    955     webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId());
    956   }
    957   mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this);
    958   new ImageLoadingHelper(this);
    959 
    960   // Create renderer_accessibility_ if needed.
    961   OnSetAccessibilityMode(params->accessibility_mode);
    962 
    963   new IdleUserDetector(this);
    964 
    965   if (command_line.HasSwitch(switches::kDomAutomationController))
    966     enabled_bindings_ |= BINDINGS_POLICY_DOM_AUTOMATION;
    967   if (command_line.HasSwitch(switches::kStatsCollectionController))
    968     enabled_bindings_ |= BINDINGS_POLICY_STATS_COLLECTION;
    969 
    970   ProcessViewLayoutFlags(command_line);
    971 
    972 #if defined(ENABLE_PLUGINS)
    973   new PepperBrowserConnection(this);
    974 #endif
    975 
    976   GetContentClient()->renderer()->RenderViewCreated(this);
    977 
    978   // If we have an opener_id but we weren't created by a renderer, then
    979   // it's the browser asking us to set our opener to another RenderView.
    980   if (params->opener_id != MSG_ROUTING_NONE && !params->is_renderer_created) {
    981     RenderViewImpl* opener_view = FromRoutingID(params->opener_id);
    982     if (opener_view)
    983       webview()->mainFrame()->setOpener(opener_view->webview()->mainFrame());
    984   }
    985 
    986   // If we are initially swapped out, navigate to kSwappedOutURL.
    987   // This ensures we are in a unique origin that others cannot script.
    988   if (is_swapped_out_)
    989     NavigateToSwappedOutURL(webview()->mainFrame());
    990 }
    991 
    992 RenderViewImpl::~RenderViewImpl() {
    993   history_page_ids_.clear();
    994 
    995   if (decrement_shared_popup_at_destruction_)
    996     shared_popup_counter_->data--;
    997 
    998   base::debug::TraceLog::GetInstance()->RemoveProcessLabel(routing_id_);
    999 
   1000   // If file chooser is still waiting for answer, dispatch empty answer.
   1001   while (!file_chooser_completions_.empty()) {
   1002     if (file_chooser_completions_.front()->completion) {
   1003       file_chooser_completions_.front()->completion->didChooseFile(
   1004           WebVector<WebString>());
   1005     }
   1006     file_chooser_completions_.pop_front();
   1007   }
   1008 
   1009 #if defined(OS_ANDROID)
   1010   // The date/time picker client is both a scoped_ptr member of this class and
   1011   // a RenderViewObserver. Reset it to prevent double deletion.
   1012   date_time_picker_client_.reset();
   1013 #endif
   1014 
   1015 #ifndef NDEBUG
   1016   // Make sure we are no longer referenced by the ViewMap or RoutingIDViewMap.
   1017   ViewMap* views = g_view_map.Pointer();
   1018   for (ViewMap::iterator it = views->begin(); it != views->end(); ++it)
   1019     DCHECK_NE(this, it->second) << "Failed to call Close?";
   1020   RoutingIDViewMap* routing_id_views = g_routing_id_view_map.Pointer();
   1021   for (RoutingIDViewMap::iterator it = routing_id_views->begin();
   1022        it != routing_id_views->end(); ++it)
   1023     DCHECK_NE(this, it->second) << "Failed to call Close?";
   1024 #endif
   1025 
   1026   FOR_EACH_OBSERVER(RenderViewObserver, observers_, RenderViewGone());
   1027   FOR_EACH_OBSERVER(RenderViewObserver, observers_, OnDestruct());
   1028 }
   1029 
   1030 /*static*/
   1031 RenderViewImpl* RenderViewImpl::FromWebView(WebView* webview) {
   1032   ViewMap* views = g_view_map.Pointer();
   1033   ViewMap::iterator it = views->find(webview);
   1034   return it == views->end() ? NULL : it->second;
   1035 }
   1036 
   1037 /*static*/
   1038 RenderView* RenderView::FromWebView(WebKit::WebView* webview) {
   1039   return RenderViewImpl::FromWebView(webview);
   1040 }
   1041 
   1042 /*static*/
   1043 RenderViewImpl* RenderViewImpl::FromRoutingID(int32 routing_id) {
   1044   RoutingIDViewMap* views = g_routing_id_view_map.Pointer();
   1045   RoutingIDViewMap::iterator it = views->find(routing_id);
   1046   return it == views->end() ? NULL : it->second;
   1047 }
   1048 
   1049 /*static*/
   1050 RenderView* RenderView::FromRoutingID(int routing_id) {
   1051   return RenderViewImpl::FromRoutingID(routing_id);
   1052 }
   1053 
   1054 /*static*/
   1055 void RenderView::ForEach(RenderViewVisitor* visitor) {
   1056   ViewMap* views = g_view_map.Pointer();
   1057   for (ViewMap::iterator it = views->begin(); it != views->end(); ++it) {
   1058     if (!visitor->Visit(it->second))
   1059       return;
   1060   }
   1061 }
   1062 
   1063 /*static*/
   1064 RenderViewImpl* RenderViewImpl::Create(
   1065     int32 opener_id,
   1066     const RendererPreferences& renderer_prefs,
   1067     const WebPreferences& webkit_prefs,
   1068     SharedRenderViewCounter* counter,
   1069     int32 routing_id,
   1070     int32 main_frame_routing_id,
   1071     int32 surface_id,
   1072     int64 session_storage_namespace_id,
   1073     const string16& frame_name,
   1074     bool is_renderer_created,
   1075     bool swapped_out,
   1076     int32 next_page_id,
   1077     const WebKit::WebScreenInfo& screen_info,
   1078     AccessibilityMode accessibility_mode,
   1079     bool allow_partial_swap) {
   1080   DCHECK(routing_id != MSG_ROUTING_NONE);
   1081   RenderViewImplParams params(
   1082       opener_id,
   1083       renderer_prefs,
   1084       webkit_prefs,
   1085       counter,
   1086       routing_id,
   1087       main_frame_routing_id,
   1088       surface_id,
   1089       session_storage_namespace_id,
   1090       frame_name,
   1091       is_renderer_created,
   1092       swapped_out,
   1093       next_page_id,
   1094       screen_info,
   1095       accessibility_mode,
   1096       allow_partial_swap);
   1097   RenderViewImpl* render_view = NULL;
   1098   if (g_create_render_view_impl)
   1099     render_view = g_create_render_view_impl(&params);
   1100   else
   1101     render_view = new RenderViewImpl(&params);
   1102   render_view->Initialize(&params);
   1103   return render_view;
   1104 }
   1105 
   1106 // static
   1107 void RenderViewImpl::InstallCreateHook(
   1108     RenderViewImpl* (*create_render_view_impl)(RenderViewImplParams*)) {
   1109   CHECK(!g_create_render_view_impl);
   1110   g_create_render_view_impl = create_render_view_impl;
   1111 }
   1112 
   1113 void RenderViewImpl::AddObserver(RenderViewObserver* observer) {
   1114   observers_.AddObserver(observer);
   1115 }
   1116 
   1117 void RenderViewImpl::RemoveObserver(RenderViewObserver* observer) {
   1118   observer->RenderViewGone();
   1119   observers_.RemoveObserver(observer);
   1120 }
   1121 
   1122 WebKit::WebView* RenderViewImpl::webview() const {
   1123   return static_cast<WebKit::WebView*>(webwidget());
   1124 }
   1125 
   1126 #if defined(ENABLE_PLUGINS)
   1127 void RenderViewImpl::PepperInstanceCreated(PepperPluginInstanceImpl* instance) {
   1128   active_pepper_instances_.insert(instance);
   1129 }
   1130 
   1131 void RenderViewImpl::PepperInstanceDeleted(PepperPluginInstanceImpl* instance) {
   1132   active_pepper_instances_.erase(instance);
   1133 
   1134   if (pepper_last_mouse_event_target_ == instance)
   1135     pepper_last_mouse_event_target_ = NULL;
   1136   if (focused_pepper_plugin_ == instance)
   1137     PepperFocusChanged(instance, false);
   1138 }
   1139 
   1140 void RenderViewImpl::PepperDidChangeCursor(
   1141     PepperPluginInstanceImpl* instance,
   1142     const WebKit::WebCursorInfo& cursor) {
   1143   // Update the cursor appearance immediately if the requesting plugin is the
   1144   // one which receives the last mouse event. Otherwise, the new cursor won't be
   1145   // picked up until the plugin gets the next input event. That is bad if, e.g.,
   1146   // the plugin would like to set an invisible cursor when there isn't any user
   1147   // input for a while.
   1148   if (instance == pepper_last_mouse_event_target_)
   1149     didChangeCursor(cursor);
   1150 }
   1151 
   1152 void RenderViewImpl::PepperDidReceiveMouseEvent(
   1153     PepperPluginInstanceImpl* instance) {
   1154   pepper_last_mouse_event_target_ = instance;
   1155 }
   1156 
   1157 void RenderViewImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance,
   1158                                         bool focused) {
   1159   if (focused)
   1160     focused_pepper_plugin_ = instance;
   1161   else if (focused_pepper_plugin_ == instance)
   1162     focused_pepper_plugin_ = NULL;
   1163 
   1164   UpdateTextInputType();
   1165   UpdateSelectionBounds();
   1166 }
   1167 
   1168 void RenderViewImpl::PepperTextInputTypeChanged(
   1169     PepperPluginInstanceImpl* instance) {
   1170   if (instance != focused_pepper_plugin_)
   1171     return;
   1172 
   1173   UpdateTextInputType();
   1174   if (renderer_accessibility_)
   1175     renderer_accessibility_->FocusedNodeChanged(WebNode());
   1176 }
   1177 
   1178 void RenderViewImpl::PepperCaretPositionChanged(
   1179     PepperPluginInstanceImpl* instance) {
   1180   if (instance != focused_pepper_plugin_)
   1181     return;
   1182   UpdateSelectionBounds();
   1183 }
   1184 
   1185 void RenderViewImpl::PepperCancelComposition(
   1186     PepperPluginInstanceImpl* instance) {
   1187   if (instance != focused_pepper_plugin_)
   1188     return;
   1189   Send(new ViewHostMsg_ImeCancelComposition(routing_id()));;
   1190 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
   1191   UpdateCompositionInfo(true);
   1192 #endif
   1193 }
   1194 
   1195 void RenderViewImpl::PepperSelectionChanged(
   1196     PepperPluginInstanceImpl* instance) {
   1197   if (instance != focused_pepper_plugin_)
   1198     return;
   1199   SyncSelectionIfRequired();
   1200 }
   1201 
   1202 RenderWidgetFullscreenPepper* RenderViewImpl::CreatePepperFullscreenContainer(
   1203     PepperPluginInstanceImpl* plugin) {
   1204   GURL active_url;
   1205   if (webview() && webview()->mainFrame())
   1206     active_url = GURL(webview()->mainFrame()->document().url());
   1207   RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create(
   1208       routing_id_, plugin, active_url, screen_info_);
   1209   widget->show(WebKit::WebNavigationPolicyIgnore);
   1210   return widget;
   1211 }
   1212 
   1213 void RenderViewImpl::PepperPluginCreated(RendererPpapiHost* host) {
   1214   FOR_EACH_OBSERVER(RenderViewObserver, observers_,
   1215                     DidCreatePepperPlugin(host));
   1216 }
   1217 
   1218 bool RenderViewImpl::GetPepperCaretBounds(gfx::Rect* rect) {
   1219   if (!focused_pepper_plugin_)
   1220     return false;
   1221   *rect = focused_pepper_plugin_->GetCaretBounds();
   1222   return true;
   1223 }
   1224 
   1225 bool RenderViewImpl::IsPepperAcceptingCompositionEvents() const {
   1226   if (!focused_pepper_plugin_)
   1227     return false;
   1228   return focused_pepper_plugin_->IsPluginAcceptingCompositionEvents();
   1229 }
   1230 
   1231 void RenderViewImpl::PluginCrashed(const base::FilePath& plugin_path,
   1232                                    base::ProcessId plugin_pid) {
   1233   Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path, plugin_pid));
   1234 }
   1235 
   1236 void RenderViewImpl::RegisterPluginDelegate(WebPluginDelegateProxy* delegate) {
   1237   plugin_delegates_.insert(delegate);
   1238   // If the renderer is visible, set initial visibility and focus state.
   1239   if (!is_hidden()) {
   1240 #if defined(OS_MACOSX)
   1241     delegate->SetContainerVisibility(true);
   1242     if (webview() && webview()->isActive())
   1243       delegate->SetWindowFocus(true);
   1244 #endif
   1245   }
   1246   // Plugins start assuming the content has focus (so that they work in
   1247   // environments where RenderView isn't hosting them), so we always have to
   1248   // set the initial state. See webplugin_delegate_impl.h for details.
   1249   delegate->SetContentAreaFocus(has_focus());
   1250 }
   1251 
   1252 void RenderViewImpl::UnregisterPluginDelegate(
   1253     WebPluginDelegateProxy* delegate) {
   1254   plugin_delegates_.erase(delegate);
   1255 }
   1256 
   1257 bool RenderViewImpl::GetPluginInfo(const GURL& url,
   1258                                    const GURL& page_url,
   1259                                    const std::string& mime_type,
   1260                                    WebPluginInfo* plugin_info,
   1261                                    std::string* actual_mime_type) {
   1262   bool found = false;
   1263   Send(new ViewHostMsg_GetPluginInfo(
   1264       routing_id_, url, page_url, mime_type, &found, plugin_info,
   1265       actual_mime_type));
   1266   return found;
   1267 }
   1268 
   1269 void RenderViewImpl::SimulateImeSetComposition(
   1270     const string16& text,
   1271     const std::vector<WebKit::WebCompositionUnderline>& underlines,
   1272     int selection_start,
   1273     int selection_end) {
   1274   OnImeSetComposition(text, underlines, selection_start, selection_end);
   1275 }
   1276 
   1277 void RenderViewImpl::SimulateImeConfirmComposition(
   1278     const string16& text,
   1279     const ui::Range& replacement_range) {
   1280   OnImeConfirmComposition(text, replacement_range, false);
   1281 }
   1282 
   1283 #if defined(OS_WIN)
   1284 void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
   1285   if (focused)
   1286     focused_plugin_id_ = plugin_id;
   1287   else
   1288     focused_plugin_id_ = -1;
   1289 }
   1290 #endif
   1291 
   1292 #if defined(OS_MACOSX)
   1293 void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
   1294   Send(new ViewHostMsg_PluginFocusChanged(routing_id(), focused, plugin_id));
   1295 }
   1296 
   1297 void RenderViewImpl::StartPluginIme() {
   1298   IPC::Message* msg = new ViewHostMsg_StartPluginIme(routing_id());
   1299   // This message can be sent during event-handling, and needs to be delivered
   1300   // within that context.
   1301   msg->set_unblock(true);
   1302   Send(msg);
   1303 }
   1304 #endif  // defined(OS_MACOSX)
   1305 
   1306 #endif  // ENABLE_PLUGINS
   1307 
   1308 void RenderViewImpl::TransferActiveWheelFlingAnimation(
   1309     const WebKit::WebActiveWheelFlingParameters& params) {
   1310   if (webview())
   1311     webview()->transferActiveWheelFlingAnimation(params);
   1312 }
   1313 
   1314 bool RenderViewImpl::HasIMETextFocus() {
   1315   return GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
   1316 }
   1317 
   1318 bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
   1319   WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL;
   1320   if (main_frame)
   1321     GetContentClient()->SetActiveURL(main_frame->document().url());
   1322 
   1323   ObserverListBase<RenderViewObserver>::Iterator it(observers_);
   1324   RenderViewObserver* observer;
   1325   while ((observer = it.GetNext()) != NULL)
   1326     if (observer->OnMessageReceived(message))
   1327       return true;
   1328 
   1329   bool handled = true;
   1330   bool msg_is_ok = true;
   1331   IPC_BEGIN_MESSAGE_MAP_EX(RenderViewImpl, message, msg_is_ok)
   1332     IPC_MESSAGE_HANDLER(InputMsg_Copy, OnCopy)
   1333     IPC_MESSAGE_HANDLER(InputMsg_Cut, OnCut)
   1334     IPC_MESSAGE_HANDLER(InputMsg_Delete, OnDelete)
   1335     IPC_MESSAGE_HANDLER(InputMsg_ExecuteEditCommand, OnExecuteEditCommand)
   1336     IPC_MESSAGE_HANDLER(InputMsg_MoveCaret, OnMoveCaret)
   1337     IPC_MESSAGE_HANDLER(InputMsg_Paste, OnPaste)
   1338     IPC_MESSAGE_HANDLER(InputMsg_PasteAndMatchStyle, OnPasteAndMatchStyle)
   1339     IPC_MESSAGE_HANDLER(InputMsg_Redo, OnRedo)
   1340     IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
   1341     IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
   1342     IPC_MESSAGE_HANDLER(InputMsg_ScrollFocusedEditableNodeIntoRect,
   1343                         OnScrollFocusedEditableNodeIntoRect)
   1344     IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
   1345     IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
   1346     IPC_MESSAGE_HANDLER(InputMsg_SetEditCommandsForNextKeyEvent,
   1347                         OnSetEditCommandsForNextKeyEvent)
   1348     IPC_MESSAGE_HANDLER(InputMsg_Undo, OnUndo)
   1349     IPC_MESSAGE_HANDLER(InputMsg_Unselect, OnUnselect)
   1350     IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
   1351     IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
   1352     IPC_MESSAGE_HANDLER(ViewMsg_ReloadFrame, OnReloadFrame)
   1353     IPC_MESSAGE_HANDLER(ViewMsg_SetName, OnSetName)
   1354     IPC_MESSAGE_HANDLER(ViewMsg_SetEditableSelectionOffsets,
   1355                         OnSetEditableSelectionOffsets)
   1356     IPC_MESSAGE_HANDLER(ViewMsg_SetCompositionFromExistingText,
   1357                         OnSetCompositionFromExistingText)
   1358     IPC_MESSAGE_HANDLER(ViewMsg_ExtendSelectionAndDelete,
   1359                         OnExtendSelectionAndDelete)
   1360     IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
   1361     IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
   1362     IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
   1363     IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
   1364     IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevel, OnSetZoomLevel)
   1365     IPC_MESSAGE_HANDLER(ViewMsg_ZoomFactor, OnZoomFactor)
   1366     IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL,
   1367                         OnSetZoomLevelForLoadingURL)
   1368     IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
   1369     IPC_MESSAGE_HANDLER(ViewMsg_ResetPageEncodingToDefault,
   1370                         OnResetPageEncodingToDefault)
   1371     IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
   1372     IPC_MESSAGE_HANDLER(ViewMsg_PostMessageEvent, OnPostMessageEvent)
   1373     IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest)
   1374     IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter)
   1375     IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver)
   1376     IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave)
   1377     IPC_MESSAGE_HANDLER(DragMsg_TargetDrop, OnDragTargetDrop)
   1378     IPC_MESSAGE_HANDLER(DragMsg_SourceEndedOrMoved, OnDragSourceEndedOrMoved)
   1379     IPC_MESSAGE_HANDLER(DragMsg_SourceSystemDragEnded,
   1380                         OnDragSourceSystemDragEnded)
   1381     IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
   1382     IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
   1383     IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
   1384     IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
   1385     IPC_MESSAGE_HANDLER(ViewMsg_TimezoneChange, OnUpdateTimezone)
   1386     IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)
   1387     IPC_MESSAGE_HANDLER(ViewMsg_EnumerateDirectoryResponse,
   1388                         OnEnumerateDirectoryResponse)
   1389     IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
   1390     IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnShouldClose)
   1391     IPC_MESSAGE_HANDLER(ViewMsg_SwapOut, OnSwapOut)
   1392     IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
   1393     IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
   1394     IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
   1395                         OnDisassociateFromPopupCount)
   1396     IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
   1397     IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode)
   1398     IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground)
   1399     IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode,
   1400                         OnEnablePreferredSizeChangedMode)
   1401     IPC_MESSAGE_HANDLER(ViewMsg_EnableAutoResize, OnEnableAutoResize)
   1402     IPC_MESSAGE_HANDLER(ViewMsg_DisableAutoResize, OnDisableAutoResize)
   1403     IPC_MESSAGE_HANDLER(ViewMsg_DisableScrollbarsForSmallWindows,
   1404                         OnDisableScrollbarsForSmallWindows)
   1405     IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs)
   1406     IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt, OnMediaPlayerActionAt)
   1407     IPC_MESSAGE_HANDLER(ViewMsg_OrientationChangeEvent,
   1408                         OnOrientationChangeEvent)
   1409     IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt)
   1410     IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive)
   1411     IPC_MESSAGE_HANDLER(ViewMsg_CustomContextMenuAction,
   1412                         OnCustomContextMenuAction)
   1413     IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
   1414                         OnGetAllSavableResourceLinksForCurrentPage)
   1415     IPC_MESSAGE_HANDLER(
   1416         ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
   1417         OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
   1418     IPC_MESSAGE_HANDLER(ViewMsg_ContextMenuClosed, OnContextMenuClosed)
   1419     IPC_MESSAGE_HANDLER(ViewMsg_ShowContextMenu, OnShowContextMenu)
   1420     // TODO(viettrungluu): Move to a separate message filter.
   1421     IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndPrune,
   1422                         OnSetHistoryLengthAndPrune)
   1423     IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
   1424 #if defined(OS_ANDROID)
   1425     IPC_MESSAGE_HANDLER(JavaBridgeMsg_Init, OnJavaBridgeInit)
   1426 #endif
   1427     IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode, OnSetAccessibilityMode)
   1428     IPC_MESSAGE_HANDLER(ViewMsg_DisownOpener, OnDisownOpener)
   1429 #if defined(OS_ANDROID)
   1430     IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult,
   1431                         OnActivateNearestFindResult)
   1432     IPC_MESSAGE_HANDLER(ViewMsg_FindMatchRects, OnFindMatchRects)
   1433     IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
   1434     IPC_MESSAGE_HANDLER(ViewMsg_UndoScrollFocusedEditableNodeIntoView,
   1435                         OnUndoScrollFocusedEditableNodeIntoRect)
   1436     IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState,
   1437                         OnUpdateTopControlsState)
   1438     IPC_MESSAGE_HANDLER(ViewMsg_PauseVideo, OnPauseVideo)
   1439 #elif defined(OS_MACOSX)
   1440     IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
   1441     IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted,
   1442                         OnPluginImeCompositionCompleted)
   1443     IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
   1444     IPC_MESSAGE_HANDLER(ViewMsg_SetInLiveResize, OnSetInLiveResize)
   1445     IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility)
   1446     IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged)
   1447 #endif
   1448     IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupDIB,
   1449                         OnReleaseDisambiguationPopupDIB)
   1450     IPC_MESSAGE_HANDLER(ViewMsg_WindowSnapshotCompleted,
   1451                         OnWindowSnapshotCompleted)
   1452 
   1453     // Have the super handle all other messages.
   1454     IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message))
   1455   IPC_END_MESSAGE_MAP()
   1456 
   1457   if (!msg_is_ok) {
   1458     // The message had a handler, but its deserialization failed.
   1459     // Kill the renderer to avoid potential spoofing attacks.
   1460     CHECK(false) << "Unable to deserialize message in RenderViewImpl.";
   1461   }
   1462 
   1463   return handled;
   1464 }
   1465 
   1466 void RenderViewImpl::OnNavigate(const ViewMsg_Navigate_Params& params) {
   1467   MaybeHandleDebugURL(params.url);
   1468   if (!webview())
   1469     return;
   1470 
   1471   FOR_EACH_OBSERVER(RenderViewObserver, observers_, Navigate(params.url));
   1472 
   1473   bool is_reload = IsReload(params);
   1474 
   1475   // If this is a stale back/forward (due to a recent navigation the browser
   1476   // didn't know about), ignore it.
   1477   if (IsBackForwardToStaleEntry(params, is_reload))
   1478     return;
   1479 
   1480   // Swap this renderer back in if necessary.
   1481   if (is_swapped_out_) {
   1482     // We marked the view as hidden when swapping the view out, so be sure to
   1483     // reset the visibility state before navigating to the new URL.
   1484     webview()->setVisibilityState(visibilityState(), false);
   1485 
   1486     // If this is an attempt to reload while we are swapped out, we should not
   1487     // reload swappedout://, but the previous page, which is stored in
   1488     // params.state.  Setting is_reload to false will treat this like a back
   1489     // navigation to accomplish that.
   1490     is_reload = false;
   1491 
   1492     // We refresh timezone when a view is swapped in since timezone
   1493     // can get out of sync when the system timezone is updated while
   1494     // the view is swapped out.
   1495     NotifyTimezoneChange(webview()->mainFrame());
   1496 
   1497     SetSwappedOut(false);
   1498   }
   1499 
   1500   if (params.should_clear_history_list) {
   1501     CHECK_EQ(params.pending_history_list_offset, -1);
   1502     CHECK_EQ(params.current_history_list_offset, -1);
   1503     CHECK_EQ(params.current_history_list_length, 0);
   1504   }
   1505   history_list_offset_ = params.current_history_list_offset;
   1506   history_list_length_ = params.current_history_list_length;
   1507   if (history_list_length_ >= 0)
   1508     history_page_ids_.resize(history_list_length_, -1);
   1509   if (params.pending_history_list_offset >= 0 &&
   1510       params.pending_history_list_offset < history_list_length_)
   1511     history_page_ids_[params.pending_history_list_offset] = params.page_id;
   1512 
   1513   GetContentClient()->SetActiveURL(params.url);
   1514 
   1515   WebFrame* frame = webview()->mainFrame();
   1516   if (!params.frame_to_navigate.empty()) {
   1517     frame = webview()->findFrameByName(
   1518         WebString::fromUTF8(params.frame_to_navigate));
   1519     CHECK(frame) << "Invalid frame name passed: " << params.frame_to_navigate;
   1520   }
   1521 
   1522   if (is_reload && frame->currentHistoryItem().isNull()) {
   1523     // We cannot reload if we do not have any history state.  This happens, for
   1524     // example, when recovering from a crash.  Our workaround here is a bit of
   1525     // a hack since it means that reload after a crashed tab does not cause an
   1526     // end-to-end cache validation.
   1527     is_reload = false;
   1528   }
   1529 
   1530   pending_navigation_params_.reset(new ViewMsg_Navigate_Params(params));
   1531 
   1532   // If we are reloading, then WebKit will use the history state of the current
   1533   // page, so we should just ignore any given history state.  Otherwise, if we
   1534   // have history state, then we need to navigate to it, which corresponds to a
   1535   // back/forward navigation event.
   1536   if (is_reload) {
   1537     bool reload_original_url =
   1538         (params.navigation_type ==
   1539             ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
   1540     bool ignore_cache = (params.navigation_type ==
   1541                              ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE);
   1542 
   1543     if (reload_original_url)
   1544       frame->reloadWithOverrideURL(params.url, true);
   1545     else
   1546       frame->reload(ignore_cache);
   1547   } else if (params.page_state.IsValid()) {
   1548     // We must know the page ID of the page we are navigating back to.
   1549     DCHECK_NE(params.page_id, -1);
   1550     WebHistoryItem item = PageStateToHistoryItem(params.page_state);
   1551     if (!item.isNull()) {
   1552       // Ensure we didn't save the swapped out URL in UpdateState, since the
   1553       // browser should never be telling us to navigate to swappedout://.
   1554       CHECK(item.urlString() != WebString::fromUTF8(kSwappedOutURL));
   1555       frame->loadHistoryItem(item);
   1556     }
   1557   } else if (!params.base_url_for_data_url.is_empty()) {
   1558     // A loadData request with a specified base URL.
   1559     std::string mime_type, charset, data;
   1560     if (net::DataURL::Parse(params.url, &mime_type, &charset, &data)) {
   1561       frame->loadData(
   1562           WebData(data.c_str(), data.length()),
   1563           WebString::fromUTF8(mime_type),
   1564           WebString::fromUTF8(charset),
   1565           params.base_url_for_data_url,
   1566           params.history_url_for_data_url,
   1567           false);
   1568     } else {
   1569       CHECK(false) <<
   1570           "Invalid URL passed: " << params.url.possibly_invalid_spec();
   1571     }
   1572   } else {
   1573     // Navigate to the given URL.
   1574     WebURLRequest request(params.url);
   1575 
   1576     // A session history navigation should have been accompanied by state.
   1577     CHECK_EQ(params.page_id, -1);
   1578 
   1579     if (frame->isViewSourceModeEnabled())
   1580       request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
   1581 
   1582     if (params.referrer.url.is_valid()) {
   1583       WebString referrer = WebSecurityPolicy::generateReferrerHeader(
   1584           params.referrer.policy,
   1585           params.url,
   1586           WebString::fromUTF8(params.referrer.url.spec()));
   1587       if (!referrer.isEmpty())
   1588         request.setHTTPHeaderField(WebString::fromUTF8("Referer"), referrer);
   1589     }
   1590 
   1591     if (!params.extra_headers.empty()) {
   1592       for (net::HttpUtil::HeadersIterator i(params.extra_headers.begin(),
   1593                                             params.extra_headers.end(), "\n");
   1594            i.GetNext(); ) {
   1595         request.addHTTPHeaderField(WebString::fromUTF8(i.name()),
   1596                                    WebString::fromUTF8(i.values()));
   1597       }
   1598     }
   1599 
   1600     if (params.is_post) {
   1601       request.setHTTPMethod(WebString::fromUTF8("POST"));
   1602 
   1603       // Set post data.
   1604       WebHTTPBody http_body;
   1605       http_body.initialize();
   1606       http_body.appendData(WebData(
   1607           reinterpret_cast<const char*>(
   1608               &params.browser_initiated_post_data.front()),
   1609           params.browser_initiated_post_data.size()));
   1610       request.setHTTPBody(http_body);
   1611     }
   1612 
   1613     frame->loadRequest(request);
   1614 
   1615     // If this is a cross-process navigation, the browser process will send
   1616     // along the proper navigation start value.
   1617     if (!params.browser_navigation_start.is_null() &&
   1618         frame->provisionalDataSource()) {
   1619       // browser_navigation_start is likely before this process existed, so we
   1620       // can't use InterProcessTimeTicksConverter. Instead, the best we can do
   1621       // is just ensure we don't report a bogus value in the future.
   1622       base::TimeTicks navigation_start = std::min(
   1623           base::TimeTicks::Now(), params.browser_navigation_start);
   1624       double navigation_start_seconds =
   1625           (navigation_start - base::TimeTicks()).InSecondsF();
   1626       frame->provisionalDataSource()->setNavigationStartTime(
   1627           navigation_start_seconds);
   1628     }
   1629   }
   1630 
   1631   // In case LoadRequest failed before DidCreateDataSource was called.
   1632   pending_navigation_params_.reset();
   1633 }
   1634 
   1635 bool RenderViewImpl::IsBackForwardToStaleEntry(
   1636     const ViewMsg_Navigate_Params& params,
   1637     bool is_reload) {
   1638   // Make sure this isn't a back/forward to an entry we have already cropped
   1639   // or replaced from our history, before the browser knew about it.  If so,
   1640   // a new navigation has committed in the mean time, and we can ignore this.
   1641   bool is_back_forward = !is_reload && params.page_state.IsValid();
   1642 
   1643   // Note: if the history_list_length_ is 0 for a back/forward, we must be
   1644   // restoring from a previous session.  We'll update our state in OnNavigate.
   1645   if (!is_back_forward || history_list_length_ <= 0)
   1646     return false;
   1647 
   1648   DCHECK_EQ(static_cast<int>(history_page_ids_.size()), history_list_length_);
   1649 
   1650   // Check for whether the forward history has been cropped due to a recent
   1651   // navigation the browser didn't know about.
   1652   if (params.pending_history_list_offset >= history_list_length_)
   1653     return true;
   1654 
   1655   // Check for whether this entry has been replaced with a new one.
   1656   int expected_page_id =
   1657       history_page_ids_[params.pending_history_list_offset];
   1658   if (expected_page_id > 0 && params.page_id != expected_page_id) {
   1659     if (params.page_id < expected_page_id)
   1660       return true;
   1661 
   1662     // Otherwise we've removed an earlier entry and should have shifted all
   1663     // entries left.  For now, it's ok to lazily update the list.
   1664     // TODO(creis): Notify all live renderers when we remove entries from
   1665     // the front of the list, so that we don't hit this case.
   1666     history_page_ids_[params.pending_history_list_offset] = params.page_id;
   1667   }
   1668 
   1669   return false;
   1670 }
   1671 
   1672 // Stop loading the current page
   1673 void RenderViewImpl::OnStop() {
   1674   if (webview()) {
   1675     WebFrame* main_frame = webview()->mainFrame();
   1676     // Stop the alt error page fetcher. If we let it continue it may complete
   1677     // and cause RenderViewHostManager to swap to this RenderView, even though
   1678     // it may no longer be active.
   1679     StopAltErrorPageFetcher(main_frame->provisionalDataSource());
   1680     StopAltErrorPageFetcher(main_frame->dataSource());
   1681     main_frame->stopLoading();
   1682   }
   1683 }
   1684 
   1685 // Reload current focused frame.
   1686 // E.g. called by right-clicking on the frame and picking "reload this frame".
   1687 void RenderViewImpl::OnReloadFrame() {
   1688   if (webview() && webview()->focusedFrame()) {
   1689     // We always obey the cache (ignore_cache=false) here.
   1690     // TODO(evanm): perhaps we could allow shift-clicking the menu item to do
   1691     // a cache-ignoring reload of the frame.
   1692     webview()->focusedFrame()->reload(false);
   1693   }
   1694 }
   1695 
   1696 void RenderViewImpl::OnCopyImageAt(int x, int y) {
   1697   webview()->copyImageAt(WebPoint(x, y));
   1698 }
   1699 
   1700 void RenderViewImpl::OnUpdateTargetURLAck() {
   1701   // Check if there is a targeturl waiting to be sent.
   1702   if (target_url_status_ == TARGET_PENDING) {
   1703     Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
   1704                                          pending_target_url_));
   1705   }
   1706 
   1707   target_url_status_ = TARGET_NONE;
   1708 }
   1709 
   1710 void RenderViewImpl::OnCopy() {
   1711   if (!webview())
   1712     return;
   1713 
   1714   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1715   WebNode current_node = context_menu_node_.isNull() ?
   1716       GetFocusedNode() : context_menu_node_;
   1717   webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Copy"),
   1718                                             current_node);
   1719 }
   1720 
   1721 void RenderViewImpl::OnCut() {
   1722   if (!webview())
   1723     return;
   1724 
   1725   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1726   webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Cut"),
   1727                                             GetFocusedNode());
   1728 }
   1729 
   1730 void RenderViewImpl::OnDelete() {
   1731   if (!webview())
   1732     return;
   1733 
   1734   webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Delete"),
   1735                                             GetFocusedNode());
   1736 }
   1737 
   1738 void RenderViewImpl::OnExecuteEditCommand(const std::string& name,
   1739     const std::string& value) {
   1740   if (!webview() || !webview()->focusedFrame())
   1741     return;
   1742 
   1743   webview()->focusedFrame()->executeCommand(
   1744       WebString::fromUTF8(name), WebString::fromUTF8(value));
   1745 }
   1746 
   1747 void RenderViewImpl::OnMoveCaret(const gfx::Point& point) {
   1748   if (!webview())
   1749     return;
   1750 
   1751   Send(new ViewHostMsg_MoveCaret_ACK(routing_id_));
   1752 
   1753   webview()->focusedFrame()->moveCaretSelectionTowardsWindowPoint(point);
   1754 }
   1755 
   1756 void RenderViewImpl::OnPaste() {
   1757   if (!webview())
   1758     return;
   1759 
   1760   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1761   webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Paste"),
   1762                                             GetFocusedNode());
   1763 }
   1764 
   1765 void RenderViewImpl::OnPasteAndMatchStyle() {
   1766   if (!webview())
   1767     return;
   1768 
   1769   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1770   webview()->focusedFrame()->executeCommand(
   1771       WebString::fromUTF8("PasteAndMatchStyle"), GetFocusedNode());
   1772 }
   1773 
   1774 void RenderViewImpl::OnRedo() {
   1775   if (!webview())
   1776     return;
   1777 
   1778   webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Redo"),
   1779                                             GetFocusedNode());
   1780 }
   1781 
   1782 void RenderViewImpl::OnReplace(const string16& text) {
   1783   if (!webview())
   1784     return;
   1785 
   1786   WebFrame* frame = webview()->focusedFrame();
   1787   if (!frame->hasSelection())
   1788     frame->selectWordAroundCaret();
   1789 
   1790   frame->replaceSelection(text);
   1791 }
   1792 
   1793 void RenderViewImpl::OnReplaceMisspelling(const string16& text) {
   1794   if (!webview())
   1795     return;
   1796 
   1797   WebFrame* frame = webview()->focusedFrame();
   1798   if (!frame->hasSelection())
   1799     return;
   1800 
   1801   frame->replaceMisspelledRange(text);
   1802 }
   1803 
   1804 void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
   1805     const gfx::Rect& rect) {
   1806   WebKit::WebNode node = GetFocusedNode();
   1807   if (!node.isNull()) {
   1808     if (IsEditableNode(node)) {
   1809       webview()->saveScrollAndScaleState();
   1810       webview()->scrollFocusedNodeIntoRect(rect);
   1811     }
   1812   }
   1813 }
   1814 
   1815 void RenderViewImpl::OnSelectAll() {
   1816   if (!webview())
   1817     return;
   1818 
   1819   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1820   webview()->focusedFrame()->executeCommand(
   1821       WebString::fromUTF8("SelectAll"), GetFocusedNode());
   1822 }
   1823 
   1824 void RenderViewImpl::OnSelectRange(const gfx::Point& start,
   1825                                    const gfx::Point& end) {
   1826   if (!webview())
   1827     return;
   1828 
   1829   Send(new ViewHostMsg_SelectRange_ACK(routing_id_));
   1830 
   1831   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1832   webview()->focusedFrame()->selectRange(start, end);
   1833 }
   1834 
   1835 void RenderViewImpl::OnSetEditCommandsForNextKeyEvent(
   1836     const EditCommands& edit_commands) {
   1837   edit_commands_ = edit_commands;
   1838 }
   1839 
   1840 void RenderViewImpl::OnUndo() {
   1841   if (!webview())
   1842     return;
   1843 
   1844   webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Undo"),
   1845                                             GetFocusedNode());
   1846 }
   1847 
   1848 void RenderViewImpl::OnUnselect() {
   1849   if (!webview())
   1850     return;
   1851 
   1852   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1853   webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"),
   1854                                             GetFocusedNode());
   1855 }
   1856 
   1857 #if defined(OS_MACOSX)
   1858 void RenderViewImpl::OnCopyToFindPboard() {
   1859   if (!webview())
   1860     return;
   1861 
   1862   // Since the find pasteboard supports only plain text, this can be simpler
   1863   // than the |OnCopy()| case.
   1864   WebFrame* frame = webview()->focusedFrame();
   1865   if (frame->hasSelection()) {
   1866     string16 selection = frame->selectionAsText();
   1867     RenderThread::Get()->Send(
   1868         new ClipboardHostMsg_FindPboardWriteStringAsync(selection));
   1869   }
   1870 }
   1871 #endif
   1872 
   1873 void RenderViewImpl::OnSetName(const std::string& name) {
   1874   if (!webview())
   1875     return;
   1876 
   1877   webview()->mainFrame()->setName(WebString::fromUTF8(name));
   1878 }
   1879 
   1880 void RenderViewImpl::OnSetEditableSelectionOffsets(int start, int end) {
   1881   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   1882   if (!ShouldHandleImeEvent())
   1883     return;
   1884   ImeEventGuard guard(this);
   1885   webview()->setEditableSelectionOffsets(start, end);
   1886 }
   1887 
   1888 void RenderViewImpl::OnSetCompositionFromExistingText(
   1889     int start, int end,
   1890     const std::vector<WebKit::WebCompositionUnderline>& underlines) {
   1891   if (!ShouldHandleImeEvent())
   1892     return;
   1893   ImeEventGuard guard(this);
   1894   webview()->setCompositionFromExistingText(start, end, underlines);
   1895 }
   1896 
   1897 void RenderViewImpl::OnExtendSelectionAndDelete(int before, int after) {
   1898   if (!ShouldHandleImeEvent())
   1899     return;
   1900   ImeEventGuard guard(this);
   1901   webview()->extendSelectionAndDelete(before, after);
   1902 }
   1903 
   1904 void RenderViewImpl::OnSetHistoryLengthAndPrune(int history_length,
   1905                                                 int32 minimum_page_id) {
   1906   DCHECK_GE(history_length, 0);
   1907   DCHECK(history_list_offset_ == history_list_length_ - 1);
   1908   DCHECK_GE(minimum_page_id, -1);
   1909 
   1910   // Generate the new list.
   1911   std::vector<int32> new_history_page_ids(history_length, -1);
   1912   for (size_t i = 0; i < history_page_ids_.size(); ++i) {
   1913     if (minimum_page_id >= 0 && history_page_ids_[i] < minimum_page_id)
   1914       continue;
   1915     new_history_page_ids.push_back(history_page_ids_[i]);
   1916   }
   1917   new_history_page_ids.swap(history_page_ids_);
   1918 
   1919   // Update indexes.
   1920   history_list_length_ = history_page_ids_.size();
   1921   history_list_offset_ = history_list_length_ - 1;
   1922 }
   1923 
   1924 
   1925 void RenderViewImpl::OnSetInitialFocus(bool reverse) {
   1926   if (!webview())
   1927     return;
   1928   webview()->setInitialFocus(reverse);
   1929 }
   1930 
   1931 #if defined(OS_MACOSX)
   1932 void RenderViewImpl::OnSetInLiveResize(bool in_live_resize) {
   1933   if (!webview())
   1934     return;
   1935   if (in_live_resize)
   1936     webview()->willStartLiveResize();
   1937   else
   1938     webview()->willEndLiveResize();
   1939 }
   1940 #endif
   1941 
   1942 #if defined(OS_ANDROID)
   1943 void RenderViewImpl::OnUndoScrollFocusedEditableNodeIntoRect() {
   1944   const WebNode node = GetFocusedNode();
   1945   if (!node.isNull() && IsEditableNode(node))
   1946     webview()->restoreScrollAndScaleState();
   1947 }
   1948 
   1949 void RenderViewImpl::OnPauseVideo() {
   1950   // Inform RendererMediaPlayerManager to release all video player resources.
   1951   // If something is in progress the resource will not be freed, it will
   1952   // only be freed once the tab is destroyed or if the user navigates away
   1953   // via WebMediaPlayerAndroid::Destroy.
   1954   media_player_manager_->ReleaseVideoResources();
   1955 }
   1956 #endif
   1957 
   1958 ///////////////////////////////////////////////////////////////////////////////
   1959 
   1960 // Tell the embedding application that the URL of the active page has changed
   1961 void RenderViewImpl::UpdateURL(WebFrame* frame) {
   1962   WebDataSource* ds = frame->dataSource();
   1963   DCHECK(ds);
   1964 
   1965   const WebURLRequest& request = ds->request();
   1966   const WebURLRequest& original_request = ds->originalRequest();
   1967   const WebURLResponse& response = ds->response();
   1968 
   1969   DocumentState* document_state = DocumentState::FromDataSource(ds);
   1970   NavigationState* navigation_state = document_state->navigation_state();
   1971   InternalDocumentStateData* internal_data =
   1972       InternalDocumentStateData::FromDocumentState(document_state);
   1973 
   1974   ViewHostMsg_FrameNavigate_Params params;
   1975   params.http_status_code = response.httpStatusCode();
   1976   params.is_post = false;
   1977   params.post_id = -1;
   1978   params.page_id = page_id_;
   1979   params.frame_id = frame->identifier();
   1980   params.socket_address.set_host(response.remoteIPAddress().utf8());
   1981   params.socket_address.set_port(response.remotePort());
   1982   WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response);
   1983   if (extra_data) {
   1984     params.was_fetched_via_proxy = extra_data->was_fetched_via_proxy();
   1985   }
   1986   params.was_within_same_page = navigation_state->was_within_same_page();
   1987   params.security_info = response.securityInfo();
   1988 
   1989   // Set the URL to be displayed in the browser UI to the user.
   1990   params.url = GetLoadingUrl(frame);
   1991   DCHECK(!is_swapped_out_ || params.url == GURL(kSwappedOutURL));
   1992 
   1993   if (frame->document().baseURL() != params.url)
   1994     params.base_url = frame->document().baseURL();
   1995 
   1996   GetRedirectChain(ds, &params.redirects);
   1997   params.should_update_history = !ds->hasUnreachableURL() &&
   1998       !response.isMultipartPayload() && (response.httpStatusCode() != 404);
   1999 
   2000   params.searchable_form_url = internal_data->searchable_form_url();
   2001   params.searchable_form_encoding = internal_data->searchable_form_encoding();
   2002 
   2003   const PasswordForm* password_form_data = document_state->password_form_data();
   2004   if (password_form_data)
   2005     params.password_form = *password_form_data;
   2006 
   2007   params.gesture = navigation_gesture_;
   2008   navigation_gesture_ = NavigationGestureUnknown;
   2009 
   2010   // Make navigation state a part of the FrameNavigate message so that commited
   2011   // entry had it at all times.
   2012   WebHistoryItem item = frame->currentHistoryItem();
   2013   if (item.isNull()) {
   2014     item.initialize();
   2015     item.setURLString(request.url().spec().utf16());
   2016   }
   2017   params.page_state = HistoryItemToPageState(item);
   2018 
   2019   if (!frame->parent()) {
   2020     // Top-level navigation.
   2021 
   2022     // Reset the zoom limits in case a plugin had changed them previously. This
   2023     // will also call us back which will cause us to send a message to
   2024     // update WebContentsImpl.
   2025     webview()->zoomLimitsChanged(ZoomFactorToZoomLevel(kMinimumZoomFactor),
   2026                                  ZoomFactorToZoomLevel(kMaximumZoomFactor));
   2027 
   2028     // Set zoom level, but don't do it for full-page plugin since they don't use
   2029     // the same zoom settings.
   2030     HostZoomLevels::iterator host_zoom =
   2031         host_zoom_levels_.find(GURL(request.url()));
   2032     if (webview()->mainFrame()->document().isPluginDocument()) {
   2033       // Reset the zoom levels for plugins.
   2034       webview()->setZoomLevel(false, 0);
   2035     } else {
   2036       if (host_zoom != host_zoom_levels_.end())
   2037         webview()->setZoomLevel(false, host_zoom->second);
   2038     }
   2039 
   2040     if (host_zoom != host_zoom_levels_.end()) {
   2041       // This zoom level was merely recorded transiently for this load.  We can
   2042       // erase it now.  If at some point we reload this page, the browser will
   2043       // send us a new, up-to-date zoom level.
   2044       host_zoom_levels_.erase(host_zoom);
   2045     }
   2046 
   2047     // Update contents MIME type for main frame.
   2048     params.contents_mime_type = ds->response().mimeType().utf8();
   2049 
   2050     params.transition = navigation_state->transition_type();
   2051     if (!PageTransitionIsMainFrame(params.transition)) {
   2052       // If the main frame does a load, it should not be reported as a subframe
   2053       // navigation.  This can occur in the following case:
   2054       // 1. You're on a site with frames.
   2055       // 2. You do a subframe navigation.  This is stored with transition type
   2056       //    MANUAL_SUBFRAME.
   2057       // 3. You navigate to some non-frame site, say, google.com.
   2058       // 4. You navigate back to the page from step 2.  Since it was initially
   2059       //    MANUAL_SUBFRAME, it will be that same transition type here.
   2060       // We don't want that, because any navigation that changes the toplevel
   2061       // frame should be tracked as a toplevel navigation (this allows us to
   2062       // update the URL bar, etc).
   2063       params.transition = PAGE_TRANSITION_LINK;
   2064     }
   2065 
   2066     // If the page contained a client redirect (meta refresh, document.loc...),
   2067     // set the referrer and transition appropriately.
   2068     if (ds->isClientRedirect()) {
   2069       params.referrer = Referrer(params.redirects[0],
   2070           GetReferrerPolicyFromRequest(frame, ds->request()));
   2071       params.transition = static_cast<PageTransition>(
   2072           params.transition | PAGE_TRANSITION_CLIENT_REDIRECT);
   2073     } else {
   2074       // Bug 654101: the referrer will be empty on https->http transitions. It
   2075       // would be nice if we could get the real referrer from somewhere.
   2076       params.referrer = GetReferrerFromRequest(frame, original_request);
   2077     }
   2078 
   2079     string16 method = request.httpMethod();
   2080     if (EqualsASCII(method, "POST")) {
   2081       params.is_post = true;
   2082       params.post_id = ExtractPostId(item);
   2083     }
   2084 
   2085     // Send the user agent override back.
   2086     params.is_overriding_user_agent = internal_data->is_overriding_user_agent();
   2087 
   2088     // Track the URL of the original request.
   2089     params.original_request_url = original_request.url();
   2090 
   2091     params.history_list_was_cleared =
   2092         navigation_state->history_list_was_cleared();
   2093 
   2094     // Save some histogram data so we can compute the average memory used per
   2095     // page load of the glyphs.
   2096     UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad",
   2097                                WebKit::WebGlyphCache::pageCount());
   2098 
   2099     // This message needs to be sent before any of allowScripts(),
   2100     // allowImages(), allowPlugins() is called for the new page, so that when
   2101     // these functions send a ViewHostMsg_ContentBlocked message, it arrives
   2102     // after the ViewHostMsg_FrameNavigate message.
   2103     Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
   2104   } else {
   2105     // Subframe navigation: the type depends on whether this navigation
   2106     // generated a new session history entry. When they do generate a session
   2107     // history entry, it means the user initiated the navigation and we should
   2108     // mark it as such. This test checks if this is the first time UpdateURL
   2109     // has been called since WillNavigateToURL was called to initiate the load.
   2110     if (page_id_ > last_page_id_sent_to_browser_)
   2111       params.transition = PAGE_TRANSITION_MANUAL_SUBFRAME;
   2112     else
   2113       params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
   2114 
   2115     DCHECK(!navigation_state->history_list_was_cleared());
   2116     params.history_list_was_cleared = false;
   2117 
   2118     Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
   2119   }
   2120 
   2121   last_page_id_sent_to_browser_ =
   2122       std::max(last_page_id_sent_to_browser_, page_id_);
   2123 
   2124   // If we end up reusing this WebRequest (for example, due to a #ref click),
   2125   // we don't want the transition type to persist.  Just clear it.
   2126   navigation_state->set_transition_type(PAGE_TRANSITION_LINK);
   2127 }
   2128 
   2129 // Tell the embedding application that the title of the active page has changed
   2130 void RenderViewImpl::UpdateTitle(WebFrame* frame,
   2131                                  const string16& title,
   2132                                  WebTextDirection title_direction) {
   2133   // Ignore all but top level navigations.
   2134   if (frame->parent())
   2135     return;
   2136 
   2137   base::debug::TraceLog::GetInstance()->UpdateProcessLabel(
   2138       routing_id_, UTF16ToUTF8(title));
   2139 
   2140   string16 shortened_title = title.substr(0, kMaxTitleChars);
   2141   Send(new ViewHostMsg_UpdateTitle(routing_id_, page_id_, shortened_title,
   2142                                    title_direction));
   2143 }
   2144 
   2145 void RenderViewImpl::UpdateEncoding(WebFrame* frame,
   2146                                     const std::string& encoding_name) {
   2147   // Only update main frame's encoding_name.
   2148   if (webview()->mainFrame() == frame &&
   2149       last_encoding_name_ != encoding_name) {
   2150     // Save the encoding name for later comparing.
   2151     last_encoding_name_ = encoding_name;
   2152 
   2153     Send(new ViewHostMsg_UpdateEncoding(routing_id_, last_encoding_name_));
   2154   }
   2155 }
   2156 
   2157 // Sends the last committed session history state to the browser so it will be
   2158 // saved before we navigate to a new page. This must be called *before* the
   2159 // page ID has been updated so we know what it was.
   2160 void RenderViewImpl::UpdateSessionHistory(WebFrame* frame) {
   2161   // If we have a valid page ID at this point, then it corresponds to the page
   2162   // we are navigating away from.  Otherwise, this is the first navigation, so
   2163   // there is no past session history to record.
   2164   if (page_id_ == -1)
   2165     return;
   2166 
   2167   const WebHistoryItem& item =
   2168       webview()->mainFrame()->previousHistoryItem();
   2169   SendUpdateState(item);
   2170 }
   2171 
   2172 void RenderViewImpl::SendUpdateState(const WebHistoryItem& item) {
   2173   if (item.isNull())
   2174     return;
   2175 
   2176   // Don't send state updates for kSwappedOutURL.
   2177   if (item.urlString() == WebString::fromUTF8(kSwappedOutURL))
   2178     return;
   2179 
   2180   Send(new ViewHostMsg_UpdateState(
   2181       routing_id_, page_id_, HistoryItemToPageState(item)));
   2182 }
   2183 
   2184 void RenderViewImpl::OpenURL(WebFrame* frame,
   2185                              const GURL& url,
   2186                              const Referrer& referrer,
   2187                              WebNavigationPolicy policy) {
   2188   ViewHostMsg_OpenURL_Params params;
   2189   params.url = url;
   2190   params.referrer = referrer;
   2191   params.disposition = NavigationPolicyToDisposition(policy);
   2192   params.frame_id = frame->identifier();
   2193   WebDataSource* ds = frame->provisionalDataSource();
   2194   if (ds) {
   2195     params.should_replace_current_entry = ds->replacesCurrentHistoryItem();
   2196   } else {
   2197     params.should_replace_current_entry = false;
   2198   }
   2199   params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
   2200   if (GetContentClient()->renderer()->AllowPopup())
   2201     params.user_gesture = true;
   2202 
   2203   if (policy == WebKit::WebNavigationPolicyNewBackgroundTab ||
   2204       policy == WebKit::WebNavigationPolicyNewForegroundTab ||
   2205       policy == WebKit::WebNavigationPolicyNewWindow ||
   2206       policy == WebKit::WebNavigationPolicyNewPopup) {
   2207     WebUserGestureIndicator::consumeUserGesture();
   2208   }
   2209 
   2210   Send(new ViewHostMsg_OpenURL(routing_id_, params));
   2211 }
   2212 
   2213 // WebViewDelegate ------------------------------------------------------------
   2214 
   2215 void RenderViewImpl::LoadNavigationErrorPage(
   2216     WebFrame* frame,
   2217     const WebURLRequest& failed_request,
   2218     const WebURLError& error,
   2219     const std::string& html,
   2220     bool replace) {
   2221   std::string alt_html;
   2222   const std::string* error_html;
   2223 
   2224   if (!html.empty()) {
   2225     error_html = &html;
   2226   } else {
   2227     GetContentClient()->renderer()->GetNavigationErrorStrings(
   2228         frame, failed_request, error, &alt_html, NULL);
   2229     error_html = &alt_html;
   2230   }
   2231 
   2232   frame->loadHTMLString(*error_html,
   2233                         GURL(kUnreachableWebDataURL),
   2234                         error.unreachableURL,
   2235                         replace);
   2236 }
   2237 
   2238 bool RenderViewImpl::RunJavaScriptMessage(JavaScriptMessageType type,
   2239                                           const string16& message,
   2240                                           const string16& default_value,
   2241                                           const GURL& frame_url,
   2242                                           string16* result) {
   2243   bool success = false;
   2244   string16 result_temp;
   2245   if (!result)
   2246     result = &result_temp;
   2247 
   2248   SendAndRunNestedMessageLoop(new ViewHostMsg_RunJavaScriptMessage(
   2249       routing_id_, message, default_value, frame_url, type, &success, result));
   2250   return success;
   2251 }
   2252 
   2253 bool RenderViewImpl::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
   2254   // Before WebKit asks us to show an alert (etc.), it takes care of doing the
   2255   // equivalent of WebView::willEnterModalLoop.  In the case of showModalDialog
   2256   // it is particularly important that we do not call willEnterModalLoop as
   2257   // that would defer resource loads for the dialog itself.
   2258   if (RenderThreadImpl::current())  // Will be NULL during unit tests.
   2259     RenderThreadImpl::current()->DoNotNotifyWebKitOfModalLoop();
   2260 
   2261   message->EnableMessagePumping();  // Runs a nested message loop.
   2262   return Send(message);
   2263 }
   2264 
   2265 void RenderViewImpl::GetWindowSnapshot(const WindowSnapshotCallback& callback) {
   2266   int id = next_snapshot_id_++;
   2267   pending_snapshots_.insert(std::make_pair(id, callback));
   2268   Send(new ViewHostMsg_GetWindowSnapshot(routing_id_, id));
   2269 }
   2270 
   2271 void RenderViewImpl::OnWindowSnapshotCompleted(const int snapshot_id,
   2272     const gfx::Size& size, const std::vector<unsigned char>& png) {
   2273   PendingSnapshotMap::iterator it = pending_snapshots_.find(snapshot_id);
   2274   DCHECK(it != pending_snapshots_.end());
   2275   it->second.Run(size, png);
   2276   pending_snapshots_.erase(it);
   2277 }
   2278 
   2279 // WebKit::WebViewClient ------------------------------------------------------
   2280 
   2281 WebView* RenderViewImpl::createView(
   2282     WebFrame* creator,
   2283     const WebURLRequest& request,
   2284     const WebWindowFeatures& features,
   2285     const WebString& frame_name,
   2286     WebNavigationPolicy policy) {
   2287   // Check to make sure we aren't overloading on popups.
   2288   if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
   2289     return NULL;
   2290 
   2291   ViewHostMsg_CreateWindow_Params params;
   2292   params.opener_id = routing_id_;
   2293   params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
   2294   if (GetContentClient()->renderer()->AllowPopup())
   2295     params.user_gesture = true;
   2296   params.window_container_type = WindowFeaturesToContainerType(features);
   2297   params.session_storage_namespace_id = session_storage_namespace_id_;
   2298   if (frame_name != "_blank")
   2299     params.frame_name = frame_name;
   2300   params.opener_frame_id = creator->identifier();
   2301   params.opener_url = creator->document().url();
   2302   params.opener_top_level_frame_url = creator->top()->document().url();
   2303   GURL security_url(creator->document().securityOrigin().toString().utf8());
   2304   if (!security_url.is_valid())
   2305     security_url = GURL();
   2306   params.opener_security_origin = security_url;
   2307   params.opener_suppressed = creator->willSuppressOpenerInNewFrame();
   2308   params.disposition = NavigationPolicyToDisposition(policy);
   2309   if (!request.isNull()) {
   2310     params.target_url = request.url();
   2311     params.referrer = GetReferrerFromRequest(creator, request);
   2312   }
   2313   params.features = features;
   2314 
   2315   int32 routing_id = MSG_ROUTING_NONE;
   2316   int32 main_frame_routing_id = MSG_ROUTING_NONE;
   2317   int32 surface_id = 0;
   2318   int64 cloned_session_storage_namespace_id;
   2319 
   2320   RenderThread::Get()->Send(
   2321       new ViewHostMsg_CreateWindow(params,
   2322                                    &routing_id,
   2323                                    &main_frame_routing_id,
   2324                                    &surface_id,
   2325                                    &cloned_session_storage_namespace_id));
   2326   if (routing_id == MSG_ROUTING_NONE)
   2327     return NULL;
   2328 
   2329   WebUserGestureIndicator::consumeUserGesture();
   2330 
   2331   WebPreferences transferred_preferences = webkit_preferences_;
   2332 
   2333   // Unless accelerated compositing has been explicitly disabled from the
   2334   // command line (e.g. via the blacklist or about:flags) re-enable it for
   2335   // new views that get spawned by this view. This gets around the issue that
   2336   // background extension pages disable accelerated compositing via web prefs
   2337   // but can themselves spawn a visible render view which should be allowed
   2338   // use gpu acceleration.
   2339   if (!webkit_preferences_.accelerated_compositing_enabled) {
   2340     const CommandLine& command_line = *CommandLine::ForCurrentProcess();
   2341     if (!command_line.HasSwitch(switches::kDisableAcceleratedCompositing))
   2342       transferred_preferences.accelerated_compositing_enabled = true;
   2343   }
   2344 
   2345   RenderViewImpl* view = RenderViewImpl::Create(
   2346       routing_id_,
   2347       renderer_preferences_,
   2348       transferred_preferences,
   2349       shared_popup_counter_.get(),
   2350       routing_id,
   2351       main_frame_routing_id,
   2352       surface_id,
   2353       cloned_session_storage_namespace_id,
   2354       string16(),  // WebCore will take care of setting the correct name.
   2355       true,
   2356       false,
   2357       1,
   2358       screen_info_,
   2359       accessibility_mode_,
   2360       allow_partial_swap_);
   2361   view->opened_by_user_gesture_ = params.user_gesture;
   2362 
   2363   // Record whether the creator frame is trying to suppress the opener field.
   2364   view->opener_suppressed_ = params.opener_suppressed;
   2365 
   2366   // Copy over the alternate error page URL so we can have alt error pages in
   2367   // the new render view (we don't need the browser to send the URL back down).
   2368   view->alternate_error_page_url_ = alternate_error_page_url_;
   2369 
   2370   return view->webview();
   2371 }
   2372 
   2373 WebWidget* RenderViewImpl::createPopupMenu(WebKit::WebPopupType popup_type) {
   2374   RenderWidget* widget =
   2375       RenderWidget::Create(routing_id_, popup_type, screen_info_);
   2376   return widget->webwidget();
   2377 }
   2378 
   2379 WebExternalPopupMenu* RenderViewImpl::createExternalPopupMenu(
   2380     const WebPopupMenuInfo& popup_menu_info,
   2381     WebExternalPopupMenuClient* popup_menu_client) {
   2382   // An IPC message is sent to the browser to build and display the actual
   2383   // popup.  The user could have time to click a different select by the time
   2384   // the popup is shown.  In that case external_popup_menu_ is non NULL.
   2385   // By returning NULL in that case, we instruct WebKit to cancel that new
   2386   // popup.  So from the user perspective, only the first one will show, and
   2387   // will have to close the first one before another one can be shown.
   2388   if (external_popup_menu_)
   2389     return NULL;
   2390   external_popup_menu_.reset(
   2391       new ExternalPopupMenu(this, popup_menu_info, popup_menu_client));
   2392   return external_popup_menu_.get();
   2393 }
   2394 
   2395 WebStorageNamespace* RenderViewImpl::createSessionStorageNamespace() {
   2396   CHECK(session_storage_namespace_id_ != kInvalidSessionStorageNamespaceId);
   2397   return new WebStorageNamespaceImpl(session_storage_namespace_id_);
   2398 }
   2399 
   2400 void RenderViewImpl::didAddMessageToConsole(
   2401     const WebConsoleMessage& message, const WebString& source_name,
   2402     unsigned source_line) {
   2403   logging::LogSeverity log_severity = logging::LOG_VERBOSE;
   2404   switch (message.level) {
   2405     case WebConsoleMessage::LevelDebug:
   2406       log_severity = logging::LOG_VERBOSE;
   2407       break;
   2408     case WebConsoleMessage::LevelLog:
   2409       log_severity = logging::LOG_INFO;
   2410       break;
   2411     case WebConsoleMessage::LevelWarning:
   2412       log_severity = logging::LOG_WARNING;
   2413       break;
   2414     case WebConsoleMessage::LevelError:
   2415       log_severity = logging::LOG_ERROR;
   2416       break;
   2417     default:
   2418       NOTREACHED();
   2419   }
   2420 
   2421   Send(new ViewHostMsg_AddMessageToConsole(routing_id_,
   2422                                            static_cast<int32>(log_severity),
   2423                                            message.text,
   2424                                            static_cast<int32>(source_line),
   2425                                            source_name));
   2426 }
   2427 
   2428 void RenderViewImpl::printPage(WebFrame* frame) {
   2429   FOR_EACH_OBSERVER(RenderViewObserver, observers_,
   2430                     PrintPage(frame, handling_input_event_));
   2431 }
   2432 
   2433 WebKit::WebNotificationPresenter* RenderViewImpl::notificationPresenter() {
   2434   return notification_provider_;
   2435 }
   2436 
   2437 bool RenderViewImpl::enumerateChosenDirectory(
   2438     const WebString& path,
   2439     WebFileChooserCompletion* chooser_completion) {
   2440   int id = enumeration_completion_id_++;
   2441   enumeration_completions_[id] = chooser_completion;
   2442   return Send(new ViewHostMsg_EnumerateDirectory(
   2443       routing_id_,
   2444       id,
   2445       base::FilePath::FromUTF16Unsafe(path)));
   2446 }
   2447 
   2448 void RenderViewImpl::initializeHelperPluginWebFrame(
   2449     WebKit::WebHelperPlugin* plugin) {
   2450   plugin->initializeFrame(main_render_frame_.get());
   2451 }
   2452 
   2453 void RenderViewImpl::didStartLoading() {
   2454   if (is_loading_) {
   2455     DVLOG(1) << "didStartLoading called while loading";
   2456     return;
   2457   }
   2458 
   2459   is_loading_ = true;
   2460 
   2461   Send(new ViewHostMsg_DidStartLoading(routing_id_));
   2462 
   2463   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStartLoading());
   2464 }
   2465 
   2466 void RenderViewImpl::didStopLoading() {
   2467   if (!is_loading_) {
   2468     DVLOG(1) << "DidStopLoading called while not loading";
   2469     return;
   2470   }
   2471 
   2472   is_loading_ = false;
   2473 
   2474   // NOTE: For now we're doing the safest thing, and sending out notification
   2475   // when done loading. This currently isn't an issue as the favicon is only
   2476   // displayed when done loading. Ideally we would send notification when
   2477   // finished parsing the head, but webkit doesn't support that yet.
   2478   // The feed discovery code would also benefit from access to the head.
   2479   Send(new ViewHostMsg_DidStopLoading(routing_id_));
   2480 
   2481   if (load_progress_tracker_ != NULL)
   2482     load_progress_tracker_->DidStopLoading();
   2483 
   2484   DidStopLoadingIcons();
   2485 
   2486   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStopLoading());
   2487 }
   2488 
   2489 void RenderViewImpl::didChangeLoadProgress(WebFrame* frame,
   2490                                            double load_progress) {
   2491   if (load_progress_tracker_ != NULL)
   2492     load_progress_tracker_->DidChangeLoadProgress(frame, load_progress);
   2493 }
   2494 
   2495 void RenderViewImpl::didCancelCompositionOnSelectionChange() {
   2496   Send(new ViewHostMsg_ImeCancelComposition(routing_id()));
   2497 }
   2498 
   2499 void RenderViewImpl::didChangeSelection(bool is_empty_selection) {
   2500   if (!handling_input_event_ && !handling_select_range_)
   2501     return;
   2502 
   2503   if (is_empty_selection)
   2504     selection_text_.clear();
   2505 
   2506   SyncSelectionIfRequired();
   2507   UpdateTextInputType();
   2508 #if defined(OS_ANDROID)
   2509   UpdateTextInputState(false, true);
   2510 #endif
   2511 }
   2512 
   2513 void RenderViewImpl::didExecuteCommand(const WebString& command_name) {
   2514   const std::string& name = UTF16ToUTF8(command_name);
   2515   if (StartsWithASCII(name, "Move", true) ||
   2516       StartsWithASCII(name, "Insert", true) ||
   2517       StartsWithASCII(name, "Delete", true))
   2518     return;
   2519   RenderThreadImpl::current()->RecordUserMetrics(name);
   2520 }
   2521 
   2522 bool RenderViewImpl::handleCurrentKeyboardEvent() {
   2523   if (edit_commands_.empty())
   2524     return false;
   2525 
   2526   WebFrame* frame = webview()->focusedFrame();
   2527   if (!frame)
   2528     return false;
   2529 
   2530   EditCommands::iterator it = edit_commands_.begin();
   2531   EditCommands::iterator end = edit_commands_.end();
   2532 
   2533   bool did_execute_command = false;
   2534   for (; it != end; ++it) {
   2535     // In gtk and cocoa, it's possible to bind multiple edit commands to one
   2536     // key (but it's the exception). Once one edit command is not executed, it
   2537     // seems safest to not execute the rest.
   2538     if (!frame->executeCommand(WebString::fromUTF8(it->name),
   2539                                WebString::fromUTF8(it->value),
   2540                                GetFocusedNode()))
   2541       break;
   2542     did_execute_command = true;
   2543   }
   2544 
   2545   return did_execute_command;
   2546 }
   2547 
   2548 WebKit::WebColorChooser* RenderViewImpl::createColorChooser(
   2549     WebKit::WebColorChooserClient* client,
   2550     const WebKit::WebColor& initial_color) {
   2551   RendererWebColorChooserImpl* color_chooser =
   2552       new RendererWebColorChooserImpl(this, client);
   2553   color_chooser->Open(static_cast<SkColor>(initial_color));
   2554   return color_chooser;
   2555 }
   2556 
   2557 bool RenderViewImpl::runFileChooser(
   2558     const WebKit::WebFileChooserParams& params,
   2559     WebFileChooserCompletion* chooser_completion) {
   2560   // Do not open the file dialog in a hidden RenderView.
   2561   if (is_hidden())
   2562     return false;
   2563   FileChooserParams ipc_params;
   2564   if (params.directory)
   2565     ipc_params.mode = FileChooserParams::UploadFolder;
   2566   else if (params.multiSelect)
   2567     ipc_params.mode = FileChooserParams::OpenMultiple;
   2568   else if (params.saveAs)
   2569     ipc_params.mode = FileChooserParams::Save;
   2570   else
   2571     ipc_params.mode = FileChooserParams::Open;
   2572   ipc_params.title = params.title;
   2573   ipc_params.default_file_name =
   2574       base::FilePath::FromUTF16Unsafe(params.initialValue);
   2575   ipc_params.accept_types.reserve(params.acceptTypes.size());
   2576   for (size_t i = 0; i < params.acceptTypes.size(); ++i)
   2577     ipc_params.accept_types.push_back(params.acceptTypes[i]);
   2578 #if defined(OS_ANDROID)
   2579   ipc_params.capture = params.useMediaCapture;
   2580 #endif
   2581 
   2582   return ScheduleFileChooser(ipc_params, chooser_completion);
   2583 }
   2584 
   2585 void RenderViewImpl::runModalAlertDialog(WebFrame* frame,
   2586                                          const WebString& message) {
   2587   RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_ALERT,
   2588                        message,
   2589                        string16(),
   2590                        frame->document().url(),
   2591                        NULL);
   2592 }
   2593 
   2594 bool RenderViewImpl::runModalConfirmDialog(WebFrame* frame,
   2595                                            const WebString& message) {
   2596   return RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_CONFIRM,
   2597                               message,
   2598                               string16(),
   2599                               frame->document().url(),
   2600                               NULL);
   2601 }
   2602 
   2603 bool RenderViewImpl::runModalPromptDialog(WebFrame* frame,
   2604                                           const WebString& message,
   2605                                           const WebString& default_value,
   2606                                           WebString* actual_value) {
   2607   string16 result;
   2608   bool ok = RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_PROMPT,
   2609                                  message,
   2610                                  default_value,
   2611                                  frame->document().url(),
   2612                                  &result);
   2613   if (ok)
   2614     actual_value->assign(result);
   2615   return ok;
   2616 }
   2617 
   2618 bool RenderViewImpl::runModalBeforeUnloadDialog(
   2619     WebFrame* frame, const WebString& message) {
   2620   bool is_reload = false;
   2621   WebDataSource* ds = frame->provisionalDataSource();
   2622   if (ds)
   2623     is_reload = (ds->navigationType() == WebKit::WebNavigationTypeReload);
   2624   return runModalBeforeUnloadDialog(frame, is_reload, message);
   2625 }
   2626 
   2627 bool RenderViewImpl::runModalBeforeUnloadDialog(
   2628     WebFrame* frame, bool is_reload, const WebString& message) {
   2629   // If we are swapping out, we have already run the beforeunload handler.
   2630   // TODO(creis): Fix OnSwapOut to clear the frame without running beforeunload
   2631   // at all, to avoid running it twice.
   2632   if (is_swapped_out_)
   2633     return true;
   2634 
   2635   bool success = false;
   2636   // This is an ignored return value, but is included so we can accept the same
   2637   // response as RunJavaScriptMessage.
   2638   string16 ignored_result;
   2639   SendAndRunNestedMessageLoop(new ViewHostMsg_RunBeforeUnloadConfirm(
   2640       routing_id_, frame->document().url(), message, is_reload,
   2641       &success, &ignored_result));
   2642   return success;
   2643 }
   2644 
   2645 void RenderViewImpl::showContextMenu(
   2646     WebFrame* frame, const WebContextMenuData& data) {
   2647   ContextMenuParams params = ContextMenuParamsBuilder::Build(data);
   2648   params.source_type = context_menu_source_type_;
   2649   if (context_menu_source_type_ == ui::MENU_SOURCE_TOUCH_EDIT_MENU) {
   2650     params.x = touch_editing_context_menu_location_.x();
   2651     params.y = touch_editing_context_menu_location_.y();
   2652   }
   2653 
   2654   // Plugins, e.g. PDF, don't currently update the render view when their
   2655   // selected text changes, but the context menu params do contain the updated
   2656   // selection. If that's the case, update the render view's state just prior
   2657   // to showing the context menu.
   2658   // TODO(asvitkine): http://crbug.com/152432
   2659   if (ShouldUpdateSelectionTextFromContextMenuParams(selection_text_,
   2660                                                      selection_text_offset_,
   2661                                                      selection_range_,
   2662                                                      params)) {
   2663     selection_text_ = params.selection_text;
   2664     // TODO(asvitkine): Text offset and range is not available in this case.
   2665     selection_text_offset_ = 0;
   2666     selection_range_ = ui::Range(0, selection_text_.length());
   2667     Send(new ViewHostMsg_SelectionChanged(routing_id_,
   2668                                           selection_text_,
   2669                                           selection_text_offset_,
   2670                                           selection_range_));
   2671   }
   2672 
   2673   // frame is NULL if invoked by BlockedPlugin.
   2674   if (frame)
   2675     params.frame_id = frame->identifier();
   2676 
   2677   // Serializing a GURL longer than kMaxURLChars will fail, so don't do
   2678   // it.  We replace it with an empty GURL so the appropriate items are disabled
   2679   // in the context menu.
   2680   // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
   2681   //                 data encoded images.  We should have a way to save them.
   2682   if (params.src_url.spec().size() > kMaxURLChars)
   2683     params.src_url = GURL();
   2684   context_menu_node_ = data.node;
   2685 
   2686 #if defined(OS_ANDROID)
   2687   gfx::Rect start_rect;
   2688   gfx::Rect end_rect;
   2689   GetSelectionBounds(&start_rect, &end_rect);
   2690   params.selection_start = gfx::Point(start_rect.x(), start_rect.bottom());
   2691   params.selection_end = gfx::Point(end_rect.right(), end_rect.bottom());
   2692 #endif
   2693 
   2694   Send(new ViewHostMsg_ContextMenu(routing_id_, params));
   2695 
   2696   FOR_EACH_OBSERVER(
   2697       RenderViewObserver, observers_, DidRequestShowContextMenu(frame, data));
   2698 }
   2699 
   2700 void RenderViewImpl::setStatusText(const WebString& text) {
   2701 }
   2702 
   2703 void RenderViewImpl::UpdateTargetURL(const GURL& url,
   2704                                      const GURL& fallback_url) {
   2705   GURL latest_url = url.is_empty() ? fallback_url : url;
   2706   if (latest_url == target_url_)
   2707     return;
   2708 
   2709   // Tell the browser to display a destination link.
   2710   if (target_url_status_ == TARGET_INFLIGHT ||
   2711       target_url_status_ == TARGET_PENDING) {
   2712     // If we have a request in-flight, save the URL to be sent when we
   2713     // receive an ACK to the in-flight request. We can happily overwrite
   2714     // any existing pending sends.
   2715     pending_target_url_ = latest_url;
   2716     target_url_status_ = TARGET_PENDING;
   2717   } else {
   2718     // URLs larger than |kMaxURLChars| cannot be sent through IPC -
   2719     // see |ParamTraits<GURL>|.
   2720     if (latest_url.possibly_invalid_spec().size() > kMaxURLChars)
   2721       latest_url = GURL();
   2722     Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, latest_url));
   2723     target_url_ = latest_url;
   2724     target_url_status_ = TARGET_INFLIGHT;
   2725   }
   2726 }
   2727 
   2728 gfx::RectF RenderViewImpl::ClientRectToPhysicalWindowRect(
   2729     const gfx::RectF& rect) const {
   2730   gfx::RectF window_rect = rect;
   2731   window_rect.Scale(device_scale_factor_ * webview()->pageScaleFactor());
   2732   return window_rect;
   2733 }
   2734 
   2735 void RenderViewImpl::StartNavStateSyncTimerIfNecessary() {
   2736   // No need to update state if no page has committed yet.
   2737   if (page_id_ == -1)
   2738     return;
   2739 
   2740   int delay;
   2741   if (send_content_state_immediately_)
   2742     delay = 0;
   2743   else if (is_hidden())
   2744     delay = kDelaySecondsForContentStateSyncHidden;
   2745   else
   2746     delay = kDelaySecondsForContentStateSync;
   2747 
   2748   if (nav_state_sync_timer_.IsRunning()) {
   2749     // The timer is already running. If the delay of the timer maches the amount
   2750     // we want to delay by, then return. Otherwise stop the timer so that it
   2751     // gets started with the right delay.
   2752     if (nav_state_sync_timer_.GetCurrentDelay().InSeconds() == delay)
   2753       return;
   2754     nav_state_sync_timer_.Stop();
   2755   }
   2756 
   2757   nav_state_sync_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(delay), this,
   2758                               &RenderViewImpl::SyncNavigationState);
   2759 }
   2760 
   2761 void RenderViewImpl::setMouseOverURL(const WebURL& url) {
   2762   mouse_over_url_ = GURL(url);
   2763   UpdateTargetURL(mouse_over_url_, focus_url_);
   2764 }
   2765 
   2766 void RenderViewImpl::setKeyboardFocusURL(const WebURL& url) {
   2767   focus_url_ = GURL(url);
   2768   UpdateTargetURL(focus_url_, mouse_over_url_);
   2769 }
   2770 
   2771 void RenderViewImpl::startDragging(WebFrame* frame,
   2772                                    const WebDragData& data,
   2773                                    WebDragOperationsMask mask,
   2774                                    const WebImage& image,
   2775                                    const WebPoint& webImageOffset) {
   2776   DropData drop_data(DropDataBuilder::Build(data));
   2777   drop_data.referrer_policy = frame->document().referrerPolicy();
   2778   gfx::Vector2d imageOffset(webImageOffset.x, webImageOffset.y);
   2779   Send(new DragHostMsg_StartDragging(routing_id_,
   2780                                      drop_data,
   2781                                      mask,
   2782                                      image.getSkBitmap(),
   2783                                      imageOffset,
   2784                                      possible_drag_event_info_));
   2785 }
   2786 
   2787 bool RenderViewImpl::acceptsLoadDrops() {
   2788   return renderer_preferences_.can_accept_load_drops;
   2789 }
   2790 
   2791 void RenderViewImpl::focusNext() {
   2792   Send(new ViewHostMsg_TakeFocus(routing_id_, false));
   2793 }
   2794 
   2795 void RenderViewImpl::focusPrevious() {
   2796   Send(new ViewHostMsg_TakeFocus(routing_id_, true));
   2797 }
   2798 
   2799 void RenderViewImpl::focusedNodeChanged(const WebNode& node) {
   2800   Send(new ViewHostMsg_FocusedNodeChanged(routing_id_, IsEditableNode(node)));
   2801 
   2802   FOR_EACH_OBSERVER(RenderViewObserver, observers_, FocusedNodeChanged(node));
   2803 }
   2804 
   2805 void RenderViewImpl::numberOfWheelEventHandlersChanged(unsigned num_handlers) {
   2806   Send(new ViewHostMsg_DidChangeNumWheelEvents(routing_id_, num_handlers));
   2807 }
   2808 
   2809 void RenderViewImpl::didUpdateLayout() {
   2810   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidUpdateLayout());
   2811 
   2812   // We don't always want to set up a timer, only if we've been put in that
   2813   // mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
   2814   // message.
   2815   if (!send_preferred_size_changes_ || !webview())
   2816     return;
   2817 
   2818   if (check_preferred_size_timer_.IsRunning())
   2819     return;
   2820   check_preferred_size_timer_.Start(FROM_HERE,
   2821                                     TimeDelta::FromMilliseconds(0), this,
   2822                                     &RenderViewImpl::CheckPreferredSize);
   2823 }
   2824 
   2825 void RenderViewImpl::navigateBackForwardSoon(int offset) {
   2826   Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset));
   2827 }
   2828 
   2829 int RenderViewImpl::historyBackListCount() {
   2830   return history_list_offset_ < 0 ? 0 : history_list_offset_;
   2831 }
   2832 
   2833 int RenderViewImpl::historyForwardListCount() {
   2834   return history_list_length_ - historyBackListCount() - 1;
   2835 }
   2836 
   2837 void RenderViewImpl::postAccessibilityNotification(
   2838     const WebAccessibilityObject& obj,
   2839     WebAccessibilityNotification notification) {
   2840   if (renderer_accessibility_) {
   2841     renderer_accessibility_->HandleWebAccessibilityNotification(
   2842         obj, notification);
   2843   }
   2844 }
   2845 
   2846 void RenderViewImpl::didUpdateInspectorSetting(const WebString& key,
   2847                                            const WebString& value) {
   2848   Send(new ViewHostMsg_UpdateInspectorSetting(routing_id_,
   2849                                               key.utf8(),
   2850                                               value.utf8()));
   2851 }
   2852 
   2853 // WebKit::WebWidgetClient ----------------------------------------------------
   2854 
   2855 void RenderViewImpl::didFocus() {
   2856   // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
   2857   //                 we won't have to test for user gesture anymore and we can
   2858   //                 move that code back to render_widget.cc
   2859   if (WebUserGestureIndicator::isProcessingUserGesture() &&
   2860       !RenderThreadImpl::current()->layout_test_mode()) {
   2861     Send(new ViewHostMsg_Focus(routing_id_));
   2862   }
   2863 }
   2864 
   2865 void RenderViewImpl::didBlur() {
   2866   // TODO(jcivelli): see TODO above in didFocus().
   2867   if (WebUserGestureIndicator::isProcessingUserGesture() &&
   2868       !RenderThreadImpl::current()->layout_test_mode()) {
   2869     Send(new ViewHostMsg_Blur(routing_id_));
   2870   }
   2871 }
   2872 
   2873 // We are supposed to get a single call to Show for a newly created RenderView
   2874 // that was created via RenderViewImpl::CreateWebView.  So, we wait until this
   2875 // point to dispatch the ShowView message.
   2876 //
   2877 // This method provides us with the information about how to display the newly
   2878 // created RenderView (i.e., as a blocked popup or as a new tab).
   2879 //
   2880 void RenderViewImpl::show(WebNavigationPolicy policy) {
   2881   if (did_show_) {
   2882     // When supports_multiple_windows is disabled, popups are reusing
   2883     // the same view. In some scenarios, this makes WebKit to call show() twice.
   2884     if (webkit_preferences_.supports_multiple_windows)
   2885       NOTREACHED() << "received extraneous Show call";
   2886     return;
   2887   }
   2888   did_show_ = true;
   2889 
   2890   DCHECK(opener_id_ != MSG_ROUTING_NONE);
   2891 
   2892   // Force new windows to a popup if they were not opened with a user gesture.
   2893   if (!opened_by_user_gesture_) {
   2894     // We exempt background tabs for compat with older versions of Chrome.
   2895     // TODO(darin): This seems bogus.  These should have a user gesture, so
   2896     // we probably don't need this check.
   2897     if (policy != WebKit::WebNavigationPolicyNewBackgroundTab)
   2898       policy = WebKit::WebNavigationPolicyNewPopup;
   2899   }
   2900 
   2901   // NOTE: initial_pos_ may still have its default values at this point, but
   2902   // that's okay.  It'll be ignored if disposition is not NEW_POPUP, or the
   2903   // browser process will impose a default position otherwise.
   2904   Send(new ViewHostMsg_ShowView(opener_id_, routing_id_,
   2905       NavigationPolicyToDisposition(policy), initial_pos_,
   2906       opened_by_user_gesture_));
   2907   SetPendingWindowRect(initial_pos_);
   2908 }
   2909 
   2910 void RenderViewImpl::runModal() {
   2911   DCHECK(did_show_) << "should already have shown the view";
   2912 
   2913   // We must keep WebKit's shared timer running in this case in order to allow
   2914   // showModalDialog to function properly.
   2915   //
   2916   // TODO(darin): WebKit should really be smarter about suppressing events and
   2917   // timers so that we do not need to manage the shared timer in such a heavy
   2918   // handed manner.
   2919   //
   2920   if (RenderThreadImpl::current())  // Will be NULL during unit tests.
   2921     RenderThreadImpl::current()->DoNotSuspendWebKitSharedTimer();
   2922 
   2923   SendAndRunNestedMessageLoop(new ViewHostMsg_RunModal(
   2924       routing_id_, opener_id_));
   2925 }
   2926 
   2927 bool RenderViewImpl::enterFullScreen() {
   2928   Send(new ViewHostMsg_ToggleFullscreen(routing_id_, true));
   2929   return true;
   2930 }
   2931 
   2932 void RenderViewImpl::exitFullScreen() {
   2933   Send(new ViewHostMsg_ToggleFullscreen(routing_id_, false));
   2934 }
   2935 
   2936 bool RenderViewImpl::requestPointerLock() {
   2937   return mouse_lock_dispatcher_->LockMouse(webwidget_mouse_lock_target_.get());
   2938 }
   2939 
   2940 void RenderViewImpl::requestPointerUnlock() {
   2941   mouse_lock_dispatcher_->UnlockMouse(webwidget_mouse_lock_target_.get());
   2942 }
   2943 
   2944 bool RenderViewImpl::isPointerLocked() {
   2945   return mouse_lock_dispatcher_->IsMouseLockedTo(
   2946       webwidget_mouse_lock_target_.get());
   2947 }
   2948 
   2949 void RenderViewImpl::didActivateCompositor(int input_handler_identifier) {
   2950 #if !defined(OS_MACOSX)  // many events are unhandled - http://crbug.com/138003
   2951   InputHandlerManager* input_handler_manager =
   2952       RenderThreadImpl::current()->input_handler_manager();
   2953   if (input_handler_manager) {
   2954      input_handler_manager->AddInputHandler(
   2955         routing_id_,
   2956         compositor_->GetInputHandler(),
   2957         AsWeakPtr());
   2958   }
   2959 #endif
   2960 
   2961   RenderWidget::didActivateCompositor(input_handler_identifier);
   2962 }
   2963 
   2964 void RenderViewImpl::didHandleGestureEvent(
   2965     const WebGestureEvent& event,
   2966     bool event_cancelled) {
   2967   RenderWidget::didHandleGestureEvent(event, event_cancelled);
   2968   FOR_EACH_OBSERVER(RenderViewObserver, observers_,
   2969                     DidHandleGestureEvent(event));
   2970 }
   2971 
   2972 void RenderViewImpl::initializeLayerTreeView() {
   2973   RenderWidget::initializeLayerTreeView();
   2974   RenderWidgetCompositor* rwc = compositor();
   2975   if (!rwc || !webview() || !webview()->devToolsAgent())
   2976     return;
   2977   webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId());
   2978 }
   2979 
   2980 // WebKit::WebFrameClient -----------------------------------------------------
   2981 
   2982 WebKit::WebPlugin* RenderViewImpl::createPlugin(WebFrame* frame,
   2983                                                 const WebPluginParams& params) {
   2984   NOTREACHED();
   2985   return NULL;
   2986 }
   2987 
   2988 WebSharedWorker* RenderViewImpl::createSharedWorker(
   2989     WebFrame* frame, const WebURL& url, const WebString& name,
   2990     unsigned long long document_id) {
   2991   NOTREACHED();
   2992   return NULL;
   2993 }
   2994 
   2995 WebMediaPlayer* RenderViewImpl::createMediaPlayer(
   2996     WebFrame* frame, const WebKit::WebURL& url, WebMediaPlayerClient* client) {
   2997   FOR_EACH_OBSERVER(
   2998       RenderViewObserver, observers_, WillCreateMediaPlayer(frame, client));
   2999 
   3000   const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
   3001 #if defined(ENABLE_WEBRTC)
   3002   EnsureMediaStreamClient();
   3003 #if !defined(GOOGLE_TV)
   3004   if (media_stream_client_ && media_stream_client_->IsMediaStream(url)) {
   3005 #if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
   3006     bool found_neon =
   3007         (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
   3008     UMA_HISTOGRAM_BOOLEAN("Platform.WebRtcNEONFound", found_neon);
   3009 #endif  // defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
   3010     return new WebMediaPlayerMS(
   3011         frame, client, AsWeakPtr(), media_stream_client_, new RenderMediaLog());
   3012   }
   3013 #endif  // !defined(GOOGLE_TV)
   3014 #endif  // defined(ENABLE_WEBRTC)
   3015 
   3016 #if defined(OS_ANDROID)
   3017   GpuChannelHost* gpu_channel_host =
   3018       RenderThreadImpl::current()->EstablishGpuChannelSync(
   3019           CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE);
   3020   if (!gpu_channel_host) {
   3021     LOG(ERROR) << "Failed to establish GPU channel for media player";
   3022     return NULL;
   3023   }
   3024 
   3025   scoped_refptr<cc::ContextProvider> context_provider =
   3026       RenderThreadImpl::current()->OffscreenContextProviderForMainThread();
   3027   scoped_ptr<StreamTextureFactory> stream_texture_factory;
   3028   if (UsingSynchronousRendererCompositor()) {
   3029     SynchronousCompositorFactory* factory =
   3030         SynchronousCompositorFactory::GetInstance();
   3031     stream_texture_factory = factory->CreateStreamTextureFactory(routing_id_);
   3032   } else {
   3033     if (!context_provider.get()) {
   3034       LOG(ERROR) << "Failed to get context3d for media player";
   3035       return NULL;
   3036     }
   3037 
   3038     stream_texture_factory.reset(new StreamTextureFactoryImpl(
   3039         context_provider->Context3d(), gpu_channel_host, routing_id_));
   3040   }
   3041 
   3042   if (!media_player_proxy_) {
   3043     media_player_proxy_ = new WebMediaPlayerProxyAndroid(
   3044         this, media_player_manager_.get());
   3045   }
   3046 
   3047   scoped_ptr<WebMediaPlayerAndroid> web_media_player_android(
   3048       new WebMediaPlayerAndroid(
   3049           frame,
   3050           client,
   3051           AsWeakPtr(),
   3052           media_player_manager_.get(),
   3053           media_player_proxy_,
   3054           stream_texture_factory.release(),
   3055           RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(),
   3056           new RenderMediaLog()));
   3057 #if defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
   3058   if (media_stream_client_->IsMediaStream(url)) {
   3059     RTCVideoDecoderFactoryTv* factory = RenderThreadImpl::current()
   3060         ->GetMediaStreamDependencyFactory()->decoder_factory_tv();
   3061     // |media_stream_client| and |factory| outlives |web_media_player_android|.
   3062     if (!factory->AcquireDemuxer() ||
   3063         !web_media_player_android->InjectMediaStream(
   3064             media_stream_client_,
   3065             factory,
   3066             base::Bind(
   3067                 base::IgnoreResult(&RTCVideoDecoderFactoryTv::ReleaseDemuxer),
   3068                 base::Unretained(factory)))) {
   3069       LOG(ERROR) << "Failed to inject media stream.";
   3070       return NULL;
   3071     }
   3072   }
   3073 #endif  // defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
   3074   return web_media_player_android.release();
   3075 #endif  // defined(OS_ANDROID)
   3076 
   3077   scoped_refptr<media::AudioRendererSink> sink;
   3078   if (!cmd_line->HasSwitch(switches::kDisableAudio)) {
   3079     sink = RenderThreadImpl::current()->GetAudioRendererMixerManager()->
   3080         CreateInput(routing_id_);
   3081     DVLOG(1) << "Using AudioRendererMixerManager-provided sink: " << sink.get();
   3082   }
   3083 
   3084   scoped_refptr<media::GpuVideoDecoderFactories> gpu_factories =
   3085       RenderThreadImpl::current()->GetGpuFactories(
   3086           RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy());
   3087 
   3088   WebMediaPlayerParams params(
   3089       RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(),
   3090       base::Bind(&ContentRendererClient::DeferMediaLoad,
   3091                  base::Unretained(GetContentClient()->renderer()),
   3092                  static_cast<RenderView*>(this)),
   3093       sink,
   3094       gpu_factories,
   3095       new RenderMediaLog());
   3096   return new WebMediaPlayerImpl(frame, client, AsWeakPtr(), params);
   3097 }
   3098 
   3099 WebApplicationCacheHost* RenderViewImpl::createApplicationCacheHost(
   3100     WebFrame* frame, WebApplicationCacheHostClient* client) {
   3101   NOTREACHED();
   3102   return NULL;
   3103 }
   3104 
   3105 WebCookieJar* RenderViewImpl::cookieJar(WebFrame* frame) {
   3106   return &cookie_jar_;
   3107 }
   3108 
   3109 void RenderViewImpl::didAccessInitialDocument(WebFrame* frame) {
   3110   // Notify the browser process that it is no longer safe to show the pending
   3111   // URL of the main frame, since a URL spoof is now possible.
   3112   if (!frame->parent() && page_id_ == -1)
   3113     Send(new ViewHostMsg_DidAccessInitialDocument(routing_id_));
   3114 }
   3115 
   3116 void RenderViewImpl::didCreateFrame(WebFrame* parent, WebFrame* child) {
   3117   NOTREACHED();
   3118 }
   3119 
   3120 void RenderViewImpl::didDisownOpener(WebKit::WebFrame* frame) {
   3121   // We only need to notify the browser if the active, top-level frame clears
   3122   // its opener.  We can ignore cases where a swapped out frame clears its
   3123   // opener after hearing about it from the browser, and the browser does not
   3124   // (yet) care about subframe openers.
   3125   if (is_swapped_out_ || frame->parent())
   3126     return;
   3127 
   3128   // Notify WebContents and all its swapped out RenderViews.
   3129   Send(new ViewHostMsg_DidDisownOpener(routing_id_));
   3130 }
   3131 
   3132 void RenderViewImpl::frameDetached(WebFrame* frame) {
   3133   FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameDetached(frame));
   3134 }
   3135 
   3136 void RenderViewImpl::willClose(WebFrame* frame) {
   3137   FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameWillClose(frame));
   3138 }
   3139 
   3140 void RenderViewImpl::didChangeName(WebFrame* frame,
   3141                                    const WebString& name)  {
   3142   NOTREACHED();
   3143 }
   3144 
   3145 void RenderViewImpl::loadURLExternally(
   3146     WebFrame* frame, const WebURLRequest& request,
   3147     WebNavigationPolicy policy) {
   3148   NOTREACHED();
   3149 }
   3150 
   3151 void RenderViewImpl::Repaint(const gfx::Size& size) {
   3152   OnRepaint(size);
   3153 }
   3154 
   3155 void RenderViewImpl::SetEditCommandForNextKeyEvent(const std::string& name,
   3156                                                    const std::string& value) {
   3157   EditCommands edit_commands;
   3158   edit_commands.push_back(EditCommand(name, value));
   3159   OnSetEditCommandsForNextKeyEvent(edit_commands);
   3160 }
   3161 
   3162 void RenderViewImpl::ClearEditCommands() {
   3163   edit_commands_.clear();
   3164 }
   3165 
   3166 SSLStatus RenderViewImpl::GetSSLStatusOfFrame(WebKit::WebFrame* frame) const {
   3167   std::string security_info;
   3168   if (frame && frame->dataSource())
   3169     security_info = frame->dataSource()->response().securityInfo();
   3170 
   3171   SSLStatus ssl_status;
   3172   DeserializeSecurityInfo(security_info,
   3173                           &ssl_status.cert_id,
   3174                           &ssl_status.cert_status,
   3175                           &ssl_status.security_bits,
   3176                           &ssl_status.connection_status);
   3177   return ssl_status;
   3178 }
   3179 
   3180 void RenderViewImpl::loadURLExternally(
   3181     WebFrame* frame, const WebURLRequest& request,
   3182     WebNavigationPolicy policy,
   3183     const WebString& suggested_name) {
   3184   NOTREACHED();
   3185 }
   3186 
   3187 WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
   3188     WebFrame* frame, WebDataSource::ExtraData* extraData,
   3189     const WebURLRequest& request, WebNavigationType type,
   3190     WebNavigationPolicy default_policy, bool is_redirect) {
   3191   if (request.url() != GURL(kSwappedOutURL) &&
   3192       GetContentClient()->renderer()->HandleNavigation(
   3193           this,
   3194           static_cast<DocumentState*>(extraData),
   3195           opener_id_,
   3196           frame,
   3197           request, type,
   3198           default_policy,
   3199           is_redirect)) {
   3200     return WebKit::WebNavigationPolicyIgnore;
   3201   }
   3202 
   3203   Referrer referrer(GetReferrerFromRequest(frame, request));
   3204 
   3205   if (is_swapped_out_) {
   3206     if (request.url() != GURL(kSwappedOutURL)) {
   3207       // Targeted links may try to navigate a swapped out frame.  Allow the
   3208       // browser process to navigate the tab instead.  Note that it is also
   3209       // possible for non-targeted navigations (from this view) to arrive
   3210       // here just after we are swapped out.  It's ok to send them to the
   3211       // browser, as long as they're for the top level frame.
   3212       // TODO(creis): Ensure this supports targeted form submissions when
   3213       // fixing http://crbug.com/101395.
   3214       if (frame->parent() == NULL) {
   3215         OpenURL(frame, request.url(), referrer, default_policy);
   3216         return WebKit::WebNavigationPolicyIgnore;  // Suppress the load here.
   3217       }
   3218 
   3219       // We should otherwise ignore in-process iframe navigations, if they
   3220       // arrive just after we are swapped out.
   3221       return WebKit::WebNavigationPolicyIgnore;
   3222     }
   3223 
   3224     // Allow kSwappedOutURL to complete.
   3225     return default_policy;
   3226   }
   3227 
   3228   // Webkit is asking whether to navigate to a new URL.
   3229   // This is fine normally, except if we're showing UI from one security
   3230   // context and they're trying to navigate to a different context.
   3231   const GURL& url = request.url();
   3232 
   3233   // A content initiated navigation may have originated from a link-click,
   3234   // script, drag-n-drop operation, etc.
   3235   bool is_content_initiated = static_cast<DocumentState*>(extraData)->
   3236           navigation_state()->is_content_initiated();
   3237 
   3238   // Experimental:
   3239   // If --enable-strict-site-isolation or --site-per-process is enabled, send
   3240   // all top-level navigations to the browser to let it swap processes when
   3241   // crossing site boundaries.  This is currently expected to break some script
   3242   // calls and navigations, such as form submissions.
   3243   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
   3244   bool force_swap_due_to_flag =
   3245       command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
   3246       command_line.HasSwitch(switches::kSitePerProcess);
   3247   if (force_swap_due_to_flag &&
   3248       !frame->parent() && (is_content_initiated || is_redirect)) {
   3249     WebString origin_str = frame->document().securityOrigin().toString();
   3250     GURL frame_url(origin_str.utf8().data());
   3251     // TODO(cevans): revisit whether this site check is still necessary once
   3252     // crbug.com/101395 is fixed.
   3253     bool same_domain_or_host =
   3254         net::registry_controlled_domains::SameDomainOrHost(
   3255             frame_url,
   3256             url,
   3257             net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
   3258     if (!same_domain_or_host || frame_url.scheme() != url.scheme()) {
   3259       OpenURL(frame, url, referrer, default_policy);
   3260       return WebKit::WebNavigationPolicyIgnore;
   3261     }
   3262   }
   3263 
   3264   // If the browser is interested, then give it a chance to look at the request.
   3265   if (is_content_initiated) {
   3266     bool is_form_post = ((type == WebKit::WebNavigationTypeFormSubmitted) ||
   3267                          (type == WebKit::WebNavigationTypeFormResubmitted)) &&
   3268                         EqualsASCII(request.httpMethod(), "POST");
   3269     bool browser_handles_request =
   3270         renderer_preferences_.browser_handles_non_local_top_level_requests &&
   3271         IsNonLocalTopLevelNavigation(url, frame, type, is_form_post);
   3272     if (!browser_handles_request) {
   3273       browser_handles_request =
   3274           renderer_preferences_.browser_handles_all_top_level_requests &&
   3275           IsTopLevelNavigation(frame);
   3276     }
   3277 
   3278     if (browser_handles_request) {
   3279       // Reset these counters as the RenderView could be reused for the next
   3280       // navigation.
   3281       page_id_ = -1;
   3282       last_page_id_sent_to_browser_ = -1;
   3283       OpenURL(frame, url, referrer, default_policy);
   3284       return WebKit::WebNavigationPolicyIgnore;  // Suppress the load here.
   3285     }
   3286   }
   3287 
   3288   // Use the frame's original request's URL rather than the document's URL for
   3289   // subsequent checks.  For a popup, the document's URL may become the opener
   3290   // window's URL if the opener has called document.write().
   3291   // See http://crbug.com/93517.
   3292   GURL old_url(frame->dataSource()->request().url());
   3293 
   3294   // Detect when we're crossing a permission-based boundary (e.g. into or out of
   3295   // an extension or app origin, leaving a WebUI page, etc). We only care about
   3296   // top-level navigations (not iframes). But we sometimes navigate to
   3297   // about:blank to clear a tab, and we want to still allow that.
   3298   //
   3299   // Note: this is known to break POST submissions when crossing process
   3300   // boundaries until http://crbug.com/101395 is fixed.  This is better for
   3301   // security than loading a WebUI, extension or app page in the wrong process.
   3302   // POST requests don't work because this mechanism does not preserve form
   3303   // POST data. We will need to send the request's httpBody data up to the
   3304   // browser process, and issue a special POST navigation in WebKit (via
   3305   // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
   3306   // for examples of how to send the httpBody data.
   3307   if (!frame->parent() && is_content_initiated &&
   3308       !url.SchemeIs(chrome::kAboutScheme)) {
   3309     bool send_referrer = false;
   3310 
   3311     // All navigations to or from WebUI URLs or within WebUI-enabled
   3312     // RenderProcesses must be handled by the browser process so that the
   3313     // correct bindings and data sources can be registered.
   3314     // Similarly, navigations to view-source URLs or within ViewSource mode
   3315     // must be handled by the browser process (except for reloads - those are
   3316     // safe to leave within the renderer).
   3317     // Lastly, access to file:// URLs from non-file:// URL pages must be
   3318     // handled by the browser so that ordinary renderer processes don't get
   3319     // blessed with file permissions.
   3320     int cumulative_bindings = RenderProcess::current()->GetEnabledBindings();
   3321     bool is_initial_navigation = page_id_ == -1;
   3322     bool should_fork = HasWebUIScheme(url) || HasWebUIScheme(old_url) ||
   3323         (cumulative_bindings & BINDINGS_POLICY_WEB_UI) ||
   3324         url.SchemeIs(kViewSourceScheme) ||
   3325         (frame->isViewSourceModeEnabled() &&
   3326             type != WebKit::WebNavigationTypeReload);
   3327 
   3328     if (!should_fork && url.SchemeIs(chrome::kFileScheme)) {
   3329       // Fork non-file to file opens.  Check the opener URL if this is the
   3330       // initial navigation in a newly opened window.
   3331       GURL source_url(old_url);
   3332       if (is_initial_navigation && source_url.is_empty() && frame->opener())
   3333         source_url = frame->opener()->top()->document().url();
   3334       DCHECK(!source_url.is_empty());
   3335       should_fork = !source_url.SchemeIs(chrome::kFileScheme);
   3336     }
   3337 
   3338     if (!should_fork) {
   3339       // Give the embedder a chance.
   3340       should_fork = GetContentClient()->renderer()->ShouldFork(
   3341           frame, url, request.httpMethod().utf8(), is_initial_navigation,
   3342           is_redirect, &send_referrer);
   3343     }
   3344 
   3345     if (should_fork) {
   3346       OpenURL(
   3347           frame, url, send_referrer ? referrer : Referrer(), default_policy);
   3348       return WebKit::WebNavigationPolicyIgnore;  // Suppress the load here.
   3349     }
   3350   }
   3351 
   3352   // Detect when a page is "forking" a new tab that can be safely rendered in
   3353   // its own process.  This is done by sites like Gmail that try to open links
   3354   // in new windows without script connections back to the original page.  We
   3355   // treat such cases as browser navigations (in which we will create a new
   3356   // renderer for a cross-site navigation), rather than WebKit navigations.
   3357   //
   3358   // We use the following heuristic to decide whether to fork a new page in its
   3359   // own process:
   3360   // The parent page must open a new tab to about:blank, set the new tab's
   3361   // window.opener to null, and then redirect the tab to a cross-site URL using
   3362   // JavaScript.
   3363   //
   3364   // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
   3365   // (see below).
   3366   bool is_fork =
   3367       // Must start from a tab showing about:blank, which is later redirected.
   3368       old_url == GURL(kAboutBlankURL) &&
   3369       // Must be the first real navigation of the tab.
   3370       historyBackListCount() < 1 &&
   3371       historyForwardListCount() < 1 &&
   3372       // The parent page must have set the child's window.opener to null before
   3373       // redirecting to the desired URL.
   3374       frame->opener() == NULL &&
   3375       // Must be a top-level frame.
   3376       frame->parent() == NULL &&
   3377       // Must not have issued the request from this page.
   3378       is_content_initiated &&
   3379       // Must be targeted at the current tab.
   3380       default_policy == WebKit::WebNavigationPolicyCurrentTab &&
   3381       // Must be a JavaScript navigation, which appears as "other".
   3382       type == WebKit::WebNavigationTypeOther;
   3383 
   3384   if (is_fork) {
   3385     // Open the URL via the browser, not via WebKit.
   3386     OpenURL(frame, url, Referrer(), default_policy);
   3387     return WebKit::WebNavigationPolicyIgnore;
   3388   }
   3389 
   3390   return default_policy;
   3391 }
   3392 
   3393 bool RenderViewImpl::shouldAbortNavigationAfterUrlResolve(const WebURL& base,
   3394                                               const WebString& fragment,
   3395                                               const WebURL& result) {
   3396   return GetContentClient()->renderer()->ShouldAbortNavigationAfterUrlResolve(
   3397       this, base, fragment, result);
   3398 }
   3399 
   3400 WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
   3401     WebFrame* frame, const WebURLRequest& request, WebNavigationType type,
   3402     WebNavigationPolicy default_policy, bool is_redirect) {
   3403   return decidePolicyForNavigation(frame,
   3404                                    frame->provisionalDataSource()->extraData(),
   3405                                    request, type, default_policy, is_redirect);
   3406 }
   3407 
   3408 void RenderViewImpl::willSendSubmitEvent(WebKit::WebFrame* frame,
   3409     const WebKit::WebFormElement& form) {
   3410   NOTREACHED();
   3411 }
   3412 
   3413 void RenderViewImpl::willSubmitForm(WebFrame* frame,
   3414                                     const WebFormElement& form) {
   3415   FOR_EACH_OBSERVER(
   3416       RenderViewObserver, observers_, WillSubmitForm(frame, form));
   3417 }
   3418 
   3419 void RenderViewImpl::didCreateDataSource(WebFrame* frame, WebDataSource* ds) {
   3420   bool content_initiated = !pending_navigation_params_.get();
   3421 
   3422   DocumentState* document_state = DocumentState::FromDataSource(ds);
   3423   if (!document_state) {
   3424     document_state = new DocumentState;
   3425     ds->setExtraData(document_state);
   3426     if (!content_initiated)
   3427       PopulateDocumentStateFromPending(document_state);
   3428   }
   3429 
   3430   // Carry over the user agent override flag, if it exists.
   3431   if (content_initiated && webview() && webview()->mainFrame() &&
   3432       webview()->mainFrame()->dataSource()) {
   3433     DocumentState* old_document_state =
   3434         DocumentState::FromDataSource(webview()->mainFrame()->dataSource());
   3435     if (old_document_state) {
   3436       InternalDocumentStateData* internal_data =
   3437           InternalDocumentStateData::FromDocumentState(document_state);
   3438       InternalDocumentStateData* old_internal_data =
   3439           InternalDocumentStateData::FromDocumentState(old_document_state);
   3440       internal_data->set_is_overriding_user_agent(
   3441           old_internal_data->is_overriding_user_agent());
   3442     }
   3443   }
   3444 
   3445   // The rest of RenderView assumes that a WebDataSource will always have a
   3446   // non-null NavigationState.
   3447   if (content_initiated) {
   3448     document_state->set_navigation_state(
   3449         NavigationState::CreateContentInitiated());
   3450   } else {
   3451     document_state->set_navigation_state(CreateNavigationStateFromPending());
   3452     pending_navigation_params_.reset();
   3453   }
   3454 
   3455   // DocumentState::referred_by_prefetcher_ is true if we are
   3456   // navigating from a page that used prefetching using a link on that
   3457   // page.  We are early enough in the request process here that we
   3458   // can still see the DocumentState of the previous page and set
   3459   // this value appropriately.
   3460   // TODO(gavinp): catch the important case of navigation in a new
   3461   // renderer process.
   3462   if (webview()) {
   3463     if (WebFrame* old_frame = webview()->mainFrame()) {
   3464       const WebURLRequest& original_request = ds->originalRequest();
   3465       const GURL referrer(
   3466           original_request.httpHeaderField(WebString::fromUTF8("Referer")));
   3467       if (!referrer.is_empty() &&
   3468           DocumentState::FromDataSource(
   3469               old_frame->dataSource())->was_prefetcher()) {
   3470         for (; old_frame; old_frame = old_frame->traverseNext(false)) {
   3471           WebDataSource* old_frame_ds = old_frame->dataSource();
   3472           if (old_frame_ds && referrer == GURL(old_frame_ds->request().url())) {
   3473             document_state->set_was_referred_by_prefetcher(true);
   3474             break;
   3475           }
   3476         }
   3477       }
   3478     }
   3479   }
   3480 
   3481   if (content_initiated) {
   3482     const WebURLRequest& request = ds->request();
   3483     switch (request.cachePolicy()) {
   3484       case WebURLRequest::UseProtocolCachePolicy:  // normal load.
   3485         document_state->set_load_type(DocumentState::LINK_LOAD_NORMAL);
   3486         break;
   3487       case WebURLRequest::ReloadIgnoringCacheData:  // reload.
   3488         document_state->set_load_type(DocumentState::LINK_LOAD_RELOAD);
   3489         break;
   3490       case WebURLRequest::ReturnCacheDataElseLoad:  // allow stale data.
   3491         document_state->set_load_type(
   3492             DocumentState::LINK_LOAD_CACHE_STALE_OK);
   3493         break;
   3494       case WebURLRequest::ReturnCacheDataDontLoad:  // Don't re-post.
   3495         document_state->set_load_type(DocumentState::LINK_LOAD_CACHE_ONLY);
   3496         break;
   3497     }
   3498   }
   3499 
   3500   FOR_EACH_OBSERVER(
   3501       RenderViewObserver, observers_, DidCreateDataSource(frame, ds));
   3502 }
   3503 
   3504 void RenderViewImpl::PopulateDocumentStateFromPending(
   3505     DocumentState* document_state) {
   3506   const ViewMsg_Navigate_Params& params = *pending_navigation_params_.get();
   3507   document_state->set_request_time(params.request_time);
   3508 
   3509   InternalDocumentStateData* internal_data =
   3510       InternalDocumentStateData::FromDocumentState(document_state);
   3511 
   3512   if (!params.url.SchemeIs(chrome::kJavaScriptScheme) &&
   3513       params.navigation_type == ViewMsg_Navigate_Type::RESTORE) {
   3514     // We're doing a load of a page that was restored from the last session. By
   3515     // default this prefers the cache over loading (LOAD_PREFERRING_CACHE) which
   3516     // can result in stale data for pages that are set to expire. We explicitly
   3517     // override that by setting the policy here so that as necessary we load
   3518     // from the network.
   3519     internal_data->set_cache_policy_override(
   3520         WebURLRequest::UseProtocolCachePolicy);
   3521   }
   3522 
   3523   if (IsReload(params))
   3524     document_state->set_load_type(DocumentState::RELOAD);
   3525   else if (params.page_state.IsValid())
   3526     document_state->set_load_type(DocumentState::HISTORY_LOAD);
   3527   else
   3528     document_state->set_load_type(DocumentState::NORMAL_LOAD);
   3529 
   3530   internal_data->set_referrer_policy(params.referrer.policy);
   3531   internal_data->set_is_overriding_user_agent(params.is_overriding_user_agent);
   3532   internal_data->set_must_reset_scroll_and_scale_state(
   3533       params.navigation_type ==
   3534           ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
   3535   document_state->set_can_load_local_resources(params.can_load_local_resources);
   3536 }
   3537 
   3538 NavigationState* RenderViewImpl::CreateNavigationStateFromPending() {
   3539   const ViewMsg_Navigate_Params& params = *pending_navigation_params_.get();
   3540   NavigationState* navigation_state = NULL;
   3541 
   3542   // A navigation resulting from loading a javascript URL should not be treated
   3543   // as a browser initiated event.  Instead, we want it to look as if the page
   3544   // initiated any load resulting from JS execution.
   3545   if (!params.url.SchemeIs(chrome::kJavaScriptScheme)) {
   3546     navigation_state = NavigationState::CreateBrowserInitiated(
   3547         params.page_id,
   3548         params.pending_history_list_offset,
   3549         params.should_clear_history_list,
   3550         params.transition);
   3551     navigation_state->set_transferred_request_child_id(
   3552         params.transferred_request_child_id);
   3553     navigation_state->set_transferred_request_request_id(
   3554         params.transferred_request_request_id);
   3555     navigation_state->set_allow_download(params.allow_download);
   3556     navigation_state->set_extra_headers(params.extra_headers);
   3557   } else {
   3558     navigation_state = NavigationState::CreateContentInitiated();
   3559   }
   3560   return navigation_state;
   3561 }
   3562 
   3563 void RenderViewImpl::ProcessViewLayoutFlags(const CommandLine& command_line) {
   3564   bool enable_viewport =
   3565       command_line.HasSwitch(switches::kEnableViewport);
   3566   bool enable_fixed_layout =
   3567       command_line.HasSwitch(switches::kEnableFixedLayout);
   3568 
   3569   webview()->enableFixedLayoutMode(enable_fixed_layout || enable_viewport);
   3570 
   3571   // If viewport tag is enabled, then the WebKit side will take care
   3572   // of setting the fixed layout size and page scale limits.
   3573   if (enable_viewport)
   3574     return;
   3575 
   3576   // When navigating to a new page, reset the page scale factor to be 1.0.
   3577   webview()->setInitialPageScaleOverride(1.f);
   3578 
   3579   if (enable_fixed_layout) {
   3580     std::string str =
   3581         command_line.GetSwitchValueASCII(switches::kEnableFixedLayout);
   3582     std::vector<std::string> tokens;
   3583     base::SplitString(str, ',', &tokens);
   3584     if (tokens.size() == 2) {
   3585       int width, height;
   3586       if (base::StringToInt(tokens[0], &width) &&
   3587           base::StringToInt(tokens[1], &height))
   3588         webview()->setFixedLayoutSize(WebSize(width, height));
   3589     }
   3590   }
   3591   float maxPageScaleFactor =
   3592       command_line.HasSwitch(switches::kEnablePinch) ? 4.f : 1.f ;
   3593   webview()->setPageScaleFactorLimits(1, maxPageScaleFactor);
   3594 }
   3595 
   3596 void RenderViewImpl::didStartProvisionalLoad(WebFrame* frame) {
   3597   WebDataSource* ds = frame->provisionalDataSource();
   3598 
   3599   // In fast/loader/stop-provisional-loads.html, we abort the load before this
   3600   // callback is invoked.
   3601   if (!ds)
   3602     return;
   3603 
   3604   DocumentState* document_state = DocumentState::FromDataSource(ds);
   3605 
   3606   // We should only navigate to swappedout:// when is_swapped_out_ is true.
   3607   CHECK((ds->request().url() != GURL(kSwappedOutURL)) ||
   3608         is_swapped_out_) << "Heard swappedout:// when not swapped out.";
   3609 
   3610   // Update the request time if WebKit has better knowledge of it.
   3611   if (document_state->request_time().is_null()) {
   3612     double event_time = ds->triggeringEventTime();
   3613     if (event_time != 0.0)
   3614       document_state->set_request_time(Time::FromDoubleT(event_time));
   3615   }
   3616 
   3617   // Start time is only set after request time.
   3618   document_state->set_start_load_time(Time::Now());
   3619 
   3620   bool is_top_most = !frame->parent();
   3621   if (is_top_most) {
   3622     navigation_gesture_ = WebUserGestureIndicator::isProcessingUserGesture() ?
   3623         NavigationGestureUser : NavigationGestureAuto;
   3624 
   3625     // If the navigation is not triggered by a user gesture, e.g. by some ajax
   3626     // callback, then inherit the submitted password form from the previous
   3627     // state. This fixes the no password save issue for ajax login, tracked in
   3628     // [http://crbug/43219]. Note that there are still some sites that this
   3629     // fails for because they use some element other than a submit button to
   3630     // trigger submission.
   3631     if (navigation_gesture_ == NavigationGestureAuto) {
   3632       DocumentState* old_document_state = DocumentState::FromDataSource(
   3633           frame->dataSource());
   3634       const content::PasswordForm* old_password_form =
   3635           old_document_state->password_form_data();
   3636       if (old_password_form) {
   3637         document_state->set_password_form_data(
   3638             make_scoped_ptr(new content::PasswordForm(*old_password_form)));
   3639       }
   3640     }
   3641   } else if (frame->parent()->isLoading()) {
   3642     // Take note of AUTO_SUBFRAME loads here, so that we can know how to
   3643     // load an error page.  See didFailProvisionalLoad.
   3644     document_state->navigation_state()->set_transition_type(
   3645         PAGE_TRANSITION_AUTO_SUBFRAME);
   3646   }
   3647 
   3648   FOR_EACH_OBSERVER(
   3649       RenderViewObserver, observers_, DidStartProvisionalLoad(frame));
   3650 
   3651   Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
   3652        routing_id_, frame->identifier(),
   3653        frame->parent() ? frame->parent()->identifier() : -1,
   3654        is_top_most, ds->request().url()));
   3655 }
   3656 
   3657 void RenderViewImpl::didReceiveServerRedirectForProvisionalLoad(
   3658     WebFrame* frame) {
   3659   if (frame->parent())
   3660     return;
   3661   // Received a redirect on the main frame.
   3662   WebDataSource* data_source = frame->provisionalDataSource();
   3663   if (!data_source) {
   3664     // Should only be invoked when we have a data source.
   3665     NOTREACHED();
   3666     return;
   3667   }
   3668   std::vector<GURL> redirects;
   3669   GetRedirectChain(data_source, &redirects);
   3670   if (redirects.size() >= 2) {
   3671     Send(new ViewHostMsg_DidRedirectProvisionalLoad(routing_id_, page_id_,
   3672         redirects[redirects.size() - 2], redirects.back()));
   3673   }
   3674 }
   3675 
   3676 void RenderViewImpl::didFailProvisionalLoad(WebFrame* frame,
   3677                                             const WebURLError& error) {
   3678   // Notify the browser that we failed a provisional load with an error.
   3679   //
   3680   // Note: It is important this notification occur before DidStopLoading so the
   3681   //       SSL manager can react to the provisional load failure before being
   3682   //       notified the load stopped.
   3683   //
   3684   WebDataSource* ds = frame->provisionalDataSource();
   3685   DCHECK(ds);
   3686 
   3687   const WebURLRequest& failed_request = ds->request();
   3688 
   3689   FOR_EACH_OBSERVER(
   3690       RenderViewObserver, observers_, DidFailProvisionalLoad(frame, error));
   3691 
   3692   bool show_repost_interstitial =
   3693       (error.reason == net::ERR_CACHE_MISS &&
   3694        EqualsASCII(failed_request.httpMethod(), "POST"));
   3695 
   3696   ViewHostMsg_DidFailProvisionalLoadWithError_Params params;
   3697   params.frame_id = frame->identifier();
   3698   params.is_main_frame = !frame->parent();
   3699   params.error_code = error.reason;
   3700   GetContentClient()->renderer()->GetNavigationErrorStrings(
   3701       frame,
   3702       failed_request,
   3703       error,
   3704       NULL,
   3705       &params.error_description);
   3706   params.url = error.unreachableURL;
   3707   params.showing_repost_interstitial = show_repost_interstitial;
   3708   Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
   3709       routing_id_, params));
   3710 
   3711   // Don't display an error page if this is simply a cancelled load.  Aside
   3712   // from being dumb, WebCore doesn't expect it and it will cause a crash.
   3713   if (error.reason == net::ERR_ABORTED)
   3714     return;
   3715 
   3716   if (RenderThreadImpl::current()->layout_test_mode())
   3717     return;
   3718 
   3719   // Make sure we never show errors in view source mode.
   3720   frame->enableViewSourceMode(false);
   3721 
   3722   DocumentState* document_state = DocumentState::FromDataSource(ds);
   3723   NavigationState* navigation_state = document_state->navigation_state();
   3724 
   3725   // If this is a failed back/forward/reload navigation, then we need to do a
   3726   // 'replace' load.  This is necessary to avoid messing up session history.
   3727   // Otherwise, we do a normal load, which simulates a 'go' navigation as far
   3728   // as session history is concerned.
   3729   //
   3730   // AUTO_SUBFRAME loads should always be treated as loads that do not advance
   3731   // the page id.
   3732   //
   3733   bool replace =
   3734       navigation_state->pending_page_id() != -1 ||
   3735       PageTransitionCoreTypeIs(navigation_state->transition_type(),
   3736                                PAGE_TRANSITION_AUTO_SUBFRAME);
   3737 
   3738   // If we failed on a browser initiated request, then make sure that our error
   3739   // page load is regarded as the same browser initiated request.
   3740   if (!navigation_state->is_content_initiated()) {
   3741     pending_navigation_params_.reset(new ViewMsg_Navigate_Params);
   3742     pending_navigation_params_->page_id =
   3743         navigation_state->pending_page_id();
   3744     pending_navigation_params_->pending_history_list_offset =
   3745         navigation_state->pending_history_list_offset();
   3746     pending_navigation_params_->should_clear_history_list =
   3747         navigation_state->history_list_was_cleared();
   3748     pending_navigation_params_->transition =
   3749         navigation_state->transition_type();
   3750     pending_navigation_params_->request_time =
   3751         document_state->request_time();
   3752   }
   3753 
   3754   // Provide the user with a more helpful error page?
   3755   if (MaybeLoadAlternateErrorPage(frame, error, replace))
   3756     return;
   3757 
   3758   // Fallback to a local error page.
   3759   LoadNavigationErrorPage(frame, failed_request, error, std::string(), replace);
   3760 }
   3761 
   3762 void RenderViewImpl::didCommitProvisionalLoad(WebFrame* frame,
   3763                                               bool is_new_navigation) {
   3764   DocumentState* document_state =
   3765       DocumentState::FromDataSource(frame->dataSource());
   3766   NavigationState* navigation_state = document_state->navigation_state();
   3767   InternalDocumentStateData* internal_data =
   3768       InternalDocumentStateData::FromDocumentState(document_state);
   3769 
   3770   if (document_state->commit_load_time().is_null())
   3771     document_state->set_commit_load_time(Time::Now());
   3772 
   3773   if (internal_data->must_reset_scroll_and_scale_state()) {
   3774     webview()->resetScrollAndScaleState();
   3775     internal_data->set_must_reset_scroll_and_scale_state(false);
   3776   }
   3777   internal_data->set_use_error_page(false);
   3778 
   3779   if (is_new_navigation) {
   3780     // When we perform a new navigation, we need to update the last committed
   3781     // session history entry with state for the page we are leaving.
   3782     UpdateSessionHistory(frame);
   3783 
   3784     // We bump our Page ID to correspond with the new session history entry.
   3785     page_id_ = next_page_id_++;
   3786 
   3787     // Don't update history_page_ids_ (etc) for kSwappedOutURL, since
   3788     // we don't want to forget the entry that was there, and since we will
   3789     // never come back to kSwappedOutURL.  Note that we have to call
   3790     // UpdateSessionHistory and update page_id_ even in this case, so that
   3791     // the current entry gets a state update and so that we don't send a
   3792     // state update to the wrong entry when we swap back in.
   3793     if (GetLoadingUrl(frame) != GURL(kSwappedOutURL)) {
   3794       // Advance our offset in session history, applying the length limit.
   3795       // There is now no forward history.
   3796       history_list_offset_++;
   3797       if (history_list_offset_ >= kMaxSessionHistoryEntries)
   3798         history_list_offset_ = kMaxSessionHistoryEntries - 1;
   3799       history_list_length_ = history_list_offset_ + 1;
   3800       history_page_ids_.resize(history_list_length_, -1);
   3801       history_page_ids_[history_list_offset_] = page_id_;
   3802     }
   3803   } else {
   3804     // Inspect the navigation_state on this frame to see if the navigation
   3805     // corresponds to a session history navigation...  Note: |frame| may or
   3806     // may not be the toplevel frame, but for the case of capturing session
   3807     // history, the first committed frame suffices.  We keep track of whether
   3808     // we've seen this commit before so that only capture session history once
   3809     // per navigation.
   3810     //
   3811     // Note that we need to check if the page ID changed. In the case of a
   3812     // reload, the page ID doesn't change, and UpdateSessionHistory gets the
   3813     // previous URL and the current page ID, which would be wrong.
   3814     if (navigation_state->pending_page_id() != -1 &&
   3815         navigation_state->pending_page_id() != page_id_ &&
   3816         !navigation_state->request_committed()) {
   3817       // This is a successful session history navigation!
   3818       UpdateSessionHistory(frame);
   3819       page_id_ = navigation_state->pending_page_id();
   3820 
   3821       history_list_offset_ = navigation_state->pending_history_list_offset();
   3822 
   3823       // If the history list is valid, our list of page IDs should be correct.
   3824       DCHECK(history_list_length_ <= 0 ||
   3825              history_list_offset_ < 0 ||
   3826              history_list_offset_ >= history_list_length_ ||
   3827              history_page_ids_[history_list_offset_] == page_id_);
   3828     }
   3829   }
   3830 
   3831   FOR_EACH_OBSERVER(RenderViewObserver, observers_,
   3832                     DidCommitProvisionalLoad(frame, is_new_navigation));
   3833 
   3834   // Remember that we've already processed this request, so we don't update
   3835   // the session history again.  We do this regardless of whether this is
   3836   // a session history navigation, because if we attempted a session history
   3837   // navigation without valid HistoryItem state, WebCore will think it is a
   3838   // new navigation.
   3839   navigation_state->set_request_committed(true);
   3840 
   3841   UpdateURL(frame);
   3842 
   3843   // Check whether we have new encoding name.
   3844   UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
   3845 
   3846   if (!frame->parent()) {  // Only for top frames.
   3847     RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
   3848     if (render_thread_impl) {  // Can be NULL in tests.
   3849       render_thread_impl->histogram_customizer()->
   3850           RenderViewNavigatedToHost(GURL(GetLoadingUrl(frame)).host(),
   3851                                     g_view_map.Get().size());
   3852     }
   3853   }
   3854 }
   3855 
   3856 void RenderViewImpl::didClearWindowObject(WebFrame* frame) {
   3857   FOR_EACH_OBSERVER(RenderViewObserver, observers_,
   3858                     DidClearWindowObject(frame));
   3859 
   3860   if (enabled_bindings_ & BINDINGS_POLICY_DOM_AUTOMATION) {
   3861     if (!dom_automation_controller_)
   3862       dom_automation_controller_.reset(new DomAutomationController());
   3863     dom_automation_controller_->set_message_sender(
   3864         static_cast<RenderView*>(this));
   3865     dom_automation_controller_->set_routing_id(routing_id());
   3866     dom_automation_controller_->BindToJavascript(frame,
   3867                                                  "domAutomationController");
   3868   }
   3869 
   3870    if (enabled_bindings_ & BINDINGS_POLICY_STATS_COLLECTION) {
   3871      if (!stats_collection_controller_.get())
   3872        stats_collection_controller_.reset(new StatsCollectionController());
   3873      stats_collection_controller_->set_message_sender(
   3874          static_cast<RenderView*>(this));
   3875      stats_collection_controller_->BindToJavascript(frame,
   3876                                                   "statsCollectionController");
   3877    }
   3878 }
   3879 
   3880 void RenderViewImpl::didCreateDocumentElement(WebFrame* frame) {
   3881   FOR_EACH_OBSERVER(RenderViewObserver, observers_,
   3882                     DidCreateDocumentElement(frame));
   3883 }
   3884 
   3885 void RenderViewImpl::didReceiveTitle(WebFrame* frame, const WebString& title,
   3886                                      WebTextDirection direction) {
   3887   UpdateTitle(frame, title, direction);
   3888 
   3889   // Also check whether we have new encoding name.
   3890   UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
   3891 }
   3892 
   3893 void RenderViewImpl::didChangeIcon(WebFrame* frame,
   3894                                    WebIconURL::Type icon_type) {
   3895   if (frame->parent())
   3896     return;
   3897 
   3898   if (!TouchEnabled() && icon_type != WebIconURL::TypeFavicon)
   3899     return;
   3900 
   3901   WebVector<WebIconURL> icon_urls = frame->iconURLs(icon_type);
   3902   std::vector<FaviconURL> urls;
   3903   for (size_t i = 0; i < icon_urls.size(); i++) {
   3904     urls.push_back(FaviconURL(icon_urls[i].iconURL(),
   3905                               ToFaviconType(icon_urls[i].iconType())));
   3906   }
   3907   SendUpdateFaviconURL(urls);
   3908 }
   3909 
   3910 void RenderViewImpl::didFinishDocumentLoad(WebFrame* frame) {
   3911   WebDataSource* ds = frame->dataSource();
   3912   DocumentState* document_state = DocumentState::FromDataSource(ds);
   3913   document_state->set_finish_document_load_time(Time::Now());
   3914 
   3915   Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_, frame->identifier()));
   3916 
   3917   FOR_EACH_OBSERVER(RenderViewObserver, observers_,
   3918                     DidFinishDocumentLoad(frame));
   3919 
   3920   // Check whether we have new encoding name.
   3921   UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
   3922 }
   3923 
   3924 void RenderViewImpl::didHandleOnloadEvents(WebFrame* frame) {
   3925   if (webview()->mainFrame() == frame) {
   3926     Send(new ViewHostMsg_DocumentOnLoadCompletedInMainFrame(routing_id_,
   3927                                                             page_id_));
   3928   }
   3929 }
   3930 
   3931 void RenderViewImpl::didFailLoad(WebFrame* frame, const WebURLError& error) {
   3932   WebDataSource* ds = frame->dataSource();
   3933   DCHECK(ds);
   3934 
   3935 
   3936   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidFailLoad(frame, error));
   3937 
   3938   const WebURLRequest& failed_request = ds->request();
   3939   string16 error_description;
   3940   GetContentClient()->renderer()->GetNavigationErrorStrings(
   3941       frame,
   3942       failed_request,
   3943       error,
   3944       NULL,
   3945       &error_description);
   3946   Send(new ViewHostMsg_DidFailLoadWithError(routing_id_,
   3947                                             frame->identifier(),
   3948                                             failed_request.url(),
   3949                                             !frame->parent(),
   3950                                             error.reason,
   3951                                             error_description));
   3952 }
   3953 
   3954 void RenderViewImpl::didFinishLoad(WebFrame* frame) {
   3955   WebDataSource* ds = frame->dataSource();
   3956   DocumentState* document_state = DocumentState::FromDataSource(ds);
   3957   if (document_state->finish_load_time().is_null()) {
   3958     if (!frame->parent()) {
   3959       TRACE_EVENT_INSTANT0("WebCore", "LoadFinished",
   3960                            TRACE_EVENT_SCOPE_PROCESS);
   3961     }
   3962     document_state->set_finish_load_time(Time::Now());
   3963   }
   3964 
   3965   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidFinishLoad(frame));
   3966 
   3967   Send(new ViewHostMsg_DidFinishLoad(routing_id_,
   3968                                      frame->identifier(),
   3969                                      ds->request().url(),
   3970                                      !frame->parent()));
   3971 }
   3972 
   3973 void RenderViewImpl::didNavigateWithinPage(
   3974     WebFrame* frame, bool is_new_navigation) {
   3975   // If this was a reference fragment navigation that we initiated, then we
   3976   // could end up having a non-null pending navigation params.  We just need to
   3977   // update the ExtraData on the datasource so that others who read the
   3978   // ExtraData will get the new NavigationState.  Similarly, if we did not
   3979   // initiate this navigation, then we need to take care to reset any pre-
   3980   // existing navigation state to a content-initiated navigation state.
   3981   // DidCreateDataSource conveniently takes care of this for us.
   3982   didCreateDataSource(frame, frame->dataSource());
   3983 
   3984   DocumentState* document_state =
   3985       DocumentState::FromDataSource(frame->dataSource());
   3986   NavigationState* new_state = document_state->navigation_state();
   3987   new_state->set_was_within_same_page(true);
   3988 
   3989   didCommitProvisionalLoad(frame, is_new_navigation);
   3990 
   3991   WebDataSource* datasource = frame->view()->mainFrame()->dataSource();
   3992   UpdateTitle(frame, datasource->pageTitle(), datasource->pageTitleDirection());
   3993 }
   3994 
   3995 void RenderViewImpl::didUpdateCurrentHistoryItem(WebFrame* frame) {
   3996   StartNavStateSyncTimerIfNecessary();
   3997 }
   3998 
   3999 void RenderViewImpl::willSendRequest(WebFrame* frame,
   4000                                      unsigned identifier,
   4001                                      WebURLRequest& request,
   4002                                      const WebURLResponse& redirect_response) {
   4003   NOTREACHED();
   4004 }
   4005 
   4006 void RenderViewImpl::didReceiveResponse(
   4007     WebFrame* frame, unsigned identifier, const WebURLResponse& response) {
   4008   NOTREACHED();
   4009 }
   4010 
   4011 void RenderViewImpl::didFinishResourceLoad(
   4012     WebFrame* frame, unsigned identifier) {
   4013   InternalDocumentStateData* internal_data =
   4014       InternalDocumentStateData::FromDataSource(frame->dataSource());
   4015   if (!internal_data->use_error_page())
   4016     return;
   4017 
   4018   // Do not show error page when DevTools is attached.
   4019   if (devtools_agent_->IsAttached())
   4020     return;
   4021 
   4022   // Display error page, if appropriate.
   4023   int http_status_code = internal_data->http_status_code();
   4024   if (http_status_code == 404) {
   4025     // On 404s, try a remote search page as a fallback.
   4026     const GURL& document_url = frame->document().url();
   4027 
   4028     const GURL& error_page_url =
   4029         GetAlternateErrorPageURL(document_url, HTTP_404);
   4030     if (error_page_url.is_valid()) {
   4031       WebURLError original_error;
   4032       original_error.domain = "http";
   4033       original_error.reason = 404;
   4034       original_error.unreachableURL = document_url;
   4035 
   4036       internal_data->set_alt_error_page_fetcher(
   4037           new AltErrorPageResourceFetcher(
   4038               error_page_url, frame, frame->dataSource()->request(),
   4039               original_error,
   4040               base::Bind(&RenderViewImpl::AltErrorPageFinished,
   4041                          base::Unretained(this))));
   4042       return;
   4043     }
   4044   }
   4045 
   4046   std::string error_domain;
   4047   if (GetContentClient()->renderer()->HasErrorPage(
   4048           http_status_code, &error_domain)) {
   4049     WebURLError error;
   4050     error.unreachableURL = frame->document().url();
   4051     error.domain = WebString::fromUTF8(error_domain);
   4052     error.reason = http_status_code;
   4053 
   4054     LoadNavigationErrorPage(
   4055         frame, frame->dataSource()->request(), error, std::string(), true);
   4056   }
   4057 }
   4058 
   4059 void RenderViewImpl::didLoadResourceFromMemoryCache(
   4060     WebFrame* frame, const WebURLRequest& request,
   4061     const WebURLResponse& response) {
   4062   NOTREACHED();
   4063 }
   4064 
   4065 void RenderViewImpl::didDisplayInsecureContent(WebFrame* frame) {
   4066   NOTREACHED();
   4067 }
   4068 
   4069 void RenderViewImpl::didRunInsecureContent(
   4070     WebFrame* frame, const WebSecurityOrigin& origin, const WebURL& target) {
   4071   NOTREACHED();
   4072 }
   4073 
   4074 void RenderViewImpl::didExhaustMemoryAvailableForScript(WebFrame* frame) {
   4075   NOTREACHED();
   4076 }
   4077 
   4078 void RenderViewImpl::didCreateScriptContext(WebFrame* frame,
   4079                                             v8::Handle<v8::Context> context,
   4080                                             int extension_group,
   4081                                             int world_id) {
   4082   NOTREACHED();
   4083 }
   4084 
   4085 void RenderViewImpl::willReleaseScriptContext(WebFrame* frame,
   4086                                               v8::Handle<v8::Context> context,
   4087                                               int world_id) {
   4088   NOTREACHED();
   4089 }
   4090 
   4091 void RenderViewImpl::CheckPreferredSize() {
   4092   // We don't always want to send the change messages over IPC, only if we've
   4093   // been put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
   4094   // message.
   4095   if (!send_preferred_size_changes_ || !webview())
   4096     return;
   4097 
   4098   gfx::Size size = webview()->contentsPreferredMinimumSize();
   4099 
   4100   // In the presence of zoom, these sizes are still reported as if unzoomed,
   4101   // so we need to adjust.
   4102   double zoom_factor = ZoomLevelToZoomFactor(webview()->zoomLevel());
   4103   size.set_width(static_cast<int>(size.width() * zoom_factor));
   4104   size.set_height(static_cast<int>(size.height() * zoom_factor));
   4105 
   4106   if (size == preferred_size_)
   4107     return;
   4108 
   4109   preferred_size_ = size;
   4110   Send(new ViewHostMsg_DidContentsPreferredSizeChange(routing_id_,
   4111                                                       preferred_size_));
   4112 }
   4113 
   4114 BrowserPluginManager* RenderViewImpl::GetBrowserPluginManager() {
   4115   if (!browser_plugin_manager_.get())
   4116     browser_plugin_manager_ = BrowserPluginManager::Create(this);
   4117   return browser_plugin_manager_.get();
   4118 }
   4119 
   4120 void RenderViewImpl::EnsureMediaStreamClient() {
   4121   if (!RenderThreadImpl::current())  // Will be NULL during unit tests.
   4122     return;
   4123 
   4124 #if defined(OS_ANDROID)
   4125   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebRTC))
   4126     return;
   4127 #endif
   4128 
   4129 #if defined(ENABLE_WEBRTC)
   4130   if (!media_stream_dispatcher_)
   4131     media_stream_dispatcher_ = new MediaStreamDispatcher(this);
   4132 
   4133   if (!media_stream_client_) {
   4134     MediaStreamImpl* media_stream_impl = new MediaStreamImpl(
   4135         this,
   4136         media_stream_dispatcher_,
   4137         RenderThreadImpl::current()->GetMediaStreamDependencyFactory());
   4138     media_stream_client_ = media_stream_impl;
   4139     web_user_media_client_ = media_stream_impl;
   4140   }
   4141 #endif
   4142 }
   4143 
   4144 void RenderViewImpl::didChangeContentsSize(WebFrame* frame,
   4145                                            const WebSize& size) {
   4146   if (webview()->mainFrame() != frame)
   4147     return;
   4148   WebView* frameView = frame->view();
   4149   if (!frameView)
   4150     return;
   4151 
   4152   bool has_horizontal_scrollbar = frame->hasHorizontalScrollbar();
   4153   bool has_vertical_scrollbar = frame->hasVerticalScrollbar();
   4154 
   4155   if (has_horizontal_scrollbar != cached_has_main_frame_horizontal_scrollbar_ ||
   4156       has_vertical_scrollbar != cached_has_main_frame_vertical_scrollbar_) {
   4157     Send(new ViewHostMsg_DidChangeScrollbarsForMainFrame(
   4158           routing_id_, has_horizontal_scrollbar, has_vertical_scrollbar));
   4159 
   4160     cached_has_main_frame_horizontal_scrollbar_ = has_horizontal_scrollbar;
   4161     cached_has_main_frame_vertical_scrollbar_ = has_vertical_scrollbar;
   4162   }
   4163 }
   4164 
   4165 void RenderViewImpl::UpdateScrollState(WebFrame* frame) {
   4166   WebSize offset = frame->scrollOffset();
   4167   WebSize minimum_offset = frame->minimumScrollOffset();
   4168   WebSize maximum_offset = frame->maximumScrollOffset();
   4169 
   4170   bool is_pinned_to_left = offset.width <= minimum_offset.width;
   4171   bool is_pinned_to_right = offset.width >= maximum_offset.width;
   4172 
   4173   if (is_pinned_to_left != cached_is_main_frame_pinned_to_left_ ||
   4174       is_pinned_to_right != cached_is_main_frame_pinned_to_right_) {
   4175     Send(new ViewHostMsg_DidChangeScrollOffsetPinningForMainFrame(
   4176           routing_id_, is_pinned_to_left, is_pinned_to_right));
   4177 
   4178     cached_is_main_frame_pinned_to_left_ = is_pinned_to_left;
   4179     cached_is_main_frame_pinned_to_right_ = is_pinned_to_right;
   4180   }
   4181 
   4182   Send(new ViewHostMsg_DidChangeScrollOffset(routing_id_));
   4183 }
   4184 
   4185 void RenderViewImpl::didChangeScrollOffset(WebFrame* frame) {
   4186   StartNavStateSyncTimerIfNecessary();
   4187 
   4188   if (webview()->mainFrame() == frame)
   4189     UpdateScrollState(frame);
   4190 
   4191   FOR_EACH_OBSERVER(
   4192       RenderViewObserver, observers_, DidChangeScrollOffset(frame));
   4193 }
   4194 
   4195 void RenderViewImpl::willInsertBody(WebKit::WebFrame* frame) {
   4196   NOTREACHED();
   4197 }
   4198 
   4199 void RenderViewImpl::didFirstVisuallyNonEmptyLayout(WebFrame* frame) {
   4200   if (frame != webview()->mainFrame())
   4201     return;
   4202 
   4203   InternalDocumentStateData* data =
   4204       InternalDocumentStateData::FromDataSource(frame->dataSource());
   4205   data->set_did_first_visually_non_empty_layout(true);
   4206 
   4207 #if defined(OS_ANDROID)
   4208   // Update body background color if necessary.
   4209   SkColor bg_color = webwidget_->backgroundColor();
   4210 
   4211   // If not initialized, default to white. Note that 0 is different from black
   4212   // as black still has alpha 0xFF.
   4213   if (!bg_color)
   4214     bg_color = SK_ColorWHITE;
   4215 
   4216   if (bg_color != body_background_color_) {
   4217     body_background_color_ = bg_color;
   4218     Send(new ViewHostMsg_DidChangeBodyBackgroundColor(
   4219         GetRoutingID(), bg_color));
   4220   }
   4221 #endif
   4222 }
   4223 
   4224 void RenderViewImpl::SendFindReply(int request_id,
   4225                                    int match_count,
   4226                                    int ordinal,
   4227                                    const WebRect& selection_rect,
   4228                                    bool final_status_update) {
   4229   Send(new ViewHostMsg_Find_Reply(routing_id_,
   4230                                   request_id,
   4231                                   match_count,
   4232                                   selection_rect,
   4233                                   ordinal,
   4234                                   final_status_update));
   4235 }
   4236 
   4237 // static
   4238 bool RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams(
   4239     const string16& selection_text,
   4240     size_t selection_text_offset,
   4241     const ui::Range& selection_range,
   4242     const ContextMenuParams& params) {
   4243   string16 trimmed_selection_text;
   4244   if (!selection_text.empty() && !selection_range.is_empty()) {
   4245     const int start = selection_range.GetMin() - selection_text_offset;
   4246     const size_t length = selection_range.length();
   4247     if (start >= 0 && start + length <= selection_text.length()) {
   4248       TrimWhitespace(selection_text.substr(start, length), TRIM_ALL,
   4249                      &trimmed_selection_text);
   4250     }
   4251   }
   4252   string16 trimmed_params_text;
   4253   TrimWhitespace(params.selection_text, TRIM_ALL, &trimmed_params_text);
   4254   return trimmed_params_text != trimmed_selection_text;
   4255 }
   4256 
   4257 void RenderViewImpl::reportFindInPageMatchCount(int request_id,
   4258                                                 int count,
   4259                                                 bool final_update) {
   4260   // TODO(jam): switch PepperPluginInstanceImpl to take a RenderFrame
   4261   main_render_frame_->reportFindInPageMatchCount(
   4262       request_id, count, final_update);
   4263 }
   4264 
   4265 void RenderViewImpl::reportFindInPageSelection(int request_id,
   4266                                                int active_match_ordinal,
   4267                                                const WebRect& selection_rect) {
   4268   // TODO(jam): switch PepperPluginInstanceImpl to take a RenderFrame
   4269   main_render_frame_->reportFindInPageSelection(
   4270       request_id, active_match_ordinal, selection_rect);
   4271 }
   4272 
   4273 void RenderViewImpl::openFileSystem(
   4274     WebFrame* frame,
   4275     WebKit::WebFileSystemType type,
   4276     long long size,
   4277     bool create,
   4278     WebFileSystemCallbacks* callbacks) {
   4279   NOTREACHED();
   4280 }
   4281 
   4282 void RenderViewImpl::deleteFileSystem(
   4283     WebFrame* frame,
   4284     WebKit::WebFileSystemType type ,
   4285     WebFileSystemCallbacks* callbacks) {
   4286   NOTREACHED();
   4287 }
   4288 
   4289 void RenderViewImpl::requestStorageQuota(
   4290     WebFrame* frame,
   4291     WebStorageQuotaType type,
   4292     unsigned long long requested_size,
   4293     WebStorageQuotaCallbacks* callbacks) {
   4294   NOTREACHED();
   4295 }
   4296 
   4297 bool RenderViewImpl::willCheckAndDispatchMessageEvent(
   4298     WebKit::WebFrame* sourceFrame,
   4299     WebKit::WebFrame* targetFrame,
   4300     WebKit::WebSecurityOrigin target_origin,
   4301     WebKit::WebDOMMessageEvent event) {
   4302   if (!is_swapped_out_)
   4303     return false;
   4304 
   4305   ViewMsg_PostMessage_Params params;
   4306   params.data = event.data().toString();
   4307   params.source_origin = event.origin();
   4308   if (!target_origin.isNull())
   4309     params.target_origin = target_origin.toString();
   4310 
   4311   // Include the routing ID for the source frame, which the browser process
   4312   // will translate into the routing ID for the equivalent frame in the target
   4313   // process.
   4314   params.source_routing_id = MSG_ROUTING_NONE;
   4315   RenderViewImpl* source_view = FromWebView(sourceFrame->view());
   4316   if (source_view)
   4317     params.source_routing_id = source_view->routing_id();
   4318 
   4319   Send(new ViewHostMsg_RouteMessageEvent(routing_id_, params));
   4320   return true;
   4321 }
   4322 
   4323 void RenderViewImpl::willOpenSocketStream(
   4324     WebSocketStreamHandle* handle) {
   4325   NOTREACHED();
   4326 }
   4327 
   4328 void RenderViewImpl::willStartUsingPeerConnectionHandler(
   4329     WebKit::WebFrame* frame, WebKit::WebRTCPeerConnectionHandler* handler) {
   4330   NOTREACHED();
   4331 }
   4332 
   4333 WebKit::WebString RenderViewImpl::acceptLanguages() {
   4334   return WebString::fromUTF8(renderer_preferences_.accept_languages);
   4335 }
   4336 
   4337 WebKit::WebString RenderViewImpl::userAgentOverride(
   4338     WebKit::WebFrame* frame,
   4339     const WebKit::WebURL& url) {
   4340   NOTREACHED();
   4341   return WebKit::WebString();
   4342 }
   4343 
   4344 WebString RenderViewImpl::doNotTrackValue(WebFrame* frame) {
   4345   NOTREACHED();
   4346   return WebKit::WebString();
   4347 }
   4348 
   4349 bool RenderViewImpl::allowWebGL(WebFrame* frame, bool default_value) {
   4350   NOTREACHED();
   4351   return false;
   4352 }
   4353 
   4354 void RenderViewImpl::didLoseWebGLContext(
   4355     WebKit::WebFrame* frame,
   4356     int arb_robustness_status_code) {
   4357   NOTREACHED();
   4358 }
   4359 
   4360 // WebKit::WebPageSerializerClient implementation ------------------------------
   4361 
   4362 void RenderViewImpl::didSerializeDataForFrame(
   4363     const WebURL& frame_url,
   4364     const WebCString& data,
   4365     WebPageSerializerClient::PageSerializationStatus status) {
   4366   Send(new ViewHostMsg_SendSerializedHtmlData(
   4367     routing_id(),
   4368     frame_url,
   4369     data.data(),
   4370     static_cast<int32>(status)));
   4371 }
   4372 
   4373 // RenderView implementation ---------------------------------------------------
   4374 
   4375 bool RenderViewImpl::Send(IPC::Message* message) {
   4376   return RenderWidget::Send(message);
   4377 }
   4378 
   4379 int RenderViewImpl::GetRoutingID() const {
   4380   return routing_id_;
   4381 }
   4382 
   4383 int RenderViewImpl::GetPageId() const {
   4384   return page_id_;
   4385 }
   4386 
   4387 gfx::Size RenderViewImpl::GetSize() const {
   4388   return size();
   4389 }
   4390 
   4391 WebPreferences& RenderViewImpl::GetWebkitPreferences() {
   4392   return webkit_preferences_;
   4393 }
   4394 
   4395 void RenderViewImpl::SetWebkitPreferences(const WebPreferences& preferences) {
   4396   OnUpdateWebPreferences(preferences);
   4397 }
   4398 
   4399 WebKit::WebView* RenderViewImpl::GetWebView() {
   4400   return webview();
   4401 }
   4402 
   4403 WebKit::WebNode RenderViewImpl::GetFocusedNode() const {
   4404   if (!webview())
   4405     return WebNode();
   4406   WebFrame* focused_frame = webview()->focusedFrame();
   4407   if (focused_frame) {
   4408     WebDocument doc = focused_frame->document();
   4409     if (!doc.isNull())
   4410       return doc.focusedNode();
   4411   }
   4412 
   4413   return WebNode();
   4414 }
   4415 
   4416 WebKit::WebNode RenderViewImpl::GetContextMenuNode() const {
   4417   return context_menu_node_;
   4418 }
   4419 
   4420 bool RenderViewImpl::IsEditableNode(const WebNode& node) const {
   4421   if (node.isNull())
   4422     return false;
   4423 
   4424   if (node.isContentEditable())
   4425     return true;
   4426 
   4427   if (node.isElementNode()) {
   4428     const WebElement& element = node.toConst<WebElement>();
   4429     if (element.isTextFormControlElement())
   4430       return true;
   4431 
   4432     // Also return true if it has an ARIA role of 'textbox'.
   4433     for (unsigned i = 0; i < element.attributeCount(); ++i) {
   4434       if (LowerCaseEqualsASCII(element.attributeLocalName(i), "role")) {
   4435         if (LowerCaseEqualsASCII(element.attributeValue(i), "textbox"))
   4436           return true;
   4437         break;
   4438       }
   4439     }
   4440   }
   4441 
   4442   return false;
   4443 }
   4444 
   4445 WebKit::WebPlugin* RenderViewImpl::CreatePlugin(
   4446     WebKit::WebFrame* frame,
   4447     const WebPluginInfo& info,
   4448     const WebKit::WebPluginParams& params) {
   4449 #if defined(ENABLE_PLUGINS)
   4450   bool pepper_plugin_was_registered = false;
   4451   scoped_refptr<PluginModule> pepper_module(PluginModule::Create(
   4452       this, info, &pepper_plugin_was_registered));
   4453   if (pepper_plugin_was_registered) {
   4454     if (pepper_module.get())
   4455       return new PepperWebPluginImpl(pepper_module.get(), params, AsWeakPtr());
   4456   }
   4457 
   4458   return new WebPluginImpl(frame, params, info.path, AsWeakPtr());
   4459 #else
   4460   return NULL;
   4461 #endif
   4462 }
   4463 
   4464 void RenderViewImpl::EvaluateScript(const string16& frame_xpath,
   4465                                     const string16& jscript,
   4466                                     int id,
   4467                                     bool notify_result) {
   4468   v8::HandleScope handle_scope;
   4469   v8::Handle<v8::Value> result;
   4470   WebFrame* web_frame = GetChildFrame(frame_xpath);
   4471   if (web_frame)
   4472     result = web_frame->executeScriptAndReturnValue(WebScriptSource(jscript));
   4473   if (notify_result) {
   4474     base::ListValue list;
   4475     if (!result.IsEmpty() && web_frame) {
   4476       v8::Local<v8::Context> context = web_frame->mainWorldScriptContext();
   4477       v8::Context::Scope context_scope(context);
   4478       V8ValueConverterImpl converter;
   4479       converter.SetDateAllowed(true);
   4480       converter.SetRegExpAllowed(true);
   4481       base::Value* result_value = converter.FromV8Value(result, context);
   4482       list.Set(0, result_value ? result_value : base::Value::CreateNullValue());
   4483     } else {
   4484       list.Set(0, base::Value::CreateNullValue());
   4485     }
   4486     Send(new ViewHostMsg_ScriptEvalResponse(routing_id_, id, list));
   4487   }
   4488 }
   4489 
   4490 bool RenderViewImpl::ShouldDisplayScrollbars(int width, int height) const {
   4491   return (!send_preferred_size_changes_ ||
   4492           (disable_scrollbars_size_limit_.width() <= width ||
   4493            disable_scrollbars_size_limit_.height() <= height));
   4494 }
   4495 
   4496 int RenderViewImpl::GetEnabledBindings() const {
   4497   return enabled_bindings_;
   4498 }
   4499 
   4500 bool RenderViewImpl::GetContentStateImmediately() const {
   4501   return send_content_state_immediately_;
   4502 }
   4503 
   4504 float RenderViewImpl::GetFilteredTimePerFrame() const {
   4505   return filtered_time_per_frame();
   4506 }
   4507 
   4508 int RenderViewImpl::ShowContextMenu(ContextMenuClient* client,
   4509                                     const ContextMenuParams& params) {
   4510   DCHECK(client);  // A null client means "internal" when we issue callbacks.
   4511   ContextMenuParams our_params(params);
   4512   our_params.custom_context.request_id = pending_context_menus_.Add(client);
   4513   Send(new ViewHostMsg_ContextMenu(routing_id_, our_params));
   4514   return our_params.custom_context.request_id;
   4515 }
   4516 
   4517 void RenderViewImpl::CancelContextMenu(int request_id) {
   4518   DCHECK(pending_context_menus_.Lookup(request_id));
   4519   pending_context_menus_.Remove(request_id);
   4520 }
   4521 
   4522 WebKit::WebPageVisibilityState RenderViewImpl::GetVisibilityState() const {
   4523   return visibilityState();
   4524 }
   4525 
   4526 void RenderViewImpl::RunModalAlertDialog(WebKit::WebFrame* frame,
   4527                                          const WebKit::WebString& message) {
   4528   return runModalAlertDialog(frame, message);
   4529 }
   4530 
   4531 void RenderViewImpl::LoadURLExternally(
   4532     WebKit::WebFrame* frame,
   4533     const WebKit::WebURLRequest& request,
   4534     WebKit::WebNavigationPolicy policy) {
   4535   main_render_frame_->loadURLExternally(frame, request, policy);
   4536 }
   4537 
   4538 void RenderViewImpl::DidStartLoading() {
   4539   didStartLoading();
   4540 }
   4541 
   4542 void RenderViewImpl::DidStopLoading() {
   4543   didStopLoading();
   4544 }
   4545 
   4546 void RenderViewImpl::DidPlay(WebKit::WebMediaPlayer* player) {
   4547   Send(new ViewHostMsg_MediaNotification(routing_id_,
   4548                                          reinterpret_cast<int64>(player),
   4549                                          player->hasVideo(),
   4550                                          player->hasAudio(),
   4551                                          true));
   4552 }
   4553 
   4554 void RenderViewImpl::DidPause(WebKit::WebMediaPlayer* player) {
   4555   Send(new ViewHostMsg_MediaNotification(routing_id_,
   4556                                          reinterpret_cast<int64>(player),
   4557                                          player->hasVideo(),
   4558                                          player->hasAudio(),
   4559                                          false));
   4560 }
   4561 
   4562 void RenderViewImpl::PlayerGone(WebKit::WebMediaPlayer* player) {
   4563   DidPause(player);
   4564 }
   4565 
   4566 void RenderViewImpl::SyncNavigationState() {
   4567   if (!webview())
   4568     return;
   4569 
   4570   const WebHistoryItem& item = webview()->mainFrame()->currentHistoryItem();
   4571   SendUpdateState(item);
   4572 }
   4573 
   4574 void RenderViewImpl::SyncSelectionIfRequired() {
   4575   WebFrame* frame = webview()->focusedFrame();
   4576   if (!frame)
   4577     return;
   4578 
   4579   string16 text;
   4580   size_t offset;
   4581   ui::Range range;
   4582 #if defined(ENABLE_PLUGINS)
   4583   if (focused_pepper_plugin_) {
   4584     focused_pepper_plugin_->GetSurroundingText(&text, &range);
   4585     offset = 0;  // Pepper API does not support offset reporting.
   4586     // TODO(kinaba): cut as needed.
   4587   } else
   4588 #endif
   4589   {
   4590     size_t location, length;
   4591     if (!webview()->caretOrSelectionRange(&location, &length))
   4592       return;
   4593 
   4594     range = ui::Range(location, location + length);
   4595 
   4596     if (webview()->textInputInfo().type != WebKit::WebTextInputTypeNone) {
   4597       // If current focused element is editable, we will send 100 more chars
   4598       // before and after selection. It is for input method surrounding text
   4599       // feature.
   4600       if (location > kExtraCharsBeforeAndAfterSelection)
   4601         offset = location - kExtraCharsBeforeAndAfterSelection;
   4602       else
   4603         offset = 0;
   4604       length = location + length - offset + kExtraCharsBeforeAndAfterSelection;
   4605       WebRange webrange = WebRange::fromDocumentRange(frame, offset, length);
   4606       if (!webrange.isNull())
   4607         text = WebRange::fromDocumentRange(frame, offset, length).toPlainText();
   4608     } else {
   4609       offset = location;
   4610       text = frame->selectionAsText();
   4611       // http://crbug.com/101435
   4612       // In some case, frame->selectionAsText() returned text's length is not
   4613       // equal to the length returned from webview()->caretOrSelectionRange().
   4614       // So we have to set the range according to text.length().
   4615       range.set_end(range.start() + text.length());
   4616     }
   4617   }
   4618 
   4619   // Sometimes we get repeated didChangeSelection calls from webkit when
   4620   // the selection hasn't actually changed. We don't want to report these
   4621   // because it will cause us to continually claim the X clipboard.
   4622   if (selection_text_offset_ != offset ||
   4623       selection_range_ != range ||
   4624       selection_text_ != text) {
   4625     selection_text_ = text;
   4626     selection_text_offset_ = offset;
   4627     selection_range_ = range;
   4628     Send(new ViewHostMsg_SelectionChanged(routing_id_, text, offset, range));
   4629   }
   4630   UpdateSelectionBounds();
   4631 }
   4632 
   4633 GURL RenderViewImpl::GetAlternateErrorPageURL(const GURL& failed_url,
   4634                                               ErrorPageType error_type) {
   4635   if (failed_url.SchemeIsSecure()) {
   4636     // If the URL that failed was secure, then the embedding web page was not
   4637     // expecting a network attacker to be able to manipulate its contents.  As
   4638     // we fetch alternate error pages over HTTP, we would be allowing a network
   4639     // attacker to manipulate the contents of the response if we tried to use
   4640     // the link doctor here.
   4641     return GURL();
   4642   }
   4643 
   4644   // Grab the base URL from the browser process.
   4645   if (!alternate_error_page_url_.is_valid())
   4646     return GURL();
   4647 
   4648   // Strip query params from the failed URL.
   4649   GURL::Replacements remove_params;
   4650   remove_params.ClearUsername();
   4651   remove_params.ClearPassword();
   4652   remove_params.ClearQuery();
   4653   remove_params.ClearRef();
   4654   const GURL url_to_send = failed_url.ReplaceComponents(remove_params);
   4655   std::string spec_to_send = url_to_send.spec();
   4656   // Notify link doctor of the url truncation by sending of "?" at the end.
   4657   if (failed_url.has_query())
   4658     spec_to_send.append("?");
   4659 
   4660   // Construct the query params to send to link doctor.
   4661   std::string params(alternate_error_page_url_.query());
   4662   params.append("&url=");
   4663   params.append(net::EscapeQueryParamValue(spec_to_send, true));
   4664   params.append("&sourceid=chrome");
   4665   params.append("&error=");
   4666   switch (error_type) {
   4667     case DNS_ERROR:
   4668       params.append("dnserror");
   4669       break;
   4670 
   4671     case HTTP_404:
   4672       params.append("http404");
   4673       break;
   4674 
   4675     case CONNECTION_ERROR:
   4676       params.append("connectionfailure");
   4677       break;
   4678 
   4679     default:
   4680       NOTREACHED() << "unknown ErrorPageType";
   4681   }
   4682 
   4683   // OK, build the final url to return.
   4684   GURL::Replacements link_doctor_params;
   4685   link_doctor_params.SetQueryStr(params);
   4686   GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params);
   4687   return url;
   4688 }
   4689 
   4690 GURL RenderViewImpl::GetLoadingUrl(WebKit::WebFrame* frame) const {
   4691   WebDataSource* ds = frame->dataSource();
   4692   if (ds->hasUnreachableURL())
   4693     return ds->unreachableURL();
   4694 
   4695   const WebURLRequest& request = ds->request();
   4696   return request.url();
   4697 }
   4698 
   4699 WebKit::WebPlugin* RenderViewImpl::GetWebPluginFromPluginDocument() {
   4700   return webview()->mainFrame()->document().to<WebPluginDocument>().plugin();
   4701 }
   4702 
   4703 void RenderViewImpl::OnFind(int request_id,
   4704                             const string16& search_text,
   4705                             const WebFindOptions& options) {
   4706   WebFrame* main_frame = webview()->mainFrame();
   4707 
   4708   // Check if the plugin still exists in the document.
   4709   if (main_frame->document().isPluginDocument() &&
   4710       GetWebPluginFromPluginDocument()) {
   4711     if (options.findNext) {
   4712       // Just navigate back/forward.
   4713       GetWebPluginFromPluginDocument()->selectFindResult(options.forward);
   4714     } else {
   4715       if (!GetWebPluginFromPluginDocument()->startFind(
   4716           search_text, options.matchCase, request_id)) {
   4717         // Send "no results".
   4718         SendFindReply(request_id, 0, 0, gfx::Rect(), true);
   4719       }
   4720     }
   4721     return;
   4722   }
   4723 
   4724   WebFrame* frame_after_main = main_frame->traverseNext(true);
   4725   WebFrame* focused_frame = webview()->focusedFrame();
   4726   WebFrame* search_frame = focused_frame;  // start searching focused frame.
   4727 
   4728   bool multi_frame = (frame_after_main != main_frame);
   4729 
   4730   // If we have multiple frames, we don't want to wrap the search within the
   4731   // frame, so we check here if we only have main_frame in the chain.
   4732   bool wrap_within_frame = !multi_frame;
   4733 
   4734   WebRect selection_rect;
   4735   bool result = false;
   4736 
   4737   // If something is selected when we start searching it means we cannot just
   4738   // increment the current match ordinal; we need to re-generate it.
   4739   WebRange current_selection = focused_frame->selectionRange();
   4740 
   4741   do {
   4742     result = search_frame->find(
   4743         request_id, search_text, options, wrap_within_frame, &selection_rect);
   4744 
   4745     if (!result) {
   4746       // don't leave text selected as you move to the next frame.
   4747       search_frame->executeCommand(WebString::fromUTF8("Unselect"),
   4748                                    GetFocusedNode());
   4749 
   4750       // Find the next frame, but skip the invisible ones.
   4751       do {
   4752         // What is the next frame to search? (we might be going backwards). Note
   4753         // that we specify wrap=true so that search_frame never becomes NULL.
   4754         search_frame = options.forward ?
   4755             search_frame->traverseNext(true) :
   4756             search_frame->traversePrevious(true);
   4757       } while (!search_frame->hasVisibleContent() &&
   4758                search_frame != focused_frame);
   4759 
   4760       // Make sure selection doesn't affect the search operation in new frame.
   4761       search_frame->executeCommand(WebString::fromUTF8("Unselect"),
   4762                                    GetFocusedNode());
   4763 
   4764       // If we have multiple frames and we have wrapped back around to the
   4765       // focused frame, we need to search it once more allowing wrap within
   4766       // the frame, otherwise it will report 'no match' if the focused frame has
   4767       // reported matches, but no frames after the focused_frame contain a
   4768       // match for the search word(s).
   4769       if (multi_frame && search_frame == focused_frame) {
   4770         result = search_frame->find(
   4771             request_id, search_text, options, true,  // Force wrapping.
   4772             &selection_rect);
   4773       }
   4774     }
   4775 
   4776     webview()->setFocusedFrame(search_frame);
   4777   } while (!result && search_frame != focused_frame);
   4778 
   4779   if (options.findNext && current_selection.isNull()) {
   4780     // Force the main_frame to report the actual count.
   4781     main_frame->increaseMatchCount(0, request_id);
   4782   } else {
   4783     // If nothing is found, set result to "0 of 0", otherwise, set it to
   4784     // "-1 of 1" to indicate that we found at least one item, but we don't know
   4785     // yet what is active.
   4786     int ordinal = result ? -1 : 0;  // -1 here means, we might know more later.
   4787     int match_count = result ? 1 : 0;  // 1 here means possibly more coming.
   4788 
   4789     // If we find no matches then this will be our last status update.
   4790     // Otherwise the scoping effort will send more results.
   4791     bool final_status_update = !result;
   4792 
   4793     SendFindReply(request_id, match_count, ordinal, selection_rect,
   4794                   final_status_update);
   4795 
   4796     // Scoping effort begins, starting with the mainframe.
   4797     search_frame = main_frame;
   4798 
   4799     main_frame->resetMatchCount();
   4800 
   4801     do {
   4802       // Cancel all old scoping requests before starting a new one.
   4803       search_frame->cancelPendingScopingEffort();
   4804 
   4805       // We don't start another scoping effort unless at least one match has
   4806       // been found.
   4807       if (result) {
   4808         // Start new scoping request. If the scoping function determines that it
   4809         // needs to scope, it will defer until later.
   4810         search_frame->scopeStringMatches(request_id,
   4811                                          search_text,
   4812                                          options,
   4813                                          true);  // reset the tickmarks
   4814       }
   4815 
   4816       // Iterate to the next frame. The frame will not necessarily scope, for
   4817       // example if it is not visible.
   4818       search_frame = search_frame->traverseNext(true);
   4819     } while (search_frame != main_frame);
   4820   }
   4821 }
   4822 
   4823 void RenderViewImpl::OnStopFinding(StopFindAction action) {
   4824   WebView* view = webview();
   4825   if (!view)
   4826     return;
   4827 
   4828   WebDocument doc = view->mainFrame()->document();
   4829   if (doc.isPluginDocument() && GetWebPluginFromPluginDocument()) {
   4830     GetWebPluginFromPluginDocument()->stopFind();
   4831     return;
   4832   }
   4833 
   4834   bool clear_selection = action == STOP_FIND_ACTION_CLEAR_SELECTION;
   4835   if (clear_selection) {
   4836     view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"),
   4837                                          GetFocusedNode());
   4838   }
   4839 
   4840   WebFrame* frame = view->mainFrame();
   4841   while (frame) {
   4842     frame->stopFinding(clear_selection);
   4843     frame = frame->traverseNext(false);
   4844   }
   4845 
   4846   if (action == STOP_FIND_ACTION_ACTIVATE_SELECTION) {
   4847     WebFrame* focused_frame = view->focusedFrame();
   4848     if (focused_frame) {
   4849       WebDocument doc = focused_frame->document();
   4850       if (!doc.isNull()) {
   4851         WebNode node = doc.focusedNode();
   4852         if (!node.isNull())
   4853           node.simulateClick();
   4854       }
   4855     }
   4856   }
   4857 }
   4858 
   4859 #if defined(OS_ANDROID)
   4860 void RenderViewImpl::OnActivateNearestFindResult(int request_id,
   4861                                                  float x, float y) {
   4862   if (!webview())
   4863       return;
   4864 
   4865   WebFrame* main_frame = webview()->mainFrame();
   4866   WebRect selection_rect;
   4867   int ordinal = main_frame->selectNearestFindMatch(WebFloatPoint(x, y),
   4868                                                    &selection_rect);
   4869   if (ordinal == -1) {
   4870     // Something went wrong, so send a no-op reply (force the main_frame to
   4871     // report the current match count) in case the host is waiting for a
   4872     // response due to rate-limiting).
   4873     main_frame->increaseMatchCount(0, request_id);
   4874     return;
   4875   }
   4876 
   4877   SendFindReply(request_id,
   4878                 -1 /* number_of_matches */,
   4879                 ordinal,
   4880                 selection_rect,
   4881                 true /* final_update */);
   4882 }
   4883 
   4884 void RenderViewImpl::OnFindMatchRects(int current_version) {
   4885   if (!webview())
   4886       return;
   4887 
   4888   WebFrame* main_frame = webview()->mainFrame();
   4889   std::vector<gfx::RectF> match_rects;
   4890 
   4891   int rects_version = main_frame->findMatchMarkersVersion();
   4892   if (current_version != rects_version) {
   4893     WebVector<WebFloatRect> web_match_rects;
   4894     main_frame->findMatchRects(web_match_rects);
   4895     match_rects.reserve(web_match_rects.size());
   4896     for (size_t i = 0; i < web_match_rects.size(); ++i)
   4897       match_rects.push_back(gfx::RectF(web_match_rects[i]));
   4898   }
   4899 
   4900   gfx::RectF active_rect = main_frame->activeFindMatchRect();
   4901   Send(new ViewHostMsg_FindMatchRects_Reply(routing_id_,
   4902                                                rects_version,
   4903                                                match_rects,
   4904                                                active_rect));
   4905 }
   4906 #endif
   4907 
   4908 void RenderViewImpl::OnZoom(PageZoom zoom) {
   4909   if (!webview())  // Not sure if this can happen, but no harm in being safe.
   4910     return;
   4911 
   4912   webview()->hidePopups();
   4913 
   4914   double old_zoom_level = webview()->zoomLevel();
   4915   double zoom_level;
   4916   if (zoom == PAGE_ZOOM_RESET) {
   4917     zoom_level = 0;
   4918   } else if (static_cast<int>(old_zoom_level) == old_zoom_level) {
   4919     // Previous zoom level is a whole number, so just increment/decrement.
   4920     zoom_level = old_zoom_level + zoom;
   4921   } else {
   4922     // Either the user hit the zoom factor limit and thus the zoom level is now
   4923     // not a whole number, or a plugin changed it to a custom value.  We want
   4924     // to go to the next whole number so that the user can always get back to
   4925     // 100% with the keyboard/menu.
   4926     if ((old_zoom_level > 1 && zoom > 0) ||
   4927         (old_zoom_level < 1 && zoom < 0)) {
   4928       zoom_level = static_cast<int>(old_zoom_level + zoom);
   4929     } else {
   4930       // We're going towards 100%, so first go to the next whole number.
   4931       zoom_level = static_cast<int>(old_zoom_level);
   4932     }
   4933   }
   4934   webview()->setZoomLevel(false, zoom_level);
   4935   zoomLevelChanged();
   4936 }
   4937 
   4938 void RenderViewImpl::OnZoomFactor(PageZoom zoom, int zoom_center_x,
   4939                                   int zoom_center_y) {
   4940   ZoomFactorHelper(zoom, zoom_center_x, zoom_center_y,
   4941                    kScalingIncrementForGesture);
   4942 }
   4943 
   4944 void RenderViewImpl::ZoomFactorHelper(PageZoom zoom,
   4945                                       int zoom_center_x,
   4946                                       int zoom_center_y,
   4947                                       float scaling_increment) {
   4948   if (!webview())  // Not sure if this can happen, but no harm in being safe.
   4949     return;
   4950 
   4951   double old_page_scale_factor = webview()->pageScaleFactor();
   4952   double page_scale_factor;
   4953   if (zoom == PAGE_ZOOM_RESET) {
   4954     page_scale_factor = 1.0;
   4955   } else {
   4956     page_scale_factor = old_page_scale_factor +
   4957         (zoom > 0 ? scaling_increment : -scaling_increment);
   4958   }
   4959   if (page_scale_factor > 0) {
   4960     webview()->setPageScaleFactor(page_scale_factor,
   4961                                   WebPoint(zoom_center_x, zoom_center_y));
   4962   }
   4963 }
   4964 
   4965 void RenderViewImpl::OnSetZoomLevel(double zoom_level) {
   4966   webview()->hidePopups();
   4967   webview()->setZoomLevel(false, zoom_level);
   4968   zoomLevelChanged();
   4969 }
   4970 
   4971 void RenderViewImpl::OnSetZoomLevelForLoadingURL(const GURL& url,
   4972                                                  double zoom_level) {
   4973 #if !defined(OS_ANDROID)
   4974   // On Android, page zoom isn't used, and in case of WebView, text zoom is used
   4975   // for legacy WebView text scaling emulation. Thus, the code that resets
   4976   // the zoom level from this map will be effectively resetting text zoom level.
   4977   host_zoom_levels_[url] = zoom_level;
   4978 #endif
   4979 }
   4980 
   4981 void RenderViewImpl::OnSetPageEncoding(const std::string& encoding_name) {
   4982   webview()->setPageEncoding(WebString::fromUTF8(encoding_name));
   4983 }
   4984 
   4985 void RenderViewImpl::OnResetPageEncodingToDefault() {
   4986   WebString no_encoding;
   4987   webview()->setPageEncoding(no_encoding);
   4988 }
   4989 
   4990 WebFrame* RenderViewImpl::GetChildFrame(const string16& xpath) const {
   4991   if (xpath.empty())
   4992     return webview()->mainFrame();
   4993 
   4994   // xpath string can represent a frame deep down the tree (across multiple
   4995   // frame DOMs).
   4996   // Example, /html/body/table/tbody/tr/td/iframe\n/frameset/frame[0]
   4997   // should break into 2 xpaths
   4998   // /html/body/table/tbody/tr/td/iframe & /frameset/frame[0]
   4999   std::vector<string16> xpaths;
   5000   base::SplitString(xpath, '\n', &xpaths);
   5001 
   5002   WebFrame* frame = webview()->mainFrame();
   5003   for (std::vector<string16>::const_iterator i = xpaths.begin();
   5004        frame && i != xpaths.end(); ++i) {
   5005     frame = frame->findChildByExpression(*i);
   5006   }
   5007 
   5008   return frame;
   5009 }
   5010 
   5011 void RenderViewImpl::OnScriptEvalRequest(const string16& frame_xpath,
   5012                                          const string16& jscript,
   5013                                          int id,
   5014                                          bool notify_result) {
   5015   TRACE_EVENT_INSTANT0("test_tracing", "OnScriptEvalRequest",
   5016                        TRACE_EVENT_SCOPE_THREAD);
   5017   EvaluateScript(frame_xpath, jscript, id, notify_result);
   5018 }
   5019 
   5020 void RenderViewImpl::OnPostMessageEvent(
   5021     const ViewMsg_PostMessage_Params& params) {
   5022   // TODO(nasko): Support sending to subframes.
   5023   WebFrame* frame = webview()->mainFrame();
   5024 
   5025   // Find the source frame if it exists.
   5026   WebFrame* source_frame = NULL;
   5027   if (params.source_routing_id != MSG_ROUTING_NONE) {
   5028     RenderViewImpl* source_view = FromRoutingID(params.source_routing_id);
   5029     if (source_view)
   5030       source_frame = source_view->webview()->mainFrame();
   5031   }
   5032 
   5033   // Create an event with the message.  The final parameter to initMessageEvent
   5034   // is the last event ID, which is not used with postMessage.
   5035   WebDOMEvent event = frame->document().createEvent("MessageEvent");
   5036   WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>();
   5037   msg_event.initMessageEvent("message",
   5038                              // |canBubble| and |cancellable| are always false
   5039                              false, false,
   5040                              WebSerializedScriptValue::fromString(params.data),
   5041                              params.source_origin, source_frame, "");
   5042 
   5043   // We must pass in the target_origin to do the security check on this side,
   5044   // since it may have changed since the original postMessage call was made.
   5045   WebSecurityOrigin target_origin;
   5046   if (!params.target_origin.empty()) {
   5047     target_origin =
   5048         WebSecurityOrigin::createFromString(WebString(params.target_origin));
   5049   }
   5050   frame->dispatchMessageEventWithOriginCheck(target_origin, msg_event);
   5051 }
   5052 
   5053 void RenderViewImpl::OnCSSInsertRequest(const string16& frame_xpath,
   5054                                         const std::string& css) {
   5055   WebFrame* frame = GetChildFrame(frame_xpath);
   5056   if (!frame)
   5057     return;
   5058 
   5059   frame->document().insertUserStyleSheet(
   5060       WebString::fromUTF8(css),
   5061       WebDocument::UserStyleAuthorLevel);
   5062 }
   5063 
   5064 void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags) {
   5065   if ((enabled_bindings_flags & BINDINGS_POLICY_WEB_UI) &&
   5066       !(enabled_bindings_ & BINDINGS_POLICY_WEB_UI)) {
   5067     RenderThread::Get()->RegisterExtension(WebUIExtension::Get());
   5068     new WebUIExtensionData(this);
   5069   }
   5070 
   5071   enabled_bindings_ |= enabled_bindings_flags;
   5072 
   5073   // Keep track of the total bindings accumulated in this process.
   5074   RenderProcess::current()->AddBindings(enabled_bindings_flags);
   5075 }
   5076 
   5077 void RenderViewImpl::OnDragTargetDragEnter(const DropData& drop_data,
   5078                                            const gfx::Point& client_point,
   5079                                            const gfx::Point& screen_point,
   5080                                            WebDragOperationsMask ops,
   5081                                            int key_modifiers) {
   5082   WebDragOperation operation = webview()->dragTargetDragEnter(
   5083       DropDataToWebDragData(drop_data),
   5084       client_point,
   5085       screen_point,
   5086       ops,
   5087       key_modifiers);
   5088 
   5089   Send(new DragHostMsg_UpdateDragCursor(routing_id_, operation));
   5090 }
   5091 
   5092 void RenderViewImpl::OnDragTargetDragOver(const gfx::Point& client_point,
   5093                                           const gfx::Point& screen_point,
   5094                                           WebDragOperationsMask ops,
   5095                                           int key_modifiers) {
   5096   WebDragOperation operation = webview()->dragTargetDragOver(
   5097       client_point,
   5098       screen_point,
   5099       ops,
   5100       key_modifiers);
   5101 
   5102   Send(new DragHostMsg_UpdateDragCursor(routing_id_, operation));
   5103 }
   5104 
   5105 void RenderViewImpl::OnDragTargetDragLeave() {
   5106   webview()->dragTargetDragLeave();
   5107 }
   5108 
   5109 void RenderViewImpl::OnDragTargetDrop(const gfx::Point& client_point,
   5110                                       const gfx::Point& screen_point,
   5111                                       int key_modifiers) {
   5112   webview()->dragTargetDrop(client_point, screen_point, key_modifiers);
   5113 
   5114   Send(new DragHostMsg_TargetDrop_ACK(routing_id_));
   5115 }
   5116 
   5117 void RenderViewImpl::OnDragSourceEndedOrMoved(const gfx::Point& client_point,
   5118                                               const gfx::Point& screen_point,
   5119                                               bool ended,
   5120                                               WebDragOperation op) {
   5121   if (ended) {
   5122     webview()->dragSourceEndedAt(client_point, screen_point, op);
   5123   } else {
   5124     webview()->dragSourceMovedTo(client_point, screen_point, op);
   5125   }
   5126 }
   5127 
   5128 void RenderViewImpl::OnDragSourceSystemDragEnded() {
   5129   webview()->dragSourceSystemDragEnded();
   5130 }
   5131 
   5132 void RenderViewImpl::OnUpdateWebPreferences(const WebPreferences& prefs) {
   5133   webkit_preferences_ = prefs;
   5134   webkit_glue::ApplyWebPreferences(webkit_preferences_, webview());
   5135 }
   5136 
   5137 void RenderViewImpl::OnUpdateTimezone() {
   5138   if (webview())
   5139     NotifyTimezoneChange(webview()->mainFrame());
   5140 }
   5141 
   5142 void RenderViewImpl::OnSetAltErrorPageURL(const GURL& url) {
   5143   alternate_error_page_url_ = url;
   5144 }
   5145 
   5146 void RenderViewImpl::OnCustomContextMenuAction(
   5147     const CustomContextMenuContext& custom_context,
   5148     unsigned action) {
   5149   if (custom_context.request_id) {
   5150     // External context menu request, look in our map.
   5151     ContextMenuClient* client =
   5152         pending_context_menus_.Lookup(custom_context.request_id);
   5153     if (client)
   5154       client->OnMenuAction(custom_context.request_id, action);
   5155   } else {
   5156     // Internal request, forward to WebKit.
   5157     webview()->performCustomContextMenuAction(action);
   5158   }
   5159 }
   5160 
   5161 void RenderViewImpl::OnEnumerateDirectoryResponse(
   5162     int id,
   5163     const std::vector<base::FilePath>& paths) {
   5164   if (!enumeration_completions_[id])
   5165     return;
   5166 
   5167   WebVector<WebString> ws_file_names(paths.size());
   5168   for (size_t i = 0; i < paths.size(); ++i)
   5169     ws_file_names[i] = paths[i].AsUTF16Unsafe();
   5170 
   5171   enumeration_completions_[id]->didChooseFile(ws_file_names);
   5172   enumeration_completions_.erase(id);
   5173 }
   5174 
   5175 void RenderViewImpl::OnFileChooserResponse(
   5176     const std::vector<ui::SelectedFileInfo>& files) {
   5177   // This could happen if we navigated to a different page before the user
   5178   // closed the chooser.
   5179   if (file_chooser_completions_.empty())
   5180     return;
   5181 
   5182   // Convert Chrome's SelectedFileInfo list to WebKit's.
   5183   WebVector<WebFileChooserCompletion::SelectedFileInfo> selected_files(
   5184       files.size());
   5185   for (size_t i = 0; i < files.size(); ++i) {
   5186     WebFileChooserCompletion::SelectedFileInfo selected_file;
   5187     selected_file.path = files[i].local_path.AsUTF16Unsafe();
   5188     selected_file.displayName =
   5189         base::FilePath(files[i].display_name).AsUTF16Unsafe();
   5190     selected_files[i] = selected_file;
   5191   }
   5192 
   5193   if (file_chooser_completions_.front()->completion)
   5194     file_chooser_completions_.front()->completion->didChooseFile(
   5195         selected_files);
   5196   file_chooser_completions_.pop_front();
   5197 
   5198   // If there are more pending file chooser requests, schedule one now.
   5199   if (!file_chooser_completions_.empty()) {
   5200     Send(new ViewHostMsg_RunFileChooser(routing_id_,
   5201         file_chooser_completions_.front()->params));
   5202   }
   5203 }
   5204 
   5205 void RenderViewImpl::OnEnableAutoResize(const gfx::Size& min_size,
   5206                                         const gfx::Size& max_size) {
   5207   DCHECK(disable_scrollbars_size_limit_.IsEmpty());
   5208   if (!webview())
   5209     return;
   5210   auto_resize_mode_ = true;
   5211   webview()->enableAutoResizeMode(min_size, max_size);
   5212 }
   5213 
   5214 void RenderViewImpl::OnDisableAutoResize(const gfx::Size& new_size) {
   5215   DCHECK(disable_scrollbars_size_limit_.IsEmpty());
   5216   if (!webview())
   5217     return;
   5218   auto_resize_mode_ = false;
   5219   webview()->disableAutoResizeMode();
   5220 
   5221   if (!new_size.IsEmpty()) {
   5222     Resize(new_size,
   5223            physical_backing_size_,
   5224            overdraw_bottom_height_,
   5225            resizer_rect_,
   5226            is_fullscreen_,
   5227            NO_RESIZE_ACK);
   5228   }
   5229 }
   5230 
   5231 void RenderViewImpl::OnEnablePreferredSizeChangedMode() {
   5232   if (send_preferred_size_changes_)
   5233     return;
   5234   send_preferred_size_changes_ = true;
   5235 
   5236   // Start off with an initial preferred size notification (in case
   5237   // |didUpdateLayout| was already called).
   5238   didUpdateLayout();
   5239 }
   5240 
   5241 void RenderViewImpl::OnDisableScrollbarsForSmallWindows(
   5242     const gfx::Size& disable_scrollbar_size_limit) {
   5243   disable_scrollbars_size_limit_ = disable_scrollbar_size_limit;
   5244 }
   5245 
   5246 void RenderViewImpl::OnSetRendererPrefs(
   5247     const RendererPreferences& renderer_prefs) {
   5248   double old_zoom_level = renderer_preferences_.default_zoom_level;
   5249   renderer_preferences_ = renderer_prefs;
   5250   UpdateFontRenderingFromRendererPrefs();
   5251 
   5252 #if defined(USE_DEFAULT_RENDER_THEME) || defined(TOOLKIT_GTK)
   5253   if (renderer_prefs.use_custom_colors) {
   5254     WebColorName name = WebKit::WebColorWebkitFocusRingColor;
   5255     WebKit::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1);
   5256     WebKit::setCaretBlinkInterval(renderer_prefs.caret_blink_interval);
   5257 #if defined(TOOLKIT_GTK)
   5258     ui::NativeTheme::instance()->SetScrollbarColors(
   5259         renderer_prefs.thumb_inactive_color,
   5260         renderer_prefs.thumb_active_color,
   5261         renderer_prefs.track_color);
   5262 #endif  // defined(TOOLKIT_GTK)
   5263 
   5264     if (webview()) {
   5265 #if defined(TOOLKIT_GTK)
   5266       webview()->setScrollbarColors(
   5267           renderer_prefs.thumb_inactive_color,
   5268           renderer_prefs.thumb_active_color,
   5269           renderer_prefs.track_color);
   5270 #endif  // defined(TOOLKIT_GTK)
   5271       webview()->setSelectionColors(
   5272           renderer_prefs.active_selection_bg_color,
   5273           renderer_prefs.active_selection_fg_color,
   5274           renderer_prefs.inactive_selection_bg_color,
   5275           renderer_prefs.inactive_selection_fg_color);
   5276       webview()->themeChanged();
   5277     }
   5278   }
   5279 #endif  // defined(USE_DEFAULT_RENDER_THEME) || defined(TOOLKIT_GTK)
   5280 
   5281   if (RenderThreadImpl::current())  // Will be NULL during unit tests.
   5282     RenderThreadImpl::current()->SetFlingCurveParameters(
   5283         renderer_prefs.touchpad_fling_profile,
   5284         renderer_prefs.touchscreen_fling_profile);
   5285 
   5286   // If the zoom level for this page matches the old zoom default, and this
   5287   // is not a plugin, update the zoom level to match the new default.
   5288   if (webview() && !webview()->mainFrame()->document().isPluginDocument() &&
   5289       !ZoomValuesEqual(old_zoom_level,
   5290                        renderer_preferences_.default_zoom_level) &&
   5291       ZoomValuesEqual(webview()->zoomLevel(), old_zoom_level)) {
   5292     webview()->setZoomLevel(false, renderer_preferences_.default_zoom_level);
   5293     zoomLevelChanged();
   5294   }
   5295 }
   5296 
   5297 void RenderViewImpl::OnMediaPlayerActionAt(const gfx::Point& location,
   5298                                            const WebMediaPlayerAction& action) {
   5299   if (webview())
   5300     webview()->performMediaPlayerAction(action, location);
   5301 }
   5302 
   5303 void RenderViewImpl::OnOrientationChangeEvent(int orientation) {
   5304   webview()->mainFrame()->sendOrientationChangeEvent(orientation);
   5305 }
   5306 
   5307 void RenderViewImpl::OnPluginActionAt(const gfx::Point& location,
   5308                                       const WebPluginAction& action) {
   5309   if (webview())
   5310     webview()->performPluginAction(action, location);
   5311 }
   5312 
   5313 void RenderViewImpl::OnGetAllSavableResourceLinksForCurrentPage(
   5314     const GURL& page_url) {
   5315   // Prepare list to storage all savable resource links.
   5316   std::vector<GURL> resources_list;
   5317   std::vector<GURL> referrer_urls_list;
   5318   std::vector<WebKit::WebReferrerPolicy> referrer_policies_list;
   5319   std::vector<GURL> frames_list;
   5320   SavableResourcesResult result(&resources_list,
   5321                                 &referrer_urls_list,
   5322                                 &referrer_policies_list,
   5323                                 &frames_list);
   5324 
   5325   // webkit/ doesn't know about Referrer.
   5326   if (!GetAllSavableResourceLinksForCurrentPage(
   5327           webview(),
   5328           page_url,
   5329           &result,
   5330           const_cast<const char**>(GetSavableSchemes()))) {
   5331     // If something is wrong when collecting all savable resource links,
   5332     // send empty list to embedder(browser) to tell it failed.
   5333     referrer_urls_list.clear();
   5334     referrer_policies_list.clear();
   5335     resources_list.clear();
   5336     frames_list.clear();
   5337   }
   5338 
   5339   std::vector<Referrer> referrers_list;
   5340   CHECK_EQ(referrer_urls_list.size(), referrer_policies_list.size());
   5341   for (unsigned i = 0; i < referrer_urls_list.size(); ++i) {
   5342     referrers_list.push_back(
   5343         Referrer(referrer_urls_list[i], referrer_policies_list[i]));
   5344   }
   5345 
   5346   // Send result of all savable resource links to embedder.
   5347   Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id(),
   5348                                                               resources_list,
   5349                                                               referrers_list,
   5350                                                               frames_list));
   5351 }
   5352 
   5353 void RenderViewImpl::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
   5354     const std::vector<GURL>& links,
   5355     const std::vector<base::FilePath>& local_paths,
   5356     const base::FilePath& local_directory_name) {
   5357 
   5358   // Convert std::vector of GURLs to WebVector<WebURL>
   5359   WebVector<WebURL> weburl_links(links);
   5360 
   5361   // Convert std::vector of base::FilePath to WebVector<WebString>
   5362   WebVector<WebString> webstring_paths(local_paths.size());
   5363   for (size_t i = 0; i < local_paths.size(); i++)
   5364     webstring_paths[i] = local_paths[i].AsUTF16Unsafe();
   5365 
   5366   WebPageSerializer::serialize(webview()->mainFrame(), true, this, weburl_links,
   5367                                webstring_paths,
   5368                                local_directory_name.AsUTF16Unsafe());
   5369 }
   5370 
   5371 void RenderViewImpl::OnShouldClose() {
   5372   base::TimeTicks before_unload_start_time = base::TimeTicks::Now();
   5373   bool should_close = webview()->dispatchBeforeUnloadEvent();
   5374   base::TimeTicks before_unload_end_time = base::TimeTicks::Now();
   5375   Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close,
   5376                                        before_unload_start_time,
   5377                                        before_unload_end_time));
   5378 }
   5379 
   5380 void RenderViewImpl::OnSwapOut() {
   5381   // Only run unload if we're not swapped out yet, but send the ack either way.
   5382   if (!is_swapped_out_) {
   5383     // Swap this RenderView out so the tab can navigate to a page rendered by a
   5384     // different process.  This involves running the unload handler and clearing
   5385     // the page.  Once WasSwappedOut is called, we also allow this process to
   5386     // exit if there are no other active RenderViews in it.
   5387 
   5388     // Send an UpdateState message before we get swapped out.
   5389     SyncNavigationState();
   5390 
   5391     // Synchronously run the unload handler before sending the ACK.
   5392     webview()->dispatchUnloadEvent();
   5393 
   5394     // Swap out and stop sending any IPC messages that are not ACKs.
   5395     SetSwappedOut(true);
   5396 
   5397     // Now that we're swapped out and filtering IPC messages, stop loading to
   5398     // ensure that no other in-progress navigation continues.  We do this here
   5399     // to avoid sending a DidStopLoading message to the browser process.
   5400     OnStop();
   5401 
   5402     // Replace the page with a blank dummy URL. The unload handler will not be
   5403     // run a second time, thanks to a check in FrameLoader::stopLoading.
   5404     // TODO(creis): Need to add a better way to do this that avoids running the
   5405     // beforeunload handler. For now, we just run it a second time silently.
   5406     NavigateToSwappedOutURL(webview()->mainFrame());
   5407 
   5408     // Let WebKit know that this view is hidden so it can drop resources and
   5409     // stop compositing.
   5410     webview()->setVisibilityState(WebKit::WebPageVisibilityStateHidden, false);
   5411   }
   5412 
   5413   Send(new ViewHostMsg_SwapOut_ACK(routing_id_));
   5414 }
   5415 
   5416 void RenderViewImpl::NavigateToSwappedOutURL(WebKit::WebFrame* frame) {
   5417   // We use loadRequest instead of loadHTMLString because the former commits
   5418   // synchronously.  Otherwise a new navigation can interrupt the navigation
   5419   // to kSwappedOutURL. If that happens to be to the page we had been
   5420   // showing, then WebKit will never send a commit and we'll be left spinning.
   5421   CHECK(is_swapped_out_);
   5422   GURL swappedOutURL(kSwappedOutURL);
   5423   WebURLRequest request(swappedOutURL);
   5424   frame->loadRequest(request);
   5425 }
   5426 
   5427 void RenderViewImpl::OnClosePage() {
   5428   FOR_EACH_OBSERVER(RenderViewObserver, observers_, ClosePage());
   5429   // TODO(creis): We'd rather use webview()->Close() here, but that currently
   5430   // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
   5431   // in the onunload handler from appearing.  For now, we're bypassing that and
   5432   // calling the FrameLoader's CloseURL method directly.  This should be
   5433   // revisited to avoid having two ways to close a page.  Having a single way
   5434   // to close that can run onunload is also useful for fixing
   5435   // http://b/issue?id=753080.
   5436   webview()->dispatchUnloadEvent();
   5437 
   5438   Send(new ViewHostMsg_ClosePage_ACK(routing_id_));
   5439 }
   5440 
   5441 void RenderViewImpl::OnThemeChanged() {
   5442 #if defined(USE_AURA)
   5443   // Aura doesn't care if we switch themes.
   5444 #elif defined(OS_WIN)
   5445   ui::NativeThemeWin::instance()->CloseHandles();
   5446   if (webview())
   5447     webview()->themeChanged();
   5448 #else  // defined(OS_WIN)
   5449   // TODO(port): we don't support theming on non-Windows platforms yet
   5450   NOTIMPLEMENTED();
   5451 #endif
   5452 }
   5453 
   5454 void RenderViewImpl::OnDisassociateFromPopupCount() {
   5455   if (decrement_shared_popup_at_destruction_)
   5456     shared_popup_counter_->data--;
   5457   shared_popup_counter_ = new SharedRenderViewCounter(0);
   5458   decrement_shared_popup_at_destruction_ = false;
   5459 }
   5460 
   5461 bool RenderViewImpl::MaybeLoadAlternateErrorPage(WebFrame* frame,
   5462                                                  const WebURLError& error,
   5463                                                  bool replace) {
   5464   // We only show alternate error pages in the main frame.  They are
   5465   // intended to assist the user when navigating, so there is not much
   5466   // value in showing them for failed subframes.  Ideally, we would be
   5467   // able to use the TYPED transition type for this, but that flag is
   5468   // not preserved across page reloads.
   5469   if (frame->parent())
   5470     return false;
   5471 
   5472   // Use the alternate error page service if this is a DNS failure or
   5473   // connection failure.
   5474   int ec = error.reason;
   5475   if (ec != net::ERR_NAME_NOT_RESOLVED &&
   5476       ec != net::ERR_CONNECTION_FAILED &&
   5477       ec != net::ERR_CONNECTION_REFUSED &&
   5478       ec != net::ERR_ADDRESS_UNREACHABLE &&
   5479       ec != net::ERR_CONNECTION_TIMED_OUT) {
   5480     return false;
   5481   }
   5482 
   5483   const GURL& error_page_url = GetAlternateErrorPageURL(error.unreachableURL,
   5484       ec == net::ERR_NAME_NOT_RESOLVED ? DNS_ERROR : CONNECTION_ERROR);
   5485   if (!error_page_url.is_valid())
   5486     return false;
   5487 
   5488   WebDataSource* ds = frame->provisionalDataSource();
   5489   const WebURLRequest& failed_request = ds->request();
   5490 
   5491   // Load an empty page first so there is an immediate response to the error,
   5492   // and then kick off a request for the alternate error page.
   5493   frame->loadHTMLString(std::string(),
   5494                         GURL(kUnreachableWebDataURL),
   5495                         error.unreachableURL,
   5496                         replace);
   5497 
   5498   // Now, create a fetcher for the error page and associate it with the data
   5499   // source we just created via the LoadHTMLString call.  That way if another
   5500   // navigation occurs, the fetcher will get destroyed.
   5501   InternalDocumentStateData* internal_data =
   5502       InternalDocumentStateData::FromDataSource(frame->provisionalDataSource());
   5503   internal_data->set_alt_error_page_fetcher(
   5504       new AltErrorPageResourceFetcher(
   5505           error_page_url, frame, failed_request, error,
   5506           base::Bind(&RenderViewImpl::AltErrorPageFinished,
   5507                      base::Unretained(this))));
   5508   return true;
   5509 }
   5510 
   5511 void RenderViewImpl::AltErrorPageFinished(WebFrame* frame,
   5512                                           const WebURLRequest& original_request,
   5513                                           const WebURLError& original_error,
   5514                                           const std::string& html) {
   5515   // Here, we replace the blank page we loaded previously.
   5516   // If we failed to download the alternate error page, LoadNavigationErrorPage
   5517   // will simply display a default error page.
   5518   LoadNavigationErrorPage(frame, original_request, original_error, html, true);
   5519 }
   5520 
   5521 void RenderViewImpl::OnMoveOrResizeStarted() {
   5522   if (webview())
   5523     webview()->hidePopups();
   5524 }
   5525 
   5526 void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) {
   5527   if (webview()) {
   5528     webview()->hidePopups();
   5529     if (send_preferred_size_changes_) {
   5530       webview()->mainFrame()->setCanHaveScrollbars(
   5531           ShouldDisplayScrollbars(params.new_size.width(),
   5532                                   params.new_size.height()));
   5533     }
   5534     UpdateScrollState(webview()->mainFrame());
   5535   }
   5536 
   5537   RenderWidget::OnResize(params);
   5538 }
   5539 
   5540 void RenderViewImpl::WillInitiatePaint() {
   5541 #if defined(ENABLE_PLUGINS)
   5542   // Notify all of our instances that we started painting. This is used for
   5543   // internal bookkeeping only, so we know that the set can not change under
   5544   // us.
   5545   for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
   5546        i != active_pepper_instances_.end(); ++i)
   5547     (*i)->ViewWillInitiatePaint();
   5548 #endif
   5549 }
   5550 
   5551 void RenderViewImpl::DidInitiatePaint() {
   5552 #if defined(ENABLE_PLUGINS)
   5553   // Notify all instances that we painted.  The same caveats apply as for
   5554   // ViewFlushedPaint regarding instances closing themselves, so we take
   5555   // similar precautions.
   5556   PepperPluginSet plugins = active_pepper_instances_;
   5557   for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
   5558     if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
   5559       (*i)->ViewInitiatedPaint();
   5560   }
   5561 #endif
   5562 }
   5563 
   5564 void RenderViewImpl::DidFlushPaint() {
   5565 #if defined(ENABLE_PLUGINS)
   5566   // Notify all instances that we flushed. This will call into the plugin, and
   5567   // we it may ask to close itself as a result. This will, in turn, modify our
   5568   // set, possibly invalidating the iterator. So we iterate on a copy that
   5569   // won't change out from under us.
   5570   PepperPluginSet plugins = active_pepper_instances_;
   5571   for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
   5572     // The copy above makes sure our iterator is never invalid if some plugins
   5573     // are destroyed. But some plugin may decide to close all of its views in
   5574     // response to a paint in one of them, so we need to make sure each one is
   5575     // still "current" before using it.
   5576     //
   5577     // It's possible that a plugin was destroyed, but another one was created
   5578     // with the same address. In this case, we'll call ViewFlushedPaint on that
   5579     // new plugin. But that's OK for this particular case since we're just
   5580     // notifying all of our instances that the view flushed, and the new one is
   5581     // one of our instances.
   5582     //
   5583     // What about the case where a new one is created in a callback at a new
   5584     // address and we don't issue the callback? We're still OK since this
   5585     // callback is used for flush callbacks and we could not have possibly
   5586     // started a new paint (ViewWillInitiatePaint) for the new plugin while
   5587     // processing a previous paint for an existing one.
   5588     if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
   5589       (*i)->ViewFlushedPaint();
   5590   }
   5591 #endif
   5592 
   5593   // If the RenderWidget is closing down then early-exit, otherwise we'll crash.
   5594   // See crbug.com/112921.
   5595   if (!webview())
   5596     return;
   5597 
   5598   WebFrame* main_frame = webview()->mainFrame();
   5599 
   5600   // If we have a provisional frame we are between the start and commit stages
   5601   // of loading and we don't want to save stats.
   5602   if (!main_frame->provisionalDataSource()) {
   5603     WebDataSource* ds = main_frame->dataSource();
   5604     DocumentState* document_state = DocumentState::FromDataSource(ds);
   5605     InternalDocumentStateData* data =
   5606         InternalDocumentStateData::FromDocumentState(document_state);
   5607     if (data->did_first_visually_non_empty_layout() &&
   5608         !data->did_first_visually_non_empty_paint()) {
   5609       data->set_did_first_visually_non_empty_paint(true);
   5610       Send(new ViewHostMsg_DidFirstVisuallyNonEmptyPaint(routing_id_,
   5611                                                          page_id_));
   5612     }
   5613 
   5614     // TODO(jar): The following code should all be inside a method, probably in
   5615     // NavigatorState.
   5616     Time now = Time::Now();
   5617     if (document_state->first_paint_time().is_null()) {
   5618       document_state->set_first_paint_time(now);
   5619     }
   5620     if (document_state->first_paint_after_load_time().is_null() &&
   5621         !document_state->finish_load_time().is_null()) {
   5622       document_state->set_first_paint_after_load_time(now);
   5623     }
   5624   }
   5625 }
   5626 
   5627 PepperPluginInstanceImpl* RenderViewImpl::GetBitmapForOptimizedPluginPaint(
   5628     const gfx::Rect& paint_bounds,
   5629     TransportDIB** dib,
   5630     gfx::Rect* location,
   5631     gfx::Rect* clip,
   5632     float* scale_factor) {
   5633 #if defined(ENABLE_PLUGINS)
   5634   for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
   5635        i != active_pepper_instances_.end(); ++i) {
   5636     PepperPluginInstanceImpl* instance = *i;
   5637     // In Flash fullscreen , the plugin contents should be painted onto the
   5638     // fullscreen widget instead of the web page.
   5639     if (!instance->FlashIsFullscreenOrPending() &&
   5640         instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location,
   5641                                                    clip, scale_factor))
   5642       return *i;
   5643   }
   5644 #endif
   5645   return NULL;
   5646 }
   5647 
   5648 gfx::Vector2d RenderViewImpl::GetScrollOffset() {
   5649   WebSize scroll_offset = webview()->mainFrame()->scrollOffset();
   5650   return gfx::Vector2d(scroll_offset.width, scroll_offset.height);
   5651 }
   5652 
   5653 void RenderViewImpl::OnClearFocusedNode() {
   5654   if (webview())
   5655     webview()->clearFocusedNode();
   5656 }
   5657 
   5658 void RenderViewImpl::OnSetBackground(const SkBitmap& background) {
   5659   if (webview())
   5660     webview()->setIsTransparent(!background.empty());
   5661   if (compositor_)
   5662     compositor_->setHasTransparentBackground(!background.empty());
   5663 
   5664   SetBackground(background);
   5665 }
   5666 
   5667 void RenderViewImpl::OnSetAccessibilityMode(AccessibilityMode new_mode) {
   5668   if (accessibility_mode_ == new_mode)
   5669     return;
   5670   accessibility_mode_ = new_mode;
   5671   if (renderer_accessibility_) {
   5672     delete renderer_accessibility_;
   5673     renderer_accessibility_ = NULL;
   5674   }
   5675   if (accessibility_mode_ == AccessibilityModeComplete)
   5676     renderer_accessibility_ = new RendererAccessibilityComplete(this);
   5677 #if !defined(OS_ANDROID)
   5678   else if (accessibility_mode_ == AccessibilityModeEditableTextOnly)
   5679     renderer_accessibility_ = new RendererAccessibilityFocusOnly(this);
   5680 #endif
   5681 }
   5682 
   5683 void RenderViewImpl::OnSetActive(bool active) {
   5684   if (webview())
   5685     webview()->setIsActive(active);
   5686 
   5687 #if defined(ENABLE_PLUGINS) && defined(OS_MACOSX)
   5688   std::set<WebPluginDelegateProxy*>::iterator plugin_it;
   5689   for (plugin_it = plugin_delegates_.begin();
   5690        plugin_it != plugin_delegates_.end(); ++plugin_it) {
   5691     (*plugin_it)->SetWindowFocus(active);
   5692   }
   5693 #endif
   5694 }
   5695 
   5696 #if defined(OS_MACOSX)
   5697 void RenderViewImpl::OnSetWindowVisibility(bool visible) {
   5698 #if defined(ENABLE_PLUGINS)
   5699   // Inform plugins that their container has changed visibility.
   5700   std::set<WebPluginDelegateProxy*>::iterator plugin_it;
   5701   for (plugin_it = plugin_delegates_.begin();
   5702        plugin_it != plugin_delegates_.end(); ++plugin_it) {
   5703     (*plugin_it)->SetContainerVisibility(visible);
   5704   }
   5705 #endif
   5706 }
   5707 
   5708 void RenderViewImpl::OnWindowFrameChanged(const gfx::Rect& window_frame,
   5709                                           const gfx::Rect& view_frame) {
   5710 #if defined(ENABLE_PLUGINS)
   5711   // Inform plugins that their window's frame has changed.
   5712   std::set<WebPluginDelegateProxy*>::iterator plugin_it;
   5713   for (plugin_it = plugin_delegates_.begin();
   5714        plugin_it != plugin_delegates_.end(); ++plugin_it) {
   5715     (*plugin_it)->WindowFrameChanged(window_frame, view_frame);
   5716   }
   5717 #endif
   5718 }
   5719 
   5720 void RenderViewImpl::OnPluginImeCompositionCompleted(const string16& text,
   5721                                                      int plugin_id) {
   5722   // WebPluginDelegateProxy is responsible for figuring out if this event
   5723   // applies to it or not, so inform all the delegates.
   5724   std::set<WebPluginDelegateProxy*>::iterator plugin_it;
   5725   for (plugin_it = plugin_delegates_.begin();
   5726        plugin_it != plugin_delegates_.end(); ++plugin_it) {
   5727     (*plugin_it)->ImeCompositionCompleted(text, plugin_id);
   5728   }
   5729 }
   5730 #endif  // OS_MACOSX
   5731 
   5732 void RenderViewImpl::Close() {
   5733   // We need to grab a pointer to the doomed WebView before we destroy it.
   5734   WebView* doomed = webview();
   5735   RenderWidget::Close();
   5736   g_view_map.Get().erase(doomed);
   5737   g_routing_id_view_map.Get().erase(routing_id_);
   5738 }
   5739 
   5740 void RenderViewImpl::DidHandleKeyEvent() {
   5741   ClearEditCommands();
   5742 }
   5743 
   5744 bool RenderViewImpl::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) {
   5745   context_menu_source_type_ = ui::MENU_SOURCE_MOUSE;
   5746   possible_drag_event_info_.event_source =
   5747       ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE;
   5748   possible_drag_event_info_.event_location =
   5749       gfx::Point(event.globalX, event.globalY);
   5750 
   5751 #if defined(ENABLE_PLUGINS)
   5752   // This method is called for every mouse event that the render view receives.
   5753   // And then the mouse event is forwarded to WebKit, which dispatches it to the
   5754   // event target. Potentially a Pepper plugin will receive the event.
   5755   // In order to tell whether a plugin gets the last mouse event and which it
   5756   // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets
   5757   // the event, it will notify us via DidReceiveMouseEvent() and set itself as
   5758   // |pepper_last_mouse_event_target_|.
   5759   pepper_last_mouse_event_target_ = NULL;
   5760 #endif
   5761 
   5762   // If the mouse is locked, only the current owner of the mouse lock can
   5763   // process mouse events.
   5764   return mouse_lock_dispatcher_->WillHandleMouseEvent(event);
   5765 }
   5766 
   5767 bool RenderViewImpl::WillHandleKeyEvent(const WebKit::WebKeyboardEvent& event) {
   5768   context_menu_source_type_ = ui::MENU_SOURCE_KEYBOARD;
   5769   return false;
   5770 }
   5771 
   5772 bool RenderViewImpl::WillHandleGestureEvent(
   5773     const WebKit::WebGestureEvent& event) {
   5774   context_menu_source_type_ = ui::MENU_SOURCE_TOUCH;
   5775   possible_drag_event_info_.event_source =
   5776       ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
   5777   possible_drag_event_info_.event_location =
   5778       gfx::Point(event.globalX, event.globalY);
   5779   return false;
   5780 }
   5781 
   5782 void RenderViewImpl::DidHandleMouseEvent(const WebMouseEvent& event) {
   5783   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidHandleMouseEvent(event));
   5784 }
   5785 
   5786 void RenderViewImpl::DidHandleTouchEvent(const WebTouchEvent& event) {
   5787   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidHandleTouchEvent(event));
   5788 }
   5789 
   5790 bool RenderViewImpl::HasTouchEventHandlersAt(const gfx::Point& point) const {
   5791   if (!webview())
   5792     return false;
   5793   return webview()->hasTouchEventHandlersAt(point);
   5794 }
   5795 
   5796 void RenderViewImpl::OnWasHidden() {
   5797   RenderWidget::OnWasHidden();
   5798 
   5799 #if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
   5800   RenderThreadImpl::current()->video_capture_impl_manager()->
   5801       SuspendDevices(true);
   5802 #endif
   5803 
   5804   if (webview())
   5805     webview()->setVisibilityState(visibilityState(), false);
   5806 
   5807 #if defined(ENABLE_PLUGINS)
   5808   // Inform PPAPI plugins that their page is no longer visible.
   5809   for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
   5810        i != active_pepper_instances_.end(); ++i)
   5811     (*i)->PageVisibilityChanged(false);
   5812 
   5813 #if defined(OS_MACOSX)
   5814   // Inform NPAPI plugins that their container is no longer visible.
   5815   std::set<WebPluginDelegateProxy*>::iterator plugin_it;
   5816   for (plugin_it = plugin_delegates_.begin();
   5817        plugin_it != plugin_delegates_.end(); ++plugin_it) {
   5818     (*plugin_it)->SetContainerVisibility(false);
   5819   }
   5820 #endif  // OS_MACOSX
   5821 #endif // ENABLE_PLUGINS
   5822 }
   5823 
   5824 void RenderViewImpl::OnWasShown(bool needs_repainting) {
   5825   RenderWidget::OnWasShown(needs_repainting);
   5826 
   5827 #if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
   5828   RenderThreadImpl::current()->video_capture_impl_manager()->
   5829       SuspendDevices(false);
   5830 #endif
   5831 
   5832   if (webview())
   5833     webview()->setVisibilityState(visibilityState(), false);
   5834 
   5835 #if defined(ENABLE_PLUGINS)
   5836   // Inform PPAPI plugins that their page is visible.
   5837   for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
   5838        i != active_pepper_instances_.end(); ++i)
   5839     (*i)->PageVisibilityChanged(true);
   5840 
   5841 #if defined(OS_MACOSX)
   5842   // Inform NPAPI plugins that their container is now visible.
   5843   std::set<WebPluginDelegateProxy*>::iterator plugin_it;
   5844   for (plugin_it = plugin_delegates_.begin();
   5845        plugin_it != plugin_delegates_.end(); ++plugin_it) {
   5846     (*plugin_it)->SetContainerVisibility(true);
   5847   }
   5848 #endif  // OS_MACOSX
   5849 #endif  // ENABLE_PLUGINS
   5850 }
   5851 
   5852 GURL RenderViewImpl::GetURLForGraphicsContext3D() {
   5853   DCHECK(webview());
   5854   if (webview()->mainFrame())
   5855     return GURL(webview()->mainFrame()->document().url());
   5856   else
   5857     return GURL("chrome://gpu/RenderViewImpl::CreateGraphicsContext3D");
   5858 }
   5859 
   5860 bool RenderViewImpl::ForceCompositingModeEnabled() {
   5861   return webkit_preferences_.force_compositing_mode;
   5862 }
   5863 
   5864 void RenderViewImpl::OnSetFocus(bool enable) {
   5865   RenderWidget::OnSetFocus(enable);
   5866 
   5867 #if defined(ENABLE_PLUGINS)
   5868   if (webview() && webview()->isActive()) {
   5869     // Notify all NPAPI plugins.
   5870     std::set<WebPluginDelegateProxy*>::iterator plugin_it;
   5871     for (plugin_it = plugin_delegates_.begin();
   5872          plugin_it != plugin_delegates_.end(); ++plugin_it) {
   5873 #if defined(OS_MACOSX)
   5874       // RenderWidget's call to setFocus can cause the underlying webview's
   5875       // activation state to change just like a call to setIsActive.
   5876       if (enable)
   5877         (*plugin_it)->SetWindowFocus(true);
   5878 #endif
   5879       (*plugin_it)->SetContentAreaFocus(enable);
   5880     }
   5881   }
   5882   // Notify all Pepper plugins.
   5883   for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
   5884        i != active_pepper_instances_.end(); ++i)
   5885     (*i)->SetContentAreaFocus(enable);
   5886 #endif
   5887   // Notify all BrowserPlugins of the RenderView's focus state.
   5888   if (browser_plugin_manager_.get())
   5889     browser_plugin_manager_->UpdateFocusState();
   5890 }
   5891 
   5892 void RenderViewImpl::OnImeSetComposition(
   5893     const string16& text,
   5894     const std::vector<WebKit::WebCompositionUnderline>& underlines,
   5895     int selection_start,
   5896     int selection_end) {
   5897 #if defined(ENABLE_PLUGINS)
   5898   if (focused_pepper_plugin_) {
   5899     // When a PPAPI plugin has focus, we bypass WebKit.
   5900     if (!IsPepperAcceptingCompositionEvents()) {
   5901       pepper_composition_text_ = text;
   5902     } else {
   5903       // TODO(kinaba) currently all composition events are sent directly to
   5904       // plugins. Use DOM event mechanism after WebKit is made aware about
   5905       // plugins that support composition.
   5906       // The code below mimics the behavior of WebCore::Editor::setComposition.
   5907 
   5908       // Empty -> nonempty: composition started.
   5909       if (pepper_composition_text_.empty() && !text.empty())
   5910         focused_pepper_plugin_->HandleCompositionStart(string16());
   5911       // Nonempty -> empty: composition canceled.
   5912       if (!pepper_composition_text_.empty() && text.empty())
   5913         focused_pepper_plugin_->HandleCompositionEnd(string16());
   5914       pepper_composition_text_ = text;
   5915       // Nonempty: composition is ongoing.
   5916       if (!pepper_composition_text_.empty()) {
   5917         focused_pepper_plugin_->HandleCompositionUpdate(
   5918             pepper_composition_text_, underlines, selection_start,
   5919             selection_end);
   5920       }
   5921     }
   5922     return;
   5923   }
   5924 
   5925 #if defined(OS_WIN)
   5926   // When a plug-in has focus, we create platform-specific IME data used by
   5927   // our IME emulator and send it directly to the focused plug-in, i.e. we
   5928   // bypass WebKit. (WebPluginDelegate dispatches this IME data only when its
   5929   // instance ID is the same one as the specified ID.)
   5930   if (focused_plugin_id_ >= 0) {
   5931     std::vector<int> clauses;
   5932     std::vector<int> target;
   5933     for (size_t i = 0; i < underlines.size(); ++i) {
   5934       clauses.push_back(underlines[i].startOffset);
   5935       clauses.push_back(underlines[i].endOffset);
   5936       if (underlines[i].thick) {
   5937         target.clear();
   5938         target.push_back(underlines[i].startOffset);
   5939         target.push_back(underlines[i].endOffset);
   5940       }
   5941     }
   5942     std::set<WebPluginDelegateProxy*>::iterator it;
   5943     for (it = plugin_delegates_.begin(); it != plugin_delegates_.end(); ++it) {
   5944       (*it)->ImeCompositionUpdated(text, clauses, target, selection_end,
   5945                                    focused_plugin_id_);
   5946     }
   5947     return;
   5948   }
   5949 #endif  // OS_WIN
   5950 #endif  // ENABLE_PLUGINS
   5951   RenderWidget::OnImeSetComposition(text,
   5952                                     underlines,
   5953                                     selection_start,
   5954                                     selection_end);
   5955 }
   5956 
   5957 void RenderViewImpl::OnImeConfirmComposition(const string16& text,
   5958                                              const ui::Range& replacement_range,
   5959                                              bool keep_selection) {
   5960 #if defined(ENABLE_PLUGINS)
   5961   if (focused_pepper_plugin_) {
   5962     // When a PPAPI plugin has focus, we bypass WebKit.
   5963     // Here, text.empty() has a special meaning. It means to commit the last
   5964     // update of composition text (see
   5965     // RenderWidgetHost::ImeConfirmComposition()).
   5966     const string16& last_text = text.empty() ? pepper_composition_text_ : text;
   5967 
   5968     // last_text is empty only when both text and pepper_composition_text_ is.
   5969     // Ignore it.
   5970     if (last_text.empty())
   5971       return;
   5972 
   5973     if (!IsPepperAcceptingCompositionEvents()) {
   5974       for (size_t i = 0; i < text.size(); ++i) {
   5975         WebKit::WebKeyboardEvent char_event;
   5976         char_event.type = WebKit::WebInputEvent::Char;
   5977         char_event.timeStampSeconds = base::Time::Now().ToDoubleT();
   5978         char_event.modifiers = 0;
   5979         char_event.windowsKeyCode = last_text[i];
   5980         char_event.nativeKeyCode = last_text[i];
   5981         char_event.text[0] = last_text[i];
   5982         char_event.unmodifiedText[0] = last_text[i];
   5983         if (webwidget())
   5984           webwidget()->handleInputEvent(char_event);
   5985       }
   5986     } else {
   5987       // Mimics the order of events sent by WebKit.
   5988       // See WebCore::Editor::setComposition() for the corresponding code.
   5989       focused_pepper_plugin_->HandleCompositionEnd(last_text);
   5990       focused_pepper_plugin_->HandleTextInput(last_text);
   5991     }
   5992     pepper_composition_text_.clear();
   5993     return;
   5994   }
   5995 #if defined(OS_WIN)
   5996   // Same as OnImeSetComposition(), we send the text from IMEs directly to
   5997   // plug-ins. When we send IME text directly to plug-ins, we should not send
   5998   // it to WebKit to prevent WebKit from controlling IMEs.
   5999   // TODO(thakis): Honor |replacement_range| for plugins?
   6000   if (focused_plugin_id_ >= 0) {
   6001     std::set<WebPluginDelegateProxy*>::iterator it;
   6002     for (it = plugin_delegates_.begin();
   6003           it != plugin_delegates_.end(); ++it) {
   6004       (*it)->ImeCompositionCompleted(text, focused_plugin_id_);
   6005     }
   6006     return;
   6007   }
   6008 #endif  // OS_WIN
   6009 #endif  // ENABLE_PLUGINS
   6010   if (replacement_range.IsValid() && webview()) {
   6011     // Select the text in |replacement_range|, it will then be replaced by
   6012     // text added by the call to RenderWidget::OnImeConfirmComposition().
   6013     if (WebFrame* frame = webview()->focusedFrame()) {
   6014       WebRange webrange = WebRange::fromDocumentRange(
   6015           frame, replacement_range.start(), replacement_range.length());
   6016       if (!webrange.isNull())
   6017         frame->selectRange(webrange);
   6018     }
   6019   }
   6020   RenderWidget::OnImeConfirmComposition(text,
   6021                                         replacement_range,
   6022                                         keep_selection);
   6023 }
   6024 
   6025 void RenderViewImpl::SetDeviceScaleFactor(float device_scale_factor) {
   6026   RenderWidget::SetDeviceScaleFactor(device_scale_factor);
   6027   if (webview()) {
   6028     webview()->setDeviceScaleFactor(device_scale_factor);
   6029     webview()->settings()->setAcceleratedCompositingForFixedPositionEnabled(
   6030         ShouldUseFixedPositionCompositing(device_scale_factor_));
   6031   webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled(
   6032       ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_));
   6033     webview()->settings()->setAcceleratedCompositingForTransitionEnabled(
   6034         ShouldUseTransitionCompositing(device_scale_factor_));
   6035     webview()->settings()->
   6036         setAcceleratedCompositingForFixedRootBackgroundEnabled(
   6037             ShouldUseAcceleratedFixedRootBackground(device_scale_factor_));
   6038   }
   6039   if (auto_resize_mode_)
   6040     AutoResizeCompositor();
   6041 
   6042   if (browser_plugin_manager_.get())
   6043     browser_plugin_manager_->UpdateDeviceScaleFactor(device_scale_factor_);
   6044 }
   6045 
   6046 ui::TextInputType RenderViewImpl::GetTextInputType() {
   6047 #if defined(ENABLE_PLUGINS)
   6048   if (focused_pepper_plugin_)
   6049     return focused_pepper_plugin_->text_input_type();
   6050 #endif
   6051   return RenderWidget::GetTextInputType();
   6052 }
   6053 
   6054 void RenderViewImpl::GetSelectionBounds(gfx::Rect* start, gfx::Rect* end) {
   6055 #if defined(ENABLE_PLUGINS)
   6056   if (focused_pepper_plugin_) {
   6057     // TODO(kinaba) http://crbug.com/101101
   6058     // Current Pepper IME API does not handle selection bounds. So we simply
   6059     // use the caret position as an empty range for now. It will be updated
   6060     // after Pepper API equips features related to surrounding text retrieval.
   6061     gfx::Rect caret = focused_pepper_plugin_->GetCaretBounds();
   6062     *start = caret;
   6063     *end = caret;
   6064     return;
   6065   }
   6066 #endif
   6067   RenderWidget::GetSelectionBounds(start, end);
   6068 }
   6069 
   6070 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
   6071 void RenderViewImpl::GetCompositionCharacterBounds(
   6072     std::vector<gfx::Rect>* bounds) {
   6073   DCHECK(bounds);
   6074   bounds->clear();
   6075 
   6076 #if defined(ENABLE_PLUGINS)
   6077   if (focused_pepper_plugin_) {
   6078     return;
   6079   }
   6080 #endif
   6081 
   6082   if (!webview())
   6083     return;
   6084   size_t start_offset = 0;
   6085   size_t character_count = 0;
   6086   if (!webview()->compositionRange(&start_offset, &character_count))
   6087     return;
   6088   if (character_count == 0)
   6089     return;
   6090 
   6091   WebKit::WebFrame* frame = webview()->focusedFrame();
   6092   if (!frame)
   6093     return;
   6094 
   6095   bounds->reserve(character_count);
   6096   WebKit::WebRect webrect;
   6097   for (size_t i = 0; i < character_count; ++i) {
   6098     if (!frame->firstRectForCharacterRange(start_offset + i, 1, webrect)) {
   6099       DLOG(ERROR) << "Could not retrieve character rectangle at " << i;
   6100       bounds->clear();
   6101       return;
   6102     }
   6103     bounds->push_back(webrect);
   6104   }
   6105 }
   6106 
   6107 void RenderViewImpl::GetCompositionRange(ui::Range* range) {
   6108 #if defined(ENABLE_PLUGINS)
   6109   if (focused_pepper_plugin_) {
   6110     return;
   6111   }
   6112 #endif
   6113   RenderWidget::GetCompositionRange(range);
   6114 }
   6115 #endif
   6116 
   6117 bool RenderViewImpl::CanComposeInline() {
   6118 #if defined(ENABLE_PLUGINS)
   6119   if (focused_pepper_plugin_)
   6120     return IsPepperAcceptingCompositionEvents();
   6121 #endif
   6122   return true;
   6123 }
   6124 
   6125 void RenderViewImpl::InstrumentWillBeginFrame() {
   6126   if (!webview())
   6127     return;
   6128   if (!webview()->devToolsAgent())
   6129     return;
   6130   webview()->devToolsAgent()->didBeginFrame();
   6131 }
   6132 
   6133 void RenderViewImpl::InstrumentDidBeginFrame() {
   6134   if (!webview())
   6135     return;
   6136   if (!webview()->devToolsAgent())
   6137     return;
   6138   // TODO(jamesr/caseq): Decide if this needs to be renamed.
   6139   webview()->devToolsAgent()->didComposite();
   6140 }
   6141 
   6142 void RenderViewImpl::InstrumentDidCancelFrame() {
   6143   if (!webview())
   6144     return;
   6145   if (!webview()->devToolsAgent())
   6146     return;
   6147   webview()->devToolsAgent()->didCancelFrame();
   6148 }
   6149 
   6150 void RenderViewImpl::InstrumentWillComposite() {
   6151   if (!webview())
   6152     return;
   6153   if (!webview()->devToolsAgent())
   6154     return;
   6155   webview()->devToolsAgent()->willComposite();
   6156 }
   6157 
   6158 bool RenderViewImpl::AllowPartialSwap() const {
   6159   return allow_partial_swap_;
   6160 }
   6161 
   6162 bool RenderViewImpl::ScheduleFileChooser(
   6163     const FileChooserParams& params,
   6164     WebFileChooserCompletion* completion) {
   6165   static const size_t kMaximumPendingFileChooseRequests = 4;
   6166   if (file_chooser_completions_.size() > kMaximumPendingFileChooseRequests) {
   6167     // This sanity check prevents too many file choose requests from getting
   6168     // queued which could DoS the user. Getting these is most likely a
   6169     // programming error (there are many ways to DoS the user so it's not
   6170     // considered a "real" security check), either in JS requesting many file
   6171     // choosers to pop up, or in a plugin.
   6172     //
   6173     // TODO(brettw) we might possibly want to require a user gesture to open
   6174     // a file picker, which will address this issue in a better way.
   6175     return false;
   6176   }
   6177 
   6178   file_chooser_completions_.push_back(linked_ptr<PendingFileChooser>(
   6179       new PendingFileChooser(params, completion)));
   6180   if (file_chooser_completions_.size() == 1) {
   6181     // Actually show the browse dialog when this is the first request.
   6182     Send(new ViewHostMsg_RunFileChooser(routing_id_, params));
   6183   }
   6184   return true;
   6185 }
   6186 
   6187 WebKit::WebGeolocationClient* RenderViewImpl::geolocationClient() {
   6188   if (!geolocation_dispatcher_)
   6189     geolocation_dispatcher_ = new GeolocationDispatcher(this);
   6190   return geolocation_dispatcher_;
   6191 }
   6192 
   6193 WebKit::WebSpeechInputController* RenderViewImpl::speechInputController(
   6194     WebKit::WebSpeechInputListener* listener) {
   6195 #if defined(ENABLE_INPUT_SPEECH)
   6196   if (!input_tag_speech_dispatcher_)
   6197     input_tag_speech_dispatcher_ =
   6198         new InputTagSpeechDispatcher(this, listener);
   6199 #endif
   6200   return input_tag_speech_dispatcher_;
   6201 }
   6202 
   6203 WebKit::WebSpeechRecognizer* RenderViewImpl::speechRecognizer() {
   6204   if (!speech_recognition_dispatcher_)
   6205     speech_recognition_dispatcher_ = new SpeechRecognitionDispatcher(this);
   6206   return speech_recognition_dispatcher_;
   6207 }
   6208 
   6209 WebKit::WebDeviceOrientationClient* RenderViewImpl::deviceOrientationClient() {
   6210   if (!device_orientation_dispatcher_)
   6211     device_orientation_dispatcher_ = new DeviceOrientationDispatcher(this);
   6212   return device_orientation_dispatcher_;
   6213 }
   6214 
   6215 void RenderViewImpl::zoomLimitsChanged(double minimum_level,
   6216                                        double maximum_level) {
   6217   // For now, don't remember plugin zoom values.  We don't want to mix them with
   6218   // normal web content (i.e. a fixed layout plugin would usually want them
   6219   // different).
   6220   bool remember = !webview()->mainFrame()->document().isPluginDocument();
   6221 
   6222   int minimum_percent = static_cast<int>(
   6223       ZoomLevelToZoomFactor(minimum_level) * 100);
   6224   int maximum_percent = static_cast<int>(
   6225       ZoomLevelToZoomFactor(maximum_level) * 100);
   6226 
   6227   Send(new ViewHostMsg_UpdateZoomLimits(
   6228       routing_id_, minimum_percent, maximum_percent, remember));
   6229 }
   6230 
   6231 void RenderViewImpl::zoomLevelChanged() {
   6232   bool remember = !webview()->mainFrame()->document().isPluginDocument();
   6233   float zoom_level = webview()->zoomLevel();
   6234 
   6235   FOR_EACH_OBSERVER(RenderViewObserver, observers_, ZoomLevelChanged());
   6236 
   6237   // Tell the browser which url got zoomed so it can update the menu and the
   6238   // saved values if necessary
   6239   Send(new ViewHostMsg_DidZoomURL(
   6240       routing_id_, zoom_level, remember,
   6241       GURL(webview()->mainFrame()->document().url())));
   6242 }
   6243 
   6244 double RenderViewImpl::zoomLevelToZoomFactor(double zoom_level) const {
   6245   return ZoomLevelToZoomFactor(zoom_level);
   6246 }
   6247 
   6248 double RenderViewImpl::zoomFactorToZoomLevel(double factor) const {
   6249   return ZoomFactorToZoomLevel(factor);
   6250 }
   6251 
   6252 void RenderViewImpl::registerProtocolHandler(const WebString& scheme,
   6253                                              const WebString& base_url,
   6254                                              const WebString& url,
   6255                                              const WebString& title) {
   6256   bool user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
   6257   GURL base(base_url);
   6258   GURL absolute_url = base.Resolve(UTF16ToUTF8(url));
   6259   if (base.GetOrigin() != absolute_url.GetOrigin()) {
   6260     return;
   6261   }
   6262   Send(new ViewHostMsg_RegisterProtocolHandler(routing_id_,
   6263                                                UTF16ToUTF8(scheme),
   6264                                                absolute_url,
   6265                                                title,
   6266                                                user_gesture));
   6267 }
   6268 
   6269 WebKit::WebPageVisibilityState RenderViewImpl::visibilityState() const {
   6270   WebKit::WebPageVisibilityState current_state = is_hidden() ?
   6271       WebKit::WebPageVisibilityStateHidden :
   6272       WebKit::WebPageVisibilityStateVisible;
   6273   WebKit::WebPageVisibilityState override_state = current_state;
   6274   if (GetContentClient()->renderer()->
   6275           ShouldOverridePageVisibilityState(this,
   6276                                             &override_state))
   6277     return override_state;
   6278   return current_state;
   6279 }
   6280 
   6281 WebKit::WebUserMediaClient* RenderViewImpl::userMediaClient() {
   6282   EnsureMediaStreamClient();
   6283   return web_user_media_client_;
   6284 }
   6285 
   6286 WebKit::WebMIDIClient* RenderViewImpl::webMIDIClient() {
   6287   if (!midi_dispatcher_)
   6288     midi_dispatcher_ = new MIDIDispatcher(this);
   6289   return midi_dispatcher_;
   6290 }
   6291 
   6292 void RenderViewImpl::draggableRegionsChanged() {
   6293   FOR_EACH_OBSERVER(
   6294       RenderViewObserver,
   6295       observers_,
   6296       DraggableRegionsChanged(webview()->mainFrame()));
   6297 }
   6298 
   6299 #if defined(OS_ANDROID)
   6300 WebContentDetectionResult RenderViewImpl::detectContentAround(
   6301     const WebHitTestResult& touch_hit) {
   6302   DCHECK(!touch_hit.isNull());
   6303   DCHECK(!touch_hit.node().isNull());
   6304   DCHECK(touch_hit.node().isTextNode());
   6305 
   6306   // Process the position with all the registered content detectors until
   6307   // a match is found. Priority is provided by their relative order.
   6308   for (ContentDetectorList::const_iterator it = content_detectors_.begin();
   6309       it != content_detectors_.end(); ++it) {
   6310     ContentDetector::Result content = (*it)->FindTappedContent(touch_hit);
   6311     if (content.valid) {
   6312       return WebContentDetectionResult(content.content_boundaries,
   6313           UTF8ToUTF16(content.text), content.intent_url);
   6314     }
   6315   }
   6316   return WebContentDetectionResult();
   6317 }
   6318 
   6319 void RenderViewImpl::scheduleContentIntent(const WebURL& intent) {
   6320   // Introduce a short delay so that the user can notice the content.
   6321   base::MessageLoop::current()->PostDelayedTask(
   6322       FROM_HERE,
   6323       base::Bind(&RenderViewImpl::LaunchAndroidContentIntent,
   6324                  AsWeakPtr(),
   6325                  intent,
   6326                  expected_content_intent_id_),
   6327       base::TimeDelta::FromMilliseconds(kContentIntentDelayMilliseconds));
   6328 }
   6329 
   6330 void RenderViewImpl::cancelScheduledContentIntents() {
   6331   ++expected_content_intent_id_;
   6332 }
   6333 
   6334 void RenderViewImpl::LaunchAndroidContentIntent(const GURL& intent,
   6335                                                 size_t request_id) {
   6336   if (request_id != expected_content_intent_id_)
   6337       return;
   6338 
   6339   // Remove the content highlighting if any.
   6340   scheduleComposite();
   6341 
   6342   if (!intent.is_empty())
   6343     Send(new ViewHostMsg_StartContentIntent(routing_id_, intent));
   6344 }
   6345 
   6346 bool RenderViewImpl::openDateTimeChooser(
   6347     const WebKit::WebDateTimeChooserParams& params,
   6348     WebKit::WebDateTimeChooserCompletion* completion) {
   6349   date_time_picker_client_.reset(
   6350       new RendererDateTimePicker(this, params, completion));
   6351   return date_time_picker_client_->Open();
   6352 }
   6353 
   6354 #endif  // defined(OS_ANDROID)
   6355 
   6356 #if defined(OS_MACOSX)
   6357 void RenderViewImpl::OnSelectPopupMenuItem(int selected_index) {
   6358   if (external_popup_menu_ == NULL) {
   6359     // Crash reports from the field indicate that we can be notified with a
   6360     // NULL external popup menu (we probably get notified twice).
   6361     // If you hit this please file a bug against jcivelli and include the page
   6362     // and steps to repro.
   6363     NOTREACHED();
   6364     return;
   6365   }
   6366   external_popup_menu_->DidSelectItem(selected_index);
   6367   external_popup_menu_.reset();
   6368 }
   6369 #endif
   6370 
   6371 #if defined(OS_ANDROID)
   6372 void RenderViewImpl::OnSelectPopupMenuItems(
   6373     bool canceled,
   6374     const std::vector<int>& selected_indices) {
   6375   // It is possible to receive more than one of these calls if the user presses
   6376   // a select faster than it takes for the show-select-popup IPC message to make
   6377   // it to the browser UI thread.  Ignore the extra-messages.
   6378   // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
   6379   if (!external_popup_menu_)
   6380     return;
   6381 
   6382   external_popup_menu_->DidSelectItems(canceled, selected_indices);
   6383   external_popup_menu_.reset();
   6384 }
   6385 #endif
   6386 
   6387 void RenderViewImpl::OnContextMenuClosed(
   6388     const CustomContextMenuContext& custom_context) {
   6389   if (custom_context.request_id) {
   6390     // External request, should be in our map.
   6391     ContextMenuClient* client =
   6392         pending_context_menus_.Lookup(custom_context.request_id);
   6393     if (client) {
   6394       client->OnMenuClosed(custom_context.request_id);
   6395       pending_context_menus_.Remove(custom_context.request_id);
   6396     }
   6397   } else {
   6398     // Internal request, forward to WebKit.
   6399     context_menu_node_.reset();
   6400   }
   6401 }
   6402 
   6403 void RenderViewImpl::OnShowContextMenu(const gfx::Point& location) {
   6404   context_menu_source_type_ = ui::MENU_SOURCE_TOUCH_EDIT_MENU;
   6405   touch_editing_context_menu_location_ = location;
   6406   if (webview())
   6407     webview()->showContextMenu();
   6408 }
   6409 
   6410 void RenderViewImpl::OnEnableViewSourceMode() {
   6411   if (!webview())
   6412     return;
   6413   WebFrame* main_frame = webview()->mainFrame();
   6414   if (!main_frame)
   6415     return;
   6416   main_frame->enableViewSourceMode(true);
   6417 }
   6418 
   6419 #if defined(OS_ANDROID)
   6420 void RenderViewImpl::OnJavaBridgeInit() {
   6421   DCHECK(!java_bridge_dispatcher_);
   6422   java_bridge_dispatcher_ = new JavaBridgeDispatcher(this);
   6423 }
   6424 #endif
   6425 
   6426 void RenderViewImpl::OnDisownOpener() {
   6427   if (!webview())
   6428     return;
   6429 
   6430   WebFrame* main_frame = webview()->mainFrame();
   6431   if (main_frame && main_frame->opener())
   6432     main_frame->setOpener(NULL);
   6433 }
   6434 
   6435 #if defined(OS_ANDROID)
   6436 bool RenderViewImpl::didTapMultipleTargets(
   6437     const WebKit::WebGestureEvent& event,
   6438     const WebVector<WebRect>& target_rects) {
   6439   // Never show a disambiguation popup when accessibility is enabled,
   6440   // as this interferes with "touch exploration".
   6441   if (accessibility_mode_ == AccessibilityModeComplete)
   6442     return false;
   6443 
   6444   gfx::Rect finger_rect(
   6445       event.x - event.data.tap.width / 2, event.y - event.data.tap.height / 2,
   6446       event.data.tap.width, event.data.tap.height);
   6447   gfx::Rect zoom_rect;
   6448   float new_total_scale =
   6449       DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
   6450           finger_rect, target_rects, GetSize(),
   6451           gfx::Rect(webview()->mainFrame()->visibleContentRect()).size(),
   6452           device_scale_factor_ * webview()->pageScaleFactor(), &zoom_rect);
   6453   if (!new_total_scale)
   6454     return false;
   6455 
   6456   TapMultipleTargetsStrategy multitarget_strategy =
   6457     renderer_preferences_.tap_multiple_targets_strategy;
   6458   if (multitarget_strategy == TAP_MULTIPLE_TARGETS_STRATEGY_ZOOM) {
   6459       return webview()->zoomToMultipleTargetsRect(zoom_rect);
   6460   } else if (multitarget_strategy == TAP_MULTIPLE_TARGETS_STRATEGY_POPUP) {
   6461       gfx::Size canvas_size =
   6462           gfx::ToCeiledSize(gfx::ScaleSize(zoom_rect.size(), new_total_scale));
   6463       TransportDIB* transport_dib = NULL;
   6464       {
   6465         scoped_ptr<skia::PlatformCanvas> canvas(
   6466             RenderProcess::current()->GetDrawingCanvas(&transport_dib,
   6467                                                        gfx::Rect(canvas_size)));
   6468         if (!canvas)
   6469           return false;
   6470 
   6471         // TODO(trchen): Cleanup the device scale factor mess.
   6472         // device scale will be applied in WebKit
   6473         // --> zoom_rect doesn't include device scale,
   6474         //     but WebKit will still draw on zoom_rect * device_scale_factor_
   6475         canvas->scale(new_total_scale / device_scale_factor_,
   6476                       new_total_scale / device_scale_factor_);
   6477         canvas->translate(-zoom_rect.x() * device_scale_factor_,
   6478                           -zoom_rect.y() * device_scale_factor_);
   6479 
   6480         webwidget_->paint(
   6481             canvas.get(),
   6482             zoom_rect,
   6483             WebWidget::ForceSoftwareRenderingAndIgnoreGPUResidentContent);
   6484       }
   6485 
   6486       gfx::Rect physical_window_zoom_rect = gfx::ToEnclosingRect(
   6487           ClientRectToPhysicalWindowRect(gfx::RectF(zoom_rect)));
   6488       Send(new ViewHostMsg_ShowDisambiguationPopup(routing_id_,
   6489                                                    physical_window_zoom_rect,
   6490                                                    canvas_size,
   6491                                                    transport_dib->id()));
   6492   } else {
   6493     return false;
   6494   }
   6495 
   6496   return true;
   6497 }
   6498 #endif
   6499 
   6500 unsigned RenderViewImpl::GetLocalSessionHistoryLengthForTesting() const {
   6501   return history_list_length_;
   6502 }
   6503 
   6504 void RenderViewImpl::SetFocusAndActivateForTesting(bool enable) {
   6505   if (enable) {
   6506     if (has_focus())
   6507       return;
   6508     OnSetActive(true);
   6509     OnSetFocus(true);
   6510   } else {
   6511     if (!has_focus())
   6512       return;
   6513     OnSetFocus(false);
   6514     OnSetActive(false);
   6515   }
   6516 }
   6517 
   6518 void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) {
   6519   ViewMsg_Resize_Params params;
   6520   params.screen_info = screen_info_;
   6521   params.screen_info.deviceScaleFactor = factor;
   6522   params.new_size = size();
   6523   params.physical_backing_size =
   6524       gfx::ToCeiledSize(gfx::ScaleSize(size(), factor));
   6525   params.overdraw_bottom_height = 0.f;
   6526   params.resizer_rect = WebRect();
   6527   params.is_fullscreen = is_fullscreen();
   6528   OnResize(params);
   6529 }
   6530 
   6531 void RenderViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_size,
   6532                                                 const gfx::Size& max_size) {
   6533   OnEnableAutoResize(min_size, max_size);
   6534 }
   6535 
   6536 void RenderViewImpl::DisableAutoResizeForTesting(const gfx::Size& new_size) {
   6537   OnDisableAutoResize(new_size);
   6538 }
   6539 
   6540 void RenderViewImpl::SetMediaStreamClientForTesting(
   6541     MediaStreamClient* media_stream_client) {
   6542   DCHECK(!media_stream_client_);
   6543   DCHECK(!web_user_media_client_);
   6544   media_stream_client_ = media_stream_client;
   6545 }
   6546 
   6547 void RenderViewImpl::OnReleaseDisambiguationPopupDIB(
   6548     TransportDIB::Handle dib_handle) {
   6549   TransportDIB* dib = TransportDIB::CreateWithHandle(dib_handle);
   6550   RenderProcess::current()->ReleaseTransportDIB(dib);
   6551 }
   6552 
   6553 void RenderViewImpl::DidCommitCompositorFrame() {
   6554   RenderWidget::DidCommitCompositorFrame();
   6555   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidCommitCompositorFrame());
   6556 }
   6557 
   6558 void RenderViewImpl::SendUpdateFaviconURL(const std::vector<FaviconURL>& urls) {
   6559   if (!urls.empty())
   6560     Send(new ViewHostMsg_UpdateFaviconURL(routing_id_, page_id_, urls));
   6561 }
   6562 
   6563 void RenderViewImpl::DidStopLoadingIcons() {
   6564   int icon_types = WebIconURL::TypeFavicon;
   6565   if (TouchEnabled())
   6566     icon_types |= WebIconURL::TypeTouchPrecomposed | WebIconURL::TypeTouch;
   6567 
   6568   WebVector<WebIconURL> icon_urls =
   6569       webview()->mainFrame()->iconURLs(icon_types);
   6570 
   6571   std::vector<FaviconURL> urls;
   6572   for (size_t i = 0; i < icon_urls.size(); i++) {
   6573     WebURL url = icon_urls[i].iconURL();
   6574     if (!url.isEmpty())
   6575       urls.push_back(FaviconURL(url,
   6576                                 ToFaviconType(icon_urls[i].iconType())));
   6577   }
   6578   SendUpdateFaviconURL(urls);
   6579 }
   6580 
   6581 
   6582 }  // namespace content
   6583