OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/render_view.h" | 5 #include "chrome/renderer/render_view.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 using WebKit::WebConsoleMessage; | 107 using WebKit::WebConsoleMessage; |
108 using WebKit::WebData; | 108 using WebKit::WebData; |
109 using WebKit::WebDataSource; | 109 using WebKit::WebDataSource; |
110 using WebKit::WebDragData; | 110 using WebKit::WebDragData; |
111 using WebKit::WebDragOperation; | 111 using WebKit::WebDragOperation; |
112 using WebKit::WebDragOperationsMask; | 112 using WebKit::WebDragOperationsMask; |
113 using WebKit::WebEditingAction; | 113 using WebKit::WebEditingAction; |
114 using WebKit::WebForm; | 114 using WebKit::WebForm; |
115 using WebKit::WebFrame; | 115 using WebKit::WebFrame; |
116 using WebKit::WebHistoryItem; | 116 using WebKit::WebHistoryItem; |
| 117 using WebKit::WebMediaPlayer; |
| 118 using WebKit::WebMediaPlayerClient; |
117 using WebKit::WebNavigationPolicy; | 119 using WebKit::WebNavigationPolicy; |
118 using WebKit::WebNavigationType; | 120 using WebKit::WebNavigationType; |
119 using WebKit::WebNode; | 121 using WebKit::WebNode; |
| 122 using WebKit::WebPlugin; |
| 123 using WebKit::WebPluginParams; |
120 using WebKit::WebPopupMenuInfo; | 124 using WebKit::WebPopupMenuInfo; |
121 using WebKit::WebRange; | 125 using WebKit::WebRange; |
122 using WebKit::WebRect; | 126 using WebKit::WebRect; |
123 using WebKit::WebScriptSource; | 127 using WebKit::WebScriptSource; |
124 using WebKit::WebSettings; | 128 using WebKit::WebSettings; |
125 using WebKit::WebSize; | 129 using WebKit::WebSize; |
126 using WebKit::WebString; | 130 using WebKit::WebString; |
127 using WebKit::WebTextAffinity; | 131 using WebKit::WebTextAffinity; |
128 using WebKit::WebTextDirection; | 132 using WebKit::WebTextDirection; |
129 using WebKit::WebURL; | 133 using WebKit::WebURL; |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 DCHECK_EQ(next_page_id_, 1); | 257 DCHECK_EQ(next_page_id_, 1); |
254 DCHECK(next_page_id >= next_page_id_); | 258 DCHECK(next_page_id >= next_page_id_); |
255 next_page_id_ = next_page_id; | 259 next_page_id_ = next_page_id; |
256 } | 260 } |
257 | 261 |
258 void RenderView::PluginCrashed(base::ProcessId pid, | 262 void RenderView::PluginCrashed(base::ProcessId pid, |
259 const FilePath& plugin_path) { | 263 const FilePath& plugin_path) { |
260 Send(new ViewHostMsg_CrashedPlugin(routing_id_, pid, plugin_path)); | 264 Send(new ViewHostMsg_CrashedPlugin(routing_id_, pid, plugin_path)); |
261 } | 265 } |
262 | 266 |
263 void RenderView::JSOutOfMemory() { | |
264 Send(new ViewHostMsg_JSOutOfMemory(routing_id_)); | |
265 } | |
266 | |
267 void RenderView::Init(gfx::NativeViewId parent_hwnd, | 267 void RenderView::Init(gfx::NativeViewId parent_hwnd, |
268 base::WaitableEvent* modal_dialog_event, | 268 base::WaitableEvent* modal_dialog_event, |
269 int32 opener_id, | 269 int32 opener_id, |
270 const RendererPreferences& renderer_prefs, | 270 const RendererPreferences& renderer_prefs, |
271 SharedRenderViewCounter* counter, | 271 SharedRenderViewCounter* counter, |
272 int32 routing_id) { | 272 int32 routing_id) { |
273 DCHECK(!webview()); | 273 DCHECK(!webview()); |
274 | 274 |
275 if (opener_id != MSG_ROUTING_NONE) | 275 if (opener_id != MSG_ROUTING_NONE) |
276 opener_id_ = opener_id; | 276 opener_id_ = opener_id; |
277 | 277 |
278 if (counter) { | 278 if (counter) { |
279 shared_popup_counter_ = counter; | 279 shared_popup_counter_ = counter; |
280 shared_popup_counter_->data++; | 280 shared_popup_counter_->data++; |
281 decrement_shared_popup_at_destruction_ = true; | 281 decrement_shared_popup_at_destruction_ = true; |
282 } else { | 282 } else { |
283 shared_popup_counter_ = new SharedRenderViewCounter(0); | 283 shared_popup_counter_ = new SharedRenderViewCounter(0); |
284 decrement_shared_popup_at_destruction_ = false; | 284 decrement_shared_popup_at_destruction_ = false; |
285 } | 285 } |
286 | 286 |
287 devtools_agent_.reset(new DevToolsAgent(routing_id, this)); | 287 devtools_agent_.reset(new DevToolsAgent(routing_id, this)); |
288 | 288 |
289 webwidget_ = WebView::Create(this, this); | 289 webwidget_ = WebView::Create(this, this); |
290 webkit_preferences_.Apply(webview()); | 290 webkit_preferences_.Apply(webview()); |
291 webview()->InitializeMainFrame(); | 291 webview()->InitializeMainFrame(this); |
292 | 292 |
293 OnSetRendererPrefs(renderer_prefs); | 293 OnSetRendererPrefs(renderer_prefs); |
294 | 294 |
295 // Don't let WebCore keep a B/F list - we have our own. | 295 // Don't let WebCore keep a B/F list - we have our own. |
296 // We let it keep 1 entry because FrameLoader::goToItem expects an item in the | 296 // We let it keep 1 entry because FrameLoader::goToItem expects an item in the |
297 // backForwardList, which is used only in ASSERTs. | 297 // backForwardList, which is used only in ASSERTs. |
298 webview()->SetBackForwardListSize(1); | 298 webview()->SetBackForwardListSize(1); |
299 | 299 |
300 routing_id_ = routing_id; | 300 routing_id_ = routing_id; |
301 render_thread_->AddRoute(routing_id_, this); | 301 render_thread_->AddRoute(routing_id_, this); |
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 if (web_accessibility_manager_.get()) { | 983 if (web_accessibility_manager_.get()) { |
984 // Clear accessibility info cache. | 984 // Clear accessibility info cache. |
985 web_accessibility_manager_->ClearAccObjMap(-1, true); | 985 web_accessibility_manager_->ClearAccObjMap(-1, true); |
986 } | 986 } |
987 #else | 987 #else |
988 // TODO(port): accessibility not yet implemented. See http://crbug.com/8288. | 988 // TODO(port): accessibility not yet implemented. See http://crbug.com/8288. |
989 #endif | 989 #endif |
990 } | 990 } |
991 | 991 |
992 // Tell the embedding application that the title of the active page has changed | 992 // Tell the embedding application that the title of the active page has changed |
993 void RenderView::UpdateTitle(WebFrame* frame, const std::wstring& title) { | 993 void RenderView::UpdateTitle(WebFrame* frame, const string16& title) { |
994 // Ignore all but top level navigations... | 994 // Ignore all but top level navigations... |
995 if (webview()->GetMainFrame() == frame) { | 995 if (!frame->parent()) { |
996 Send(new ViewHostMsg_UpdateTitle( | 996 Send(new ViewHostMsg_UpdateTitle( |
997 routing_id_, | 997 routing_id_, |
998 page_id_, | 998 page_id_, |
999 title.length() > chrome::kMaxTitleChars ? | 999 UTF16ToWideHack(title.length() > chrome::kMaxTitleChars ? |
1000 title.substr(0, chrome::kMaxTitleChars) : title)); | 1000 title.substr(0, chrome::kMaxTitleChars) : title))); |
1001 } | 1001 } |
1002 } | 1002 } |
1003 | 1003 |
1004 void RenderView::UpdateEncoding(WebFrame* frame, | 1004 void RenderView::UpdateEncoding(WebFrame* frame, |
1005 const std::string& encoding_name) { | 1005 const std::string& encoding_name) { |
1006 // Only update main frame's encoding_name. | 1006 // Only update main frame's encoding_name. |
1007 if (webview()->GetMainFrame() == frame && | 1007 if (webview()->GetMainFrame() == frame && |
1008 last_encoding_name_ != encoding_name) { | 1008 last_encoding_name_ != encoding_name) { |
1009 // Save the encoding name for later comparing. | 1009 // Save the encoding name for later comparing. |
1010 last_encoding_name_ = encoding_name; | 1010 last_encoding_name_ = encoding_name; |
(...skipping 14 matching lines...) Expand all Loading... |
1025 | 1025 |
1026 const WebHistoryItem& item = | 1026 const WebHistoryItem& item = |
1027 webview()->GetMainFrame()->previousHistoryItem(); | 1027 webview()->GetMainFrame()->previousHistoryItem(); |
1028 if (item.isNull()) | 1028 if (item.isNull()) |
1029 return; | 1029 return; |
1030 | 1030 |
1031 Send(new ViewHostMsg_UpdateState( | 1031 Send(new ViewHostMsg_UpdateState( |
1032 routing_id_, page_id_, webkit_glue::HistoryItemToString(item))); | 1032 routing_id_, page_id_, webkit_glue::HistoryItemToString(item))); |
1033 } | 1033 } |
1034 | 1034 |
| 1035 void RenderView::OpenURL( |
| 1036 const GURL& url, const GURL& referrer, WebNavigationPolicy policy) { |
| 1037 Send(new ViewHostMsg_OpenURL( |
| 1038 routing_id_, url, referrer, NavigationPolicyToDisposition(policy))); |
| 1039 } |
| 1040 |
1035 // WebViewDelegate ------------------------------------------------------------ | 1041 // WebViewDelegate ------------------------------------------------------------ |
1036 | 1042 |
1037 bool RenderView::CanAcceptLoadDrops() const { | 1043 bool RenderView::CanAcceptLoadDrops() const { |
1038 return renderer_preferences_.can_accept_load_drops; | 1044 return renderer_preferences_.can_accept_load_drops; |
1039 } | 1045 } |
1040 | 1046 |
1041 void RenderView::DidStartLoading(WebView* webview) { | 1047 void RenderView::DidStartLoading(WebView* webview) { |
1042 if (is_loading_) { | 1048 if (is_loading_) { |
1043 DLOG(WARNING) << "DidStartLoading called while loading"; | 1049 DLOG(WARNING) << "DidStartLoading called while loading"; |
1044 return; | 1050 return; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1080 kDelayForCaptureMs); | 1086 kDelayForCaptureMs); |
1081 | 1087 |
1082 // The page is loaded. Try to process the file we need to upload if any. | 1088 // The page is loaded. Try to process the file we need to upload if any. |
1083 ProcessPendingUpload(); | 1089 ProcessPendingUpload(); |
1084 | 1090 |
1085 // Since the page is done loading, we are sure we don't need to try | 1091 // Since the page is done loading, we are sure we don't need to try |
1086 // again. | 1092 // again. |
1087 ResetPendingUpload(); | 1093 ResetPendingUpload(); |
1088 } | 1094 } |
1089 | 1095 |
1090 void RenderView::DidCreateDataSource(WebFrame* frame, WebDataSource* ds) { | |
1091 // The rest of RenderView assumes that a WebDataSource will always have a | |
1092 // non-null NavigationState. | |
1093 if (pending_navigation_state_.get()) { | |
1094 ds->setExtraData(pending_navigation_state_.release()); | |
1095 } else { | |
1096 ds->setExtraData(NavigationState::CreateContentInitiated()); | |
1097 } | |
1098 } | |
1099 | |
1100 void RenderView::DidPaint() { | 1096 void RenderView::DidPaint() { |
1101 WebFrame* main_frame = webview()->GetMainFrame(); | 1097 WebFrame* main_frame = webview()->GetMainFrame(); |
1102 | 1098 |
1103 if (main_frame->provisionalDataSource()) { | 1099 if (main_frame->provisionalDataSource()) { |
1104 // If we have a provisional frame we are between the start | 1100 // If we have a provisional frame we are between the start |
1105 // and commit stages of loading...ignore this paint. | 1101 // and commit stages of loading...ignore this paint. |
1106 return; | 1102 return; |
1107 } | 1103 } |
1108 | 1104 |
1109 WebDataSource* ds = main_frame->dataSource(); | 1105 WebDataSource* ds = main_frame->dataSource(); |
1110 NavigationState* navigation_state = NavigationState::FromDataSource(ds); | 1106 NavigationState* navigation_state = NavigationState::FromDataSource(ds); |
1111 DCHECK(navigation_state); | 1107 DCHECK(navigation_state); |
1112 | 1108 |
1113 Time now = Time::Now(); | 1109 Time now = Time::Now(); |
1114 if (navigation_state->first_paint_time().is_null()) { | 1110 if (navigation_state->first_paint_time().is_null()) { |
1115 navigation_state->set_first_paint_time(now); | 1111 navigation_state->set_first_paint_time(now); |
1116 } | 1112 } |
1117 if (navigation_state->first_paint_after_load_time().is_null() && | 1113 if (navigation_state->first_paint_after_load_time().is_null() && |
1118 !navigation_state->finish_load_time().is_null()) { | 1114 !navigation_state->finish_load_time().is_null()) { |
1119 navigation_state->set_first_paint_after_load_time(now); | 1115 navigation_state->set_first_paint_after_load_time(now); |
1120 } | 1116 } |
1121 } | 1117 } |
1122 | 1118 |
1123 void RenderView::DidStartProvisionalLoadForFrame( | |
1124 WebView* webview, | |
1125 WebFrame* frame, | |
1126 NavigationGesture gesture) { | |
1127 WebDataSource* ds = frame->provisionalDataSource(); | |
1128 NavigationState* navigation_state = NavigationState::FromDataSource(ds); | |
1129 | |
1130 navigation_state->set_start_load_time(Time::Now()); | |
1131 | |
1132 // Update the request time if WebKit has better knowledge of it. | |
1133 if (navigation_state->request_time().is_null()) { | |
1134 double event_time = ds->triggeringEventTime(); | |
1135 if (event_time != 0.0) | |
1136 navigation_state->set_request_time(Time::FromDoubleT(event_time)); | |
1137 } | |
1138 | |
1139 bool is_top_most = !frame->parent(); | |
1140 if (is_top_most) { | |
1141 navigation_gesture_ = gesture; | |
1142 | |
1143 // Make sure redirect tracking state is clear for the new load. | |
1144 completed_client_redirect_src_ = GURL(); | |
1145 } else if (frame->parent()->isLoading()) { | |
1146 // Take note of AUTO_SUBFRAME loads here, so that we can know how to | |
1147 // load an error page. See DidFailProvisionalLoadWithError. | |
1148 navigation_state->set_transition_type(PageTransition::AUTO_SUBFRAME); | |
1149 } | |
1150 | |
1151 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame( | |
1152 routing_id_, is_top_most, ds->request().url())); | |
1153 } | |
1154 | |
1155 bool RenderView::DidLoadResourceFromMemoryCache(WebView* webview, | |
1156 const WebURLRequest& request, | |
1157 const WebURLResponse& response, | |
1158 WebFrame* frame) { | |
1159 // Let the browser know we loaded a resource from the memory cache. This | |
1160 // message is needed to display the correct SSL indicators. | |
1161 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache( | |
1162 routing_id_, | |
1163 request.url(), | |
1164 frame->securityOrigin().utf8(), | |
1165 frame->top()->securityOrigin().utf8(), | |
1166 response.securityInfo())); | |
1167 | |
1168 return false; | |
1169 } | |
1170 | |
1171 void RenderView::DidReceiveProvisionalLoadServerRedirect(WebView* webview, | |
1172 WebFrame* frame) { | |
1173 if (frame == webview->GetMainFrame()) { | |
1174 // Received a redirect on the main frame. | |
1175 WebDataSource* data_source = | |
1176 webview->GetMainFrame()->provisionalDataSource(); | |
1177 if (!data_source) { | |
1178 // Should only be invoked when we have a data source. | |
1179 NOTREACHED(); | |
1180 return; | |
1181 } | |
1182 std::vector<GURL> redirects; | |
1183 GetRedirectChain(data_source, &redirects); | |
1184 if (redirects.size() >= 2) { | |
1185 Send(new ViewHostMsg_DidRedirectProvisionalLoad( | |
1186 routing_id_, page_id_, redirects[redirects.size() - 2], | |
1187 redirects[redirects.size() - 1])); | |
1188 } | |
1189 } | |
1190 } | |
1191 | |
1192 void RenderView::DidFailProvisionalLoadWithError(WebView* webview, | |
1193 const WebURLError& error, | |
1194 WebFrame* frame) { | |
1195 // Notify the browser that we failed a provisional load with an error. | |
1196 // | |
1197 // Note: It is important this notification occur before DidStopLoading so the | |
1198 // SSL manager can react to the provisional load failure before being | |
1199 // notified the load stopped. | |
1200 // | |
1201 WebDataSource* ds = frame->provisionalDataSource(); | |
1202 DCHECK(ds); | |
1203 | |
1204 const WebURLRequest& failed_request = ds->request(); | |
1205 | |
1206 bool show_repost_interstitial = | |
1207 (error.reason == net::ERR_CACHE_MISS && | |
1208 EqualsASCII(failed_request.httpMethod(), "POST")); | |
1209 Send(new ViewHostMsg_DidFailProvisionalLoadWithError( | |
1210 routing_id_, !frame->parent(), error.reason, error.unreachableURL, | |
1211 show_repost_interstitial)); | |
1212 | |
1213 // Don't display an error page if this is simply a cancelled load. Aside | |
1214 // from being dumb, WebCore doesn't expect it and it will cause a crash. | |
1215 if (error.reason == net::ERR_ABORTED) | |
1216 return; | |
1217 | |
1218 // Make sure we never show errors in view source mode. | |
1219 frame->enableViewSourceMode(false); | |
1220 | |
1221 NavigationState* navigation_state = NavigationState::FromDataSource(ds); | |
1222 | |
1223 // If this is a failed back/forward/reload navigation, then we need to do a | |
1224 // 'replace' load. This is necessary to avoid messing up session history. | |
1225 // Otherwise, we do a normal load, which simulates a 'go' navigation as far | |
1226 // as session history is concerned. | |
1227 // | |
1228 // AUTO_SUBFRAME loads should always be treated as loads that do not advance | |
1229 // the page id. | |
1230 // | |
1231 bool replace = | |
1232 navigation_state->pending_page_id() != -1 || | |
1233 navigation_state->transition_type() == PageTransition::AUTO_SUBFRAME; | |
1234 | |
1235 // If we failed on a browser initiated request, then make sure that our error | |
1236 // page load is regarded as the same browser initiated request. | |
1237 if (!navigation_state->is_content_initiated()) { | |
1238 pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated( | |
1239 navigation_state->pending_page_id(), | |
1240 navigation_state->transition_type(), | |
1241 navigation_state->request_time())); | |
1242 } | |
1243 | |
1244 // Provide the user with a more helpful error page? | |
1245 if (MaybeLoadAlternateErrorPage(frame, error, replace)) | |
1246 return; | |
1247 | |
1248 // Fallback to a local error page. | |
1249 LoadNavigationErrorPage(frame, failed_request, error, std::string(), | |
1250 replace); | |
1251 } | |
1252 | |
1253 void RenderView::LoadNavigationErrorPage(WebFrame* frame, | 1119 void RenderView::LoadNavigationErrorPage(WebFrame* frame, |
1254 const WebURLRequest& failed_request, | 1120 const WebURLRequest& failed_request, |
1255 const WebURLError& error, | 1121 const WebURLError& error, |
1256 const std::string& html, | 1122 const std::string& html, |
1257 bool replace) { | 1123 bool replace) { |
1258 GURL failed_url = error.unreachableURL; | 1124 GURL failed_url = error.unreachableURL; |
1259 | 1125 |
1260 std::string alt_html; | 1126 std::string alt_html; |
1261 if (html.empty()) { | 1127 if (html.empty()) { |
1262 // Use a local error page. | 1128 // Use a local error page. |
(...skipping 15 matching lines...) Expand all Loading... |
1278 } else { | 1144 } else { |
1279 alt_html = html; | 1145 alt_html = html; |
1280 } | 1146 } |
1281 | 1147 |
1282 frame->loadHTMLString(alt_html, | 1148 frame->loadHTMLString(alt_html, |
1283 GURL(kUnreachableWebDataURL), | 1149 GURL(kUnreachableWebDataURL), |
1284 failed_url, | 1150 failed_url, |
1285 replace); | 1151 replace); |
1286 } | 1152 } |
1287 | 1153 |
1288 void RenderView::DidReceiveDocumentData(WebFrame* frame, const char* data, | |
1289 size_t data_len) { | |
1290 NavigationState* navigation_state = | |
1291 NavigationState::FromDataSource(frame->dataSource()); | |
1292 if (!navigation_state->postpone_loading_data()) { | |
1293 frame->commitDocumentData(data, data_len); | |
1294 return; | |
1295 } | |
1296 | |
1297 // Continue buffering the response data for the original 404 page. If it | |
1298 // grows too large, then we'll just let it through. | |
1299 navigation_state->append_postponed_data(data, data_len); | |
1300 if (navigation_state->postponed_data().size() >= 512) { | |
1301 navigation_state->set_postpone_loading_data(false); | |
1302 frame->commitDocumentData(navigation_state->postponed_data().data(), | |
1303 navigation_state->postponed_data().size()); | |
1304 navigation_state->clear_postponed_data(); | |
1305 } | |
1306 } | |
1307 | |
1308 void RenderView::DidCommitLoadForFrame(WebView *webview, WebFrame* frame, | |
1309 bool is_new_navigation) { | |
1310 NavigationState* navigation_state = | |
1311 NavigationState::FromDataSource(frame->dataSource()); | |
1312 | |
1313 navigation_state->set_commit_load_time(Time::Now()); | |
1314 if (is_new_navigation) { | |
1315 // When we perform a new navigation, we need to update the previous session | |
1316 // history entry with state for the page we are leaving. | |
1317 UpdateSessionHistory(frame); | |
1318 | |
1319 // We bump our Page ID to correspond with the new session history entry. | |
1320 page_id_ = next_page_id_++; | |
1321 | |
1322 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
1323 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, | |
1324 page_id_, true), | |
1325 kDelayForForcedCaptureMs); | |
1326 } else { | |
1327 // Inspect the navigation_state on this frame to see if the navigation | |
1328 // corresponds to a session history navigation... Note: |frame| may or | |
1329 // may not be the toplevel frame, but for the case of capturing session | |
1330 // history, the first committed frame suffices. We keep track of whether | |
1331 // we've seen this commit before so that only capture session history once | |
1332 // per navigation. | |
1333 // | |
1334 // Note that we need to check if the page ID changed. In the case of a | |
1335 // reload, the page ID doesn't change, and UpdateSessionHistory gets the | |
1336 // previous URL and the current page ID, which would be wrong. | |
1337 if (navigation_state->pending_page_id() != -1 && | |
1338 navigation_state->pending_page_id() != page_id_ && | |
1339 !navigation_state->request_committed()) { | |
1340 // This is a successful session history navigation! | |
1341 UpdateSessionHistory(frame); | |
1342 page_id_ = navigation_state->pending_page_id(); | |
1343 } | |
1344 } | |
1345 | |
1346 // Remember that we've already processed this request, so we don't update | |
1347 // the session history again. We do this regardless of whether this is | |
1348 // a session history navigation, because if we attempted a session history | |
1349 // navigation without valid HistoryItem state, WebCore will think it is a | |
1350 // new navigation. | |
1351 navigation_state->set_request_committed(true); | |
1352 | |
1353 UpdateURL(frame); | |
1354 | |
1355 // If this committed load was initiated by a client redirect, we're | |
1356 // at the last stop now, so clear it. | |
1357 completed_client_redirect_src_ = GURL(); | |
1358 | |
1359 // Check whether we have new encoding name. | |
1360 UpdateEncoding(frame, webview->GetMainFrameEncodingName()); | |
1361 } | |
1362 | |
1363 void RenderView::DidReceiveTitle(WebView* webview, | |
1364 const std::wstring& title, | |
1365 WebFrame* frame) { | |
1366 UpdateTitle(frame, title); | |
1367 | |
1368 // Also check whether we have new encoding name. | |
1369 UpdateEncoding(frame, webview->GetMainFrameEncodingName()); | |
1370 } | |
1371 | |
1372 void RenderView::DidFinishLoadForFrame(WebView* webview, WebFrame* frame) { | |
1373 WebDataSource* ds = frame->dataSource(); | |
1374 NavigationState* navigation_state = NavigationState::FromDataSource(ds); | |
1375 DCHECK(navigation_state); | |
1376 navigation_state->set_finish_load_time(Time::Now()); | |
1377 } | |
1378 | |
1379 void RenderView::DidFailLoadWithError(WebView* webview, | |
1380 const WebURLError& error, | |
1381 WebFrame* frame) { | |
1382 // Currently this function is empty. When you implement something here and it | |
1383 // will display any error messages in HTML, please make sure to call | |
1384 // frame->SetInViewSourceMode(false) not to show them in view source mode. | |
1385 } | |
1386 | |
1387 void RenderView::DidFinishDocumentLoadForFrame(WebView* webview, | |
1388 WebFrame* frame) { | |
1389 WebDataSource* ds = frame->dataSource(); | |
1390 NavigationState* navigation_state = NavigationState::FromDataSource(ds); | |
1391 DCHECK(navigation_state); | |
1392 navigation_state->set_finish_document_load_time(Time::Now()); | |
1393 | |
1394 Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_)); | |
1395 | |
1396 // The document has now been fully loaded. Scan for password forms to be | |
1397 // sent up to the browser. | |
1398 SendPasswordForms(frame); | |
1399 | |
1400 // Check whether we have new encoding name. | |
1401 UpdateEncoding(frame, webview->GetMainFrameEncodingName()); | |
1402 | |
1403 if (RenderThread::current()) // Will be NULL during unit tests. | |
1404 RenderThread::current()->user_script_slave()->InjectScripts( | |
1405 frame, UserScript::DOCUMENT_END); | |
1406 } | |
1407 | |
1408 void RenderView::DidHandleOnloadEventsForFrame(WebView* webview, | |
1409 WebFrame* frame) { | |
1410 } | |
1411 | |
1412 void RenderView::DidChangeLocationWithinPageForFrame(WebView* webview, | |
1413 WebFrame* frame, | |
1414 bool is_new_navigation) { | |
1415 // If this was a reference fragment navigation that we initiated, then we | |
1416 // could end up having a non-null pending navigation state. We just need to | |
1417 // update the ExtraData on the datasource so that others who read the | |
1418 // ExtraData will get the new NavigationState. Similarly, if we did not | |
1419 // initiate this navigation, then we need to take care to reset any pre- | |
1420 // existing navigation state to a content-initiated navigation state. | |
1421 // DidCreateDataSource conveniently takes care of this for us. | |
1422 DidCreateDataSource(frame, frame->dataSource()); | |
1423 | |
1424 DidCommitLoadForFrame(webview, frame, is_new_navigation); | |
1425 | |
1426 const string16& title = | |
1427 webview->GetMainFrame()->dataSource()->pageTitle(); | |
1428 UpdateTitle(frame, UTF16ToWideHack(title)); | |
1429 } | |
1430 | |
1431 void RenderView::DidCompleteClientRedirect(WebView* webview, | |
1432 WebFrame* frame, | |
1433 const GURL& source) { | |
1434 if (webview->GetMainFrame() == frame) | |
1435 completed_client_redirect_src_ = source; | |
1436 } | |
1437 | |
1438 void RenderView::WillCloseFrame(WebView* webview, WebFrame* frame) { | |
1439 if (!frame->parent()) { | |
1440 const GURL& url = frame->url(); | |
1441 if (url.SchemeIs("http") || url.SchemeIs("https")) | |
1442 DumpLoadHistograms(); | |
1443 } | |
1444 } | |
1445 | |
1446 void RenderView::WillSubmitForm(WebView* webview, WebFrame* frame, | |
1447 const WebForm& form) { | |
1448 NavigationState* navigation_state = | |
1449 NavigationState::FromDataSource(frame->provisionalDataSource()); | |
1450 | |
1451 if (navigation_state->transition_type() == PageTransition::LINK) | |
1452 navigation_state->set_transition_type(PageTransition::FORM_SUBMIT); | |
1453 | |
1454 // Save these to be processed when the ensuing navigation is committed. | |
1455 navigation_state->set_searchable_form_data( | |
1456 SearchableFormData::Create(form)); | |
1457 navigation_state->set_password_form_data( | |
1458 PasswordFormDomManager::CreatePasswordForm(form)); | |
1459 | |
1460 if (form.isAutoCompleteEnabled()) { | |
1461 scoped_ptr<AutofillForm> autofill_form(AutofillForm::Create(form)); | |
1462 if (autofill_form.get()) | |
1463 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, *autofill_form)); | |
1464 } | |
1465 } | |
1466 | |
1467 void RenderView::WillSendRequest(WebFrame* frame, uint32 identifier, | |
1468 WebURLRequest* request, | |
1469 const WebURLResponse& redirect_response) { | |
1470 request->setRequestorID(routing_id_); | |
1471 } | |
1472 | |
1473 void RenderView::DidReceiveResponse(WebFrame* frame, uint32 identifier, | |
1474 const WebURLResponse& response) { | |
1475 // Consider loading an alternate error page for 404 responses. | |
1476 if (response.httpStatusCode() != 404) | |
1477 return; | |
1478 | |
1479 // Only do this for responses that correspond to a provisional data source | |
1480 // of the top-most frame. If we have a provisional data source, then we | |
1481 // can't have any sub-resources yet, so we know that this response must | |
1482 // correspond to a frame load. | |
1483 if (!frame->provisionalDataSource() || frame->parent()) | |
1484 return; | |
1485 | |
1486 // If we are in view source mode, then just let the user see the source of | |
1487 // the server's 404 error page. | |
1488 if (frame->isViewSourceModeEnabled()) | |
1489 return; | |
1490 | |
1491 // Can we even load an alternate error page for this URL? | |
1492 if (!GetAlternateErrorPageURL(response.url(), HTTP_404).is_valid()) | |
1493 return; | |
1494 | |
1495 NavigationState* navigation_state = | |
1496 NavigationState::FromDataSource(frame->provisionalDataSource()); | |
1497 navigation_state->set_postpone_loading_data(true); | |
1498 navigation_state->clear_postponed_data(); | |
1499 } | |
1500 | |
1501 void RenderView::DidFinishLoading(WebFrame* frame, uint32 identifier) { | |
1502 NavigationState* navigation_state = | |
1503 NavigationState::FromDataSource(frame->dataSource()); | |
1504 if (!navigation_state->postpone_loading_data()) | |
1505 return; | |
1506 | |
1507 // The server returned a 404 and the content was < 512 bytes (which we | |
1508 // suppressed). Go ahead and fetch the alternate page content. | |
1509 | |
1510 const GURL& frame_url = frame->url(); | |
1511 | |
1512 const GURL& error_page_url = GetAlternateErrorPageURL(frame_url, HTTP_404); | |
1513 DCHECK(error_page_url.is_valid()); | |
1514 | |
1515 WebURLError original_error; | |
1516 original_error.unreachableURL = frame_url; | |
1517 | |
1518 navigation_state->set_alt_error_page_fetcher( | |
1519 new AltErrorPageResourceFetcher( | |
1520 error_page_url, frame, original_error, | |
1521 NewCallback(this, &RenderView::AltErrorPageFinished))); | |
1522 } | |
1523 | |
1524 void RenderView::BindDOMAutomationController(WebFrame* frame) { | 1154 void RenderView::BindDOMAutomationController(WebFrame* frame) { |
1525 dom_automation_controller_.set_message_sender(this); | 1155 dom_automation_controller_.set_message_sender(this); |
1526 dom_automation_controller_.set_routing_id(routing_id_); | 1156 dom_automation_controller_.set_routing_id(routing_id_); |
1527 dom_automation_controller_.BindToJavascript(frame, | 1157 dom_automation_controller_.BindToJavascript(frame, |
1528 L"domAutomationController"); | 1158 L"domAutomationController"); |
1529 } | 1159 } |
1530 | 1160 |
1531 void RenderView::WindowObjectCleared(WebFrame* frame) { | |
1532 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_)) | |
1533 BindDOMAutomationController(frame); | |
1534 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) { | |
1535 dom_ui_bindings_.set_message_sender(this); | |
1536 dom_ui_bindings_.set_routing_id(routing_id_); | |
1537 dom_ui_bindings_.BindToJavascript(frame, L"chrome"); | |
1538 } | |
1539 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) { | |
1540 external_host_bindings_.set_message_sender(this); | |
1541 external_host_bindings_.set_routing_id(routing_id_); | |
1542 external_host_bindings_.BindToJavascript(frame, L"externalHost"); | |
1543 } | |
1544 } | |
1545 | |
1546 void RenderView::DocumentElementAvailable(WebFrame* frame) { | |
1547 if (RenderThread::current()) // Will be NULL during unit tests. | |
1548 RenderThread::current()->user_script_slave()->InjectScripts( | |
1549 frame, UserScript::DOCUMENT_START); | |
1550 | |
1551 // Notify the browser about non-blank documents loading in the top frame. | |
1552 GURL url = frame->url(); | |
1553 if (url.is_valid() && url.spec() != "about:blank") { | |
1554 if (frame == webview()->GetMainFrame()) | |
1555 Send(new ViewHostMsg_DocumentAvailableInMainFrame(routing_id_)); | |
1556 } | |
1557 } | |
1558 | |
1559 void RenderView::DidCreateScriptContextForFrame(WebFrame* webframe) { | 1161 void RenderView::DidCreateScriptContextForFrame(WebFrame* webframe) { |
1560 EventBindings::HandleContextCreated(webframe, false); | 1162 EventBindings::HandleContextCreated(webframe, false); |
1561 } | 1163 } |
1562 | 1164 |
1563 void RenderView::DidDestroyScriptContextForFrame(WebFrame* webframe) { | 1165 void RenderView::DidDestroyScriptContextForFrame(WebFrame* webframe) { |
1564 EventBindings::HandleContextDestroyed(webframe); | 1166 EventBindings::HandleContextDestroyed(webframe); |
1565 } | 1167 } |
1566 | 1168 |
1567 void RenderView::DidCreateIsolatedScriptContext(WebFrame* webframe) { | 1169 void RenderView::DidCreateIsolatedScriptContext(WebFrame* webframe) { |
1568 EventBindings::HandleContextCreated(webframe, true); | 1170 EventBindings::HandleContextCreated(webframe, true); |
1569 } | 1171 } |
1570 | 1172 |
1571 WebNavigationPolicy RenderView::PolicyForNavigationAction( | |
1572 WebView* webview, | |
1573 WebFrame* frame, | |
1574 const WebURLRequest& request, | |
1575 WebNavigationType type, | |
1576 WebNavigationPolicy default_policy, | |
1577 bool is_redirect) { | |
1578 // Webkit is asking whether to navigate to a new URL. | |
1579 // This is fine normally, except if we're showing UI from one security | |
1580 // context and they're trying to navigate to a different context. | |
1581 const GURL& url = request.url(); | |
1582 | |
1583 // If the browser is interested, then give it a chance to look at top level | |
1584 // navigations | |
1585 if (renderer_preferences_.browser_handles_top_level_requests && | |
1586 // Only send once. | |
1587 last_top_level_navigation_page_id_ != page_id_ && | |
1588 // Not interested in reloads. | |
1589 type != WebKit::WebNavigationTypeReload && | |
1590 type != WebKit::WebNavigationTypeFormSubmitted && | |
1591 // Must be a top level frame. | |
1592 frame->parent() == NULL) { | |
1593 // Skip if navigation is on the same page (using '#'). | |
1594 GURL frame_origin = GURL(frame->url()).GetOrigin(); | |
1595 if (url.GetOrigin() != frame_origin || url.ref().empty()) { | |
1596 last_top_level_navigation_page_id_ = page_id_; | |
1597 OpenURL(webview, url, GURL(), default_policy); | |
1598 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here. | |
1599 } | |
1600 } | |
1601 | |
1602 // A content initiated navigation may have originated from a link-click, | |
1603 // script, drag-n-drop operation, etc. | |
1604 bool is_content_initiated = | |
1605 NavigationState::FromDataSource(frame->provisionalDataSource())-> | |
1606 is_content_initiated(); | |
1607 | |
1608 // We only care about navigations that are within the current tab (as opposed | |
1609 // to, for example, opening a new window). | |
1610 // But we sometimes navigate to about:blank to clear a tab, and we want to | |
1611 // still allow that. | |
1612 if (default_policy == WebKit::WebNavigationPolicyCurrentTab && | |
1613 is_content_initiated && frame->parent() == NULL && | |
1614 !url.SchemeIs(chrome::kAboutScheme)) { | |
1615 // When we received such unsolicited navigations, we sometimes want to | |
1616 // punt them up to the browser to handle. | |
1617 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_) || | |
1618 BindingsPolicy::is_extension_enabled(enabled_bindings_) || | |
1619 frame->isViewSourceModeEnabled() || | |
1620 url.SchemeIs(chrome::kViewSourceScheme) || | |
1621 url.SchemeIs(chrome::kPrintScheme)) { | |
1622 OpenURL(webview, url, GURL(), default_policy); | |
1623 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here. | |
1624 } | |
1625 } | |
1626 | |
1627 // Detect when a page is "forking" a new tab that can be safely rendered in | |
1628 // its own process. This is done by sites like Gmail that try to open links | |
1629 // in new windows without script connections back to the original page. We | |
1630 // treat such cases as browser navigations (in which we will create a new | |
1631 // renderer for a cross-site navigation), rather than WebKit navigations. | |
1632 // | |
1633 // We use the following heuristic to decide whether to fork a new page in its | |
1634 // own process: | |
1635 // The parent page must open a new tab to about:blank, set the new tab's | |
1636 // window.opener to null, and then redirect the tab to a cross-site URL using | |
1637 // JavaScript. | |
1638 bool is_fork = | |
1639 // Must start from a tab showing about:blank, which is later redirected. | |
1640 GURL(frame->url()) == GURL("about:blank") && | |
1641 // Must be the first real navigation of the tab. | |
1642 GetHistoryBackListCount() < 1 && | |
1643 GetHistoryForwardListCount() < 1 && | |
1644 // The parent page must have set the child's window.opener to null before | |
1645 // redirecting to the desired URL. | |
1646 frame->opener() == NULL && | |
1647 // Must be a top-level frame. | |
1648 frame->parent() == NULL && | |
1649 // Must not have issued the request from this page. | |
1650 is_content_initiated && | |
1651 // Must be targeted at the current tab. | |
1652 default_policy == WebKit::WebNavigationPolicyCurrentTab && | |
1653 // Must be a JavaScript navigation, which appears as "other". | |
1654 type == WebKit::WebNavigationTypeOther; | |
1655 if (is_fork) { | |
1656 // Open the URL via the browser, not via WebKit. | |
1657 OpenURL(webview, url, GURL(), default_policy); | |
1658 return WebKit::WebNavigationPolicyIgnore; | |
1659 } | |
1660 | |
1661 return default_policy; | |
1662 } | |
1663 | |
1664 void RenderView::RunJavaScriptAlert(WebFrame* webframe, | 1173 void RenderView::RunJavaScriptAlert(WebFrame* webframe, |
1665 const std::wstring& message) { | 1174 const std::wstring& message) { |
1666 RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptAlert, | 1175 RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptAlert, |
1667 message, | 1176 message, |
1668 std::wstring(), | 1177 std::wstring(), |
1669 webframe->url(), | 1178 webframe->url(), |
1670 NULL); | 1179 NULL); |
1671 } | 1180 } |
1672 | 1181 |
1673 bool RenderView::RunJavaScriptConfirm(WebFrame* webframe, | 1182 bool RenderView::RunJavaScriptConfirm(WebFrame* webframe, |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1871 | 1380 |
1872 WebWidget* RenderView::CreatePopupWidgetWithInfo(WebView* webview, | 1381 WebWidget* RenderView::CreatePopupWidgetWithInfo(WebView* webview, |
1873 const WebPopupMenuInfo& info) { | 1382 const WebPopupMenuInfo& info) { |
1874 RenderWidget* widget = RenderWidget::Create(routing_id_, | 1383 RenderWidget* widget = RenderWidget::Create(routing_id_, |
1875 render_thread_, | 1384 render_thread_, |
1876 true); | 1385 true); |
1877 widget->ConfigureAsExternalPopupMenu(info); | 1386 widget->ConfigureAsExternalPopupMenu(info); |
1878 return widget->webwidget(); | 1387 return widget->webwidget(); |
1879 } | 1388 } |
1880 | 1389 |
1881 WebKit::WebPlugin* RenderView::CreatePlugin( | |
1882 WebFrame* frame, const WebKit::WebPluginParams& params) { | |
1883 return new webkit_glue::WebPluginImpl(frame, params, AsWeakPtr()); | |
1884 } | |
1885 | |
1886 WebKit::WebMediaPlayer* RenderView::CreateWebMediaPlayer( | |
1887 WebKit::WebMediaPlayerClient* client) { | |
1888 scoped_refptr<media::FilterFactoryCollection> factory = | |
1889 new media::FilterFactoryCollection(); | |
1890 // Add in any custom filter factories first. | |
1891 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | |
1892 if (!cmd_line->HasSwitch(switches::kDisableAudio)) { | |
1893 // Add the chrome specific audio renderer. | |
1894 factory->AddFactory( | |
1895 AudioRendererImpl::CreateFactory(audio_message_filter())); | |
1896 } | |
1897 | |
1898 // TODO(hclam): obtain the following parameters from |client|. | |
1899 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory = | |
1900 new webkit_glue::MediaResourceLoaderBridgeFactory( | |
1901 GURL::EmptyGURL(), // referrer | |
1902 "null", // frame origin | |
1903 "null", // main_frame_origin | |
1904 base::GetCurrentProcId(), | |
1905 appcache::kNoHostId, | |
1906 routing_id()); | |
1907 | |
1908 if (!cmd_line->HasSwitch(switches::kSimpleDataSource)) { | |
1909 // Add the chrome specific media data source. | |
1910 factory->AddFactory( | |
1911 webkit_glue::BufferedDataSource::CreateFactory(MessageLoop::current(), | |
1912 bridge_factory)); | |
1913 } else { | |
1914 factory->AddFactory( | |
1915 webkit_glue::SimpleDataSource::CreateFactory(MessageLoop::current(), | |
1916 bridge_factory)); | |
1917 } | |
1918 return new webkit_glue::WebMediaPlayerImpl(client, factory); | |
1919 } | |
1920 | |
1921 void RenderView::OnMissingPluginStatus( | 1390 void RenderView::OnMissingPluginStatus( |
1922 WebPluginDelegateProxy* delegate, | 1391 WebPluginDelegateProxy* delegate, |
1923 int status) { | 1392 int status) { |
1924 #if defined(OS_WIN) | 1393 #if defined(OS_WIN) |
1925 if (!first_default_plugin_) { | 1394 if (!first_default_plugin_) { |
1926 // Show the InfoBar for the first available plugin. | 1395 // Show the InfoBar for the first available plugin. |
1927 if (status == default_plugin::MISSING_PLUGIN_AVAILABLE) { | 1396 if (status == default_plugin::MISSING_PLUGIN_AVAILABLE) { |
1928 first_default_plugin_ = delegate->AsWeakPtr(); | 1397 first_default_plugin_ = delegate->AsWeakPtr(); |
1929 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status)); | 1398 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status)); |
1930 } | 1399 } |
1931 } else { | 1400 } else { |
1932 // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar) | 1401 // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar) |
1933 // to start the download/install. | 1402 // to start the download/install. |
1934 if (status == default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) { | 1403 if (status == default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) { |
1935 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status)); | 1404 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status)); |
1936 } | 1405 } |
1937 } | 1406 } |
1938 #else | 1407 #else |
1939 // TODO(port): plugins current not supported | 1408 // TODO(port): plugins current not supported |
1940 NOTIMPLEMENTED(); | 1409 NOTIMPLEMENTED(); |
1941 #endif | 1410 #endif |
1942 } | 1411 } |
1943 | 1412 |
1944 WebWorker* RenderView::CreateWebWorker(WebWorkerClient* client) { | |
1945 return new WebWorkerProxy(client, RenderThread::current(), routing_id_); | |
1946 } | |
1947 | |
1948 void RenderView::OpenURL(WebView* webview, const GURL& url, | |
1949 const GURL& referrer, | |
1950 WebNavigationPolicy policy) { | |
1951 Send(new ViewHostMsg_OpenURL( | |
1952 routing_id_, url, referrer, NavigationPolicyToDisposition(policy))); | |
1953 } | |
1954 | |
1955 void RenderView::DidContentsSizeChange(WebWidget* webwidget, | |
1956 int new_width, | |
1957 int new_height) { | |
1958 // We don't always want to send the change messages over IPC, only if we've | |
1959 // be put in that mode by getting a |ViewMsg_EnableIntrinsicWidthChangedMode| | |
1960 // message. | |
1961 // TODO(rafaelw): Figure out where the best place to set this for extensions | |
1962 // is. It isn't clean to test for ExtensionView by examining the | |
1963 // enabled_bindings. This needs to be generalized as it becomes clear what | |
1964 // extension toolbars need. | |
1965 if (BindingsPolicy::is_extension_enabled(enabled_bindings_) || | |
1966 send_preferred_width_changes_) { | |
1967 // WebCore likes to tell us things have changed even when they haven't, so | |
1968 // cache the width and only send the IPC message when we're sure the | |
1969 // width is different. | |
1970 int width = webview()->GetMainFrame()->contentsPreferredWidth(); | |
1971 if (width != preferred_width_) { | |
1972 Send(new ViewHostMsg_DidContentsPreferredWidthChange(routing_id_, width)); | |
1973 preferred_width_ = width; | |
1974 } | |
1975 } | |
1976 } | |
1977 | |
1978 // WebKit::WebWidgetClient ---------------------------------------------------- | 1413 // WebKit::WebWidgetClient ---------------------------------------------------- |
1979 | 1414 |
1980 // We are supposed to get a single call to Show for a newly created RenderView | 1415 // We are supposed to get a single call to Show for a newly created RenderView |
1981 // that was created via RenderView::CreateWebView. So, we wait until this | 1416 // that was created via RenderView::CreateWebView. So, we wait until this |
1982 // point to dispatch the ShowView message. | 1417 // point to dispatch the ShowView message. |
1983 // | 1418 // |
1984 // This method provides us with the information about how to display the newly | 1419 // This method provides us with the information about how to display the newly |
1985 // created RenderView (i.e., as a constrained popup or as a new tab). | 1420 // created RenderView (i.e., as a constrained popup or as a new tab). |
1986 // | 1421 // |
1987 void RenderView::show(WebNavigationPolicy policy) { | 1422 void RenderView::show(WebNavigationPolicy policy) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2099 | 1534 |
2100 void RenderView::didExecuteCommand(const WebString& command_name) { | 1535 void RenderView::didExecuteCommand(const WebString& command_name) { |
2101 const std::wstring& name = UTF16ToWideHack(command_name); | 1536 const std::wstring& name = UTF16ToWideHack(command_name); |
2102 if (StartsWith(name, L"Move", true) || | 1537 if (StartsWith(name, L"Move", true) || |
2103 StartsWith(name, L"Insert", true) || | 1538 StartsWith(name, L"Insert", true) || |
2104 StartsWith(name, L"Delete", true)) | 1539 StartsWith(name, L"Delete", true)) |
2105 return; | 1540 return; |
2106 UserMetricsRecordAction(name); | 1541 UserMetricsRecordAction(name); |
2107 } | 1542 } |
2108 | 1543 |
| 1544 // WebKit::WebFrameClient ----------------------------------------------------- |
| 1545 |
| 1546 WebPlugin* RenderView::createPlugin( |
| 1547 WebFrame* frame, const WebPluginParams& params) { |
| 1548 return new webkit_glue::WebPluginImpl(frame, params, AsWeakPtr()); |
| 1549 } |
| 1550 |
| 1551 WebWorker* RenderView::createWorker(WebFrame* frame, WebWorkerClient* client) { |
| 1552 return new WebWorkerProxy(client, RenderThread::current(), routing_id_); |
| 1553 } |
| 1554 |
| 1555 WebMediaPlayer* RenderView::createMediaPlayer( |
| 1556 WebFrame* frame, WebMediaPlayerClient* client) { |
| 1557 scoped_refptr<media::FilterFactoryCollection> factory = |
| 1558 new media::FilterFactoryCollection(); |
| 1559 // Add in any custom filter factories first. |
| 1560 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
| 1561 if (!cmd_line->HasSwitch(switches::kDisableAudio)) { |
| 1562 // Add the chrome specific audio renderer. |
| 1563 factory->AddFactory( |
| 1564 AudioRendererImpl::CreateFactory(audio_message_filter())); |
| 1565 } |
| 1566 |
| 1567 // TODO(hclam): obtain the following parameters from |client|. |
| 1568 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory = |
| 1569 new webkit_glue::MediaResourceLoaderBridgeFactory( |
| 1570 GURL::EmptyGURL(), // referrer |
| 1571 "null", // frame origin |
| 1572 "null", // main_frame_origin |
| 1573 base::GetCurrentProcId(), |
| 1574 appcache::kNoHostId, |
| 1575 routing_id()); |
| 1576 |
| 1577 if (!cmd_line->HasSwitch(switches::kSimpleDataSource)) { |
| 1578 // Add the chrome specific media data source. |
| 1579 factory->AddFactory( |
| 1580 webkit_glue::BufferedDataSource::CreateFactory(MessageLoop::current(), |
| 1581 bridge_factory)); |
| 1582 } else { |
| 1583 factory->AddFactory( |
| 1584 webkit_glue::SimpleDataSource::CreateFactory(MessageLoop::current(), |
| 1585 bridge_factory)); |
| 1586 } |
| 1587 return new webkit_glue::WebMediaPlayerImpl(client, factory); |
| 1588 } |
| 1589 |
| 1590 void RenderView::willClose(WebFrame* frame) { |
| 1591 if (!frame->parent()) { |
| 1592 const GURL& url = frame->url(); |
| 1593 if (url.SchemeIs("http") || url.SchemeIs("https")) |
| 1594 DumpLoadHistograms(); |
| 1595 } |
| 1596 } |
| 1597 |
| 1598 void RenderView::loadURLExternally( |
| 1599 WebFrame* frame, const WebURLRequest& request, |
| 1600 WebNavigationPolicy policy) { |
| 1601 OpenURL(request.url(), |
| 1602 GURL(request.httpHeaderField(WebString::fromUTF8("Referer"))), |
| 1603 policy); |
| 1604 } |
| 1605 |
| 1606 WebNavigationPolicy RenderView::decidePolicyForNavigation( |
| 1607 WebFrame* frame, const WebURLRequest& request, WebNavigationType type, |
| 1608 WebNavigationPolicy default_policy, bool is_redirect) { |
| 1609 // Webkit is asking whether to navigate to a new URL. |
| 1610 // This is fine normally, except if we're showing UI from one security |
| 1611 // context and they're trying to navigate to a different context. |
| 1612 const GURL& url = request.url(); |
| 1613 |
| 1614 // If the browser is interested, then give it a chance to look at top level |
| 1615 // navigations |
| 1616 if (renderer_preferences_.browser_handles_top_level_requests && |
| 1617 // Only send once. |
| 1618 last_top_level_navigation_page_id_ != page_id_ && |
| 1619 // Not interested in reloads. |
| 1620 type != WebKit::WebNavigationTypeReload && |
| 1621 type != WebKit::WebNavigationTypeFormSubmitted && |
| 1622 // Must be a top level frame. |
| 1623 frame->parent() == NULL) { |
| 1624 // Skip if navigation is on the same page (using '#'). |
| 1625 GURL frame_origin = GURL(frame->url()).GetOrigin(); |
| 1626 if (url.GetOrigin() != frame_origin || url.ref().empty()) { |
| 1627 last_top_level_navigation_page_id_ = page_id_; |
| 1628 OpenURL(url, GURL(), default_policy); |
| 1629 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here. |
| 1630 } |
| 1631 } |
| 1632 |
| 1633 // A content initiated navigation may have originated from a link-click, |
| 1634 // script, drag-n-drop operation, etc. |
| 1635 bool is_content_initiated = |
| 1636 NavigationState::FromDataSource(frame->provisionalDataSource())-> |
| 1637 is_content_initiated(); |
| 1638 |
| 1639 // We only care about navigations that are within the current tab (as opposed |
| 1640 // to, for example, opening a new window). |
| 1641 // But we sometimes navigate to about:blank to clear a tab, and we want to |
| 1642 // still allow that. |
| 1643 if (default_policy == WebKit::WebNavigationPolicyCurrentTab && |
| 1644 is_content_initiated && frame->parent() == NULL && |
| 1645 !url.SchemeIs(chrome::kAboutScheme)) { |
| 1646 // When we received such unsolicited navigations, we sometimes want to |
| 1647 // punt them up to the browser to handle. |
| 1648 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_) || |
| 1649 BindingsPolicy::is_extension_enabled(enabled_bindings_) || |
| 1650 frame->isViewSourceModeEnabled() || |
| 1651 url.SchemeIs(chrome::kViewSourceScheme) || |
| 1652 url.SchemeIs(chrome::kPrintScheme)) { |
| 1653 OpenURL(url, GURL(), default_policy); |
| 1654 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here. |
| 1655 } |
| 1656 } |
| 1657 |
| 1658 // Detect when a page is "forking" a new tab that can be safely rendered in |
| 1659 // its own process. This is done by sites like Gmail that try to open links |
| 1660 // in new windows without script connections back to the original page. We |
| 1661 // treat such cases as browser navigations (in which we will create a new |
| 1662 // renderer for a cross-site navigation), rather than WebKit navigations. |
| 1663 // |
| 1664 // We use the following heuristic to decide whether to fork a new page in its |
| 1665 // own process: |
| 1666 // The parent page must open a new tab to about:blank, set the new tab's |
| 1667 // window.opener to null, and then redirect the tab to a cross-site URL using |
| 1668 // JavaScript. |
| 1669 bool is_fork = |
| 1670 // Must start from a tab showing about:blank, which is later redirected. |
| 1671 GURL(frame->url()) == GURL("about:blank") && |
| 1672 // Must be the first real navigation of the tab. |
| 1673 GetHistoryBackListCount() < 1 && |
| 1674 GetHistoryForwardListCount() < 1 && |
| 1675 // The parent page must have set the child's window.opener to null before |
| 1676 // redirecting to the desired URL. |
| 1677 frame->opener() == NULL && |
| 1678 // Must be a top-level frame. |
| 1679 frame->parent() == NULL && |
| 1680 // Must not have issued the request from this page. |
| 1681 is_content_initiated && |
| 1682 // Must be targeted at the current tab. |
| 1683 default_policy == WebKit::WebNavigationPolicyCurrentTab && |
| 1684 // Must be a JavaScript navigation, which appears as "other". |
| 1685 type == WebKit::WebNavigationTypeOther; |
| 1686 if (is_fork) { |
| 1687 // Open the URL via the browser, not via WebKit. |
| 1688 OpenURL(url, GURL(), default_policy); |
| 1689 return WebKit::WebNavigationPolicyIgnore; |
| 1690 } |
| 1691 |
| 1692 return default_policy; |
| 1693 } |
| 1694 |
| 1695 void RenderView::willSubmitForm(WebFrame* frame, const WebForm& form) { |
| 1696 NavigationState* navigation_state = |
| 1697 NavigationState::FromDataSource(frame->provisionalDataSource()); |
| 1698 |
| 1699 if (navigation_state->transition_type() == PageTransition::LINK) |
| 1700 navigation_state->set_transition_type(PageTransition::FORM_SUBMIT); |
| 1701 |
| 1702 // Save these to be processed when the ensuing navigation is committed. |
| 1703 navigation_state->set_searchable_form_data( |
| 1704 SearchableFormData::Create(form)); |
| 1705 navigation_state->set_password_form_data( |
| 1706 PasswordFormDomManager::CreatePasswordForm(form)); |
| 1707 |
| 1708 if (form.isAutoCompleteEnabled()) { |
| 1709 scoped_ptr<AutofillForm> autofill_form(AutofillForm::Create(form)); |
| 1710 if (autofill_form.get()) |
| 1711 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, *autofill_form)); |
| 1712 } |
| 1713 } |
| 1714 |
| 1715 void RenderView::willPerformClientRedirect( |
| 1716 WebFrame* frame, const WebURL& from, const WebURL& to, double interval, |
| 1717 double fire_time) { |
| 1718 // Ignore |
| 1719 } |
| 1720 |
| 1721 void RenderView::didCancelClientRedirect(WebFrame* frame) { |
| 1722 // Ignore |
| 1723 } |
| 1724 |
| 1725 void RenderView::didCompleteClientRedirect( |
| 1726 WebFrame* frame, const WebURL& from) { |
| 1727 if (!frame->parent()) |
| 1728 completed_client_redirect_src_ = from; |
| 1729 } |
| 1730 |
| 1731 void RenderView::didCreateDataSource(WebFrame* frame, WebDataSource* ds) { |
| 1732 // The rest of RenderView assumes that a WebDataSource will always have a |
| 1733 // non-null NavigationState. |
| 1734 if (pending_navigation_state_.get()) { |
| 1735 ds->setExtraData(pending_navigation_state_.release()); |
| 1736 } else { |
| 1737 ds->setExtraData(NavigationState::CreateContentInitiated()); |
| 1738 } |
| 1739 } |
| 1740 |
| 1741 void RenderView::didStartProvisionalLoad(WebFrame* frame) { |
| 1742 WebDataSource* ds = frame->provisionalDataSource(); |
| 1743 NavigationState* navigation_state = NavigationState::FromDataSource(ds); |
| 1744 |
| 1745 navigation_state->set_start_load_time(Time::Now()); |
| 1746 |
| 1747 // Update the request time if WebKit has better knowledge of it. |
| 1748 if (navigation_state->request_time().is_null()) { |
| 1749 double event_time = ds->triggeringEventTime(); |
| 1750 if (event_time != 0.0) |
| 1751 navigation_state->set_request_time(Time::FromDoubleT(event_time)); |
| 1752 } |
| 1753 |
| 1754 bool is_top_most = !frame->parent(); |
| 1755 if (is_top_most) { |
| 1756 navigation_gesture_ = frame->isProcessingUserGesture() ? |
| 1757 NavigationGestureUnknown : NavigationGestureAuto; |
| 1758 |
| 1759 // Make sure redirect tracking state is clear for the new load. |
| 1760 completed_client_redirect_src_ = GURL(); |
| 1761 } else if (frame->parent()->isLoading()) { |
| 1762 // Take note of AUTO_SUBFRAME loads here, so that we can know how to |
| 1763 // load an error page. See DidFailProvisionalLoadWithError. |
| 1764 navigation_state->set_transition_type(PageTransition::AUTO_SUBFRAME); |
| 1765 } |
| 1766 |
| 1767 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame( |
| 1768 routing_id_, is_top_most, ds->request().url())); |
| 1769 } |
| 1770 |
| 1771 void RenderView::didReceiveServerRedirectForProvisionalLoad(WebFrame* frame) { |
| 1772 if (frame->parent()) |
| 1773 return; |
| 1774 // Received a redirect on the main frame. |
| 1775 WebDataSource* data_source = frame->provisionalDataSource(); |
| 1776 if (!data_source) { |
| 1777 // Should only be invoked when we have a data source. |
| 1778 NOTREACHED(); |
| 1779 return; |
| 1780 } |
| 1781 std::vector<GURL> redirects; |
| 1782 GetRedirectChain(data_source, &redirects); |
| 1783 if (redirects.size() >= 2) { |
| 1784 Send(new ViewHostMsg_DidRedirectProvisionalLoad( |
| 1785 routing_id_, page_id_, redirects[redirects.size() - 2], |
| 1786 redirects[redirects.size() - 1])); |
| 1787 } |
| 1788 } |
| 1789 |
| 1790 void RenderView::didFailProvisionalLoad( |
| 1791 WebFrame* frame, const WebURLError& error) { |
| 1792 // Notify the browser that we failed a provisional load with an error. |
| 1793 // |
| 1794 // Note: It is important this notification occur before DidStopLoading so the |
| 1795 // SSL manager can react to the provisional load failure before being |
| 1796 // notified the load stopped. |
| 1797 // |
| 1798 WebDataSource* ds = frame->provisionalDataSource(); |
| 1799 DCHECK(ds); |
| 1800 |
| 1801 const WebURLRequest& failed_request = ds->request(); |
| 1802 |
| 1803 bool show_repost_interstitial = |
| 1804 (error.reason == net::ERR_CACHE_MISS && |
| 1805 EqualsASCII(failed_request.httpMethod(), "POST")); |
| 1806 Send(new ViewHostMsg_DidFailProvisionalLoadWithError( |
| 1807 routing_id_, !frame->parent(), error.reason, error.unreachableURL, |
| 1808 show_repost_interstitial)); |
| 1809 |
| 1810 // Don't display an error page if this is simply a cancelled load. Aside |
| 1811 // from being dumb, WebCore doesn't expect it and it will cause a crash. |
| 1812 if (error.reason == net::ERR_ABORTED) |
| 1813 return; |
| 1814 |
| 1815 // Make sure we never show errors in view source mode. |
| 1816 frame->enableViewSourceMode(false); |
| 1817 |
| 1818 NavigationState* navigation_state = NavigationState::FromDataSource(ds); |
| 1819 |
| 1820 // If this is a failed back/forward/reload navigation, then we need to do a |
| 1821 // 'replace' load. This is necessary to avoid messing up session history. |
| 1822 // Otherwise, we do a normal load, which simulates a 'go' navigation as far |
| 1823 // as session history is concerned. |
| 1824 // |
| 1825 // AUTO_SUBFRAME loads should always be treated as loads that do not advance |
| 1826 // the page id. |
| 1827 // |
| 1828 bool replace = |
| 1829 navigation_state->pending_page_id() != -1 || |
| 1830 navigation_state->transition_type() == PageTransition::AUTO_SUBFRAME; |
| 1831 |
| 1832 // If we failed on a browser initiated request, then make sure that our error |
| 1833 // page load is regarded as the same browser initiated request. |
| 1834 if (!navigation_state->is_content_initiated()) { |
| 1835 pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated( |
| 1836 navigation_state->pending_page_id(), |
| 1837 navigation_state->transition_type(), |
| 1838 navigation_state->request_time())); |
| 1839 } |
| 1840 |
| 1841 // Provide the user with a more helpful error page? |
| 1842 if (MaybeLoadAlternateErrorPage(frame, error, replace)) |
| 1843 return; |
| 1844 |
| 1845 // Fallback to a local error page. |
| 1846 LoadNavigationErrorPage(frame, failed_request, error, std::string(), |
| 1847 replace); |
| 1848 } |
| 1849 |
| 1850 void RenderView::didReceiveDocumentData( |
| 1851 WebFrame* frame, const char* data, size_t data_len, |
| 1852 bool& prevent_default) { |
| 1853 NavigationState* navigation_state = |
| 1854 NavigationState::FromDataSource(frame->dataSource()); |
| 1855 if (!navigation_state->postpone_loading_data()) |
| 1856 return; |
| 1857 |
| 1858 // We're going to call commitDocumentData ourselves... |
| 1859 prevent_default = true; |
| 1860 |
| 1861 // Continue buffering the response data for the original 404 page. If it |
| 1862 // grows too large, then we'll just let it through. |
| 1863 navigation_state->append_postponed_data(data, data_len); |
| 1864 if (navigation_state->postponed_data().size() >= 512) { |
| 1865 navigation_state->set_postpone_loading_data(false); |
| 1866 frame->commitDocumentData(navigation_state->postponed_data().data(), |
| 1867 navigation_state->postponed_data().size()); |
| 1868 navigation_state->clear_postponed_data(); |
| 1869 } |
| 1870 } |
| 1871 |
| 1872 void RenderView::didCommitProvisionalLoad( |
| 1873 WebFrame* frame, bool is_new_navigation) { |
| 1874 NavigationState* navigation_state = |
| 1875 NavigationState::FromDataSource(frame->dataSource()); |
| 1876 |
| 1877 navigation_state->set_commit_load_time(Time::Now()); |
| 1878 if (is_new_navigation) { |
| 1879 // When we perform a new navigation, we need to update the previous session |
| 1880 // history entry with state for the page we are leaving. |
| 1881 UpdateSessionHistory(frame); |
| 1882 |
| 1883 // We bump our Page ID to correspond with the new session history entry. |
| 1884 page_id_ = next_page_id_++; |
| 1885 |
| 1886 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 1887 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, |
| 1888 page_id_, true), |
| 1889 kDelayForForcedCaptureMs); |
| 1890 } else { |
| 1891 // Inspect the navigation_state on this frame to see if the navigation |
| 1892 // corresponds to a session history navigation... Note: |frame| may or |
| 1893 // may not be the toplevel frame, but for the case of capturing session |
| 1894 // history, the first committed frame suffices. We keep track of whether |
| 1895 // we've seen this commit before so that only capture session history once |
| 1896 // per navigation. |
| 1897 // |
| 1898 // Note that we need to check if the page ID changed. In the case of a |
| 1899 // reload, the page ID doesn't change, and UpdateSessionHistory gets the |
| 1900 // previous URL and the current page ID, which would be wrong. |
| 1901 if (navigation_state->pending_page_id() != -1 && |
| 1902 navigation_state->pending_page_id() != page_id_ && |
| 1903 !navigation_state->request_committed()) { |
| 1904 // This is a successful session history navigation! |
| 1905 UpdateSessionHistory(frame); |
| 1906 page_id_ = navigation_state->pending_page_id(); |
| 1907 } |
| 1908 } |
| 1909 |
| 1910 // Remember that we've already processed this request, so we don't update |
| 1911 // the session history again. We do this regardless of whether this is |
| 1912 // a session history navigation, because if we attempted a session history |
| 1913 // navigation without valid HistoryItem state, WebCore will think it is a |
| 1914 // new navigation. |
| 1915 navigation_state->set_request_committed(true); |
| 1916 |
| 1917 UpdateURL(frame); |
| 1918 |
| 1919 // If this committed load was initiated by a client redirect, we're |
| 1920 // at the last stop now, so clear it. |
| 1921 completed_client_redirect_src_ = GURL(); |
| 1922 |
| 1923 // Check whether we have new encoding name. |
| 1924 UpdateEncoding(frame, frame->view()->GetMainFrameEncodingName()); |
| 1925 } |
| 1926 |
| 1927 void RenderView::didClearWindowObject(WebFrame* frame) { |
| 1928 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_)) |
| 1929 BindDOMAutomationController(frame); |
| 1930 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) { |
| 1931 dom_ui_bindings_.set_message_sender(this); |
| 1932 dom_ui_bindings_.set_routing_id(routing_id_); |
| 1933 dom_ui_bindings_.BindToJavascript(frame, L"chrome"); |
| 1934 } |
| 1935 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) { |
| 1936 external_host_bindings_.set_message_sender(this); |
| 1937 external_host_bindings_.set_routing_id(routing_id_); |
| 1938 external_host_bindings_.BindToJavascript(frame, L"externalHost"); |
| 1939 } |
| 1940 } |
| 1941 |
| 1942 void RenderView::didCreateDocumentElement(WebFrame* frame) { |
| 1943 if (RenderThread::current()) { // Will be NULL during unit tests. |
| 1944 RenderThread::current()->user_script_slave()->InjectScripts( |
| 1945 frame, UserScript::DOCUMENT_START); |
| 1946 } |
| 1947 |
| 1948 // Notify the browser about non-blank documents loading in the top frame. |
| 1949 GURL url = frame->url(); |
| 1950 if (url.is_valid() && url.spec() != "about:blank") { |
| 1951 if (frame == webview()->GetMainFrame()) |
| 1952 Send(new ViewHostMsg_DocumentAvailableInMainFrame(routing_id_)); |
| 1953 } |
| 1954 } |
| 1955 |
| 1956 void RenderView::didReceiveTitle(WebFrame* frame, const WebString& title) { |
| 1957 UpdateTitle(frame, title); |
| 1958 |
| 1959 // Also check whether we have new encoding name. |
| 1960 UpdateEncoding(frame, frame->view()->GetMainFrameEncodingName()); |
| 1961 } |
| 1962 |
| 1963 void RenderView::didFinishDocumentLoad(WebFrame* frame) { |
| 1964 WebDataSource* ds = frame->dataSource(); |
| 1965 NavigationState* navigation_state = NavigationState::FromDataSource(ds); |
| 1966 DCHECK(navigation_state); |
| 1967 navigation_state->set_finish_document_load_time(Time::Now()); |
| 1968 |
| 1969 Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_)); |
| 1970 |
| 1971 // The document has now been fully loaded. Scan for password forms to be |
| 1972 // sent up to the browser. |
| 1973 SendPasswordForms(frame); |
| 1974 |
| 1975 // Check whether we have new encoding name. |
| 1976 UpdateEncoding(frame, frame->view()->GetMainFrameEncodingName()); |
| 1977 |
| 1978 if (RenderThread::current()) { // Will be NULL during unit tests. |
| 1979 RenderThread::current()->user_script_slave()->InjectScripts( |
| 1980 frame, UserScript::DOCUMENT_END); |
| 1981 } |
| 1982 } |
| 1983 |
| 1984 void RenderView::didHandleOnloadEvents(WebFrame* frame) { |
| 1985 // Ignore |
| 1986 } |
| 1987 |
| 1988 void RenderView::didFailLoad(WebFrame* frame, const WebURLError& error) { |
| 1989 // Ignore |
| 1990 } |
| 1991 |
| 1992 void RenderView::didFinishLoad(WebFrame* frame) { |
| 1993 WebDataSource* ds = frame->dataSource(); |
| 1994 NavigationState* navigation_state = NavigationState::FromDataSource(ds); |
| 1995 DCHECK(navigation_state); |
| 1996 navigation_state->set_finish_load_time(Time::Now()); |
| 1997 } |
| 1998 |
| 1999 void RenderView::didChangeLocationWithinPage( |
| 2000 WebFrame* frame, bool is_new_navigation) { |
| 2001 // If this was a reference fragment navigation that we initiated, then we |
| 2002 // could end up having a non-null pending navigation state. We just need to |
| 2003 // update the ExtraData on the datasource so that others who read the |
| 2004 // ExtraData will get the new NavigationState. Similarly, if we did not |
| 2005 // initiate this navigation, then we need to take care to reset any pre- |
| 2006 // existing navigation state to a content-initiated navigation state. |
| 2007 // DidCreateDataSource conveniently takes care of this for us. |
| 2008 didCreateDataSource(frame, frame->dataSource()); |
| 2009 |
| 2010 didCommitProvisionalLoad(frame, is_new_navigation); |
| 2011 |
| 2012 UpdateTitle(frame, frame->view()->GetMainFrame()->dataSource()->pageTitle()); |
| 2013 } |
| 2014 |
| 2015 void RenderView::assignIdentifierToRequest( |
| 2016 WebFrame* frame, unsigned identifier, const WebURLRequest& request) { |
| 2017 // Ignore |
| 2018 } |
| 2019 |
| 2020 void RenderView::willSendRequest( |
| 2021 WebFrame* frame, unsigned identifier, WebURLRequest& request, |
| 2022 const WebURLResponse& redirect_response) { |
| 2023 request.setRequestorID(routing_id_); |
| 2024 } |
| 2025 |
| 2026 void RenderView::didReceiveResponse( |
| 2027 WebFrame* frame, unsigned identifier, const WebURLResponse& response) { |
| 2028 // Consider loading an alternate error page for 404 responses. |
| 2029 if (response.httpStatusCode() != 404) |
| 2030 return; |
| 2031 |
| 2032 // Only do this for responses that correspond to a provisional data source |
| 2033 // of the top-most frame. If we have a provisional data source, then we |
| 2034 // can't have any sub-resources yet, so we know that this response must |
| 2035 // correspond to a frame load. |
| 2036 if (!frame->provisionalDataSource() || frame->parent()) |
| 2037 return; |
| 2038 |
| 2039 // If we are in view source mode, then just let the user see the source of |
| 2040 // the server's 404 error page. |
| 2041 if (frame->isViewSourceModeEnabled()) |
| 2042 return; |
| 2043 |
| 2044 // Can we even load an alternate error page for this URL? |
| 2045 if (!GetAlternateErrorPageURL(response.url(), HTTP_404).is_valid()) |
| 2046 return; |
| 2047 |
| 2048 NavigationState* navigation_state = |
| 2049 NavigationState::FromDataSource(frame->provisionalDataSource()); |
| 2050 navigation_state->set_postpone_loading_data(true); |
| 2051 navigation_state->clear_postponed_data(); |
| 2052 } |
| 2053 |
| 2054 void RenderView::didFinishResourceLoad( |
| 2055 WebFrame* frame, unsigned identifier) { |
| 2056 NavigationState* navigation_state = |
| 2057 NavigationState::FromDataSource(frame->dataSource()); |
| 2058 if (!navigation_state->postpone_loading_data()) |
| 2059 return; |
| 2060 |
| 2061 // The server returned a 404 and the content was < 512 bytes (which we |
| 2062 // suppressed). Go ahead and fetch the alternate page content. |
| 2063 |
| 2064 const GURL& frame_url = frame->url(); |
| 2065 |
| 2066 const GURL& error_page_url = GetAlternateErrorPageURL(frame_url, HTTP_404); |
| 2067 DCHECK(error_page_url.is_valid()); |
| 2068 |
| 2069 WebURLError original_error; |
| 2070 original_error.unreachableURL = frame_url; |
| 2071 |
| 2072 navigation_state->set_alt_error_page_fetcher( |
| 2073 new AltErrorPageResourceFetcher( |
| 2074 error_page_url, frame, original_error, |
| 2075 NewCallback(this, &RenderView::AltErrorPageFinished))); |
| 2076 } |
| 2077 |
| 2078 void RenderView::didFailResourceLoad( |
| 2079 WebFrame* frame, unsigned identifier, const WebURLError& error) { |
| 2080 // Ignore |
| 2081 } |
| 2082 |
| 2083 void RenderView::didLoadResourceFromMemoryCache( |
| 2084 WebFrame* frame, const WebURLRequest& request, |
| 2085 const WebURLResponse& response) { |
| 2086 // Let the browser know we loaded a resource from the memory cache. This |
| 2087 // message is needed to display the correct SSL indicators. |
| 2088 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache( |
| 2089 routing_id_, |
| 2090 request.url(), |
| 2091 frame->securityOrigin().utf8(), |
| 2092 frame->top()->securityOrigin().utf8(), |
| 2093 response.securityInfo())); |
| 2094 } |
| 2095 |
| 2096 void RenderView::didExhaustMemoryAvailableForScript(WebFrame* frame) { |
| 2097 Send(new ViewHostMsg_JSOutOfMemory(routing_id_)); |
| 2098 } |
| 2099 |
| 2100 void RenderView::didChangeContentsSize(WebFrame* frame, const WebSize& size) { |
| 2101 // We don't always want to send the change messages over IPC, only if we've |
| 2102 // be put in that mode by getting a |ViewMsg_EnableIntrinsicWidthChangedMode| |
| 2103 // message. |
| 2104 // TODO(rafaelw): Figure out where the best place to set this for extensions |
| 2105 // is. It isn't clean to test for ExtensionView by examining the |
| 2106 // enabled_bindings. This needs to be generalized as it becomes clear what |
| 2107 // extension toolbars need. |
| 2108 if (BindingsPolicy::is_extension_enabled(enabled_bindings_) || |
| 2109 send_preferred_width_changes_) { |
| 2110 // WebCore likes to tell us things have changed even when they haven't, so |
| 2111 // cache the width and only send the IPC message when we're sure the |
| 2112 // width is different. |
| 2113 int width = webview()->GetMainFrame()->contentsPreferredWidth(); |
| 2114 if (width != preferred_width_) { |
| 2115 Send(new ViewHostMsg_DidContentsPreferredWidthChange(routing_id_, width)); |
| 2116 preferred_width_ = width; |
| 2117 } |
| 2118 } |
| 2119 } |
| 2120 |
2109 // webkit_glue::WebPluginPageDelegate ----------------------------------------- | 2121 // webkit_glue::WebPluginPageDelegate ----------------------------------------- |
2110 | 2122 |
2111 webkit_glue::WebPluginDelegate* RenderView::CreatePluginDelegate( | 2123 webkit_glue::WebPluginDelegate* RenderView::CreatePluginDelegate( |
2112 const GURL& url, | 2124 const GURL& url, |
2113 const std::string& mime_type, | 2125 const std::string& mime_type, |
2114 std::string* actual_mime_type) { | 2126 std::string* actual_mime_type) { |
2115 if (!PluginChannelHost::IsListening()) | 2127 if (!PluginChannelHost::IsListening()) |
2116 return NULL; | 2128 return NULL; |
2117 | 2129 |
2118 GURL policy_url; | 2130 GURL policy_url; |
(...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2956 // TODO(creis): We'd rather use webview()->Close() here, but that currently | 2968 // TODO(creis): We'd rather use webview()->Close() here, but that currently |
2957 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs | 2969 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs |
2958 // in the onunload handler from appearing. For now, we're bypassing that and | 2970 // in the onunload handler from appearing. For now, we're bypassing that and |
2959 // calling the FrameLoader's CloseURL method directly. This should be | 2971 // calling the FrameLoader's CloseURL method directly. This should be |
2960 // revisited to avoid having two ways to close a page. Having a single way | 2972 // revisited to avoid having two ways to close a page. Having a single way |
2961 // to close that can run onunload is also useful for fixing | 2973 // to close that can run onunload is also useful for fixing |
2962 // http://b/issue?id=753080. | 2974 // http://b/issue?id=753080. |
2963 WebFrame* main_frame = webview()->GetMainFrame(); | 2975 WebFrame* main_frame = webview()->GetMainFrame(); |
2964 if (main_frame) { | 2976 if (main_frame) { |
2965 const GURL& url = main_frame->url(); | 2977 const GURL& url = main_frame->url(); |
2966 // TODO(davemoore) this code should be removed once WillCloseFrame() gets | 2978 // TODO(davemoore) this code should be removed once willClose() gets |
2967 // called when a page is destroyed. DumpLoadHistograms() is safe to call | 2979 // called when a page is destroyed. DumpLoadHistograms() is safe to call |
2968 // multiple times for the same frame, but it will simplify things. | 2980 // multiple times for the same frame, but it will simplify things. |
2969 if (url.SchemeIs(chrome::kHttpScheme) || | 2981 if (url.SchemeIs(chrome::kHttpScheme) || |
2970 url.SchemeIs(chrome::kHttpsScheme)) | 2982 url.SchemeIs(chrome::kHttpsScheme)) |
2971 DumpLoadHistograms(); | 2983 DumpLoadHistograms(); |
2972 } | 2984 } |
2973 webview()->ClosePage(); | 2985 webview()->ClosePage(); |
2974 | 2986 |
2975 // Just echo back the params in the ACK. | 2987 // Just echo back the params in the ACK. |
2976 Send(new ViewHostMsg_ClosePage_ACK(routing_id_, params)); | 2988 Send(new ViewHostMsg_ClosePage_ACK(routing_id_, params)); |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3374 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, password_forms)); | 3386 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, password_forms)); |
3375 } | 3387 } |
3376 | 3388 |
3377 void RenderView::Print(WebFrame* frame, bool script_initiated) { | 3389 void RenderView::Print(WebFrame* frame, bool script_initiated) { |
3378 DCHECK(frame); | 3390 DCHECK(frame); |
3379 if (print_helper_.get() == NULL) { | 3391 if (print_helper_.get() == NULL) { |
3380 print_helper_.reset(new PrintWebViewHelper(this)); | 3392 print_helper_.reset(new PrintWebViewHelper(this)); |
3381 } | 3393 } |
3382 print_helper_->Print(frame, script_initiated); | 3394 print_helper_->Print(frame, script_initiated); |
3383 } | 3395 } |
OLD | NEW |