blob: 376aaf1d921db34803c2b1b31a286c882ce8b114 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/browser_instant_controller.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/instant/instant_controller.h"
#include "chrome/browser/instant/instant_unload_handler.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/omnibox/location_bar.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
namespace chrome {
////////////////////////////////////////////////////////////////////////////////
// BrowserInstantController, public:
BrowserInstantController::BrowserInstantController(Browser* browser)
: browser_(browser) {
profile_pref_registrar_.Init(browser_->profile()->GetPrefs());
profile_pref_registrar_.Add(prefs::kInstantEnabled, this);
ResetInstant();
browser_->tab_strip_model()->AddObserver(this);
}
BrowserInstantController::~BrowserInstantController() {
browser_->tab_strip_model()->RemoveObserver(this);
}
bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition) {
// NEW_BACKGROUND_TAB results in leaving the omnibox open, so we don't attempt
// to use the Instant preview.
if (!instant() || !instant_->IsCurrent() || disposition == NEW_BACKGROUND_TAB)
return false;
if (disposition == CURRENT_TAB) {
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_INSTANT_COMMITTED,
content::Source<TabContents>(instant_->CommitCurrentPreview(
INSTANT_COMMIT_PRESSED_ENTER)),
content::NotificationService::NoDetails());
return true;
}
if (disposition == NEW_FOREGROUND_TAB) {
TabContents* preview = instant_->ReleasePreviewContents(
INSTANT_COMMIT_PRESSED_ENTER);
preview->web_contents()->GetController().PruneAllButActive();
browser_->tab_strip_model()->AddTabContents(preview, -1,
instant_->last_transition_type(), TabStripModel::ADD_ACTIVE);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_INSTANT_COMMITTED,
content::Source<TabContents>(preview),
content::NotificationService::NoDetails());
return true;
}
// The omnibox currently doesn't use other dispositions, so we don't attempt
// to handle them. If you hit this NOTREACHED file a bug and I'll (sky) add
// support for the new disposition.
NOTREACHED();
return false;
}
////////////////////////////////////////////////////////////////////////////////
// BrowserInstantController, InstantControllerDelegate implementation:
void BrowserInstantController::ShowInstant(int height, InstantSizeUnits units) {
browser_->window()->ShowInstant(instant_->GetPreviewContents(),
height, units);
}
void BrowserInstantController::HideInstant() {
browser_->window()->HideInstant();
}
void BrowserInstantController::CommitInstant(TabContents* preview) {
TabContents* active_tab = chrome::GetActiveTabContents(browser_);
int index = browser_->tab_strip_model()->GetIndexOfTabContents(active_tab);
DCHECK_NE(TabStripModel::kNoTab, index);
// TabStripModel takes ownership of |preview|.
browser_->tab_strip_model()->ReplaceTabContentsAt(index, preview);
// InstantUnloadHandler takes ownership of |active_tab|.
instant_unload_handler_->RunUnloadListenersOrDestroy(active_tab, index);
GURL url = preview->web_contents()->GetURL();
DCHECK(browser_->profile()->GetExtensionService());
if (browser_->profile()->GetExtensionService()->IsInstalledApp(url)) {
AppLauncherHandler::RecordAppLaunchType(
extension_misc::APP_LAUNCH_OMNIBOX_INSTANT);
}
}
void BrowserInstantController::SetSuggestedText(
const string16& text,
InstantCompleteBehavior behavior) {
if (browser_->window()->GetLocationBar())
browser_->window()->GetLocationBar()->SetSuggestedText(text, behavior);
}
gfx::Rect BrowserInstantController::GetInstantBounds() {
return browser_->window()->GetInstantBounds();
}
void BrowserInstantController::InstantPreviewFocused() {
// NOTE: This is only invoked on aura.
browser_->window()->WebContentsFocused(
instant_->GetPreviewContents()->web_contents());
}
TabContents* BrowserInstantController::GetActiveTabContents() const {
return chrome::GetActiveTabContents(browser_);
}
////////////////////////////////////////////////////////////////////////////////
// BrowserInstantController, content::NotificationObserver implementation:
void BrowserInstantController::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK_EQ(chrome::NOTIFICATION_PREF_CHANGED, type);
DCHECK_EQ(std::string(prefs::kInstantEnabled),
*content::Details<std::string>(details).ptr());
ResetInstant();
}
////////////////////////////////////////////////////////////////////////////////
// BrowserInstantController, TabStripModelObserver implementation:
void BrowserInstantController::TabDeactivated(TabContents* contents) {
if (instant())
instant_->Hide();
}
////////////////////////////////////////////////////////////////////////////////
// BrowserInstantController, private:
void BrowserInstantController::ResetInstant() {
instant_.reset(
!browser_shutdown::ShuttingDownWithoutClosingBrowsers() &&
browser_->is_type_tabbed() ?
InstantController::CreateInstant(browser_->profile(), this) : NULL);
instant_unload_handler_.reset(instant() ?
new InstantUnloadHandler(browser_) : NULL);
}
} // namespace chrome