blob: 9bdca3c1dd6c7f22bff1778daa61f765abdbd144 [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]d5f942ba2008-09-26 19:30:3449 capturing_contents_(false) {
initial.commit09911bf2008-07-26 23:55:2950 last_focused_view_storage_id_ =
[email protected]c2dacc92008-10-16 23:51:3851 views::ViewStorage::GetSharedInstance()->CreateStorageID();
initial.commit09911bf2008-07-26 23:55:2952}
53
54TabContents::~TabContents() {
55 // Makes sure to remove any stored view we may still have in the ViewStorage.
56 //
57 // It is possible the view went away before us, so we only do this if the
58 // view is registered.
[email protected]c2dacc92008-10-16 23:51:3859 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
initial.commit09911bf2008-07-26 23:55:2960 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
61 view_storage->RemoveView(last_focused_view_storage_id_);
62}
63
[email protected]d5f942ba2008-09-26 19:30:3464// static
65void TabContents::RegisterUserPrefs(PrefService* prefs) {
66 prefs->RegisterBooleanPref(prefs::kBlockPopups, false);
initial.commit09911bf2008-07-26 23:55:2967}
68
initial.commit09911bf2008-07-26 23:55:2969
70void TabContents::CloseContents() {
71 // Destroy our NavigationController, which will Destroy all tabs it owns.
72 controller_->Destroy();
73 // Note that the controller may have deleted us at this point,
74 // so don't touch any member variables here.
75}
76
77void TabContents::Destroy() {
78 // First cleanly close all child windows.
79 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
80 // some of these to close. CloseWindows is async, so it might get called
81 // twice before it runs.
82 int size = static_cast<int>(child_windows_.size());
83 for (int i = size - 1; i >= 0; --i) {
84 ConstrainedWindow* window = child_windows_[i];
85 if (window)
86 window->CloseConstrainedWindow();
87 }
88
89 // Notify any observer that have a reference on this tab contents.
90 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_DESTROYED,
91 Source<TabContents>(this),
92 NotificationService::NoDetails());
93
94 // If we still have a window handle, destroy it. GetContainerHWND can return
95 // NULL if this contents was part of a window that closed.
96 if (GetContainerHWND())
97 ::DestroyWindow(GetContainerHWND());
98
99 // Notify our NavigationController. Make sure we are deleted first, so
100 // that the controller is the last to die.
101 NavigationController* controller = controller_;
102 TabContentsType type = this->type();
103
104 delete this;
105
106 controller->TabContentsWasDestroyed(type);
107}
108
[email protected]d5f942ba2008-09-26 19:30:34109void TabContents::SetupController(Profile* profile) {
110 DCHECK(!controller_);
111 controller_ = new NavigationController(this, profile);
112}
113
114bool TabContents::SupportsURL(GURL* url) {
115 GURL u(*url);
116 if (TabContents::TypeForURL(&u) == type()) {
117 *url = u;
118 return true;
119 }
120 return false;
121}
122
123const GURL& TabContents::GetURL() const {
124 // We may not have a navigation entry yet
125 NavigationEntry* entry = controller_->GetActiveEntry();
126 return entry ? entry->display_url() : GURL::EmptyGURL();
127}
128
129const std::wstring& TabContents::GetTitle() const {
[email protected]cbab76d2008-10-13 22:42:47130 // We use the title for the last committed entry rather than a pending
131 // navigation entry. For example, when the user types in a URL, we want to
132 // keep the old page's title until the new load has committed and we get a new
133 // title.
134 // The exception is with transient pages, for which we really want to use
135 // their title, as they are not committed.
136 NavigationEntry* entry = controller_->GetTransientEntry();
[email protected]3d627bbc2008-10-23 20:49:07137 if (entry)
138 return entry->GetTitleForDisplay();
[email protected]cbab76d2008-10-13 22:42:47139
140 entry = controller_->GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34141 if (entry)
[email protected]3d627bbc2008-10-23 20:49:07142 return entry->GetTitleForDisplay();
[email protected]d5f942ba2008-09-26 19:30:34143 else if (controller_->LoadingURLLazily())
144 return controller_->GetLazyTitle();
145 return EmptyWString();
146}
147
148int32 TabContents::GetMaxPageID() {
149 if (GetSiteInstance())
150 return GetSiteInstance()->max_page_id();
151 else
152 return max_page_id_;
153}
154
155void TabContents::UpdateMaxPageID(int32 page_id) {
156 // Ensure both the SiteInstance and RenderProcessHost update their max page
157 // IDs in sync. Only WebContents will also have site instances, except during
158 // testing.
159 if (GetSiteInstance())
160 GetSiteInstance()->UpdateMaxPageID(page_id);
161
162 if (AsWebContents())
163 AsWebContents()->process()->UpdateMaxPageID(page_id);
164 else
165 max_page_id_ = std::max(max_page_id_, page_id);
166}
167
168const std::wstring TabContents::GetDefaultTitle() const {
169 return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE);
170}
171
172SkBitmap TabContents::GetFavIcon() const {
173 // Like GetTitle(), we also want to use the favicon for the last committed
174 // entry rather than a pending navigation entry.
[email protected]cbab76d2008-10-13 22:42:47175 NavigationEntry* entry = controller_->GetTransientEntry();
176 if (entry)
177 return entry->favicon().bitmap();
178
179 entry = controller_->GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34180 if (entry)
181 return entry->favicon().bitmap();
182 else if (controller_->LoadingURLLazily())
183 return controller_->GetLazyFavIcon();
184 return SkBitmap();
185}
186
187SecurityStyle TabContents::GetSecurityStyle() const {
188 // We may not have a navigation entry yet.
189 NavigationEntry* entry = controller_->GetActiveEntry();
190 return entry ? entry->ssl().security_style() : SECURITY_STYLE_UNKNOWN;
191}
192
193bool TabContents::GetSSLEVText(std::wstring* ev_text,
194 std::wstring* ev_tooltip_text) const {
195 DCHECK(ev_text && ev_tooltip_text);
196 ev_text->clear();
197 ev_tooltip_text->clear();
198
199 NavigationEntry* entry = controller_->GetActiveEntry();
200 if (!entry ||
201 net::IsCertStatusError(entry->ssl().cert_status()) ||
202 ((entry->ssl().cert_status() & net::CERT_STATUS_IS_EV) == 0))
203 return false;
204
205 scoped_refptr<net::X509Certificate> cert;
206 CertStore::GetSharedInstance()->RetrieveCert(entry->ssl().cert_id(), &cert);
207 if (!cert.get()) {
208 NOTREACHED();
209 return false;
210 }
211
212 return SSLManager::GetEVCertNames(*cert, ev_text, ev_tooltip_text);
213}
214
215void TabContents::SetIsCrashed(bool state) {
216 if (state == is_crashed_)
217 return;
218
219 is_crashed_ = state;
220 if (delegate_)
221 delegate_->ContentsStateChanged(this);
222}
223
224void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) {
225 if (delegate_)
226 delegate_->NavigationStateChanged(this, changed_flags);
227}
228
229void TabContents::DidBecomeSelected() {
230 if (controller_)
231 controller_->SetActive(true);
232
233 // Invalidate all descendants. (take care to exclude invalidating ourselves!)
234 EnumChildWindows(GetContainerHWND(), InvalidateWindow, 0);
235}
236
237void TabContents::WasHidden() {
238 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_HIDDEN,
239 Source<TabContents>(this),
240 NotificationService::NoDetails());
241}
242
243void TabContents::Activate() {
244 if (delegate_)
245 delegate_->ActivateContents(this);
246}
247
[email protected]c0588052008-10-27 23:01:50248void TabContents::OpenURL(const GURL& url, const GURL& referrer,
[email protected]d5f942ba2008-09-26 19:30:34249 WindowOpenDisposition disposition,
250 PageTransition::Type transition) {
251 if (delegate_)
[email protected]c0588052008-10-27 23:01:50252 delegate_->OpenURLFromTab(this, url, referrer, disposition, transition);
[email protected]d5f942ba2008-09-26 19:30:34253}
254
255bool TabContents::NavigateToPendingEntry(bool reload) {
256 // Our benavior is just to report that the entry was committed.
257 controller()->GetPendingEntry()->set_title(GetDefaultTitle());
258 controller()->CommitPendingEntry();
259 return true;
260}
261
initial.commit09911bf2008-07-26 23:55:29262ConstrainedWindow* TabContents::CreateConstrainedDialog(
[email protected]c2dacc92008-10-16 23:51:38263 views::WindowDelegate* window_delegate,
264 views::View* contents_view) {
initial.commit09911bf2008-07-26 23:55:29265 ConstrainedWindow* window =
266 ConstrainedWindow::CreateConstrainedDialog(
267 this, gfx::Rect(), contents_view, window_delegate);
268 child_windows_.push_back(window);
269 return window;
270}
271
272void TabContents::AddNewContents(TabContents* new_contents,
273 WindowOpenDisposition disposition,
274 const gfx::Rect& initial_pos,
275 bool user_gesture) {
276 if (!delegate_)
277 return;
278
[email protected]3b0a45e82008-10-13 21:01:03279 if ((disposition == NEW_POPUP) && !user_gesture) {
280 // Unrequested popups from normal pages are constrained.
281 TabContents* popup_owner = this;
282 TabContents* our_owner = delegate_->GetConstrainingContents(this);
283 if (our_owner)
284 popup_owner = our_owner;
285 popup_owner->AddConstrainedPopup(new_contents, initial_pos);
initial.commit09911bf2008-07-26 23:55:29286 } else {
[email protected]0aa55312008-10-17 21:53:08287 new_contents->DisassociateFromPopupCount();
288
initial.commit09911bf2008-07-26 23:55:29289 delegate_->AddNewContents(this, new_contents, disposition, initial_pos,
290 user_gesture);
291 }
292}
293
294void TabContents::AddConstrainedPopup(TabContents* new_contents,
295 const gfx::Rect& initial_pos) {
[email protected]d6598c052008-11-05 19:03:25296 if (!blocked_popups_) {
297 CRect client_rect;
298 GetClientRect(GetContainerHWND(), &client_rect);
299 gfx::Point anchor_position(
300 client_rect.Width() -
301 views::NativeScrollBar::GetVerticalScrollBarWidth(),
302 client_rect.Height());
initial.commit09911bf2008-07-26 23:55:29303
[email protected]d6598c052008-11-05 19:03:25304 blocked_popups_ = BlockedPopupContainer::Create(
305 this, profile(), anchor_position);
306 child_windows_.push_back(blocked_popups_);
307 }
308
309 blocked_popups_->AddTabContents(new_contents, initial_pos);
initial.commit09911bf2008-07-26 23:55:29310}
311
initial.commit09911bf2008-07-26 23:55:29312void TabContents::CloseAllSuppressedPopups() {
[email protected]d6598c052008-11-05 19:03:25313 if (blocked_popups_)
314 blocked_popups_->CloseAllPopups();
initial.commit09911bf2008-07-26 23:55:29315}
316
initial.commit09911bf2008-07-26 23:55:29317void TabContents::Focus() {
[email protected]c2dacc92008-10-16 23:51:38318 views::FocusManager* focus_manager =
319 views::FocusManager::GetFocusManager(GetContainerHWND());
initial.commit09911bf2008-07-26 23:55:29320 DCHECK(focus_manager);
[email protected]c2dacc92008-10-16 23:51:38321 views::View* v =
initial.commit09911bf2008-07-26 23:55:29322 focus_manager->GetViewForWindow(GetContainerHWND(), true);
323 DCHECK(v);
324 if (v)
325 v->RequestFocus();
326}
327
328void TabContents::StoreFocus() {
[email protected]c2dacc92008-10-16 23:51:38329 views::ViewStorage* view_storage =
330 views::ViewStorage::GetSharedInstance();
initial.commit09911bf2008-07-26 23:55:29331
332 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
333 view_storage->RemoveView(last_focused_view_storage_id_);
334
[email protected]c2dacc92008-10-16 23:51:38335 views::FocusManager* focus_manager =
336 views::FocusManager::GetFocusManager(GetContainerHWND());
initial.commit09911bf2008-07-26 23:55:29337 if (focus_manager) {
338 // |focus_manager| can be NULL if the tab has been detached but still
339 // exists.
[email protected]c2dacc92008-10-16 23:51:38340 views::View* focused_view = focus_manager->GetFocusedView();
initial.commit09911bf2008-07-26 23:55:29341 if (focused_view)
342 view_storage->StoreView(last_focused_view_storage_id_, focused_view);
343
344 // If the focus was on the page, explicitly clear the focus so that we
345 // don't end up with the focused HWND not part of the window hierarchy.
[email protected]c80c5632008-10-10 20:34:35346 // TODO(brettw) this should move to the view somehow.
initial.commit09911bf2008-07-26 23:55:29347 HWND container_hwnd = GetContainerHWND();
348 if (container_hwnd) {
[email protected]c2dacc92008-10-16 23:51:38349 views::View* focused_view = focus_manager->GetFocusedView();
initial.commit09911bf2008-07-26 23:55:29350 if (focused_view) {
[email protected]a0dde122008-11-21 20:51:20351 HWND hwnd = focused_view->GetRootView()->GetWidget()->GetHWND();
initial.commit09911bf2008-07-26 23:55:29352 if (container_hwnd == hwnd || ::IsChild(container_hwnd, hwnd))
353 focus_manager->ClearFocus();
354 }
355 }
356 }
357}
358
359void TabContents::RestoreFocus() {
[email protected]c2dacc92008-10-16 23:51:38360 views::ViewStorage* view_storage =
361 views::ViewStorage::GetSharedInstance();
362 views::View* last_focused_view =
initial.commit09911bf2008-07-26 23:55:29363 view_storage->RetrieveView(last_focused_view_storage_id_);
364
365 if (!last_focused_view) {
366 SetInitialFocus();
367 } else {
[email protected]c2dacc92008-10-16 23:51:38368 views::FocusManager* focus_manager =
369 views::FocusManager::GetFocusManager(GetContainerHWND());
[email protected]6e2f2cec2008-09-23 22:59:06370
371 // If you hit this DCHECK, please report it to Jay (jcampan).
372 DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";
373
374 if (focus_manager && focus_manager->ContainsView(last_focused_view)) {
initial.commit09911bf2008-07-26 23:55:29375 last_focused_view->RequestFocus();
376 } else {
377 // The focused view may not belong to the same window hierarchy (for
378 // example if the location bar was focused and the tab is dragged out).
379 // In that case we default to the default focus.
380 SetInitialFocus();
381 }
382 view_storage->RemoveView(last_focused_view_storage_id_);
383 }
384}
385
[email protected]d5f942ba2008-09-26 19:30:34386void TabContents::SetInitialFocus() {
387 ::SetFocus(GetContainerHWND());
initial.commit09911bf2008-07-26 23:55:29388}
389
[email protected]616ed5a2008-11-21 22:27:24390void TabContents::AddInfoBar(InfoBarDelegate* delegate) {
391 // Look through the existing InfoBarDelegates we have for a match. If we've
392 // already got one that matches, then we don't add the new one.
[email protected]f86a07022008-11-25 01:06:05393 for (int i = 0; i < infobar_delegate_count(); ++i) {
[email protected]616ed5a2008-11-21 22:27:24394 if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate))
395 return;
396 }
397
398 infobar_delegates_.push_back(delegate);
399 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_ADDED,
400 Source<TabContents>(this),
401 Details<InfoBarDelegate>(delegate));
402
403 // Add ourselves as an observer for navigations the first time a delegate is
404 // added. We use this notification to expire InfoBars that need to expire on
405 // page transitions.
406 if (infobar_delegates_.size() == 1) {
407 NotificationService::current()->AddObserver(
408 this, NOTIFY_NAV_ENTRY_COMMITTED,
409 Source<NavigationController>(controller()));
410 }
411}
412
413void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) {
414 std::vector<InfoBarDelegate*>::iterator it =
415 find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate);
416 if (it != infobar_delegates_.end()) {
417 InfoBarDelegate* delegate = *it;
[email protected]616ed5a2008-11-21 22:27:24418 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED,
419 Source<TabContents>(this),
420 Details<InfoBarDelegate>(delegate));
[email protected]f86a07022008-11-25 01:06:05421 infobar_delegates_.erase(it);
[email protected]616ed5a2008-11-21 22:27:24422 }
423
424 // Remove ourselves as an observer if we are tracking no more InfoBars.
425 if (infobar_delegates_.empty()) {
426 NotificationService::current()->RemoveObserver(
427 this, NOTIFY_NAV_ENTRY_COMMITTED,
428 Source<NavigationController>(controller()));
429 }
430}
431
initial.commit09911bf2008-07-26 23:55:29432void TabContents::SetDownloadShelfVisible(bool visible) {
433 if (shelf_visible_ != visible) {
434 if (visible) {
435 // Invoke GetDownloadShelfView to force the shelf to be created.
436 GetDownloadShelfView();
437 }
438 shelf_visible_ = visible;
439
[email protected]019d83502008-07-30 22:44:50440 if (delegate_)
441 delegate_->ContentsStateChanged(this);
initial.commit09911bf2008-07-26 23:55:29442 }
[email protected]ce2390b682008-08-08 22:24:51443
444 // SetShelfVisible can force-close the shelf, so make sure we lay out
445 // everything correctly, as if the animation had finished. This doesn't
446 // matter for showing the shelf, as the show animation will do it.
447 ToolbarSizeChanged(false);
initial.commit09911bf2008-07-26 23:55:29448}
449
initial.commit09911bf2008-07-26 23:55:29450void TabContents::ToolbarSizeChanged(bool is_animating) {
451 TabContentsDelegate* d = delegate();
452 if (d)
453 d->ToolbarSizeChanged(this, is_animating);
454}
455
[email protected]d5f942ba2008-09-26 19:30:34456void TabContents::OnStartDownload(DownloadItem* download) {
457 DCHECK(download);
458 TabContents* tab_contents = this;
459
460 // Download in a constrained popup is shown in the tab that opened it.
461 TabContents* constraining_tab = delegate()->GetConstrainingContents(this);
462 if (constraining_tab)
463 tab_contents = constraining_tab;
464
465 // GetDownloadShelfView creates the download shelf if it was not yet created.
466 tab_contents->GetDownloadShelfView()->AddDownload(download);
467 tab_contents->SetDownloadShelfVisible(true);
468
469 // This animation will delete itself when it finishes, or if we become hidden
470 // or destroyed.
471 if (IsWindowVisible(GetContainerHWND())) { // For minimized windows, unit
472 // tests, etc.
473 new DownloadStartedAnimation(tab_contents);
474 }
475}
476
initial.commit09911bf2008-07-26 23:55:29477DownloadShelfView* TabContents::GetDownloadShelfView() {
478 if (!download_shelf_view_.get()) {
479 download_shelf_view_.reset(new DownloadShelfView(this));
480 // The TabContents owns the download-shelf.
481 download_shelf_view_->SetParentOwned(false);
482 }
483 return download_shelf_view_.get();
484}
485
486void TabContents::MigrateShelfViewFrom(TabContents* tab_contents) {
487 download_shelf_view_.reset(tab_contents->GetDownloadShelfView());
488 download_shelf_view_->ChangeTabContents(tab_contents, this);
489 tab_contents->ReleaseDownloadShelfView();
490}
491
[email protected]d5f942ba2008-09-26 19:30:34492void TabContents::WillClose(ConstrainedWindow* window) {
493 ConstrainedWindowList::iterator it =
494 find(child_windows_.begin(), child_windows_.end(), window);
495 if (it != child_windows_.end())
496 child_windows_.erase(it);
497
[email protected]d6598c052008-11-05 19:03:25498 if (window == blocked_popups_)
499 blocked_popups_ = NULL;
500
[email protected]d5f942ba2008-09-26 19:30:34501 if (::IsWindow(GetContainerHWND())) {
502 CRect client_rect;
503 GetClientRect(GetContainerHWND(), &client_rect);
504 RepositionSupressedPopupsToFit(
505 gfx::Size(client_rect.Width(), client_rect.Height()));
506 }
507}
508
[email protected]d5f942ba2008-09-26 19:30:34509void TabContents::DidMoveOrResize(ConstrainedWindow* window) {
510 UpdateWindow(GetContainerHWND());
511}
512
[email protected]616ed5a2008-11-21 22:27:24513void TabContents::Observe(NotificationType type,
514 const NotificationSource& source,
515 const NotificationDetails& details) {
516 DCHECK(type == NOTIFY_NAV_ENTRY_COMMITTED);
517 DCHECK(controller() == Source<NavigationController>(source).ptr());
518
519 NavigationController::LoadCommittedDetails& committed_details =
520 *(Details<NavigationController::LoadCommittedDetails>(details).ptr());
521 ExpireInfoBars(committed_details);
522}
523
initial.commit09911bf2008-07-26 23:55:29524// static
525void TabContents::MigrateShelfView(TabContents* from, TabContents* to) {
526 bool was_shelf_visible = from->IsDownloadShelfVisible();
527 if (was_shelf_visible)
528 to->MigrateShelfViewFrom(from);
529 to->SetDownloadShelfVisible(was_shelf_visible);
530}
531
[email protected]d5f942ba2008-09-26 19:30:34532void TabContents::SetIsLoading(bool is_loading,
533 LoadNotificationDetails* details) {
534 if (is_loading == is_loading_)
535 return;
536
537 is_loading_ = is_loading;
538 waiting_for_response_ = is_loading;
539
540 // Suppress notifications for this TabContents if we are not active.
541 if (!is_active_)
542 return;
543
544 if (delegate_)
545 delegate_->LoadingStateChanged(this);
546
547 NotificationService::current()->
548 Notify((is_loading ? NOTIFY_LOAD_START : NOTIFY_LOAD_STOP),
549 Source<NavigationController>(this->controller()),
550 details ? Details<LoadNotificationDetails>(details) :
551 NotificationService::NoDetails());
initial.commit09911bf2008-07-26 23:55:29552}
license.botbf09a502008-08-24 00:55:55553
[email protected]9e0534b2008-10-21 15:03:01554// TODO(brettw) This should be on the WebContentsView.
[email protected]d5f942ba2008-09-26 19:30:34555void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) {
556 // TODO(erg): There's no way to detect whether scroll bars are
557 // visible, so for beta, we're just going to assume that the
558 // vertical scroll bar is visible, and not care about covering up
559 // the horizontal scroll bar. Fixing this is half of
560 // http://b/1118139.
561 gfx::Point anchor_position(
562 new_size.width() -
[email protected]c2dacc92008-10-16 23:51:38563 views::NativeScrollBar::GetVerticalScrollBarWidth(),
[email protected]d5f942ba2008-09-26 19:30:34564 new_size.height());
[email protected]d6598c052008-11-05 19:03:25565
566 if (blocked_popups_)
567 blocked_popups_->RepositionConstrainedWindowTo(anchor_position);
[email protected]d5f942ba2008-09-26 19:30:34568}
569
570void TabContents::ReleaseDownloadShelfView() {
571 download_shelf_view_.release();
572}
[email protected]b9681312008-11-07 00:08:26573
574bool TabContents::ShowingBlockedPopupNotification() const {
575 return blocked_popups_ != NULL &&
576 blocked_popups_->GetTabContentsCount() != 0;
577}
[email protected]616ed5a2008-11-21 22:27:24578
579namespace {
580bool TransitionIsReload(PageTransition::Type transition) {
581 return PageTransition::StripQualifier(transition) == PageTransition::RELOAD;
582}
583}
584
585void TabContents::ExpireInfoBars(
586 const NavigationController::LoadCommittedDetails& details) {
587 // Only hide InfoBars when the user has done something that makes the main
588 // frame load. We don't want various automatic or subframe navigations making
589 // it disappear.
590 if (!details.is_user_initiated_main_frame_load())
591 return;
592
[email protected]f86a07022008-11-25 01:06:05593 for (int i = infobar_delegate_count() - 1; i >= 0; --i) {
[email protected]616ed5a2008-11-21 22:27:24594 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
[email protected]f86a07022008-11-25 01:06:05595 if (delegate->ShouldExpire(details))
[email protected]616ed5a2008-11-21 22:27:24596 RemoveInfoBar(delegate);
[email protected]616ed5a2008-11-21 22:27:24597 }
598}