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

Side by Side Diff: chrome/browser/web_contents.cc

Issue 5005: Reorganize the declarations to have some grouping and logical ordering in tab... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/web_contents.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/web_contents.h" 5 #include "chrome/browser/web_contents.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/compiler_specific.h"
8 #include "base/file_version_info.h" 9 #include "base/file_version_info.h"
9 #include "chrome/app/locales/locale_settings.h" 10 #include "chrome/app/locales/locale_settings.h"
10 #include "chrome/browser/bookmarks/bookmark_model.h" 11 #include "chrome/browser/bookmarks/bookmark_model.h"
11 #include "chrome/browser/browser.h" 12 #include "chrome/browser/browser.h"
12 #include "chrome/browser/cache_manager_host.h" 13 #include "chrome/browser/cache_manager_host.h"
13 #include "chrome/browser/character_encoding.h" 14 #include "chrome/browser/character_encoding.h"
14 #include "chrome/browser/dom_operation_notification_details.h" 15 #include "chrome/browser/dom_operation_notification_details.h"
15 #include "chrome/browser/download/download_manager.h" 16 #include "chrome/browser/download/download_manager.h"
16 #include "chrome/browser/find_in_page_controller.h" 17 #include "chrome/browser/find_in_page_controller.h"
17 #include "chrome/browser/find_notification_details.h" 18 #include "chrome/browser/find_notification_details.h"
(...skipping 25 matching lines...) Expand all
43 #include "chrome/common/pref_names.h" 44 #include "chrome/common/pref_names.h"
44 #include "chrome/common/pref_service.h" 45 #include "chrome/common/pref_service.h"
45 #include "chrome/common/resource_bundle.h" 46 #include "chrome/common/resource_bundle.h"
46 #include "net/base/mime_util.h" 47 #include "net/base/mime_util.h"
47 #include "net/base/registry_controlled_domain.h" 48 #include "net/base/registry_controlled_domain.h"
48 #include "webkit/glue/webkit_glue.h" 49 #include "webkit/glue/webkit_glue.h"
49 #include "webkit/glue/plugins/webplugin_delegate_impl.h" 50 #include "webkit/glue/plugins/webplugin_delegate_impl.h"
50 51
51 #include "generated_resources.h" 52 #include "generated_resources.h"
52 53
54 // Cross-Site Navigations
55 //
56 // If a WebContents is told to navigate to a different web site (as determined
57 // by SiteInstance), it will replace its current RenderViewHost with a new
58 // RenderViewHost dedicated to the new SiteInstance. This works as follows:
59 //
60 // - Navigate determines whether the destination is cross-site, and if so,
61 // it creates a pending_render_view_host_ and moves into the PENDING
62 // RendererState.
63 // - The pending RVH is "suspended," so that no navigation messages are sent to
64 // its renderer until the onbeforeunload JavaScript handler has a chance to
65 // run in the current RVH.
66 // - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
67 // that it has a pending cross-site request. ResourceDispatcherHost will
68 // check for this when the response arrives.
69 // - The current RVH runs its onbeforeunload handler. If it returns false, we
70 // cancel all the pending logic and go back to NORMAL. Otherwise we allow
71 // the pending RVH to send the navigation request to its renderer.
72 // - ResourceDispatcherHost receives a ResourceRequest on the IO thread. It
73 // checks CrossSiteRequestManager to see that the RVH responsible has a
74 // pending cross-site request, and then installs a CrossSiteEventHandler.
75 // - When RDH receives a response, the BufferedEventHandler determines whether
76 // it is a download. If so, it sends a message to the new renderer causing
77 // it to cancel the request, and the download proceeds in the download
78 // thread. For now, we stay in a PENDING state (with a pending RVH) until
79 // the next DidNavigate event for this WebContents. This isn't ideal, but it
80 // doesn't affect any functionality.
81 // - After RDH receives a response and determines that it is safe and not a
82 // download, it pauses the response to first run the old page's onunload
83 // handler. It does this by asynchronously calling the OnCrossSiteResponse
84 // method of WebContents on the UI thread, which sends a ClosePage message
85 // to the current RVH.
86 // - Once the onunload handler is finished, a ClosePage_ACK message is sent to
87 // the ResourceDispatcherHost, who unpauses the response. Data is then sent
88 // to the pending RVH.
89 // - The pending renderer sends a FrameNavigate message that invokes the
90 // DidNavigate method. This replaces the current RVH with the
91 // pending RVH and goes back to the NORMAL RendererState.
92
53 namespace { 93 namespace {
54 94
55 // Amount of time we wait between when a key event is received and the renderer 95 // Amount of time we wait between when a key event is received and the renderer
56 // is queried for its state and pushed to the NavigationEntry. 96 // is queried for its state and pushed to the NavigationEntry.
57 const int kQueryStateDelay = 5000; 97 const int kQueryStateDelay = 5000;
58 98
59 const int kSyncWaitDelay = 40; 99 const int kSyncWaitDelay = 40;
60 100
61 // If another javascript message box is displayed within 101 // If another javascript message box is displayed within
62 // kJavascriptMessageExpectedDelay of a previous javascript message box being 102 // kJavascriptMessageExpectedDelay of a previous javascript message box being
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 const int kPrefsToObserveLength = arraysize(kPrefsToObserve); 137 const int kPrefsToObserveLength = arraysize(kPrefsToObserve);
98 138
99 void InitWebContentsClass() { 139 void InitWebContentsClass() {
100 static bool web_contents_class_initialized = false; 140 static bool web_contents_class_initialized = false;
101 if (!web_contents_class_initialized) { 141 if (!web_contents_class_initialized) {
102 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 142 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
103 web_contents_class_initialized = true; 143 web_contents_class_initialized = true;
104 } 144 }
105 } 145 }
106 146
147 // Returns true if the entry's transition type is FORM_SUBMIT.
148 bool IsFormSubmit(const NavigationEntry* entry) {
149 return (PageTransition::StripQualifier(entry->transition_type()) ==
150 PageTransition::FORM_SUBMIT);
151 }
152
107 } // namespace 153 } // namespace
108 154
109 ///////////////////////////////////////////////////////////////////////////////
110 // WebContents
111
112 class WebContents::GearsCreateShortcutCallbackFunctor { 155 class WebContents::GearsCreateShortcutCallbackFunctor {
113 public: 156 public:
114 explicit GearsCreateShortcutCallbackFunctor(WebContents* contents) 157 explicit GearsCreateShortcutCallbackFunctor(WebContents* contents)
115 : contents_(contents) {} 158 : contents_(contents) {}
116 159
117 void Run(const GearsShortcutData& shortcut_data, bool success) { 160 void Run(const GearsShortcutData& shortcut_data, bool success) {
118 if (contents_) 161 if (contents_)
119 contents_->OnGearsCreateShortcutDone(shortcut_data, success); 162 contents_->OnGearsCreateShortcutDone(shortcut_data, success);
120 delete this; 163 delete this;
121 } 164 }
122 void Cancel() { 165 void Cancel() {
123 contents_ = NULL; 166 contents_ = NULL;
124 } 167 }
125 168
126 private: 169 private:
127 WebContents* contents_; 170 WebContents* contents_;
128 }; 171 };
129 172
173 WebContents::WebContents(Profile* profile,
174 SiteInstance* site_instance,
175 RenderViewHostFactory* render_view_factory,
176 int routing_id,
177 HANDLE modal_dialog_event)
178 : TabContents(TAB_CONTENTS_WEB),
179 ALLOW_THIS_IN_INITIALIZER_LIST(
180 render_manager_(render_view_factory, this, this)),
181 render_view_factory_(render_view_factory),
182 has_page_title_(false),
183 info_bar_visible_(false),
184 is_starred_(false),
185 printing_(*this),
186 notify_disconnection_(false),
187 message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)),
188 ALLOW_THIS_IN_INITIALIZER_LIST(fav_icon_helper_(this)),
189 crashed_plugin_info_bar_(NULL),
190 suppress_javascript_messages_(false),
191 load_state_(net::LOAD_STATE_IDLE) {
192 InitWebContentsClass();
193
194 pending_install_.page_id = 0;
195 pending_install_.callback_functor = NULL;
196
197 render_manager_.Init(profile, site_instance, routing_id, modal_dialog_event);
198
199 // Register for notifications about all interested prefs change.
200 PrefService* prefs = profile->GetPrefs();
201 if (prefs)
202 for (int i = 0; i < kPrefsToObserveLength; ++i)
203 prefs->AddPrefObserver(kPrefsToObserve[i], this);
204
205 // Register for notifications about URL starredness changing on any profile.
206 NotificationService::current()->
207 AddObserver(this, NOTIFY_URLS_STARRED, NotificationService::AllSources());
208 NotificationService::current()->
209 AddObserver(this, NOTIFY_BOOKMARK_MODEL_LOADED,
210 NotificationService::AllSources());
211 }
212
213 WebContents::~WebContents() {
214 if (web_app_.get())
215 web_app_->RemoveObserver(this);
216 if (pending_install_.callback_functor)
217 pending_install_.callback_functor->Cancel();
218 }
219
130 // static 220 // static
131 void WebContents::RegisterUserPrefs(PrefService* prefs) { 221 void WebContents::RegisterUserPrefs(PrefService* prefs) {
132 prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true); 222 prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true);
133 223
134 WebPreferences pref_defaults; 224 WebPreferences pref_defaults;
135 prefs->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled, 225 prefs->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled,
136 pref_defaults.javascript_enabled); 226 pref_defaults.javascript_enabled);
137 prefs->RegisterBooleanPref( 227 prefs->RegisterBooleanPref(
138 prefs::kWebKitJavascriptCanOpenWindowsAutomatically, true); 228 prefs::kWebKitJavascriptCanOpenWindowsAutomatically, true);
139 prefs->RegisterBooleanPref(prefs::kWebKitLoadsImagesAutomatically, 229 prefs->RegisterBooleanPref(prefs::kWebKitLoadsImagesAutomatically,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumFontSize, 264 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumFontSize,
175 IDS_MINIMUM_FONT_SIZE); 265 IDS_MINIMUM_FONT_SIZE);
176 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumLogicalFontSize, 266 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumLogicalFontSize,
177 IDS_MINIMUM_LOGICAL_FONT_SIZE); 267 IDS_MINIMUM_LOGICAL_FONT_SIZE);
178 prefs->RegisterLocalizedBooleanPref(prefs::kWebKitUsesUniversalDetector, 268 prefs->RegisterLocalizedBooleanPref(prefs::kWebKitUsesUniversalDetector,
179 IDS_USES_UNIVERSAL_DETECTOR); 269 IDS_USES_UNIVERSAL_DETECTOR);
180 prefs->RegisterLocalizedStringPref(prefs::kStaticEncodings, 270 prefs->RegisterLocalizedStringPref(prefs::kStaticEncodings,
181 IDS_STATIC_ENCODING_LIST); 271 IDS_STATIC_ENCODING_LIST);
182 } 272 }
183 273
184 WebContents::WebContents(Profile* profile, 274 PasswordManager* WebContents::GetPasswordManager() {
185 SiteInstance* site_instance, 275 if (password_manager_.get() == NULL)
186 RenderViewHostFactory* render_view_factory, 276 password_manager_.reset(new PasswordManager(this));
187 int routing_id, 277 return password_manager_.get();
188 HANDLE modal_dialog_event)
189 : TabContents(TAB_CONTENTS_WEB),
190 #pragma warning(suppress: 4355) // Okay to pass "this" here.
191 render_manager_(render_view_factory, this, this),
192 render_view_factory_(render_view_factory),
193 has_page_title_(false),
194 info_bar_visible_(false),
195 is_starred_(false),
196 printing_(*this),
197 notify_disconnection_(false),
198 message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)),
199 capturing_contents_(false),
200 #pragma warning(suppress: 4355) // Okay to pass "this" here.
201 fav_icon_helper_(this),
202 crashed_plugin_info_bar_(NULL),
203 suppress_javascript_messages_(false),
204 load_state_(net::LOAD_STATE_IDLE) {
205 InitWebContentsClass();
206
207 pending_install_.page_id = 0;
208 pending_install_.callback_functor = NULL;
209
210 render_manager_.Init(profile, site_instance, routing_id, modal_dialog_event);
211
212 // Register for notifications about all interested prefs change.
213 PrefService* prefs = profile->GetPrefs();
214 if (prefs)
215 for (int i = 0; i < kPrefsToObserveLength; ++i)
216 prefs->AddPrefObserver(kPrefsToObserve[i], this);
217
218 // Register for notifications about URL starredness changing on any profile.
219 NotificationService::current()->
220 AddObserver(this, NOTIFY_URLS_STARRED, NotificationService::AllSources());
221 NotificationService::current()->
222 AddObserver(this, NOTIFY_BOOKMARK_MODEL_LOADED,
223 NotificationService::AllSources());
224 } 278 }
225 279
226 WebContents::~WebContents() { 280 PluginInstaller* WebContents::GetPluginInstaller() {
227 if (web_app_.get()) 281 if (plugin_installer_.get() == NULL)
228 web_app_->RemoveObserver(this); 282 plugin_installer_.reset(new PluginInstaller(this));
229 if (pending_install_.callback_functor) 283 return plugin_installer_.get();
230 pending_install_.callback_functor->Cancel();
231 }
232
233 void WebContents::CreateView(HWND parent_hwnd,
234 const gfx::Rect& initial_bounds) {
235 set_delete_on_destroy(false);
236 HWNDViewContainer::Init(parent_hwnd, initial_bounds, false);
237
238 // Remove the root view drop target so we can register our own.
239 RevokeDragDrop(GetHWND());
240 drop_target_ = new WebDropTarget(GetHWND(), this);
241 }
242
243 void WebContents::GetContainerBounds(gfx::Rect *out) const {
244 CRect r;
245 GetBounds(&r, false);
246 *out = r;
247 }
248
249 void WebContents::ShowContents() {
250 if (view())
251 view()->DidBecomeSelected();
252
253 // Loop through children and send DidBecomeSelected to them, too.
254 int count = static_cast<int>(child_windows_.size());
255 for (int i = count - 1; i >= 0; --i) {
256 ConstrainedWindow* window = child_windows_.at(i);
257 window->DidBecomeSelected();
258 }
259
260 // If we have a FindInPage dialog, notify it that its tab was selected.
261 if (find_in_page_controller_.get())
262 find_in_page_controller_->DidBecomeSelected();
263 }
264
265 void WebContents::HideContents() {
266 // TODO(pkasting): http://b/1239839 Right now we purposefully don't call
267 // our superclass HideContents(), because some callers want to be very picky
268 // about the order in which these get called. In addition to making the code
269 // here practically impossible to understand, this also means we end up
270 // calling TabContents::WasHidden() twice if callers call both versions of
271 // HideContents() on a WebContents.
272
273 WasHidden();
274 }
275
276 void WebContents::SizeContents(const gfx::Size& size) {
277 if (view())
278 view()->SetSize(size);
279 if (find_in_page_controller_.get())
280 find_in_page_controller_->RespondToResize(size);
281 RepositionSupressedPopupsToFit(size);
282 } 284 }
283 285
284 void WebContents::Destroy() { 286 void WebContents::Destroy() {
285 // Tell the notification service we no longer want notifications. 287 // Tell the notification service we no longer want notifications.
286 NotificationService::current()-> 288 NotificationService::current()->
287 RemoveObserver(this, NOTIFY_URLS_STARRED, 289 RemoveObserver(this, NOTIFY_URLS_STARRED,
288 NotificationService::AllSources()); 290 NotificationService::AllSources());
289 NotificationService::current()-> 291 NotificationService::current()->
290 RemoveObserver(this, NOTIFY_BOOKMARK_MODEL_LOADED, 292 RemoveObserver(this, NOTIFY_BOOKMARK_MODEL_LOADED,
291 NotificationService::AllSources()); 293 NotificationService::AllSources());
(...skipping 17 matching lines...) Expand all
309 // Detach plugin windows so that they are not destroyed automatically. 311 // Detach plugin windows so that they are not destroyed automatically.
310 // They will be cleaned up properly in plugin process. 312 // They will be cleaned up properly in plugin process.
311 DetachPluginWindows(); 313 DetachPluginWindows();
312 314
313 NotifyDisconnected(); 315 NotifyDisconnected();
314 HungRendererWarning::HideForWebContents(this); 316 HungRendererWarning::HideForWebContents(this);
315 render_manager_.Shutdown(); 317 render_manager_.Shutdown();
316 TabContents::Destroy(); 318 TabContents::Destroy();
317 } 319 }
318 320
319 /////////////////////////////////////////////////////////////////////////////// 321 SiteInstance* WebContents::GetSiteInstance() const {
320 // Event Handlers 322 return render_manager_.current_host()->site_instance();
321
322 void WebContents::OnDestroy() {
323 if (drop_target_.get()) {
324 RevokeDragDrop(GetHWND());
325 drop_target_ = NULL;
326 }
327 } 323 }
328 324
329 void WebContents::OnWindowPosChanged(WINDOWPOS* window_pos) { 325 SkBitmap WebContents::GetFavIcon() {
330 if (window_pos->flags & SWP_HIDEWINDOW) { 326 if (web_app_.get() && IsWebApplicationActive()) {
331 HideContents(); 327 SkBitmap app_icon = web_app_->GetFavIcon();
332 } else { 328 if (!app_icon.isNull())
333 // The WebContents was shown by a means other than the user selecting a 329 return app_icon;
334 // Tab, e.g. the window was minimized then restored.
335 if (window_pos->flags & SWP_SHOWWINDOW)
336 ShowContents();
337 // Unless we were specifically told not to size, cause the renderer to be
338 // sized to the new bounds, which forces a repaint. Not required for the
339 // simple minimize-restore case described above, for example, since the
340 // size hasn't changed.
341 if (!(window_pos->flags & SWP_NOSIZE)) {
342 gfx::Size size(window_pos->cx, window_pos->cy);
343 SizeContents(size);
344 }
345
346 // If we have a FindInPage dialog, notify it that the window changed.
347 if (find_in_page_controller_.get() && find_in_page_controller_->IsVisible())
348 find_in_page_controller_->MoveWindowIfNecessary(gfx::Rect());
349 } 330 }
331 return TabContents::GetFavIcon();
350 } 332 }
351 333
352 void WebContents::OnPaint(HDC junk_dc) { 334 std::wstring WebContents::GetStatusText() const {
353 if (render_view_host() && !render_view_host()->IsRenderViewLive()) { 335 if (!is_loading() || load_state_ == net::LOAD_STATE_IDLE)
354 if (!sad_tab_.get()) 336 return std::wstring();
355 sad_tab_.reset(new SadTabView); 337
356 CRect cr; 338 switch (load_state_) {
357 GetClientRect(&cr); 339 case net::LOAD_STATE_WAITING_FOR_CACHE:
358 sad_tab_->SetBounds(cr); 340 return l10n_util::GetString(IDS_LOAD_STATE_WAITING_FOR_CACHE);
359 ChromeCanvasPaint canvas(GetHWND(), true); 341 case net::LOAD_STATE_RESOLVING_PROXY_FOR_URL:
360 sad_tab_->ProcessPaint(&canvas); 342 return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_PROXY_FOR_URL);
361 return; 343 case net::LOAD_STATE_RESOLVING_HOST:
344 return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_HOST);
345 case net::LOAD_STATE_CONNECTING:
346 return l10n_util::GetString(IDS_LOAD_STATE_CONNECTING);
347 case net::LOAD_STATE_SENDING_REQUEST:
348 return l10n_util::GetString(IDS_LOAD_STATE_SENDING_REQUEST);
349 case net::LOAD_STATE_WAITING_FOR_RESPONSE:
350 return l10n_util::GetStringF(IDS_LOAD_STATE_WAITING_FOR_RESPONSE,
351 load_state_host_);
352 // Ignore net::LOAD_STATE_READING_RESPONSE and net::LOAD_STATE_IDLE
362 } 353 }
363 354
364 // We need to do this to validate the dirty area so we don't end up in a 355 return std::wstring();
365 // WM_PAINTstorm that causes other mysterious bugs (such as WM_TIMERs not
366 // firing etc). It doesn't matter that we don't have any non-clipped area.
367 CPaintDC dc(GetHWND());
368 SetMsgHandled(FALSE);
369 } 356 }
370 357
371 LRESULT WebContents::OnMouseRange(UINT msg, WPARAM w_param, LPARAM l_param) {
372 switch (msg) {
373 case WM_LBUTTONDOWN:
374 case WM_MBUTTONDOWN:
375 case WM_RBUTTONDOWN:
376 // Make sure this TabContents is activated when it is clicked on.
377 if (delegate())
378 delegate()->ActivateContents(this);
379 break;
380 case WM_MOUSEMOVE:
381 // Let our delegate know that the mouse moved (useful for resetting status
382 // bubble state).
383 if (delegate())
384 delegate()->ContentsMouseEvent(this, WM_MOUSEMOVE);
385 break;
386 default:
387 break;
388 }
389
390 return 0;
391 }
392
393 void WebContents::OnMouseLeave() {
394 // Let our delegate know that the mouse moved (useful for resetting status
395 // bubble state).
396 if (delegate())
397 delegate()->ContentsMouseEvent(this, WM_MOUSELEAVE);
398 SetMsgHandled(FALSE);
399 }
400
401 // A message is reflected here from view().
402 // Return non-zero to indicate that it is handled here.
403 // Return 0 to allow view() to further process it.
404 LRESULT WebContents::OnReflectedMessage(UINT msg, WPARAM w_param,
405 LPARAM l_param) {
406 MSG* message = reinterpret_cast<MSG*>(l_param);
407 switch (message->message) {
408 case WM_MOUSEWHEEL:
409 // This message is reflected from the view() to this window.
410 if (GET_KEYSTATE_WPARAM(message->wParam) & MK_CONTROL) {
411 WheelZoom(GET_WHEEL_DELTA_WPARAM(message->wParam));
412 return 1;
413 }
414 break;
415 case WM_HSCROLL:
416 case WM_VSCROLL:
417 if (ScrollZoom(LOWORD(message->wParam)))
418 return 1;
419 default:
420 break;
421 }
422
423 return 0;
424 }
425
426 void WebContents::OnSize(UINT param, const CSize& size) {
427 HWNDViewContainer::OnSize(param, size);
428
429 // Hack for thinkpad touchpad driver.
430 // Set fake scrollbars so that we can get scroll messages,
431 SCROLLINFO si = {0};
432 si.cbSize = sizeof(si);
433 si.fMask = SIF_ALL;
434
435 si.nMin = 1;
436 si.nMax = 100;
437 si.nPage = 10;
438 si.nTrackPos = 50;
439
440 ::SetScrollInfo(GetHWND(), SB_HORZ, &si, FALSE);
441 ::SetScrollInfo(GetHWND(), SB_VERT, &si, FALSE);
442 }
443
444 LRESULT WebContents::OnNCCalcSize(BOOL w_param, LPARAM l_param) {
445 // Hack for thinkpad mouse wheel driver. We have set the fake scroll bars
446 // to receive scroll messages from thinkpad touchpad driver. Suppress
447 // painting of scrollbars by returning 0 size for them.
448 return 0;
449 }
450
451 void WebContents::OnNCPaint(HRGN rgn) {
452 // Suppress default WM_NCPAINT handling. We don't need to do anything
453 // here since the view will draw everything correctly.
454 }
455
456 void WebContents::OnHScroll(int scroll_type, short position, HWND scrollbar) {
457 ScrollCommon(WM_HSCROLL, scroll_type, position, scrollbar);
458 }
459
460 void WebContents::OnVScroll(int scroll_type, short position, HWND scrollbar) {
461 ScrollCommon(WM_VSCROLL, scroll_type, position, scrollbar);
462 }
463
464 void WebContents::ScrollCommon(UINT message, int scroll_type, short position,
465 HWND scrollbar) {
466 // This window can receive scroll events as a result of the ThinkPad's
467 // Trackpad scroll wheel emulation.
468 if (!ScrollZoom(scroll_type)) {
469 // Reflect scroll message to the view() to give it a chance
470 // to process scrolling.
471 SendMessage(GetContentHWND(), message, MAKELONG(scroll_type, position),
472 (LPARAM) scrollbar);
473 }
474 }
475
476 bool WebContents::ScrollZoom(int scroll_type) {
477 // If ctrl is held, zoom the UI. There are three issues with this:
478 // 1) Should the event be eaten or forwarded to content? We eat the event,
479 // which is like Firefox and unlike IE.
480 // 2) Should wheel up zoom in or out? We zoom in (increase font size), which
481 // is like IE and Google maps, but unlike Firefox.
482 // 3) Should the mouse have to be over the content area? We zoom as long as
483 // content has focus, although FF and IE require that the mouse is over
484 // content. This is because all events get forwarded when content has
485 // focus.
486 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) {
487 int distance = 0;
488 switch (scroll_type) {
489 case SB_LINEUP:
490 distance = WHEEL_DELTA;
491 break;
492 case SB_LINEDOWN:
493 distance = -WHEEL_DELTA;
494 break;
495 // TODO(joshia): Handle SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION,
496 // and SB_THUMBTRACK for completeness
497 default:
498 break;
499 }
500
501 WheelZoom(distance);
502 return true;
503 }
504 return false;
505 }
506
507 void WebContents::WheelZoom(int distance) {
508 if (delegate()) {
509 bool zoom_in = distance > 0;
510 delegate()->ContentsZoomChange(zoom_in);
511 }
512 }
513
514 void WebContents::OnSetFocus(HWND window) {
515 // TODO(jcampan): figure out why removing this prevents tabs opened in the
516 // background from properly taking focus.
517 // We NULL-check the render_view_host_ here because Windows can send us
518 // messages during the destruction process after it has been destroyed.
519 if (view()) {
520 HWND inner_hwnd = view()->GetPluginHWND();
521 if (::IsWindow(inner_hwnd))
522 ::SetFocus(inner_hwnd);
523 }
524 }
525
526 void WebContents::OnSavePage() {
527 // If we can not save the page, try to download it.
528 if (!SavePackage::IsSavableContents(contents_mime_type())) {
529 DownloadManager* dlm = profile()->GetDownloadManager();
530 const GURL& current_page_url = GetURL();
531 if (dlm && current_page_url.is_valid())
532 dlm->DownloadUrl(current_page_url, GURL(), this);
533 return;
534 }
535
536 // Get our user preference state.
537 PrefService* prefs = profile()->GetPrefs();
538 DCHECK(prefs);
539
540 std::wstring suggest_name =
541 SavePackage::GetSuggestNameForSaveAs(prefs, GetTitle());
542
543 SavePackage::SavePackageParam param(contents_mime_type());
544 param.prefs = prefs;
545
546 // TODO(rocking): Use new asynchronous dialog boxes to prevent the SaveAs
547 // dialog blocking the UI thread. See bug: http://b/issue?id=1129694.
548 if (SavePackage::GetSaveInfo(suggest_name, GetContainerHWND(), &param))
549 SavePage(param.saved_main_file_path, param.dir, param.save_type);
550 }
551
552 void WebContents::SavePage(const std::wstring& main_file,
553 const std::wstring& dir_path,
554 SavePackage::SavePackageType save_type) {
555 // Stop the page from navigating.
556 Stop();
557
558 save_package_ = new SavePackage(this, save_type, main_file, dir_path);
559 save_package_->Init();
560 }
561
562 ///////////////////////////////////////////////////////////////////////////////
563
564 // Cross-Site Navigations
565 //
566 // If a WebContents is told to navigate to a different web site (as determined
567 // by SiteInstance), it will replace its current RenderViewHost with a new
568 // RenderViewHost dedicated to the new SiteInstance. This works as follows:
569 //
570 // - Navigate determines whether the destination is cross-site, and if so,
571 // it creates a pending_render_view_host_ and moves into the PENDING
572 // RendererState.
573 // - The pending RVH is "suspended," so that no navigation messages are sent to
574 // its renderer until the onbeforeunload JavaScript handler has a chance to
575 // run in the current RVH.
576 // - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
577 // that it has a pending cross-site request. ResourceDispatcherHost will
578 // check for this when the response arrives.
579 // - The current RVH runs its onbeforeunload handler. If it returns false, we
580 // cancel all the pending logic and go back to NORMAL. Otherwise we allow
581 // the pending RVH to send the navigation request to its renderer.
582 // - ResourceDispatcherHost receives a ResourceRequest on the IO thread. It
583 // checks CrossSiteRequestManager to see that the RVH responsible has a
584 // pending cross-site request, and then installs a CrossSiteEventHandler.
585 // - When RDH receives a response, the BufferedEventHandler determines whether
586 // it is a download. If so, it sends a message to the new renderer causing
587 // it to cancel the request, and the download proceeds in the download
588 // thread. For now, we stay in a PENDING state (with a pending RVH) until
589 // the next DidNavigate event for this WebContents. This isn't ideal, but it
590 // doesn't affect any functionality.
591 // - After RDH receives a response and determines that it is safe and not a
592 // download, it pauses the response to first run the old page's onunload
593 // handler. It does this by asynchronously calling the OnCrossSiteResponse
594 // method of WebContents on the UI thread, which sends a ClosePage message
595 // to the current RVH.
596 // - Once the onunload handler is finished, a ClosePage_ACK message is sent to
597 // the ResourceDispatcherHost, who unpauses the response. Data is then sent
598 // to the pending RVH.
599 // - The pending renderer sends a FrameNavigate message that invokes the
600 // DidNavigate method. This replaces the current RVH with the
601 // pending RVH and goes back to the NORMAL RendererState.
602
603 bool WebContents::NavigateToPendingEntry(bool reload) { 358 bool WebContents::NavigateToPendingEntry(bool reload) {
604 NavigationEntry* entry = controller()->GetPendingEntry(); 359 NavigationEntry* entry = controller()->GetPendingEntry();
605 RenderViewHost* dest_render_view_host = render_manager_.Navigate(*entry); 360 RenderViewHost* dest_render_view_host = render_manager_.Navigate(*entry);
606 if (!dest_render_view_host) 361 if (!dest_render_view_host)
607 return false; // Unable to create the desired render view host. 362 return false; // Unable to create the desired render view host.
608 363
609 // Used for page load time metrics. 364 // Used for page load time metrics.
610 current_load_start_ = TimeTicks::Now(); 365 current_load_start_ = TimeTicks::Now();
611 366
612 // Navigate in the desired RenderViewHost. 367 // Navigate in the desired RenderViewHost.
(...skipping 17 matching lines...) Expand all
630 } 385 }
631 386
632 return true; 387 return true;
633 } 388 }
634 389
635 void WebContents::Stop() { 390 void WebContents::Stop() {
636 render_manager_.Stop(); 391 render_manager_.Stop();
637 printing_.Stop(); 392 printing_.Stop();
638 } 393 }
639 394
395 void WebContents::StartFinding(int request_id,
396 const std::wstring& search_string,
397 bool forward,
398 bool match_case,
399 bool find_next) {
400 render_view_host()->StartFinding(request_id, search_string, forward,
401 match_case, find_next);
402 }
403
404 void WebContents::StopFinding(bool clear_selection) {
405 render_view_host()->StopFinding(clear_selection);
406 }
407
408 void WebContents::Cut() {
409 render_view_host()->Cut();
410 }
411
412 void WebContents::Copy() {
413 render_view_host()->Copy();
414 }
415
416 void WebContents::Paste() {
417 render_view_host()->Paste();
418 }
419
640 void WebContents::DidBecomeSelected() { 420 void WebContents::DidBecomeSelected() {
641 TabContents::DidBecomeSelected(); 421 TabContents::DidBecomeSelected();
642 422
643 if (view()) 423 if (view())
644 view()->DidBecomeSelected(); 424 view()->DidBecomeSelected();
645 425
646 CacheManagerHost::GetInstance()->ObserveActivity(process()->host_id()); 426 CacheManagerHost::GetInstance()->ObserveActivity(process()->host_id());
647 } 427 }
648 428
649 void WebContents::WasHidden() { 429 void WebContents::WasHidden() {
650 if (!capturing_contents_) { 430 if (!capturing_contents()) {
651 // |render_view_host()| can be NULL if the user middle clicks a link to open 431 // |render_view_host()| can be NULL if the user middle clicks a link to open
652 // a tab in then background, then closes the tab before selecting it. This 432 // a tab in then background, then closes the tab before selecting it. This
653 // is because closing the tab calls WebContents::Destroy(), which removes 433 // is because closing the tab calls WebContents::Destroy(), which removes
654 // the |render_view_host()|; then when we actually destroy the window, 434 // the |render_view_host()|; then when we actually destroy the window,
655 // OnWindowPosChanged() notices and calls HideContents() (which calls us). 435 // OnWindowPosChanged() notices and calls HideContents() (which calls us).
656 if (view()) 436 if (view())
657 view()->WasHidden(); 437 view()->WasHidden();
658 438
659 // Loop through children and send WasHidden to them, too. 439 // Loop through children and send WasHidden to them, too.
660 int count = static_cast<int>(child_windows_.size()); 440 int count = static_cast<int>(child_windows_.size());
661 for (int i = count - 1; i >= 0; --i) { 441 for (int i = count - 1; i >= 0; --i) {
662 ConstrainedWindow* window = child_windows_.at(i); 442 ConstrainedWindow* window = child_windows_.at(i);
663 window->WasHidden(); 443 window->WasHidden();
664 } 444 }
665 } 445 }
666 446
667 // If we have a FindInPage dialog, notify it that its tab was hidden. 447 // If we have a FindInPage dialog, notify it that its tab was hidden.
668 if (find_in_page_controller_.get()) 448 if (find_in_page_controller_.get())
669 find_in_page_controller_->DidBecomeUnselected(); 449 find_in_page_controller_->DidBecomeUnselected();
670 450
671 TabContents::WasHidden(); 451 TabContents::WasHidden();
672 } 452 }
673 453
674 void WebContents::StartFinding(int request_id, 454 void WebContents::ShowContents() {
675 const std::wstring& search_string, 455 if (view())
676 bool forward, 456 view()->DidBecomeSelected();
677 bool match_case, 457
678 bool find_next) { 458 // Loop through children and send DidBecomeSelected to them, too.
679 render_view_host()->StartFinding(request_id, search_string, forward, 459 int count = static_cast<int>(child_windows_.size());
680 match_case, find_next); 460 for (int i = count - 1; i >= 0; --i) {
461 ConstrainedWindow* window = child_windows_.at(i);
462 window->DidBecomeSelected();
463 }
464
465 // If we have a FindInPage dialog, notify it that its tab was selected.
466 if (find_in_page_controller_.get())
467 find_in_page_controller_->DidBecomeSelected();
681 } 468 }
682 469
683 void WebContents::StopFinding(bool clear_selection) { 470 void WebContents::HideContents() {
684 render_view_host()->StopFinding(clear_selection); 471 // TODO(pkasting): http://b/1239839 Right now we purposefully don't call
472 // our superclass HideContents(), because some callers want to be very picky
473 // about the order in which these get called. In addition to making the code
474 // here practically impossible to understand, this also means we end up
475 // calling TabContents::WasHidden() twice if callers call both versions of
476 // HideContents() on a WebContents.
477 WasHidden();
478 }
479
480 void WebContents::SizeContents(const gfx::Size& size) {
481 if (view())
482 view()->SetSize(size);
483 if (find_in_page_controller_.get())
484 find_in_page_controller_->RespondToResize(size);
485 RepositionSupressedPopupsToFit(size);
486 }
487
488 HWND WebContents::GetContentHWND() {
489 if (!view())
490 return NULL;
491 return view()->GetPluginHWND();
492 }
493
494 void WebContents::CreateView(HWND parent_hwnd,
495 const gfx::Rect& initial_bounds) {
496 set_delete_on_destroy(false);
497 HWNDViewContainer::Init(parent_hwnd, initial_bounds, false);
498
499 // Remove the root view drop target so we can register our own.
500 RevokeDragDrop(GetHWND());
501 drop_target_ = new WebDropTarget(GetHWND(), this);
502 }
503
504 void WebContents::GetContainerBounds(gfx::Rect *out) const {
505 CRect r;
506 GetBounds(&r, false);
507 *out = r;
508 }
509
510 InfoBarView* WebContents::GetInfoBarView() {
511 if (info_bar_view_.get() == NULL) {
512 info_bar_view_.reset(new InfoBarView(this));
513 // The WebContents owns the info-bar.
514 info_bar_view_->SetParentOwned(false);
515 }
516 return info_bar_view_.get();
517 }
518
519 void WebContents::SetDownloadShelfVisible(bool visible) {
520 TabContents::SetDownloadShelfVisible(visible);
521 if (visible) {
522 // Always set this value as it reflects the last time the download shelf
523 // was made visible (even if it was already visible).
524 last_download_shelf_show_ = TimeTicks::Now();
525 }
685 } 526 }
686 527
687 void WebContents::OpenFindInPageWindow(const Browser& browser) { 528 void WebContents::OpenFindInPageWindow(const Browser& browser) {
688 if (!find_in_page_controller_.get()) { 529 if (!find_in_page_controller_.get()) {
689 // Get the Chrome top-level (Frame) window. 530 // Get the Chrome top-level (Frame) window.
690 HWND hwnd = browser.GetTopLevelHWND(); 531 HWND hwnd = browser.GetTopLevelHWND();
691 find_in_page_controller_.reset(new FindInPageController(this, hwnd)); 532 find_in_page_controller_.reset(new FindInPageController(this, hwnd));
692 } else { 533 } else {
693 find_in_page_controller_->Show(); 534 find_in_page_controller_->Show();
694 } 535 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 if (IsFindWindowFullyVisible() && 570 if (IsFindWindowFullyVisible() &&
730 ::IsWindow(find_wnd) && 571 ::IsWindow(find_wnd) &&
731 ::GetWindowRect(find_wnd, &window_rect)) { 572 ::GetWindowRect(find_wnd, &window_rect)) {
732 *x = window_rect.TopLeft().x; 573 *x = window_rect.TopLeft().x;
733 *y = window_rect.TopLeft().y; 574 *y = window_rect.TopLeft().y;
734 return true; 575 return true;
735 } 576 }
736 577
737 return false; 578 return false;
738 } 579 }
739 void WebContents::OnJavaScriptMessageBoxClosed(IPC::Message* reply_msg,
740 bool success,
741 const std::wstring& prompt) {
742 last_javascript_message_dismissal_ = TimeTicks::Now();
743 render_manager_.OnJavaScriptMessageBoxClosed(reply_msg, success, prompt);
744 }
745
746 // Generic NotificationObserver callback.
747 void WebContents::Observe(NotificationType type,
748 const NotificationSource& source,
749 const NotificationDetails& details) {
750 TabContents::Observe(type, source, details);
751 switch (type) {
752 case NOTIFY_BOOKMARK_MODEL_LOADED: // BookmarkModel finished loading, fall
753 // through to update starred state.
754 case NOTIFY_URLS_STARRED: { // Somewhere, a URL has been starred.
755 // Ignore notifications for profiles other than our current one.
756 Profile* source_profile = Source<Profile>(source).ptr();
757 if (!source_profile->IsSameProfile(profile()))
758 return;
759
760 UpdateStarredStateForCurrentURL();
761 break;
762 }
763 case NOTIFY_PREF_CHANGED: {
764 std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
765 DCHECK(Source<PrefService>(source).ptr() == profile()->GetPrefs());
766 if (*pref_name_in == prefs::kAlternateErrorPagesEnabled) {
767 UpdateAlternateErrorPageURL();
768 } else if (*pref_name_in == prefs::kDefaultCharset ||
769 StartsWithASCII(WideToUTF8(*pref_name_in), "webkit.webprefs.", true)
770 ) {
771 UpdateWebPreferences();
772 } else {
773 NOTREACHED() << "unexpected pref change notification" << *pref_name_in;
774 }
775 break;
776 }
777 default: {
778 NOTREACHED();
779 break;
780 }
781 }
782 }
783
784 void WebContents::NotifySwapped() {
785 // After sending out a swap notification, we need to send a disconnect
786 // notification so that clients that pick up a pointer to |this| can NULL the
787 // pointer. See Bug 1230284.
788 notify_disconnection_ = true;
789 NotificationService::current()->
790 Notify(NOTIFY_WEB_CONTENTS_SWAPPED,
791 Source<WebContents>(this),
792 NotificationService::NoDetails());
793 }
794
795 void WebContents::NotifyConnected() {
796 notify_disconnection_ = true;
797 NotificationService::current()->
798 Notify(NOTIFY_WEB_CONTENTS_CONNECTED,
799 Source<WebContents>(this),
800 NotificationService::NoDetails());
801 }
802
803 void WebContents::NotifyDisconnected() {
804 if (!notify_disconnection_)
805 return;
806
807 notify_disconnection_ = false;
808 NotificationService::current()->
809 Notify(NOTIFY_WEB_CONTENTS_DISCONNECTED,
810 Source<WebContents>(this),
811 NotificationService::NoDetails());
812 }
813
814 void WebContents::UpdateHistoryForNavigation(const GURL& display_url,
815 const ViewHostMsg_FrameNavigate_Params& params) {
816 if (profile()->IsOffTheRecord())
817 return;
818
819 // Add to history service.
820 HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
821 if (hs) {
822 if (PageTransition::IsMainFrame(params.transition) &&
823 display_url != params.url) {
824 // Hack on the "display" URL so that it will appear in history. For some
825 // types of URLs, we will display a magic URL that is different from where
826 // the page is actually navigated. We want the user to see in history
827 // what they saw in the URL bar, so we add the display URL as a redirect.
828 // This only applies to the main frame, as the display URL doesn't apply
829 // to sub-frames.
830 std::vector<GURL> redirects = params.redirects;
831 if (!redirects.empty())
832 redirects.back() = display_url;
833 hs->AddPage(display_url, this, params.page_id, params.referrer,
834 params.transition, redirects);
835 } else {
836 hs->AddPage(params.url, this, params.page_id, params.referrer,
837 params.transition, params.redirects);
838 }
839 }
840 }
841
842 void WebContents::MaybeCloseChildWindows(
843 const ViewHostMsg_FrameNavigate_Params& params) {
844 if (net::RegistryControlledDomainService::SameDomainOrHost(
845 last_url_, params.url))
846 return;
847 last_url_ = params.url;
848
849 // Clear out any child windows since we are leaving this page entirely.
850 // We use indices instead of iterators in case CloseWindow does something
851 // that may invalidate an iterator.
852 int size = static_cast<int>(child_windows_.size());
853 for (int i = size - 1; i >= 0; --i) {
854 ConstrainedWindow* window = child_windows_[i];
855 if (window)
856 window->CloseConstrainedWindow();
857 }
858 }
859
860 void WebContents::SetDownloadShelfVisible(bool visible) {
861 TabContents::SetDownloadShelfVisible(visible);
862 if (visible) {
863 // Always set this value as it reflects the last time the download shelf
864 // was made visible (even if it was already visible).
865 last_download_shelf_show_ = TimeTicks::Now();
866 }
867 }
868
869 void WebContents::SetInfoBarVisible(bool visible) {
870 if (info_bar_visible_ != visible) {
871 info_bar_visible_ = visible;
872 if (info_bar_visible_) {
873 // Invoke GetInfoBarView to force the info bar to be created.
874 GetInfoBarView();
875 }
876 ToolbarSizeChanged(false);
877 }
878 }
879 580
880 void WebContents::SetFindInPageVisible(bool visible) { 581 void WebContents::SetFindInPageVisible(bool visible) {
881 if (find_in_page_controller_.get()) { 582 if (find_in_page_controller_.get()) {
882 if (visible) 583 if (visible)
883 find_in_page_controller_->Show(); 584 find_in_page_controller_->Show();
884 else 585 else
885 find_in_page_controller_->EndFindSession(); 586 find_in_page_controller_->EndFindSession();
886 } 587 }
887 } 588 }
888 589
889 InfoBarView* WebContents::GetInfoBarView() {
890 if (info_bar_view_.get() == NULL) {
891 info_bar_view_.reset(new InfoBarView(this));
892 // The WebContents owns the info-bar.
893 info_bar_view_->SetParentOwned(false);
894 }
895 return info_bar_view_.get();
896 }
897
898 void WebContents::SetWebApp(WebApp* web_app) { 590 void WebContents::SetWebApp(WebApp* web_app) {
899 if (web_app_.get()) { 591 if (web_app_.get()) {
900 web_app_->RemoveObserver(this); 592 web_app_->RemoveObserver(this);
901 web_app_->SetWebContents(NULL); 593 web_app_->SetWebContents(NULL);
902 } 594 }
903 595
904 web_app_ = web_app; 596 web_app_ = web_app;
905 if (web_app) { 597 if (web_app) {
906 web_app->AddObserver(this); 598 web_app->AddObserver(this);
907 web_app_->SetWebContents(this); 599 web_app_->SetWebContents(this);
(...skipping 21 matching lines...) Expand all
929 } 621 }
930 DCHECK(!pending_install_.icon.isNull()) << "Menu item should be disabled."; 622 DCHECK(!pending_install_.icon.isNull()) << "Menu item should be disabled.";
931 if (pending_install_.title.empty()) 623 if (pending_install_.title.empty())
932 pending_install_.title = UTF8ToWide(GetURL().spec()); 624 pending_install_.title = UTF8ToWide(GetURL().spec());
933 625
934 // Request the application info. When done OnDidGetApplicationInfo is invoked 626 // Request the application info. When done OnDidGetApplicationInfo is invoked
935 // and we'll create the shortcut. 627 // and we'll create the shortcut.
936 render_view_host()->GetApplicationInfo(pending_install_.page_id); 628 render_view_host()->GetApplicationInfo(pending_install_.page_id);
937 } 629 }
938 630
939 PasswordManager* WebContents::GetPasswordManager() { 631 void WebContents::OnJavaScriptMessageBoxClosed(IPC::Message* reply_msg,
940 if (password_manager_.get() == NULL) 632 bool success,
941 password_manager_.reset(new PasswordManager(this)); 633 const std::wstring& prompt) {
942 return password_manager_.get(); 634 last_javascript_message_dismissal_ = TimeTicks::Now();
635 render_manager_.OnJavaScriptMessageBoxClosed(reply_msg, success, prompt);
943 } 636 }
944 637
945 PluginInstaller* WebContents::GetPluginInstaller() { 638 void WebContents::SetInfoBarVisible(bool visible) {
946 if (plugin_installer_.get() == NULL) 639 if (info_bar_visible_ != visible) {
947 plugin_installer_.reset(new PluginInstaller(this)); 640 info_bar_visible_ = visible;
948 return plugin_installer_.get(); 641 if (info_bar_visible_) {
642 // Invoke GetInfoBarView to force the info bar to be created.
643 GetInfoBarView();
644 }
645 ToolbarSizeChanged(false);
646 }
647 }
648
649 void WebContents::OnSavePage() {
650 // If we can not save the page, try to download it.
651 if (!SavePackage::IsSavableContents(contents_mime_type())) {
652 DownloadManager* dlm = profile()->GetDownloadManager();
653 const GURL& current_page_url = GetURL();
654 if (dlm && current_page_url.is_valid())
655 dlm->DownloadUrl(current_page_url, GURL(), this);
656 return;
657 }
658
659 // Get our user preference state.
660 PrefService* prefs = profile()->GetPrefs();
661 DCHECK(prefs);
662
663 std::wstring suggest_name =
664 SavePackage::GetSuggestNameForSaveAs(prefs, GetTitle());
665
666 SavePackage::SavePackageParam param(contents_mime_type());
667 param.prefs = prefs;
668
669 // TODO(rocking): Use new asynchronous dialog boxes to prevent the SaveAs
670 // dialog blocking the UI thread. See bug: http://b/issue?id=1129694.
671 if (SavePackage::GetSaveInfo(suggest_name, GetContainerHWND(), &param))
672 SavePage(param.saved_main_file_path, param.dir, param.save_type);
673 }
674
675 void WebContents::SavePage(const std::wstring& main_file,
676 const std::wstring& dir_path,
677 SavePackage::SavePackageType save_type) {
678 // Stop the page from navigating.
679 Stop();
680
681 save_package_ = new SavePackage(this, save_type, main_file, dir_path);
682 save_package_->Init();
683 }
684
685 void WebContents::PrintPreview() {
686 // We can't print interstitial page for now.
687 if (render_manager_.showing_interstitial_page())
688 return;
689
690 // If we have a FindInPage dialog, notify it that its tab was hidden.
691 if (find_in_page_controller_.get())
692 find_in_page_controller_->DidBecomeUnselected();
693
694 // We don't show the print preview for the beta, only the print dialog.
695 printing_.ShowPrintDialog();
696 }
697
698 bool WebContents::PrintNow() {
699 // We can't print interstitial page for now.
700 if (render_manager_.showing_interstitial_page())
701 return false;
702
703 // If we have a FindInPage dialog, notify it that its tab was hidden.
704 if (find_in_page_controller_.get())
705 find_in_page_controller_->DidBecomeUnselected();
706
707 return printing_.PrintNow();
949 } 708 }
950 709
951 bool WebContents::IsActiveEntry(int32 page_id) { 710 bool WebContents::IsActiveEntry(int32 page_id) {
952 NavigationEntry* active_entry = controller()->GetActiveEntry(); 711 NavigationEntry* active_entry = controller()->GetActiveEntry();
953 return (active_entry != NULL && 712 return (active_entry != NULL &&
954 active_entry->site_instance() == GetSiteInstance() && 713 active_entry->site_instance() == GetSiteInstance() &&
955 active_entry->page_id() == page_id); 714 active_entry->page_id() == page_id);
956 } 715 }
957 716
958 /////////////////////////////////////////////////////////////////////////////// 717 void WebContents::SetInitialFocus(bool reverse) {
959 // RenderViewHostDelegate implementation: 718 render_view_host()->SetInitialFocus(reverse);
719 }
720
721 // Notifies the RenderWidgetHost instance about the fact that the page is
722 // loading, or done loading and calls the base implementation.
723 void WebContents::SetIsLoading(bool is_loading,
724 LoadNotificationDetails* details) {
725 if (!is_loading) {
726 load_state_ = net::LOAD_STATE_IDLE;
727 load_state_host_.clear();
728 }
729
730 TabContents::SetIsLoading(is_loading, details);
731 render_manager_.SetIsLoading(is_loading);
732 }
960 733
961 RenderViewHostDelegate::FindInPage* WebContents::GetFindInPageDelegate() const { 734 RenderViewHostDelegate::FindInPage* WebContents::GetFindInPageDelegate() const {
962 // The find in page controller implements this interface for us. Our return 735 // The find in page controller implements this interface for us. Our return
963 // value can be NULL, so it's fine if the find in controller doesn't exist. 736 // value can be NULL, so it's fine if the find in controller doesn't exist.
964 return find_in_page_controller_.get(); 737 return find_in_page_controller_.get();
965 } 738 }
966 739
967 RenderViewHostDelegate::Save* WebContents::GetSaveDelegate() const { 740 RenderViewHostDelegate::Save* WebContents::GetSaveDelegate() const {
968 return save_package_.get(); // May be NULL, but we can return NULL. 741 return save_package_.get(); // May be NULL, but we can return NULL.
969 } 742 }
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 888
1116 // In the case of interstitial, we don't mess with the navigation entries. 889 // In the case of interstitial, we don't mess with the navigation entries.
1117 // TODO(brettw) this seems like a bug. What happens if the page goes and 890 // TODO(brettw) this seems like a bug. What happens if the page goes and
1118 // does something on its own (or something that just got delayed), then 891 // does something on its own (or something that just got delayed), then
1119 // we won't have a navigation entry for that stuff when the interstitial 892 // we won't have a navigation entry for that stuff when the interstitial
1120 // is hidden. 893 // is hidden.
1121 if (render_manager_.showing_interstitial_page()) 894 if (render_manager_.showing_interstitial_page())
1122 return; 895 return;
1123 896
1124 // We can't do anything about navigations when we're inactive. 897 // We can't do anything about navigations when we're inactive.
1125 if (!controller() || !is_active_) 898 if (!controller() || !is_active())
1126 return; 899 return;
1127 900
1128 // Update the site of the SiteInstance if it doesn't have one yet, unless we 901 // Update the site of the SiteInstance if it doesn't have one yet, unless we
1129 // are showing an interstitial page. If we are, we should wait until the 902 // are showing an interstitial page. If we are, we should wait until the
1130 // real page commits. 903 // real page commits.
1131 // 904 //
1132 // TODO(brettw) the old code only checked for INTERSTIAL, this new code also 905 // TODO(brettw) the old code only checked for INTERSTIAL, this new code also
1133 // checks for LEAVING_INTERSTITIAL mode in the manager. Is this difference 906 // checks for LEAVING_INTERSTITIAL mode in the manager. Is this difference
1134 // important? 907 // important?
1135 if (!GetSiteInstance()->has_site() && 908 if (!GetSiteInstance()->has_site() &&
(...skipping 11 matching lines...) Expand all
1147 // for the appropriate notification (best) or you can add it to 920 // for the appropriate notification (best) or you can add it to
1148 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if 921 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if
1149 // necessary, please). 922 // necessary, please).
1150 923
1151 // Run post-commit tasks. 924 // Run post-commit tasks.
1152 if (details.is_main_frame) 925 if (details.is_main_frame)
1153 DidNavigateMainFramePostCommit(details, params); 926 DidNavigateMainFramePostCommit(details, params);
1154 DidNavigateAnyFramePostCommit(rvh, details, params); 927 DidNavigateAnyFramePostCommit(rvh, details, params);
1155 } 928 }
1156 929
1157 void WebContents::DidNavigateMainFramePostCommit(
1158 const NavigationController::LoadCommittedDetails& details,
1159 const ViewHostMsg_FrameNavigate_Params& params) {
1160 // Hide the download shelf if all the following conditions are true:
1161 // - there are no active downloads.
1162 // - this is a navigation to a different TLD.
1163 // - at least 5 seconds have elapsed since the download shelf was shown.
1164 // TODO(jcampan): bug 1156075 when user gestures are reliable, they should
1165 // be used to ensure we are hiding only on user initiated
1166 // navigations.
1167 DownloadManager* download_manager = profile()->GetDownloadManager();
1168 // download_manager can be NULL in unit test context.
1169 if (download_manager && download_manager->in_progress_count() == 0 &&
1170 !details.previous_url.is_empty() &&
1171 !net::RegistryControlledDomainService::SameDomainOrHost(
1172 details.previous_url, details.entry->url())) {
1173 TimeDelta time_delta(
1174 TimeTicks::Now() - last_download_shelf_show_);
1175 if (time_delta >
1176 TimeDelta::FromMilliseconds(kDownloadShelfHideDelay)) {
1177 SetDownloadShelfVisible(false);
1178 }
1179 }
1180
1181 if (details.is_user_initiated_main_frame_load()) {
1182 // Clear the status bubble. This is a workaround for a bug where WebKit
1183 // doesn't let us know that the cursor left an element during a
1184 // transition (this is also why the mouse cursor remains as a hand after
1185 // clicking on a link); see bugs 1184641 and 980803. We don't want to
1186 // clear the bubble when a user navigates to a named anchor in the same
1187 // page.
1188 UpdateTargetURL(details.entry->page_id(), GURL());
1189
1190 // UpdateHelpersForDidNavigate will handle the case where the password_form
1191 // origin is valid.
1192 // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
1193 // cleaned up and covered by tests.
1194 if (!params.password_form.origin.is_valid())
1195 GetPasswordManager()->DidNavigate();
1196 }
1197
1198 // The keyword generator uses the navigation entries, so must be called after
1199 // the commit.
1200 GenerateKeywordIfNecessary(params);
1201
1202 // We no longer know the title after this navigation.
1203 has_page_title_ = false;
1204
1205 // Update contents MIME type of the main webframe.
1206 contents_mime_type_ = params.contents_mime_type;
1207
1208 // Get the favicon, either from history or request it from the net.
1209 fav_icon_helper_.FetchFavIcon(details.entry->url());
1210
1211 // Close constrained popups if necessary.
1212 MaybeCloseChildWindows(params);
1213
1214 // We hide the FindInPage window when the user navigates away, except on
1215 // reload.
1216 if (PageTransition::StripQualifier(params.transition) !=
1217 PageTransition::RELOAD)
1218 SetFindInPageVisible(false);
1219
1220 // Update the starred state.
1221 UpdateStarredStateForCurrentURL();
1222 }
1223
1224 void WebContents::DidNavigateAnyFramePostCommit(
1225 RenderViewHost* render_view_host,
1226 const NavigationController::LoadCommittedDetails& details,
1227 const ViewHostMsg_FrameNavigate_Params& params) {
1228 // If we navigate, start showing messages again. This does nothing to prevent
1229 // a malicious script from spamming messages, since the script could just
1230 // reload the page to stop blocking.
1231 suppress_javascript_messages_ = false;
1232
1233 // Update history. Note that this needs to happen after the entry is complete,
1234 // which WillNavigate[Main,Sub]Frame will do before this function is called.
1235 if (params.should_update_history) {
1236 // Most of the time, the displayURL matches the loaded URL, but for about:
1237 // URLs, we use a data: URL as the real value. We actually want to save
1238 // the about: URL to the history db and keep the data: URL hidden. This is
1239 // what the TabContents' URL getter does.
1240 UpdateHistoryForNavigation(GetURL(), params);
1241 }
1242
1243 // Notify the password manager of the navigation or form submit.
1244 // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
1245 // cleaned up and covered by tests.
1246 if (params.password_form.origin.is_valid())
1247 GetPasswordManager()->ProvisionallySavePassword(params.password_form);
1248 }
1249
1250 bool WebContents::IsWebApplicationActive() const {
1251 if (!web_app_.get())
1252 return false;
1253
1254 // If we are inside an application, the application is always active. For
1255 // example, this allows us to display the GMail icon even when we are bounced
1256 // the login page.
1257 if (delegate() && delegate()->IsApplication())
1258 return true;
1259
1260 return (GetURL() == web_app_->url());
1261 }
1262
1263 void WebContents::WebAppImagesChanged(WebApp* web_app) {
1264 DCHECK(web_app == web_app_.get());
1265 if (delegate() && IsWebApplicationActive())
1266 delegate()->NavigationStateChanged(this, TabContents::INVALIDATE_FAVICON);
1267 }
1268
1269 void WebContents::UpdateStarredStateForCurrentURL() {
1270 BookmarkModel* model = profile()->GetBookmarkModel();
1271 const bool old_state = is_starred_;
1272 is_starred_ = (model && model->IsBookmarked(GetURL()));
1273
1274 if (is_starred_ != old_state && delegate())
1275 delegate()->URLStarredChanged(this, is_starred_);
1276 }
1277
1278 void WebContents::UpdateAlternateErrorPageURL() {
1279 GURL url = GetAlternateErrorPageURL();
1280 render_view_host()->SetAlternateErrorPageURL(url);
1281 }
1282
1283 void WebContents::UpdateWebPreferences() {
1284 render_view_host()->UpdateWebPreferences(GetWebkitPrefs());
1285 }
1286
1287 void WebContents::UpdateRenderViewSize() {
1288 // Using same technique as OnPaint, which sets size of SadTab.
1289 CRect cr;
1290 GetClientRect(&cr);
1291 gfx::Size new_size(cr.Width(), cr.Height());
1292 SizeContents(new_size);
1293 }
1294
1295 void WebContents::UpdateState(RenderViewHost* rvh, 930 void WebContents::UpdateState(RenderViewHost* rvh,
1296 int32 page_id, 931 int32 page_id,
1297 const GURL& url, 932 const GURL& url,
1298 const std::wstring& title, 933 const std::wstring& title,
1299 const std::string& state) { 934 const std::string& state) {
1300 if (rvh != render_view_host() || 935 if (rvh != render_view_host() ||
1301 render_manager_.showing_interstitial_page()) { 936 render_manager_.showing_interstitial_page()) {
1302 // This UpdateState is either: 937 // This UpdateState is either:
1303 // - targeted not at the current RenderViewHost. This could be that we are 938 // - targeted not at the current RenderViewHost. This could be that we are
1304 // showing the interstitial page and getting an update for the regular page, 939 // showing the interstitial page and getting an update for the regular page,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1368 controller()->NotifyEntryChanged(entry, entry_index); 1003 controller()->NotifyEntryChanged(entry, entry_index);
1369 } 1004 }
1370 1005
1371 void WebContents::UpdateTitle(RenderViewHost* rvh, 1006 void WebContents::UpdateTitle(RenderViewHost* rvh,
1372 int32 page_id, const std::wstring& title) { 1007 int32 page_id, const std::wstring& title) {
1373 if (!controller()) 1008 if (!controller())
1374 return; 1009 return;
1375 1010
1376 // If we have a title, that's a pretty good indication that we've started 1011 // If we have a title, that's a pretty good indication that we've started
1377 // getting useful data. 1012 // getting useful data.
1378 response_started_ = false; 1013 SetNotWaitingForResponse();
1379 1014
1380 NavigationEntry* entry; 1015 NavigationEntry* entry;
1381 if (render_manager_.showing_interstitial_page() && 1016 if (render_manager_.showing_interstitial_page() &&
1382 (rvh == render_view_host())) { 1017 (rvh == render_view_host())) {
1383 // We are showing an interstitial page in a different RenderViewHost, so 1018 // We are showing an interstitial page in a different RenderViewHost, so
1384 // the page_id is not sufficient to find the entry from the controller. 1019 // the page_id is not sufficient to find the entry from the controller.
1385 // (both RenderViewHost page_ids overlap). We know it is the last entry, 1020 // (both RenderViewHost page_ids overlap). We know it is the last entry,
1386 // so just use that. 1021 // so just use that.
1387 entry = controller()->GetLastCommittedEntry(); 1022 entry = controller()->GetLastCommittedEntry();
1388 } else { 1023 } else {
(...skipping 22 matching lines...) Expand all
1411 HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); 1046 HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
1412 if (hs && !has_page_title_ && !trimmed_title.empty()) { 1047 if (hs && !has_page_title_ && !trimmed_title.empty()) {
1413 hs->SetPageTitle(entry->display_url(), trimmed_title); 1048 hs->SetPageTitle(entry->display_url(), trimmed_title);
1414 has_page_title_ = true; 1049 has_page_title_ = true;
1415 } 1050 }
1416 } 1051 }
1417 1052
1418 1053
1419 void WebContents::UpdateEncoding(RenderViewHost* render_view_host, 1054 void WebContents::UpdateEncoding(RenderViewHost* render_view_host,
1420 const std::wstring& encoding_name) { 1055 const std::wstring& encoding_name) {
1421 SetEncoding(encoding_name); 1056 set_encoding(encoding_name);
1422 } 1057 }
1423 1058
1424 void WebContents::UpdateTargetURL(int32 page_id, const GURL& url) { 1059 void WebContents::UpdateTargetURL(int32 page_id, const GURL& url) {
1425 if (delegate()) 1060 if (delegate())
1426 delegate()->UpdateTargetURL(this, url); 1061 delegate()->UpdateTargetURL(this, url);
1427 } 1062 }
1428 1063
1429 void WebContents::UpdateThumbnail(const GURL& url, 1064 void WebContents::UpdateThumbnail(const GURL& url,
1430 const SkBitmap& bitmap, 1065 const SkBitmap& bitmap,
1431 const ThumbnailScore& score) { 1066 const ThumbnailScore& score) {
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
1762 ChromeViews::FocusManager* focus_manager = 1397 ChromeViews::FocusManager* focus_manager =
1763 ChromeViews::FocusManager::GetFocusManager(GetHWND()); 1398 ChromeViews::FocusManager::GetFocusManager(GetHWND());
1764 1399
1765 // We may not have a focus manager if the tab has been switched before this 1400 // We may not have a focus manager if the tab has been switched before this
1766 // message arrived. 1401 // message arrived.
1767 if (focus_manager) { 1402 if (focus_manager) {
1768 focus_manager->AdvanceFocus(reverse); 1403 focus_manager->AdvanceFocus(reverse);
1769 } 1404 }
1770 } 1405 }
1771 1406
1407 // Checks to see if we should generate a keyword based on the OSDD, and if
1408 // necessary uses TemplateURLFetcher to download the OSDD and create a keyword.
1409 void WebContents::PageHasOSDD(RenderViewHost* render_view_host,
1410 int32 page_id, const GURL& url,
1411 bool autodetected) {
1412 // Make sure page_id is the current page, and the TemplateURLModel is loaded.
1413 DCHECK(url.is_valid());
1414 if (!controller() || !IsActiveEntry(page_id))
1415 return;
1416 TemplateURLModel* url_model = profile()->GetTemplateURLModel();
1417 if (!url_model)
1418 return;
1419 if (!url_model->loaded()) {
1420 url_model->Load();
1421 return;
1422 }
1423 if (!profile()->GetTemplateURLFetcher())
1424 return;
1425
1426 if (profile()->IsOffTheRecord())
1427 return;
1428
1429 const NavigationEntry* entry = controller()->GetLastCommittedEntry();
1430 DCHECK(entry);
1431
1432 const NavigationEntry* base_entry = entry;
1433 if (IsFormSubmit(base_entry)) {
1434 // If the current page is a form submit, find the last page that was not
1435 // a form submit and use its url to generate the keyword from.
1436 int index = controller()->GetLastCommittedEntryIndex() - 1;
1437 while (index >= 0 && IsFormSubmit(controller()->GetEntryAtIndex(index)))
1438 index--;
1439 if (index >= 0)
1440 base_entry = controller()->GetEntryAtIndex(index);
1441 else
1442 base_entry = NULL;
1443 }
1444
1445 // We want to use the user typed URL if available since that represents what
1446 // the user typed to get here, and fall back on the regular URL if not.
1447 if (!base_entry)
1448 return;
1449 GURL keyword_url = base_entry->user_typed_url().is_valid() ?
1450 base_entry->user_typed_url() : base_entry->url();
1451 if (!keyword_url.is_valid())
1452 return;
1453 std::wstring keyword = TemplateURLModel::GenerateKeyword(keyword_url,
1454 autodetected);
1455 if (keyword.empty())
1456 return;
1457 const TemplateURL* template_url =
1458 url_model->GetTemplateURLForKeyword(keyword);
1459 if (template_url && (!template_url->safe_for_autoreplace() ||
1460 template_url->originating_url() == url)) {
1461 // Either there is a user created TemplateURL for this keyword, or the
1462 // keyword has the same OSDD url and we've parsed it.
1463 return;
1464 }
1465
1466 // Download the OpenSearch description document. If this is successful a
1467 // new keyword will be created when done.
1468 profile()->GetTemplateURLFetcher()->ScheduleDownload(
1469 keyword,
1470 url,
1471 base_entry->favicon().url(),
1472 GetAncestor(GetHWND(), GA_ROOT),
1473 autodetected);
1474 }
1475
1476 void WebContents::InspectElementReply(int num_resources) {
1477 // We have received reply from inspect element request. Notify the
1478 // automation provider in case we need to notify automation client.
1479 NotificationService::current()->
1480 Notify(NOTIFY_DOM_INSPECT_ELEMENT_RESPONSE, Source<WebContents>(this),
1481 Details<int>(&num_resources));
1482 }
1483
1484 void WebContents::DidGetPrintedPagesCount(int cookie, int number_pages) {
1485 printing_.DidGetPrintedPagesCount(cookie, number_pages);
1486 }
1487
1488 void WebContents::DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params) {
1489 printing_.DidPrintPage(params);
1490 }
1491
1492 // The renderer sends back to the browser the key events it did not process.
1493 void WebContents::HandleKeyboardEvent(const WebKeyboardEvent& event) {
1494 // The renderer returned a keyboard event it did not process. This may be
1495 // a keyboard shortcut that we have to process.
1496 if (event.type == WebInputEvent::KEY_DOWN) {
1497 ChromeViews::FocusManager* focus_manager =
1498 ChromeViews::FocusManager::GetFocusManager(GetHWND());
1499 // We may not have a focus_manager at this point (if the tab has been
1500 // switched by the time this message returned).
1501 if (focus_manager) {
1502 ChromeViews::Accelerator accelerator(event.key_code,
1503 (event.modifiers & WebInputEvent::SHIFT_KEY) ==
1504 WebInputEvent::SHIFT_KEY,
1505 (event.modifiers & WebInputEvent::CTRL_KEY) ==
1506 WebInputEvent::CTRL_KEY,
1507 (event.modifiers & WebInputEvent::ALT_KEY) ==
1508 WebInputEvent::ALT_KEY);
1509 if (focus_manager->ProcessAccelerator(accelerator, false))
1510 return;
1511 }
1512 }
1513
1514 // Any unhandled keyboard/character messages should be defproced.
1515 // This allows stuff like Alt+F4, etc to work correctly.
1516 DefWindowProc(event.actual_message.hwnd,
1517 event.actual_message.message,
1518 event.actual_message.wParam,
1519 event.actual_message.lParam);
1520 }
1521
1772 GURL WebContents::GetAlternateErrorPageURL() const { 1522 GURL WebContents::GetAlternateErrorPageURL() const {
1773 GURL url; 1523 GURL url;
1774 PrefService* prefs = profile()->GetPrefs(); 1524 PrefService* prefs = profile()->GetPrefs();
1775 DCHECK(prefs); 1525 DCHECK(prefs);
1776 if (prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled)) { 1526 if (prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled)) {
1777 url = google_util::AppendGoogleLocaleParam(GURL(kLinkDoctorBaseURL)); 1527 url = google_util::AppendGoogleLocaleParam(GURL(kLinkDoctorBaseURL));
1778 url = google_util::AppendGoogleTLDParam(url); 1528 url = google_util::AppendGoogleTLDParam(url);
1779 } 1529 }
1780 return url; 1530 return url;
1781 } 1531 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1892 1642
1893 InfoBarView* view = GetInfoBarView(); 1643 InfoBarView* view = GetInfoBarView();
1894 if (-1 == view->GetChildIndex(crashed_plugin_info_bar_)) { 1644 if (-1 == view->GetChildIndex(crashed_plugin_info_bar_)) {
1895 crashed_plugin_info_bar_ = new InfoBarMessageView(info_bar_message); 1645 crashed_plugin_info_bar_ = new InfoBarMessageView(info_bar_message);
1896 view->AddChildView(crashed_plugin_info_bar_); 1646 view->AddChildView(crashed_plugin_info_bar_);
1897 } else { 1647 } else {
1898 crashed_plugin_info_bar_->SetMessageText(info_bar_message); 1648 crashed_plugin_info_bar_->SetMessageText(info_bar_message);
1899 } 1649 }
1900 } 1650 }
1901 1651
1902 // Returns true if the entry's transition type is FORM_SUBMIT. 1652 bool WebContents::CanBlur() const {
1903 static bool IsFormSubmit(const NavigationEntry* entry) { 1653 return delegate() ? delegate()->CanBlur() : true;
1904 DCHECK(entry);
1905 return (PageTransition::StripQualifier(entry->transition_type()) ==
1906 PageTransition::FORM_SUBMIT);
1907 } 1654 }
1908 1655
1909 void WebContents::PageHasOSDD(RenderViewHost* render_view_host, 1656 void WebContents::RendererUnresponsive(RenderViewHost* rvh) {
1910 int32 page_id, const GURL& url, 1657 if (render_view_host() && render_view_host()->IsRenderViewLive())
1911 bool autodetected) { 1658 HungRendererWarning::ShowForWebContents(this);
1912 // Make sure page_id is the current page, and the TemplateURLModel is loaded. 1659 }
1913 DCHECK(url.is_valid());
1914 if (!controller() || !IsActiveEntry(page_id))
1915 return;
1916 TemplateURLModel* url_model = profile()->GetTemplateURLModel();
1917 if (!url_model)
1918 return;
1919 if (!url_model->loaded()) {
1920 url_model->Load();
1921 return;
1922 }
1923 if (!profile()->GetTemplateURLFetcher())
1924 return;
1925 1660
1926 if (profile()->IsOffTheRecord()) 1661 void WebContents::RendererResponsive(RenderViewHost* render_view_host) {
1927 return; 1662 HungRendererWarning::HideForWebContents(this);
1663 }
1928 1664
1929 const NavigationEntry* entry = controller()->GetLastCommittedEntry(); 1665 void WebContents::LoadStateChanged(const GURL& url,
1930 DCHECK(entry); 1666 net::LoadState load_state) {
1931 1667 load_state_ = load_state;
1932 const NavigationEntry* base_entry = entry; 1668 load_state_host_ = UTF8ToWide(url.host());
1933 if (IsFormSubmit(base_entry)) { 1669 if (load_state_ == net::LOAD_STATE_READING_RESPONSE)
1934 // If the current page is a form submit, find the last page that was not 1670 SetNotWaitingForResponse();
1935 // a form submit and use its url to generate the keyword from. 1671 if (is_loading())
1936 int index = controller()->GetLastCommittedEntryIndex() - 1; 1672 NotifyNavigationStateChanged(INVALIDATE_LOAD);
1937 while (index >= 0 && IsFormSubmit(controller()->GetEntryAtIndex(index)))
1938 index--;
1939 if (index >= 0)
1940 base_entry = controller()->GetEntryAtIndex(index);
1941 else
1942 base_entry = NULL;
1943 }
1944
1945 // We want to use the user typed URL if available since that represents what
1946 // the user typed to get here, and fall back on the regular URL if not.
1947 if (!base_entry)
1948 return;
1949 GURL keyword_url = base_entry->user_typed_url().is_valid() ?
1950 base_entry->user_typed_url() : base_entry->url();
1951 if (!keyword_url.is_valid())
1952 return;
1953 std::wstring keyword = TemplateURLModel::GenerateKeyword(keyword_url,
1954 autodetected);
1955 if (keyword.empty())
1956 return;
1957 const TemplateURL* template_url =
1958 url_model->GetTemplateURLForKeyword(keyword);
1959 if (template_url && (!template_url->safe_for_autoreplace() ||
1960 template_url->originating_url() == url)) {
1961 // Either there is a user created TemplateURL for this keyword, or the
1962 // keyword has the same OSDD url and we've parsed it.
1963 return;
1964 }
1965
1966 // Download the OpenSearch description document. If this is successful a
1967 // new keyword will be created when done.
1968 profile()->GetTemplateURLFetcher()->ScheduleDownload(
1969 keyword,
1970 url,
1971 base_entry->favicon().url(),
1972 GetAncestor(GetHWND(), GA_ROOT),
1973 autodetected);
1974 } 1673 }
1975 1674
1976 void WebContents::OnDidGetApplicationInfo( 1675 void WebContents::OnDidGetApplicationInfo(
1977 int32 page_id, 1676 int32 page_id,
1978 const webkit_glue::WebApplicationInfo& info) { 1677 const webkit_glue::WebApplicationInfo& info) {
1979 if (pending_install_.page_id != page_id) 1678 if (pending_install_.page_id != page_id)
1980 return; // The user clicked create on a separate page. Ignore this. 1679 return; // The user clicked create on a separate page. Ignore this.
1981 1680
1982 pending_install_.callback_functor = 1681 pending_install_.callback_functor =
1983 new GearsCreateShortcutCallbackFunctor(this); 1682 new GearsCreateShortcutCallbackFunctor(this);
1984 GearsCreateShortcut( 1683 GearsCreateShortcut(
1985 info, pending_install_.title, pending_install_.url, pending_install_.icon, 1684 info, pending_install_.title, pending_install_.url, pending_install_.icon,
1986 NewCallback(pending_install_.callback_functor, 1685 NewCallback(pending_install_.callback_functor,
1987 &GearsCreateShortcutCallbackFunctor::Run)); 1686 &GearsCreateShortcutCallbackFunctor::Run));
1988 } 1687 }
1989 1688
1689 void WebContents::FileSelected(const std::wstring& path, void* params) {
1690 render_view_host()->FileSelected(path);
1691 }
1692
1693 void WebContents::FileSelectionCanceled(void* params) {
1694 // If the user cancels choosing a file to upload we need to pass back the
1695 // empty string.
1696 render_view_host()->FileSelected(std::wstring());
1697 }
1698
1699 void WebContents::BeforeUnloadFiredFromRenderManager(
1700 bool proceed,
1701 bool* proceed_to_fire_unload) {
1702 delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
1703 }
1704
1705 void WebContents::UpdateRenderViewSizeForRenderManager() {
1706 // Using same technique as OnPaint, which sets size of SadTab.
1707 CRect cr;
1708 GetClientRect(&cr);
1709 gfx::Size new_size(cr.Width(), cr.Height());
1710 SizeContents(new_size);
1711 }
1712
1713 bool WebContents::CreateRenderViewForRenderManager(
1714 RenderViewHost* render_view_host) {
1715 RenderWidgetHostHWND* view = CreatePageView(render_view_host);
1716
1717 bool ok = render_view_host->CreateRenderView();
1718 if (ok) {
1719 CRect client_rect;
1720 ::GetClientRect(GetHWND(), &client_rect);
1721 view->SetSize(gfx::Size(client_rect.Width(), client_rect.Height()));
1722 UpdateMaxPageIDIfNecessary(render_view_host->site_instance(),
1723 render_view_host);
1724 }
1725 return ok;
1726 }
1727
1728 void WebContents::Observe(NotificationType type,
1729 const NotificationSource& source,
1730 const NotificationDetails& details) {
1731 switch (type) {
1732 case NOTIFY_BOOKMARK_MODEL_LOADED: // BookmarkModel finished loading, fall
1733 // through to update starred state.
1734 case NOTIFY_URLS_STARRED: { // Somewhere, a URL has been starred.
1735 // Ignore notifications for profiles other than our current one.
1736 Profile* source_profile = Source<Profile>(source).ptr();
1737 if (!source_profile->IsSameProfile(profile()))
1738 return;
1739
1740 UpdateStarredStateForCurrentURL();
1741 break;
1742 }
1743 case NOTIFY_PREF_CHANGED: {
1744 std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
1745 DCHECK(Source<PrefService>(source).ptr() == profile()->GetPrefs());
1746 if (*pref_name_in == prefs::kAlternateErrorPagesEnabled) {
1747 UpdateAlternateErrorPageURL();
1748 } else if (*pref_name_in == prefs::kDefaultCharset ||
1749 StartsWithASCII(WideToUTF8(*pref_name_in), "webkit.webprefs.", true)
1750 ) {
1751 UpdateWebPreferences();
1752 } else {
1753 NOTREACHED() << "unexpected pref change notification" << *pref_name_in;
1754 }
1755 break;
1756 }
1757 default: {
1758 NOTREACHED();
1759 break;
1760 }
1761 }
1762 }
1763
1764 void WebContents::OnDestroy() {
1765 if (drop_target_.get()) {
1766 RevokeDragDrop(GetHWND());
1767 drop_target_ = NULL;
1768 }
1769 }
1770
1771 void WebContents::OnHScroll(int scroll_type, short position, HWND scrollbar) {
1772 ScrollCommon(WM_HSCROLL, scroll_type, position, scrollbar);
1773 }
1774
1775 void WebContents::OnMouseLeave() {
1776 // Let our delegate know that the mouse moved (useful for resetting status
1777 // bubble state).
1778 if (delegate())
1779 delegate()->ContentsMouseEvent(this, WM_MOUSELEAVE);
1780 SetMsgHandled(FALSE);
1781 }
1782
1783 LRESULT WebContents::OnMouseRange(UINT msg, WPARAM w_param, LPARAM l_param) {
1784 switch (msg) {
1785 case WM_LBUTTONDOWN:
1786 case WM_MBUTTONDOWN:
1787 case WM_RBUTTONDOWN:
1788 // Make sure this TabContents is activated when it is clicked on.
1789 if (delegate())
1790 delegate()->ActivateContents(this);
1791 break;
1792 case WM_MOUSEMOVE:
1793 // Let our delegate know that the mouse moved (useful for resetting status
1794 // bubble state).
1795 if (delegate())
1796 delegate()->ContentsMouseEvent(this, WM_MOUSEMOVE);
1797 break;
1798 default:
1799 break;
1800 }
1801
1802 return 0;
1803 }
1804
1805 void WebContents::OnPaint(HDC junk_dc) {
1806 if (render_view_host() && !render_view_host()->IsRenderViewLive()) {
1807 if (!sad_tab_.get())
1808 sad_tab_.reset(new SadTabView);
1809 CRect cr;
1810 GetClientRect(&cr);
1811 sad_tab_->SetBounds(cr);
1812 ChromeCanvasPaint canvas(GetHWND(), true);
1813 sad_tab_->ProcessPaint(&canvas);
1814 return;
1815 }
1816
1817 // We need to do this to validate the dirty area so we don't end up in a
1818 // WM_PAINTstorm that causes other mysterious bugs (such as WM_TIMERs not
1819 // firing etc). It doesn't matter that we don't have any non-clipped area.
1820 CPaintDC dc(GetHWND());
1821 SetMsgHandled(FALSE);
1822 }
1823
1824 // A message is reflected here from view().
1825 // Return non-zero to indicate that it is handled here.
1826 // Return 0 to allow view() to further process it.
1827 LRESULT WebContents::OnReflectedMessage(UINT msg, WPARAM w_param,
1828 LPARAM l_param) {
1829 MSG* message = reinterpret_cast<MSG*>(l_param);
1830 switch (message->message) {
1831 case WM_MOUSEWHEEL:
1832 // This message is reflected from the view() to this window.
1833 if (GET_KEYSTATE_WPARAM(message->wParam) & MK_CONTROL) {
1834 WheelZoom(GET_WHEEL_DELTA_WPARAM(message->wParam));
1835 return 1;
1836 }
1837 break;
1838 case WM_HSCROLL:
1839 case WM_VSCROLL:
1840 if (ScrollZoom(LOWORD(message->wParam)))
1841 return 1;
1842 default:
1843 break;
1844 }
1845
1846 return 0;
1847 }
1848
1849 void WebContents::OnSetFocus(HWND window) {
1850 // TODO(jcampan): figure out why removing this prevents tabs opened in the
1851 // background from properly taking focus.
1852 // We NULL-check the render_view_host_ here because Windows can send us
1853 // messages during the destruction process after it has been destroyed.
1854 if (view()) {
1855 HWND inner_hwnd = view()->GetPluginHWND();
1856 if (::IsWindow(inner_hwnd))
1857 ::SetFocus(inner_hwnd);
1858 }
1859 }
1860
1861 void WebContents::OnVScroll(int scroll_type, short position, HWND scrollbar) {
1862 ScrollCommon(WM_VSCROLL, scroll_type, position, scrollbar);
1863 }
1864
1865 void WebContents::OnWindowPosChanged(WINDOWPOS* window_pos) {
1866 if (window_pos->flags & SWP_HIDEWINDOW) {
1867 HideContents();
1868 } else {
1869 // The WebContents was shown by a means other than the user selecting a
1870 // Tab, e.g. the window was minimized then restored.
1871 if (window_pos->flags & SWP_SHOWWINDOW)
1872 ShowContents();
1873 // Unless we were specifically told not to size, cause the renderer to be
1874 // sized to the new bounds, which forces a repaint. Not required for the
1875 // simple minimize-restore case described above, for example, since the
1876 // size hasn't changed.
1877 if (!(window_pos->flags & SWP_NOSIZE)) {
1878 gfx::Size size(window_pos->cx, window_pos->cy);
1879 SizeContents(size);
1880 }
1881
1882 // If we have a FindInPage dialog, notify it that the window changed.
1883 if (find_in_page_controller_.get() && find_in_page_controller_->IsVisible())
1884 find_in_page_controller_->MoveWindowIfNecessary(gfx::Rect());
1885 }
1886 }
1887
1888 void WebContents::OnSize(UINT param, const CSize& size) {
1889 HWNDViewContainer::OnSize(param, size);
1890
1891 // Hack for thinkpad touchpad driver.
1892 // Set fake scrollbars so that we can get scroll messages,
1893 SCROLLINFO si = {0};
1894 si.cbSize = sizeof(si);
1895 si.fMask = SIF_ALL;
1896
1897 si.nMin = 1;
1898 si.nMax = 100;
1899 si.nPage = 10;
1900 si.nTrackPos = 50;
1901
1902 ::SetScrollInfo(GetHWND(), SB_HORZ, &si, FALSE);
1903 ::SetScrollInfo(GetHWND(), SB_VERT, &si, FALSE);
1904 }
1905
1906 LRESULT WebContents::OnNCCalcSize(BOOL w_param, LPARAM l_param) {
1907 // Hack for thinkpad mouse wheel driver. We have set the fake scroll bars
1908 // to receive scroll messages from thinkpad touchpad driver. Suppress
1909 // painting of scrollbars by returning 0 size for them.
1910 return 0;
1911 }
1912
1913 void WebContents::OnNCPaint(HRGN rgn) {
1914 // Suppress default WM_NCPAINT handling. We don't need to do anything
1915 // here since the view will draw everything correctly.
1916 }
1917
1918 void WebContents::ScrollCommon(UINT message, int scroll_type, short position,
1919 HWND scrollbar) {
1920 // This window can receive scroll events as a result of the ThinkPad's
1921 // Trackpad scroll wheel emulation.
1922 if (!ScrollZoom(scroll_type)) {
1923 // Reflect scroll message to the view() to give it a chance
1924 // to process scrolling.
1925 SendMessage(GetContentHWND(), message, MAKELONG(scroll_type, position),
1926 (LPARAM) scrollbar);
1927 }
1928 }
1929
1930 bool WebContents::ScrollZoom(int scroll_type) {
1931 // If ctrl is held, zoom the UI. There are three issues with this:
1932 // 1) Should the event be eaten or forwarded to content? We eat the event,
1933 // which is like Firefox and unlike IE.
1934 // 2) Should wheel up zoom in or out? We zoom in (increase font size), which
1935 // is like IE and Google maps, but unlike Firefox.
1936 // 3) Should the mouse have to be over the content area? We zoom as long as
1937 // content has focus, although FF and IE require that the mouse is over
1938 // content. This is because all events get forwarded when content has
1939 // focus.
1940 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) {
1941 int distance = 0;
1942 switch (scroll_type) {
1943 case SB_LINEUP:
1944 distance = WHEEL_DELTA;
1945 break;
1946 case SB_LINEDOWN:
1947 distance = -WHEEL_DELTA;
1948 break;
1949 // TODO(joshia): Handle SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION,
1950 // and SB_THUMBTRACK for completeness
1951 default:
1952 break;
1953 }
1954
1955 WheelZoom(distance);
1956 return true;
1957 }
1958 return false;
1959 }
1960
1961 void WebContents::WheelZoom(int distance) {
1962 if (delegate()) {
1963 bool zoom_in = distance > 0;
1964 delegate()->ContentsZoomChange(zoom_in);
1965 }
1966 }
1967
1968 void WebContents::DidNavigateMainFramePostCommit(
1969 const NavigationController::LoadCommittedDetails& details,
1970 const ViewHostMsg_FrameNavigate_Params& params) {
1971 // Hide the download shelf if all the following conditions are true:
1972 // - there are no active downloads.
1973 // - this is a navigation to a different TLD.
1974 // - at least 5 seconds have elapsed since the download shelf was shown.
1975 // TODO(jcampan): bug 1156075 when user gestures are reliable, they should
1976 // be used to ensure we are hiding only on user initiated
1977 // navigations.
1978 DownloadManager* download_manager = profile()->GetDownloadManager();
1979 // download_manager can be NULL in unit test context.
1980 if (download_manager && download_manager->in_progress_count() == 0 &&
1981 !details.previous_url.is_empty() &&
1982 !net::RegistryControlledDomainService::SameDomainOrHost(
1983 details.previous_url, details.entry->url())) {
1984 TimeDelta time_delta(
1985 TimeTicks::Now() - last_download_shelf_show_);
1986 if (time_delta >
1987 TimeDelta::FromMilliseconds(kDownloadShelfHideDelay)) {
1988 SetDownloadShelfVisible(false);
1989 }
1990 }
1991
1992 if (details.is_user_initiated_main_frame_load()) {
1993 // Clear the status bubble. This is a workaround for a bug where WebKit
1994 // doesn't let us know that the cursor left an element during a
1995 // transition (this is also why the mouse cursor remains as a hand after
1996 // clicking on a link); see bugs 1184641 and 980803. We don't want to
1997 // clear the bubble when a user navigates to a named anchor in the same
1998 // page.
1999 UpdateTargetURL(details.entry->page_id(), GURL());
2000
2001 // UpdateHelpersForDidNavigate will handle the case where the password_form
2002 // origin is valid.
2003 // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
2004 // cleaned up and covered by tests.
2005 if (!params.password_form.origin.is_valid())
2006 GetPasswordManager()->DidNavigate();
2007 }
2008
2009 // The keyword generator uses the navigation entries, so must be called after
2010 // the commit.
2011 GenerateKeywordIfNecessary(params);
2012
2013 // We no longer know the title after this navigation.
2014 has_page_title_ = false;
2015
2016 // Update contents MIME type of the main webframe.
2017 contents_mime_type_ = params.contents_mime_type;
2018
2019 // Get the favicon, either from history or request it from the net.
2020 fav_icon_helper_.FetchFavIcon(details.entry->url());
2021
2022 // Close constrained popups if necessary.
2023 MaybeCloseChildWindows(params);
2024
2025 // We hide the FindInPage window when the user navigates away, except on
2026 // reload.
2027 if (PageTransition::StripQualifier(params.transition) !=
2028 PageTransition::RELOAD)
2029 SetFindInPageVisible(false);
2030
2031 // Update the starred state.
2032 UpdateStarredStateForCurrentURL();
2033 }
2034
2035 void WebContents::DidNavigateAnyFramePostCommit(
2036 RenderViewHost* render_view_host,
2037 const NavigationController::LoadCommittedDetails& details,
2038 const ViewHostMsg_FrameNavigate_Params& params) {
2039 // If we navigate, start showing messages again. This does nothing to prevent
2040 // a malicious script from spamming messages, since the script could just
2041 // reload the page to stop blocking.
2042 suppress_javascript_messages_ = false;
2043
2044 // Update history. Note that this needs to happen after the entry is complete,
2045 // which WillNavigate[Main,Sub]Frame will do before this function is called.
2046 if (params.should_update_history) {
2047 // Most of the time, the displayURL matches the loaded URL, but for about:
2048 // URLs, we use a data: URL as the real value. We actually want to save
2049 // the about: URL to the history db and keep the data: URL hidden. This is
2050 // what the TabContents' URL getter does.
2051 UpdateHistoryForNavigation(GetURL(), params);
2052 }
2053
2054 // Notify the password manager of the navigation or form submit.
2055 // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
2056 // cleaned up and covered by tests.
2057 if (params.password_form.origin.is_valid())
2058 GetPasswordManager()->ProvisionallySavePassword(params.password_form);
2059 }
2060
2061 void WebContents::MaybeCloseChildWindows(
2062 const ViewHostMsg_FrameNavigate_Params& params) {
2063 if (net::RegistryControlledDomainService::SameDomainOrHost(
2064 last_url_, params.url))
2065 return;
2066 last_url_ = params.url;
2067
2068 // Clear out any child windows since we are leaving this page entirely.
2069 // We use indices instead of iterators in case CloseWindow does something
2070 // that may invalidate an iterator.
2071 int size = static_cast<int>(child_windows_.size());
2072 for (int i = size - 1; i >= 0; --i) {
2073 ConstrainedWindow* window = child_windows_[i];
2074 if (window)
2075 window->CloseConstrainedWindow();
2076 }
2077 }
2078
2079 void WebContents::UpdateStarredStateForCurrentURL() {
2080 BookmarkModel* model = profile()->GetBookmarkModel();
2081 const bool old_state = is_starred_;
2082 is_starred_ = (model && model->IsBookmarked(GetURL()));
2083
2084 if (is_starred_ != old_state && delegate())
2085 delegate()->URLStarredChanged(this, is_starred_);
2086 }
2087
2088 void WebContents::UpdateAlternateErrorPageURL() {
2089 GURL url = GetAlternateErrorPageURL();
2090 render_view_host()->SetAlternateErrorPageURL(url);
2091 }
2092
2093 void WebContents::UpdateWebPreferences() {
2094 render_view_host()->UpdateWebPreferences(GetWebkitPrefs());
2095 }
2096
2097 bool WebContents::IsWebApplicationActive() const {
2098 if (!web_app_.get())
2099 return false;
2100
2101 // If we are inside an application, the application is always active. For
2102 // example, this allows us to display the GMail icon even when we are bounced
2103 // the login page.
2104 if (delegate() && delegate()->IsApplication())
2105 return true;
2106
2107 return (GetURL() == web_app_->url());
2108 }
2109
2110 void WebContents::WebAppImagesChanged(WebApp* web_app) {
2111 DCHECK(web_app == web_app_.get());
2112 if (delegate() && IsWebApplicationActive())
2113 delegate()->NavigationStateChanged(this, TabContents::INVALIDATE_FAVICON);
2114 }
2115
1990 void WebContents::OnGearsCreateShortcutDone( 2116 void WebContents::OnGearsCreateShortcutDone(
1991 const GearsShortcutData& shortcut_data, bool success) { 2117 const GearsShortcutData& shortcut_data, bool success) {
1992 NavigationEntry* current_entry = controller()->GetLastCommittedEntry(); 2118 NavigationEntry* current_entry = controller()->GetLastCommittedEntry();
1993 bool same_page = 2119 bool same_page =
1994 current_entry && pending_install_.page_id == current_entry->page_id(); 2120 current_entry && pending_install_.page_id == current_entry->page_id();
1995 2121
1996 if (success && same_page) { 2122 if (success && same_page) {
1997 // Only switch to app mode if the user chose to create a shortcut and 2123 // Only switch to app mode if the user chose to create a shortcut and
1998 // we're still on the same page that it corresponded to. 2124 // we're still on the same page that it corresponded to.
1999 SetWebApp(new WebApp(profile(), shortcut_data)); 2125 SetWebApp(new WebApp(profile(), shortcut_data));
(...skipping 24 matching lines...) Expand all
2024 // Also tell the renderer to update its internal representation. We 2150 // Also tell the renderer to update its internal representation. We
2025 // need to reserve enough IDs to make all restored page IDs less than 2151 // need to reserve enough IDs to make all restored page IDs less than
2026 // the max. 2152 // the max.
2027 if (curr_max_page_id < 0) 2153 if (curr_max_page_id < 0)
2028 curr_max_page_id = 0; 2154 curr_max_page_id = 0;
2029 rvh->ReservePageIDRange(max_restored_page_id - curr_max_page_id); 2155 rvh->ReservePageIDRange(max_restored_page_id - curr_max_page_id);
2030 } 2156 }
2031 } 2157 }
2032 } 2158 }
2033 2159
2034 void WebContents::BeforeUnloadFiredFromRenderManager( 2160 void WebContents::UpdateHistoryForNavigation(const GURL& display_url,
2035 bool proceed, 2161 const ViewHostMsg_FrameNavigate_Params& params) {
2036 bool* proceed_to_fire_unload) { 2162 if (profile()->IsOffTheRecord())
2037 delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); 2163 return;
2164
2165 // Add to history service.
2166 HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
2167 if (hs) {
2168 if (PageTransition::IsMainFrame(params.transition) &&
2169 display_url != params.url) {
2170 // Hack on the "display" URL so that it will appear in history. For some
2171 // types of URLs, we will display a magic URL that is different from where
2172 // the page is actually navigated. We want the user to see in history
2173 // what they saw in the URL bar, so we add the display URL as a redirect.
2174 // This only applies to the main frame, as the display URL doesn't apply
2175 // to sub-frames.
2176 std::vector<GURL> redirects = params.redirects;
2177 if (!redirects.empty())
2178 redirects.back() = display_url;
2179 hs->AddPage(display_url, this, params.page_id, params.referrer,
2180 params.transition, redirects);
2181 } else {
2182 hs->AddPage(params.url, this, params.page_id, params.referrer,
2183 params.transition, params.redirects);
2184 }
2185 }
2038 } 2186 }
2039 2187
2040 2188 RenderWidgetHostHWND* WebContents::CreatePageView(
2041 HWND WebContents::GetContentHWND() { 2189 RenderViewHost* render_view_host) {
2042 if (!view()) 2190 // Create the View as well. Its lifetime matches the child process'.
2043 return NULL; 2191 DCHECK(!render_view_host->view());
2044 return view()->GetPluginHWND(); 2192 RenderWidgetHostHWND* view = new RenderWidgetHostHWND(render_view_host);
2193 render_view_host->set_view(view);
2194 view->Create(GetHWND());
2195 view->ShowWindow(SW_SHOW);
2196 return view;
2045 } 2197 }
2046 2198
2047 bool WebContents::CanDisplayFile(const std::wstring& full_path) { 2199 void WebContents::DetachPluginWindows() {
2048 bool allow_wildcard = false; 2200 EnumChildWindows(GetHWND(), WebContents::EnumPluginWindowsCallback, NULL);
2049 std::string mime_type;
2050 net::GetMimeTypeFromFile(full_path, &mime_type);
2051 if (net::IsSupportedMimeType(mime_type) ||
2052 (PluginService::GetInstance() &&
2053 PluginService::GetInstance()->HavePluginFor(mime_type, allow_wildcard)))
2054 return true;
2055 return false;
2056 } 2201 }
2057 2202
2058 void WebContents::PrintPreview() { 2203 BOOL WebContents::EnumPluginWindowsCallback(HWND window, LPARAM) {
2059 // We can't print interstitial page for now. 2204 if (WebPluginDelegateImpl::IsPluginDelegateWindow(window)) {
2060 if (render_manager_.showing_interstitial_page()) 2205 ::ShowWindow(window, SW_HIDE);
2206 SetParent(window, NULL);
2207 }
2208
2209 return TRUE;
2210 }
2211
2212 void WebContents::NotifySwapped() {
2213 // After sending out a swap notification, we need to send a disconnect
2214 // notification so that clients that pick up a pointer to |this| can NULL the
2215 // pointer. See Bug 1230284.
2216 notify_disconnection_ = true;
2217 NotificationService::current()->
2218 Notify(NOTIFY_WEB_CONTENTS_SWAPPED,
2219 Source<WebContents>(this),
2220 NotificationService::NoDetails());
2221 }
2222
2223 void WebContents::NotifyConnected() {
2224 notify_disconnection_ = true;
2225 NotificationService::current()->
2226 Notify(NOTIFY_WEB_CONTENTS_CONNECTED,
2227 Source<WebContents>(this),
2228 NotificationService::NoDetails());
2229 }
2230
2231 void WebContents::NotifyDisconnected() {
2232 if (!notify_disconnection_)
2061 return; 2233 return;
2062 2234
2063 // If we have a FindInPage dialog, notify it that its tab was hidden. 2235 notify_disconnection_ = false;
2064 if (find_in_page_controller_.get()) 2236 NotificationService::current()->
2065 find_in_page_controller_->DidBecomeUnselected(); 2237 Notify(NOTIFY_WEB_CONTENTS_DISCONNECTED,
2066 2238 Source<WebContents>(this),
2067 // We don't show the print preview for the beta, only the print dialog. 2239 NotificationService::NoDetails());
2068 printing_.ShowPrintDialog();
2069 }
2070
2071 bool WebContents::PrintNow() {
2072 // We can't print interstitial page for now.
2073 if (render_manager_.showing_interstitial_page())
2074 return false;
2075
2076 // If we have a FindInPage dialog, notify it that its tab was hidden.
2077 if (find_in_page_controller_.get())
2078 find_in_page_controller_->DidBecomeUnselected();
2079
2080 return printing_.PrintNow();
2081 }
2082
2083 void WebContents::WillCaptureContents() {
2084 capturing_contents_ = true;
2085 }
2086
2087 void WebContents::DidCaptureContents() {
2088 capturing_contents_ = false;
2089 }
2090
2091 void WebContents::Cut() {
2092 render_view_host()->Cut();
2093 }
2094
2095 void WebContents::Copy() {
2096 render_view_host()->Copy();
2097 }
2098
2099 void WebContents::Paste() {
2100 render_view_host()->Paste();
2101 }
2102
2103 void WebContents::SetInitialFocus(bool reverse) {
2104 render_view_host()->SetInitialFocus(reverse);
2105 } 2240 }
2106 2241
2107 void WebContents::GenerateKeywordIfNecessary( 2242 void WebContents::GenerateKeywordIfNecessary(
2108 const ViewHostMsg_FrameNavigate_Params& params) { 2243 const ViewHostMsg_FrameNavigate_Params& params) {
2109 DCHECK(controller()); 2244 DCHECK(controller());
2110 if (!params.searchable_form_url.is_valid()) 2245 if (!params.searchable_form_url.is_valid())
2111 return; 2246 return;
2112 2247
2113 if (profile()->IsOffTheRecord()) 2248 if (profile()->IsOffTheRecord())
2114 return; 2249 return;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2171 // The favicon url isn't valid. This means there really isn't a favicon, 2306 // The favicon url isn't valid. This means there really isn't a favicon,
2172 // or the favicon url wasn't obtained before the load started. This assumes 2307 // or the favicon url wasn't obtained before the load started. This assumes
2173 // the later. 2308 // the later.
2174 // TODO(sky): Need a way to set the favicon that doesn't involve generating 2309 // TODO(sky): Need a way to set the favicon that doesn't involve generating
2175 // its url. 2310 // its url.
2176 new_url->SetFavIconURL(TemplateURL::GenerateFaviconURL(params.referrer)); 2311 new_url->SetFavIconURL(TemplateURL::GenerateFaviconURL(params.referrer));
2177 } 2312 }
2178 new_url->set_safe_for_autoreplace(true); 2313 new_url->set_safe_for_autoreplace(true);
2179 url_model->Add(new_url); 2314 url_model->Add(new_url);
2180 } 2315 }
2181
2182 void WebContents::InspectElementReply(int num_resources) {
2183 // We have received reply from inspect element request. Notify the
2184 // automation provider in case we need to notify automation client.
2185 NotificationService::current()->
2186 Notify(NOTIFY_DOM_INSPECT_ELEMENT_RESPONSE, Source<WebContents>(this),
2187 Details<int>(&num_resources));
2188 }
2189
2190 // The renderer sends back to the browser the key events it did not process.
2191 void WebContents::HandleKeyboardEvent(const WebKeyboardEvent& event) {
2192 // The renderer returned a keyboard event it did not process. This may be
2193 // a keyboard shortcut that we have to process.
2194 if (event.type == WebInputEvent::KEY_DOWN) {
2195 ChromeViews::FocusManager* focus_manager =
2196 ChromeViews::FocusManager::GetFocusManager(GetHWND());
2197 // We may not have a focus_manager at this point (if the tab has been
2198 // switched by the time this message returned).
2199 if (focus_manager) {
2200 ChromeViews::Accelerator accelerator(event.key_code,
2201 (event.modifiers & WebInputEvent::SHIFT_KEY) ==
2202 WebInputEvent::SHIFT_KEY,
2203 (event.modifiers & WebInputEvent::CTRL_KEY) ==
2204 WebInputEvent::CTRL_KEY,
2205 (event.modifiers & WebInputEvent::ALT_KEY) ==
2206 WebInputEvent::ALT_KEY);
2207 if (focus_manager->ProcessAccelerator(accelerator, false))
2208 return;
2209 }
2210 }
2211
2212 // Any unhandled keyboard/character messages should be defproced.
2213 // This allows stuff like Alt+F4, etc to work correctly.
2214 DefWindowProc(event.actual_message.hwnd,
2215 event.actual_message.message,
2216 event.actual_message.wParam,
2217 event.actual_message.lParam);
2218 }
2219
2220 bool WebContents::CreateRenderViewForRenderManager(
2221 RenderViewHost* render_view_host) {
2222 RenderWidgetHostHWND* view = CreatePageView(render_view_host);
2223
2224 bool ok = render_view_host->CreateRenderView();
2225 if (ok) {
2226 CRect client_rect;
2227 ::GetClientRect(GetHWND(), &client_rect);
2228 view->SetSize(gfx::Size(client_rect.Width(), client_rect.Height()));
2229 UpdateMaxPageIDIfNecessary(render_view_host->site_instance(),
2230 render_view_host);
2231 }
2232 return ok;
2233 }
2234
2235 RenderWidgetHostHWND* WebContents::CreatePageView(
2236 RenderViewHost* render_view_host) {
2237 // Create the View as well. Its lifetime matches the child process'.
2238 DCHECK(!render_view_host->view());
2239 RenderWidgetHostHWND* view = new RenderWidgetHostHWND(render_view_host);
2240 render_view_host->set_view(view);
2241 view->Create(GetHWND());
2242 view->ShowWindow(SW_SHOW);
2243 return view;
2244 }
2245
2246 void WebContents::DidGetPrintedPagesCount(int cookie, int number_pages) {
2247 printing_.DidGetPrintedPagesCount(cookie, number_pages);
2248 }
2249
2250 void WebContents::DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params) {
2251 printing_.DidPrintPage(params);
2252 }
2253
2254 void WebContents::SetIsLoading(bool is_loading,
2255 LoadNotificationDetails* details) {
2256 if (!is_loading) {
2257 load_state_ = net::LOAD_STATE_IDLE;
2258 load_state_host_.clear();
2259 }
2260
2261 TabContents::SetIsLoading(is_loading, details);
2262 render_manager_.SetIsLoading(is_loading);
2263 }
2264
2265 void WebContents::FileSelected(const std::wstring& path, void* params) {
2266 render_view_host()->FileSelected(path);
2267 }
2268
2269 void WebContents::FileSelectionCanceled(void* params) {
2270 // If the user cancels choosing a file to upload we need to pass back the
2271 // empty string.
2272 render_view_host()->FileSelected(std::wstring());
2273 }
2274
2275 ///////////////////////////////////////////////////////////////////////////////
2276
2277 SkBitmap WebContents::GetFavIcon() {
2278 if (web_app_.get() && IsWebApplicationActive()) {
2279 SkBitmap app_icon = web_app_->GetFavIcon();
2280 if (!app_icon.isNull())
2281 return app_icon;
2282 }
2283 return TabContents::GetFavIcon();
2284 }
2285
2286 std::wstring WebContents::GetStatusText() const {
2287 if (!is_loading() || load_state_ == net::LOAD_STATE_IDLE)
2288 return std::wstring();
2289
2290 switch (load_state_) {
2291 case net::LOAD_STATE_WAITING_FOR_CACHE:
2292 return l10n_util::GetString(IDS_LOAD_STATE_WAITING_FOR_CACHE);
2293 case net::LOAD_STATE_RESOLVING_PROXY_FOR_URL:
2294 return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_PROXY_FOR_URL);
2295 case net::LOAD_STATE_RESOLVING_HOST:
2296 return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_HOST);
2297 case net::LOAD_STATE_CONNECTING:
2298 return l10n_util::GetString(IDS_LOAD_STATE_CONNECTING);
2299 case net::LOAD_STATE_SENDING_REQUEST:
2300 return l10n_util::GetString(IDS_LOAD_STATE_SENDING_REQUEST);
2301 case net::LOAD_STATE_WAITING_FOR_RESPONSE:
2302 return l10n_util::GetStringF(IDS_LOAD_STATE_WAITING_FOR_RESPONSE,
2303 load_state_host_);
2304 // Ignore net::LOAD_STATE_READING_RESPONSE and net::LOAD_STATE_IDLE
2305 }
2306
2307 return std::wstring();
2308 }
2309
2310 bool WebContents::CanBlur() const {
2311 return delegate() ? delegate()->CanBlur() : true;
2312 }
2313
2314 void WebContents::RendererUnresponsive(RenderViewHost* rvh) {
2315 if (render_view_host() && render_view_host()->IsRenderViewLive())
2316 HungRendererWarning::ShowForWebContents(this);
2317 }
2318
2319 void WebContents::RendererResponsive(RenderViewHost* render_view_host) {
2320 HungRendererWarning::HideForWebContents(this);
2321 }
2322
2323 void WebContents::LoadStateChanged(const GURL& url,
2324 net::LoadState load_state) {
2325 load_state_ = load_state;
2326 load_state_host_ = UTF8ToWide(url.host());
2327 if (load_state_ == net::LOAD_STATE_READING_RESPONSE)
2328 response_started_ = false;
2329 if (is_loading())
2330 NotifyNavigationStateChanged(INVALIDATE_LOAD);
2331 }
2332
2333 void WebContents::DetachPluginWindows() {
2334 EnumChildWindows(GetHWND(), WebContents::EnumPluginWindowsCallback, NULL);
2335 }
2336
2337 BOOL WebContents::EnumPluginWindowsCallback(HWND window, LPARAM) {
2338 if (WebPluginDelegateImpl::IsPluginDelegateWindow(window)) {
2339 ::ShowWindow(window, SW_HIDE);
2340 SetParent(window, NULL);
2341 }
2342
2343 return TRUE;
2344 }
OLDNEW
« no previous file with comments | « chrome/browser/web_contents.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698