blob: faabb5437edb52d3889e8db0cbabe278958eabc8 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// 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
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/browser/tab_contents.h"
6
7#include "chrome/browser/cert_store.h"
8#include "chrome/browser/navigation_entry.h"
[email protected]616ed5a2008-11-21 22:27:249#include "chrome/browser/infobar_delegate.h"
initial.commit09911bf2008-07-26 23:55:2910#include "chrome/browser/views/download_shelf_view.h"
11#include "chrome/browser/views/download_started_animation.h"
[email protected]d6598c052008-11-05 19:03:2512#include "chrome/browser/views/blocked_popup_container.h"
initial.commit09911bf2008-07-26 23:55:2913#include "chrome/browser/web_contents.h"
14#include "chrome/browser/tab_contents_delegate.h"
[email protected]a4feef82008-10-02 15:11:2215#include "chrome/common/l10n_util.h"
initial.commit09911bf2008-07-26 23:55:2916#include "chrome/common/pref_names.h"
[email protected]1eb89e82008-08-15 12:27:0317#include "chrome/common/pref_service.h"
initial.commit09911bf2008-07-26 23:55:2918#include "chrome/views/native_scroll_bar.h"
[email protected]1eb89e82008-08-15 12:27:0319#include "chrome/views/root_view.h"
initial.commit09911bf2008-07-26 23:55:2920#include "chrome/views/view.h"
21#include "chrome/views/view_storage.h"
[email protected]a0dde122008-11-21 20:51:2022#include "chrome/views/widget.h"
initial.commit09911bf2008-07-26 23:55:2923
24#include "generated_resources.h"
25
[email protected]d5f942ba2008-09-26 19:30:3426namespace {
27
28BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) {
[email protected]4d0bd102008-10-16 00:26:3029 // Note: erase is required to properly paint some widgets borders. This can
30 // be seen with textfields.
[email protected]d5f942ba2008-09-26 19:30:3431 InvalidateRect(hwnd, NULL, TRUE);
32 return TRUE;
33}
34
35} // namespace
36
initial.commit09911bf2008-07-26 23:55:2937TabContents::TabContents(TabContentsType type)
[email protected]d5f942ba2008-09-26 19:30:3438 : type_(type),
initial.commit09911bf2008-07-26 23:55:2939 delegate_(NULL),
40 controller_(NULL),
[email protected]d5f942ba2008-09-26 19:30:3441 is_loading_(false),
42 is_active_(true),
initial.commit09911bf2008-07-26 23:55:2943 is_crashed_(false),
[email protected]d5f942ba2008-09-26 19:30:3444 waiting_for_response_(false),
45 saved_location_bar_state_(NULL),
46 shelf_visible_(false),
47 max_page_id_(-1),
[email protected]d6598c052008-11-05 19:03:2548 blocked_popups_(NULL),
[email protected]2d843e62008-11-26 21:16:3549 capturing_contents_(false),
50 is_being_destroyed_(false) {
initial.commit09911bf2008-07-26 23:55:2951 last_focused_view_storage_id_ =
[email protected]c2dacc92008-10-16 23:51:3852 views::ViewStorage::GetSharedInstance()->CreateStorageID();
initial.commit09911bf2008-07-26 23:55:2953}
54
55TabContents::~TabContents() {
56 // Makes sure to remove any stored view we may still have in the ViewStorage.
57 //
58 // It is possible the view went away before us, so we only do this if the
59 // view is registered.
[email protected]c2dacc92008-10-16 23:51:3860 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
initial.commit09911bf2008-07-26 23:55:2961 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
62 view_storage->RemoveView(last_focused_view_storage_id_);
63}
64
[email protected]d5f942ba2008-09-26 19:30:3465// static
66void TabContents::RegisterUserPrefs(PrefService* prefs) {
67 prefs->RegisterBooleanPref(prefs::kBlockPopups, false);
initial.commit09911bf2008-07-26 23:55:2968}
69
initial.commit09911bf2008-07-26 23:55:2970
71void TabContents::CloseContents() {
72 // Destroy our NavigationController, which will Destroy all tabs it owns.
73 controller_->Destroy();
74 // Note that the controller may have deleted us at this point,
75 // so don't touch any member variables here.
76}
77
78void TabContents::Destroy() {
[email protected]2d843e62008-11-26 21:16:3579 // TODO(jcampan): reenable that DCHECK. It seems to cause the RendererCrash
80 // ui tests to hang for some unclear reason.
81 // DCHECK(!is_being_destroyed_);
82 is_being_destroyed_ = true;
83
initial.commit09911bf2008-07-26 23:55:2984 // First cleanly close all child windows.
85 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
86 // some of these to close. CloseWindows is async, so it might get called
87 // twice before it runs.
88 int size = static_cast<int>(child_windows_.size());
89 for (int i = size - 1; i >= 0; --i) {
90 ConstrainedWindow* window = child_windows_[i];
91 if (window)
92 window->CloseConstrainedWindow();
93 }
94
95 // Notify any observer that have a reference on this tab contents.
96 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_DESTROYED,
97 Source<TabContents>(this),
98 NotificationService::NoDetails());
99
100 // If we still have a window handle, destroy it. GetContainerHWND can return
101 // NULL if this contents was part of a window that closed.
102 if (GetContainerHWND())
103 ::DestroyWindow(GetContainerHWND());
104
105 // Notify our NavigationController. Make sure we are deleted first, so
106 // that the controller is the last to die.
107 NavigationController* controller = controller_;
108 TabContentsType type = this->type();
109
110 delete this;
111
112 controller->TabContentsWasDestroyed(type);
113}
114
[email protected]d5f942ba2008-09-26 19:30:34115void TabContents::SetupController(Profile* profile) {
116 DCHECK(!controller_);
117 controller_ = new NavigationController(this, profile);
118}
119
120bool TabContents::SupportsURL(GURL* url) {
121 GURL u(*url);
122 if (TabContents::TypeForURL(&u) == type()) {
123 *url = u;
124 return true;
125 }
126 return false;
127}
128
129const GURL& TabContents::GetURL() const {
130 // We may not have a navigation entry yet
131 NavigationEntry* entry = controller_->GetActiveEntry();
132 return entry ? entry->display_url() : GURL::EmptyGURL();
133}
134
135const std::wstring& TabContents::GetTitle() const {
[email protected]cbab76d2008-10-13 22:42:47136 // We use the title for the last committed entry rather than a pending
137 // navigation entry. For example, when the user types in a URL, we want to
138 // keep the old page's title until the new load has committed and we get a new
139 // title.
140 // The exception is with transient pages, for which we really want to use
141 // their title, as they are not committed.
142 NavigationEntry* entry = controller_->GetTransientEntry();
[email protected]3d627bbc2008-10-23 20:49:07143 if (entry)
144 return entry->GetTitleForDisplay();
[email protected]cbab76d2008-10-13 22:42:47145
146 entry = controller_->GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34147 if (entry)
[email protected]3d627bbc2008-10-23 20:49:07148 return entry->GetTitleForDisplay();
[email protected]d5f942ba2008-09-26 19:30:34149 else if (controller_->LoadingURLLazily())
150 return controller_->GetLazyTitle();
151 return EmptyWString();
152}
153
154int32 TabContents::GetMaxPageID() {
155 if (GetSiteInstance())
156 return GetSiteInstance()->max_page_id();
157 else
158 return max_page_id_;
159}
160
161void TabContents::UpdateMaxPageID(int32 page_id) {
162 // Ensure both the SiteInstance and RenderProcessHost update their max page
163 // IDs in sync. Only WebContents will also have site instances, except during
164 // testing.
165 if (GetSiteInstance())
166 GetSiteInstance()->UpdateMaxPageID(page_id);
167
168 if (AsWebContents())
169 AsWebContents()->process()->UpdateMaxPageID(page_id);
170 else
171 max_page_id_ = std::max(max_page_id_, page_id);
172}
173
174const std::wstring TabContents::GetDefaultTitle() const {
175 return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE);
176}
177
178SkBitmap TabContents::GetFavIcon() const {
179 // Like GetTitle(), we also want to use the favicon for the last committed
180 // entry rather than a pending navigation entry.
[email protected]cbab76d2008-10-13 22:42:47181 NavigationEntry* entry = controller_->GetTransientEntry();
182 if (entry)
183 return entry->favicon().bitmap();
184
185 entry = controller_->GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34186 if (entry)
187 return entry->favicon().bitmap();
188 else if (controller_->LoadingURLLazily())
189 return controller_->GetLazyFavIcon();
190 return SkBitmap();
191}
192
193SecurityStyle TabContents::GetSecurityStyle() const {
194 // We may not have a navigation entry yet.
195 NavigationEntry* entry = controller_->GetActiveEntry();
196 return entry ? entry->ssl().security_style() : SECURITY_STYLE_UNKNOWN;
197}
198
199bool TabContents::GetSSLEVText(std::wstring* ev_text,
200 std::wstring* ev_tooltip_text) const {
201 DCHECK(ev_text && ev_tooltip_text);
202 ev_text->clear();
203 ev_tooltip_text->clear();
204
205 NavigationEntry* entry = controller_->GetActiveEntry();
206 if (!entry ||
207 net::IsCertStatusError(entry->ssl().cert_status()) ||
208 ((entry->ssl().cert_status() & net::CERT_STATUS_IS_EV) == 0))
209 return false;
210
211 scoped_refptr<net::X509Certificate> cert;
212 CertStore::GetSharedInstance()->RetrieveCert(entry->ssl().cert_id(), &cert);
213 if (!cert.get()) {
214 NOTREACHED();
215 return false;
216 }
217
218 return SSLManager::GetEVCertNames(*cert, ev_text, ev_tooltip_text);
219}
220
221void TabContents::SetIsCrashed(bool state) {
222 if (state == is_crashed_)
223 return;
224
225 is_crashed_ = state;
226 if (delegate_)
227 delegate_->ContentsStateChanged(this);
228}
229
230void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) {
231 if (delegate_)
232 delegate_->NavigationStateChanged(this, changed_flags);
233}
234
235void TabContents::DidBecomeSelected() {
236 if (controller_)
237 controller_->SetActive(true);
238
239 // Invalidate all descendants. (take care to exclude invalidating ourselves!)
240 EnumChildWindows(GetContainerHWND(), InvalidateWindow, 0);
241}
242
243void TabContents::WasHidden() {
244 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_HIDDEN,
245 Source<TabContents>(this),
246 NotificationService::NoDetails());
247}
248
249void TabContents::Activate() {
250 if (delegate_)
251 delegate_->ActivateContents(this);
252}
253
[email protected]c0588052008-10-27 23:01:50254void TabContents::OpenURL(const GURL& url, const GURL& referrer,
[email protected]d5f942ba2008-09-26 19:30:34255 WindowOpenDisposition disposition,
256 PageTransition::Type transition) {
257 if (delegate_)
[email protected]c0588052008-10-27 23:01:50258 delegate_->OpenURLFromTab(this, url, referrer, disposition, transition);
[email protected]d5f942ba2008-09-26 19:30:34259}
260
261bool TabContents::NavigateToPendingEntry(bool reload) {
262 // Our benavior is just to report that the entry was committed.
263 controller()->GetPendingEntry()->set_title(GetDefaultTitle());
264 controller()->CommitPendingEntry();
265 return true;
266}
267
initial.commit09911bf2008-07-26 23:55:29268ConstrainedWindow* TabContents::CreateConstrainedDialog(
[email protected]c2dacc92008-10-16 23:51:38269 views::WindowDelegate* window_delegate,
270 views::View* contents_view) {
initial.commit09911bf2008-07-26 23:55:29271 ConstrainedWindow* window =
272 ConstrainedWindow::CreateConstrainedDialog(
273 this, gfx::Rect(), contents_view, window_delegate);
274 child_windows_.push_back(window);
275 return window;
276}
277
278void TabContents::AddNewContents(TabContents* new_contents,
279 WindowOpenDisposition disposition,
280 const gfx::Rect& initial_pos,
281 bool user_gesture) {
282 if (!delegate_)
283 return;
284
[email protected]3b0a45e82008-10-13 21:01:03285 if ((disposition == NEW_POPUP) && !user_gesture) {
286 // Unrequested popups from normal pages are constrained.
287 TabContents* popup_owner = this;
288 TabContents* our_owner = delegate_->GetConstrainingContents(this);
289 if (our_owner)
290 popup_owner = our_owner;
291 popup_owner->AddConstrainedPopup(new_contents, initial_pos);
initial.commit09911bf2008-07-26 23:55:29292 } else {
[email protected]0aa55312008-10-17 21:53:08293 new_contents->DisassociateFromPopupCount();
294
initial.commit09911bf2008-07-26 23:55:29295 delegate_->AddNewContents(this, new_contents, disposition, initial_pos,
296 user_gesture);
297 }
298}
299
300void TabContents::AddConstrainedPopup(TabContents* new_contents,
301 const gfx::Rect& initial_pos) {
[email protected]d6598c052008-11-05 19:03:25302 if (!blocked_popups_) {
303 CRect client_rect;
304 GetClientRect(GetContainerHWND(), &client_rect);
305 gfx::Point anchor_position(
306 client_rect.Width() -
307 views::NativeScrollBar::GetVerticalScrollBarWidth(),
308 client_rect.Height());
initial.commit09911bf2008-07-26 23:55:29309
[email protected]d6598c052008-11-05 19:03:25310 blocked_popups_ = BlockedPopupContainer::Create(
311 this, profile(), anchor_position);
312 child_windows_.push_back(blocked_popups_);
313 }
314
315 blocked_popups_->AddTabContents(new_contents, initial_pos);
initial.commit09911bf2008-07-26 23:55:29316}
317
initial.commit09911bf2008-07-26 23:55:29318void TabContents::CloseAllSuppressedPopups() {
[email protected]d6598c052008-11-05 19:03:25319 if (blocked_popups_)
320 blocked_popups_->CloseAllPopups();
initial.commit09911bf2008-07-26 23:55:29321}
322
initial.commit09911bf2008-07-26 23:55:29323void TabContents::Focus() {
[email protected]c2dacc92008-10-16 23:51:38324 views::FocusManager* focus_manager =
325 views::FocusManager::GetFocusManager(GetContainerHWND());
initial.commit09911bf2008-07-26 23:55:29326 DCHECK(focus_manager);
[email protected]c2dacc92008-10-16 23:51:38327 views::View* v =
initial.commit09911bf2008-07-26 23:55:29328 focus_manager->GetViewForWindow(GetContainerHWND(), true);
329 DCHECK(v);
330 if (v)
331 v->RequestFocus();
332}
333
334void TabContents::StoreFocus() {
[email protected]c2dacc92008-10-16 23:51:38335 views::ViewStorage* view_storage =
336 views::ViewStorage::GetSharedInstance();
initial.commit09911bf2008-07-26 23:55:29337
338 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
339 view_storage->RemoveView(last_focused_view_storage_id_);
340
[email protected]c2dacc92008-10-16 23:51:38341 views::FocusManager* focus_manager =
342 views::FocusManager::GetFocusManager(GetContainerHWND());
initial.commit09911bf2008-07-26 23:55:29343 if (focus_manager) {
344 // |focus_manager| can be NULL if the tab has been detached but still
345 // exists.
[email protected]c2dacc92008-10-16 23:51:38346 views::View* focused_view = focus_manager->GetFocusedView();
initial.commit09911bf2008-07-26 23:55:29347 if (focused_view)
348 view_storage->StoreView(last_focused_view_storage_id_, focused_view);
349
350 // If the focus was on the page, explicitly clear the focus so that we
351 // don't end up with the focused HWND not part of the window hierarchy.
[email protected]c80c5632008-10-10 20:34:35352 // TODO(brettw) this should move to the view somehow.
initial.commit09911bf2008-07-26 23:55:29353 HWND container_hwnd = GetContainerHWND();
354 if (container_hwnd) {
[email protected]c2dacc92008-10-16 23:51:38355 views::View* focused_view = focus_manager->GetFocusedView();
initial.commit09911bf2008-07-26 23:55:29356 if (focused_view) {
[email protected]a0dde122008-11-21 20:51:20357 HWND hwnd = focused_view->GetRootView()->GetWidget()->GetHWND();
initial.commit09911bf2008-07-26 23:55:29358 if (container_hwnd == hwnd || ::IsChild(container_hwnd, hwnd))
359 focus_manager->ClearFocus();
360 }
361 }
362 }
363}
364
365void TabContents::RestoreFocus() {
[email protected]c2dacc92008-10-16 23:51:38366 views::ViewStorage* view_storage =
367 views::ViewStorage::GetSharedInstance();
368 views::View* last_focused_view =
initial.commit09911bf2008-07-26 23:55:29369 view_storage->RetrieveView(last_focused_view_storage_id_);
370
371 if (!last_focused_view) {
372 SetInitialFocus();
373 } else {
[email protected]c2dacc92008-10-16 23:51:38374 views::FocusManager* focus_manager =
375 views::FocusManager::GetFocusManager(GetContainerHWND());
[email protected]6e2f2cec2008-09-23 22:59:06376
377 // If you hit this DCHECK, please report it to Jay (jcampan).
378 DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";
379
380 if (focus_manager && focus_manager->ContainsView(last_focused_view)) {
initial.commit09911bf2008-07-26 23:55:29381 last_focused_view->RequestFocus();
382 } else {
383 // The focused view may not belong to the same window hierarchy (for
384 // example if the location bar was focused and the tab is dragged out).
385 // In that case we default to the default focus.
386 SetInitialFocus();
387 }
388 view_storage->RemoveView(last_focused_view_storage_id_);
389 }
390}
391
[email protected]d5f942ba2008-09-26 19:30:34392void TabContents::SetInitialFocus() {
393 ::SetFocus(GetContainerHWND());
initial.commit09911bf2008-07-26 23:55:29394}
395
[email protected]616ed5a2008-11-21 22:27:24396void TabContents::AddInfoBar(InfoBarDelegate* delegate) {
397 // Look through the existing InfoBarDelegates we have for a match. If we've
398 // already got one that matches, then we don't add the new one.
[email protected]f86a07022008-11-25 01:06:05399 for (int i = 0; i < infobar_delegate_count(); ++i) {
[email protected]616ed5a2008-11-21 22:27:24400 if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate))
401 return;
402 }
403
404 infobar_delegates_.push_back(delegate);
405 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_ADDED,
406 Source<TabContents>(this),
407 Details<InfoBarDelegate>(delegate));
408
409 // Add ourselves as an observer for navigations the first time a delegate is
410 // added. We use this notification to expire InfoBars that need to expire on
411 // page transitions.
412 if (infobar_delegates_.size() == 1) {
413 NotificationService::current()->AddObserver(
414 this, NOTIFY_NAV_ENTRY_COMMITTED,
415 Source<NavigationController>(controller()));
416 }
417}
418
419void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) {
420 std::vector<InfoBarDelegate*>::iterator it =
421 find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate);
422 if (it != infobar_delegates_.end()) {
423 InfoBarDelegate* delegate = *it;
[email protected]616ed5a2008-11-21 22:27:24424 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED,
425 Source<TabContents>(this),
426 Details<InfoBarDelegate>(delegate));
[email protected]f86a07022008-11-25 01:06:05427 infobar_delegates_.erase(it);
[email protected]616ed5a2008-11-21 22:27:24428 }
429
430 // Remove ourselves as an observer if we are tracking no more InfoBars.
431 if (infobar_delegates_.empty()) {
432 NotificationService::current()->RemoveObserver(
433 this, NOTIFY_NAV_ENTRY_COMMITTED,
434 Source<NavigationController>(controller()));
435 }
436}
437
initial.commit09911bf2008-07-26 23:55:29438void TabContents::SetDownloadShelfVisible(bool visible) {
439 if (shelf_visible_ != visible) {
440 if (visible) {
441 // Invoke GetDownloadShelfView to force the shelf to be created.
442 GetDownloadShelfView();
443 }
444 shelf_visible_ = visible;
445
[email protected]019d83502008-07-30 22:44:50446 if (delegate_)
447 delegate_->ContentsStateChanged(this);
initial.commit09911bf2008-07-26 23:55:29448 }
[email protected]ce2390b682008-08-08 22:24:51449
450 // SetShelfVisible can force-close the shelf, so make sure we lay out
451 // everything correctly, as if the animation had finished. This doesn't
452 // matter for showing the shelf, as the show animation will do it.
453 ToolbarSizeChanged(false);
initial.commit09911bf2008-07-26 23:55:29454}
455
initial.commit09911bf2008-07-26 23:55:29456void TabContents::ToolbarSizeChanged(bool is_animating) {
457 TabContentsDelegate* d = delegate();
458 if (d)
459 d->ToolbarSizeChanged(this, is_animating);
460}
461
[email protected]d5f942ba2008-09-26 19:30:34462void TabContents::OnStartDownload(DownloadItem* download) {
463 DCHECK(download);
464 TabContents* tab_contents = this;
465
466 // Download in a constrained popup is shown in the tab that opened it.
467 TabContents* constraining_tab = delegate()->GetConstrainingContents(this);
468 if (constraining_tab)
469 tab_contents = constraining_tab;
470
471 // GetDownloadShelfView creates the download shelf if it was not yet created.
472 tab_contents->GetDownloadShelfView()->AddDownload(download);
473 tab_contents->SetDownloadShelfVisible(true);
474
475 // This animation will delete itself when it finishes, or if we become hidden
476 // or destroyed.
477 if (IsWindowVisible(GetContainerHWND())) { // For minimized windows, unit
478 // tests, etc.
479 new DownloadStartedAnimation(tab_contents);
480 }
481}
482
initial.commit09911bf2008-07-26 23:55:29483DownloadShelfView* TabContents::GetDownloadShelfView() {
484 if (!download_shelf_view_.get()) {
485 download_shelf_view_.reset(new DownloadShelfView(this));
486 // The TabContents owns the download-shelf.
487 download_shelf_view_->SetParentOwned(false);
488 }
489 return download_shelf_view_.get();
490}
491
492void TabContents::MigrateShelfViewFrom(TabContents* tab_contents) {
493 download_shelf_view_.reset(tab_contents->GetDownloadShelfView());
494 download_shelf_view_->ChangeTabContents(tab_contents, this);
495 tab_contents->ReleaseDownloadShelfView();
496}
497
[email protected]d5f942ba2008-09-26 19:30:34498void TabContents::WillClose(ConstrainedWindow* window) {
499 ConstrainedWindowList::iterator it =
500 find(child_windows_.begin(), child_windows_.end(), window);
501 if (it != child_windows_.end())
502 child_windows_.erase(it);
503
[email protected]d6598c052008-11-05 19:03:25504 if (window == blocked_popups_)
505 blocked_popups_ = NULL;
506
[email protected]d5f942ba2008-09-26 19:30:34507 if (::IsWindow(GetContainerHWND())) {
508 CRect client_rect;
509 GetClientRect(GetContainerHWND(), &client_rect);
510 RepositionSupressedPopupsToFit(
511 gfx::Size(client_rect.Width(), client_rect.Height()));
512 }
513}
514
[email protected]d5f942ba2008-09-26 19:30:34515void TabContents::DidMoveOrResize(ConstrainedWindow* window) {
516 UpdateWindow(GetContainerHWND());
517}
518
[email protected]616ed5a2008-11-21 22:27:24519void TabContents::Observe(NotificationType type,
520 const NotificationSource& source,
521 const NotificationDetails& details) {
522 DCHECK(type == NOTIFY_NAV_ENTRY_COMMITTED);
523 DCHECK(controller() == Source<NavigationController>(source).ptr());
524
525 NavigationController::LoadCommittedDetails& committed_details =
526 *(Details<NavigationController::LoadCommittedDetails>(details).ptr());
527 ExpireInfoBars(committed_details);
528}
529
initial.commit09911bf2008-07-26 23:55:29530// static
531void TabContents::MigrateShelfView(TabContents* from, TabContents* to) {
532 bool was_shelf_visible = from->IsDownloadShelfVisible();
533 if (was_shelf_visible)
534 to->MigrateShelfViewFrom(from);
535 to->SetDownloadShelfVisible(was_shelf_visible);
536}
537
[email protected]d5f942ba2008-09-26 19:30:34538void TabContents::SetIsLoading(bool is_loading,
539 LoadNotificationDetails* details) {
540 if (is_loading == is_loading_)
541 return;
542
543 is_loading_ = is_loading;
544 waiting_for_response_ = is_loading;
545
546 // Suppress notifications for this TabContents if we are not active.
547 if (!is_active_)
548 return;
549
550 if (delegate_)
551 delegate_->LoadingStateChanged(this);
552
553 NotificationService::current()->
554 Notify((is_loading ? NOTIFY_LOAD_START : NOTIFY_LOAD_STOP),
555 Source<NavigationController>(this->controller()),
556 details ? Details<LoadNotificationDetails>(details) :
557 NotificationService::NoDetails());
initial.commit09911bf2008-07-26 23:55:29558}
license.botbf09a502008-08-24 00:55:55559
[email protected]9e0534b2008-10-21 15:03:01560// TODO(brettw) This should be on the WebContentsView.
[email protected]d5f942ba2008-09-26 19:30:34561void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) {
562 // TODO(erg): There's no way to detect whether scroll bars are
563 // visible, so for beta, we're just going to assume that the
564 // vertical scroll bar is visible, and not care about covering up
565 // the horizontal scroll bar. Fixing this is half of
566 // http://b/1118139.
567 gfx::Point anchor_position(
568 new_size.width() -
[email protected]c2dacc92008-10-16 23:51:38569 views::NativeScrollBar::GetVerticalScrollBarWidth(),
[email protected]d5f942ba2008-09-26 19:30:34570 new_size.height());
[email protected]d6598c052008-11-05 19:03:25571
572 if (blocked_popups_)
573 blocked_popups_->RepositionConstrainedWindowTo(anchor_position);
[email protected]d5f942ba2008-09-26 19:30:34574}
575
576void TabContents::ReleaseDownloadShelfView() {
577 download_shelf_view_.release();
578}
[email protected]b9681312008-11-07 00:08:26579
580bool TabContents::ShowingBlockedPopupNotification() const {
581 return blocked_popups_ != NULL &&
582 blocked_popups_->GetTabContentsCount() != 0;
583}
[email protected]616ed5a2008-11-21 22:27:24584
585namespace {
586bool TransitionIsReload(PageTransition::Type transition) {
587 return PageTransition::StripQualifier(transition) == PageTransition::RELOAD;
588}
589}
590
591void TabContents::ExpireInfoBars(
592 const NavigationController::LoadCommittedDetails& details) {
593 // Only hide InfoBars when the user has done something that makes the main
594 // frame load. We don't want various automatic or subframe navigations making
595 // it disappear.
596 if (!details.is_user_initiated_main_frame_load())
597 return;
598
[email protected]f86a07022008-11-25 01:06:05599 for (int i = infobar_delegate_count() - 1; i >= 0; --i) {
[email protected]616ed5a2008-11-21 22:27:24600 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
[email protected]f86a07022008-11-25 01:06:05601 if (delegate->ShouldExpire(details))
[email protected]616ed5a2008-11-21 22:27:24602 RemoveInfoBar(delegate);
[email protected]616ed5a2008-11-21 22:27:24603 }
604}