summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-26 04:06:43 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-26 04:06:43 +0000
commitf075fe0a20acba35df51e93e635db8f0b0d89d7b (patch)
tree68cc0fe76b8897b1f6162f176f1ba62a227929e1
parent62cdc5bf2d94c02ef33ebff1ede7e0cde31c7285 (diff)
downloadchromium_src-f075fe0a20acba35df51e93e635db8f0b0d89d7b.zip
chromium_src-f075fe0a20acba35df51e93e635db8f0b0d89d7b.tar.gz
chromium_src-f075fe0a20acba35df51e93e635db8f0b0d89d7b.tar.bz2
Reland r45520. This adds a new browser type: EXTENSION_APP that
has a larger titlebar and a big icon, along with a tabstrip, but no titlebar. Review URL: http://codereview.chromium.org/1774003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45566 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/browser.cc63
-rw-r--r--chrome/browser/browser.h38
-rw-r--r--chrome/browser/browser_init.cc2
-rw-r--r--chrome/browser/extensions/extension_tabs_module.cc2
-rw-r--r--chrome/browser/resources/calendar_app/manifest.json2
-rw-r--r--chrome/browser/resources/docs_app/manifest.json2
-rw-r--r--chrome/browser/resources/gmail_app/manifest.json2
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc10
-rw-r--r--chrome/browser/view_ids.h4
-rw-r--r--chrome/browser/views/frame/browser_view.cc49
-rw-r--r--chrome/browser/views/frame/browser_view.h29
-rw-r--r--chrome/browser/views/frame/browser_view_layout.cc56
-rw-r--r--chrome/browser/views/frame/browser_view_layout.h5
-rw-r--r--chrome/browser/views/frame/opaque_browser_frame_view.cc27
-rw-r--r--chrome/browser/views/tabs/dragged_tab_controller.cc3
-rw-r--r--chrome/browser/views/tabs/tab_strip.cc10
-rw-r--r--chrome/browser/views/tabs/tab_strip.h13
-rw-r--r--chrome/browser/views/toolbar_view.cc3
18 files changed, 268 insertions, 52 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 714268c..0ee8753 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -165,7 +165,8 @@ Browser::Browser(Type type, Profile* profile)
block_command_execution_(false),
last_blocked_command_id_(-1),
last_blocked_command_disposition_(CURRENT_TAB),
- pending_web_app_action_(NONE) {
+ pending_web_app_action_(NONE),
+ extension_app_(NULL) {
tabstrip_model_.AddObserver(this);
registrar_.Add(this, NotificationType::SSL_VISIBLE_STATE_CHANGED,
@@ -255,10 +256,19 @@ Browser* Browser::CreateForPopup(Profile* profile) {
// static
Browser* Browser::CreateForApp(const std::wstring& app_name,
+ Extension* extension,
Profile* profile,
bool is_panel) {
- Browser* browser = new Browser(is_panel ? TYPE_APP_PANEL : TYPE_APP, profile);
+ Browser::Type type = TYPE_APP;
+
+ if (is_panel)
+ type = TYPE_APP_PANEL;
+ else if (extension)
+ type = TYPE_EXTENSION_APP;
+
+ Browser* browser = new Browser(type, profile);
browser->app_name_ = app_name;
+ browser->extension_app_ = extension;
browser->CreateBrowserWindow();
return browser;
}
@@ -410,13 +420,15 @@ bool Browser::OpenApplication(Profile* profile, const std::string& app_id) {
}
// static
-void Browser::OpenApplicationWindow(Profile* profile, const GURL& url,
- bool as_panel) {
+void Browser::OpenApplicationWindow(Profile* profile, Extension* extension,
+ const GURL& url, bool as_panel) {
std::wstring app_name = web_app::GenerateApplicationNameFromURL(url);
RegisterAppPrefs(app_name);
- Browser* browser = Browser::CreateForApp(app_name, profile, as_panel);
- browser->AddTabWithURL(url, GURL(), PageTransition::START_PAGE, true, -1,
+ Browser* browser = Browser::CreateForApp(app_name, extension, profile,
+ as_panel);
+ browser->AddTabWithURL(extension ? extension->GetFullLaunchURL() : url,
+ GURL(), PageTransition::START_PAGE, true, -1,
false, NULL);
TabContents* tab_contents = browser->GetSelectedTabContents();
@@ -440,8 +452,7 @@ void Browser::OpenApplicationWindow(Profile* profile, const GURL& url,
// static
void Browser::OpenApplicationWindow(Profile* profile, Extension* extension) {
- OpenApplicationWindow(profile,
- extension->GetFullLaunchURL(),
+ OpenApplicationWindow(profile, extension, GURL(),
(extension->launch_container() == Extension::LAUNCH_PANEL));
}
@@ -720,7 +731,7 @@ TabContents* Browser::AddTabWithURL(const GURL& url,
SiteInstance* instance,
const std::string& app_extension_id) {
TabContents* contents = NULL;
- if (type_ == TYPE_NORMAL || tabstrip_model()->empty()) {
+ if (SupportsWindowFeature(FEATURE_TABSTRIP) || tabstrip_model()->empty()) {
GURL url_to_load = url;
if (url_to_load.is_empty())
url_to_load = GetHomePage();
@@ -1262,11 +1273,18 @@ bool Browser::SupportsWindowFeature(WindowFeature feature) const {
hide_ui_for_fullscreen = window_ && window_->IsFullscreen();
#endif
if (!hide_ui_for_fullscreen) {
- if (type() == TYPE_NORMAL)
- features |= FEATURE_TABSTRIP | FEATURE_TOOLBAR;
- else
+ if (type() != TYPE_NORMAL && type() != TYPE_EXTENSION_APP)
features |= FEATURE_TITLEBAR;
- if ((type() & Browser::TYPE_APP) == 0)
+
+ if (type() == TYPE_NORMAL || type() == TYPE_EXTENSION_APP)
+ features |= FEATURE_TABSTRIP;
+
+ // Note: the toolbar is collapsed for TYPE_EXTENSION_APP but it is still
+ // there.
+ if (type() == TYPE_NORMAL || type() == TYPE_EXTENSION_APP)
+ features |= FEATURE_TOOLBAR;
+
+ if (type() != TYPE_EXTENSION_APP && (type() & Browser::TYPE_APP) == 0)
features |= FEATURE_LOCATIONBAR;
}
return !!(features & feature);
@@ -1904,7 +1922,7 @@ TabContents* Browser::AddBlankTabAt(int index, bool foreground) {
Browser* Browser::CreateNewStripWithContents(TabContents* detached_contents,
const gfx::Rect& window_bounds,
const DockInfo& dock_info) {
- DCHECK(type_ == TYPE_NORMAL);
+ DCHECK(SupportsWindowFeature(FEATURE_TABSTRIP));
gfx::Rect new_window_bounds = window_bounds;
bool maximize = false;
@@ -1979,7 +1997,8 @@ void Browser::DuplicateContentsAt(int index) {
if (type_ & TYPE_APP) {
DCHECK((type_ & TYPE_POPUP) == 0);
DCHECK(type_ != TYPE_APP_PANEL);
- browser = Browser::CreateForApp(app_name_, profile_, false);
+ browser = Browser::CreateForApp(app_name_, extension_app_, profile_,
+ false);
} else if (type_ == TYPE_POPUP) {
browser = Browser::CreateForPopup(profile_);
}
@@ -2243,9 +2262,9 @@ void Browser::AddNewContents(TabContents* source,
DCHECK(disposition != CURRENT_TAB); // Can't create a new contents for the
// current tab.
- // If this is an application we can only have one tab so we need to process
- // this in tabbed browser window.
- if (type_ != TYPE_NORMAL && tabstrip_model_.count() > 0 &&
+ // If this is a window with no tabstrip, we can only have one tab so we need
+ // to process this in tabbed browser window.
+ if (!SupportsWindowFeature(FEATURE_TABSTRIP) && tabstrip_model_.count() > 0 &&
disposition != NEW_WINDOW && disposition != NEW_POPUP) {
Browser* b = GetOrCreateTabbedBrowser(profile_);
DCHECK(b);
@@ -2428,7 +2447,7 @@ void Browser::ConvertContentsToApplication(TabContents* contents) {
RegisterAppPrefs(app_name);
DetachContents(contents);
- Browser* browser = Browser::CreateForApp(app_name, profile_, false);
+ Browser* browser = Browser::CreateForApp(app_name, NULL, profile_, false);
browser->tabstrip_model()->AppendTabContents(contents, true);
TabContents* tab_contents = browser->GetSelectedTabContents();
tab_contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
@@ -3342,9 +3361,9 @@ void Browser::OpenURLAtIndex(TabContents* source,
}
}
- // If this is not a normal window (such as a popup or an application), we can
- // only have one tab so a new tab always goes into a tabbed browser window.
- if (type_ != TYPE_NORMAL &&
+ // If this browser doeesn't support tabs, we can only have one tab so a new
+ // tab always goes into a tabbed browser window.
+ if (!SupportsWindowFeature(FEATURE_TABSTRIP) &&
disposition != CURRENT_TAB && disposition != NEW_WINDOW) {
// If the disposition is OFF_THE_RECORD we don't want to create a new
// browser that will itself create another OTR browser. This will result in
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index c293e97f..8c28147 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -55,13 +55,21 @@ class Browser : public TabStripModelDelegate,
enum Type {
TYPE_NORMAL = 1,
TYPE_POPUP = 2,
+ // The old-style app created via "Create application shortcuts".
TYPE_APP = 4,
+ // The new-style app created by installing a crx. This kinda needs to be
+ // separate because we require larger icons and an application name that
+ // are found in the crx. If we ever decide to create this kind of app using
+ // some other system (eg some web standard), maybe we should generalize this
+ // name to TYPE_MULTITAB or something.
+ TYPE_EXTENSION_APP = 8,
TYPE_APP_POPUP = TYPE_APP | TYPE_POPUP,
- TYPE_DEVTOOLS = TYPE_APP | 8,
- TYPE_APP_PANEL = TYPE_APP | 16,
+ TYPE_DEVTOOLS = TYPE_APP | 16,
+ TYPE_APP_PANEL = TYPE_APP | 32,
TYPE_ANY = TYPE_NORMAL |
TYPE_POPUP |
TYPE_APP |
+ TYPE_EXTENSION_APP |
TYPE_DEVTOOLS |
TYPE_APP_PANEL
};
@@ -118,16 +126,22 @@ class Browser : public TabStripModelDelegate,
// Like Create, but creates a tabstrip-less popup window.
static Browser* CreateForPopup(Profile* profile);
- // Like Create, but creates a tabstrip-less and toolbar-less "app" window for
- // the specified app. |is_panel| specifies whether the browser should be
- // opened in an app panel window.
- static Browser* CreateForApp(const std::wstring& app_name, Profile* profile,
+ // Like Create, but creates a toolbar-less "app" window for the specified
+ // app. |app_name| is required and is used to identify the window to the
+ // shell. |extension| is optional. If supplied, we create a window with
+ // a bigger icon and title text, that supports tabs.
+ static Browser* CreateForApp(const std::wstring& app_name,
+ Extension* extension,
+ Profile* profile,
bool is_panel);
// Like Create, but creates a tabstrip-less and toolbar-less
// DevTools "app" window.
static Browser* CreateForDevTools(Profile* profile);
+ // Returns the extension app associated with this window, if any.
+ Extension* extension_app() { return extension_app_; }
+
// Set overrides for the initial window bounds and maximized state.
void set_override_bounds(const gfx::Rect& bounds) {
override_bounds_ = bounds;
@@ -200,10 +214,11 @@ class Browser : public TabStripModelDelegate,
// Opens a new application window for the specified url. If |as_panel|
// is true, the application will be opened as a Browser::Type::APP_PANEL in
- // app panel window, otherwise it will be opened as a Browser::Type::APP,
- // a.k.a. "thin frame".
- static void OpenApplicationWindow(Profile* profile, const GURL& url,
- bool as_panel);
+ // app panel window, otherwise it will be opened as as either
+ // Browser::Type::APP a.k.a. "thin frame" (if |extension| is NULL) or
+ // Browser::Type::EXTENSION_APP (if |extension| is non-NULL).
+ static void OpenApplicationWindow(Profile* profile, Extension* extension,
+ const GURL& url, bool as_panel);
// Open an application for |extension| in a new application window or panel.
static void OpenApplicationWindow(Profile* profile, Extension* extension);
@@ -946,6 +961,9 @@ class Browser : public TabStripModelDelegate,
// from a TabContents. Currently, only one pending action is allowed.
WebAppAction pending_web_app_action_;
+ // The extension app associated with this window, if any.
+ Extension* extension_app_;
+
DISALLOW_COPY_AND_ASSIGN(Browser);
};
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc
index db5d173..a5e1706 100644
--- a/chrome/browser/browser_init.cc
+++ b/chrome/browser/browser_init.cc
@@ -595,7 +595,7 @@ bool BrowserInit::LaunchWithProfile::OpenApplicationWindow(Profile* profile) {
ChildProcessSecurityPolicy::GetInstance();
if (policy->IsWebSafeScheme(url.scheme()) ||
url.SchemeIs(chrome::kFileScheme)) {
- Browser::OpenApplicationWindow(profile, url, false);
+ Browser::OpenApplicationWindow(profile, NULL, url, false);
return true;
}
}
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index 1ac66b7..46e0e89 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -1096,7 +1096,7 @@ static bool GetTabById(int tab_id, Profile* profile,
static std::string GetWindowTypeText(Browser::Type type) {
// Note: for app popups, we report "app".
- if ((type & Browser::TYPE_APP) != 0)
+ if ((type & Browser::TYPE_APP) != 0 || type == Browser::TYPE_EXTENSION_APP)
return keys::kWindowTypeValueApp;
if ((type & Browser::TYPE_POPUP) != 0)
return keys::kWindowTypeValuePopup;
diff --git a/chrome/browser/resources/calendar_app/manifest.json b/chrome/browser/resources/calendar_app/manifest.json
index 4cf0e5b..f04088b 100644
--- a/chrome/browser/resources/calendar_app/manifest.json
+++ b/chrome/browser/resources/calendar_app/manifest.json
@@ -15,7 +15,7 @@
"paths": [ "calendar" ]
},
"launch": {
- "type": "tab",
+ "container": "tab",
"web_url": "https://www.google.com/calendar/"
}
}
diff --git a/chrome/browser/resources/docs_app/manifest.json b/chrome/browser/resources/docs_app/manifest.json
index f4893b5..edb3cc71 100644
--- a/chrome/browser/resources/docs_app/manifest.json
+++ b/chrome/browser/resources/docs_app/manifest.json
@@ -13,7 +13,7 @@
"origin": "https://docs.google.com/"
},
"launch": {
- "type": "tab",
+ "container": "window",
"web_url": "https://docs.google.com/"
}
}
diff --git a/chrome/browser/resources/gmail_app/manifest.json b/chrome/browser/resources/gmail_app/manifest.json
index ec75488..69897d8 100644
--- a/chrome/browser/resources/gmail_app/manifest.json
+++ b/chrome/browser/resources/gmail_app/manifest.json
@@ -15,7 +15,7 @@
"paths": [ "mail" ]
},
"launch": {
- "type": "tab",
+ "container": "window",
"web_url": "https://mail.google.com/"
}
}
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 9ac90a9..1908aa3 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -2949,6 +2949,16 @@ void TabContents::Observe(NotificationType type,
void TabContents::UpdateAppExtensionIcon(Extension* extension) {
app_extension_icon_.reset();
+
+ // We don't show the big icons in tabs for TYPE_EXTENSION_APP windows because
+ // for those windows, we already have a big icon in the top-left outside any
+ // tab. Having big tab icons too looks kinda redonk.
+ if (!delegate_ ||
+ !delegate_->GetBrowser() ||
+ delegate_->GetBrowser()->type() == Browser::TYPE_EXTENSION_APP) {
+ return;
+ }
+
if (extension) {
app_extension_image_loader_.reset(new ImageLoadingTracker(this));
app_extension_image_loader_->LoadImage(
diff --git a/chrome/browser/view_ids.h b/chrome/browser/view_ids.h
index 57943da..74fb526 100644
--- a/chrome/browser/view_ids.h
+++ b/chrome/browser/view_ids.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2010 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.
@@ -27,6 +27,8 @@ enum ViewID {
VIEW_ID_TAB_9,
VIEW_ID_TAB_LAST,
+ VIEW_ID_EXTENSION_APP_ICON,
+ VIEW_ID_EXTENSION_APP_TITLE,
VIEW_ID_TAB_STRIP,
// Toolbar & toolbar elements.
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 614659e..eb9620d 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -98,6 +98,10 @@ static int explicit_show_state = -1;
// How round the 'new tab' style bookmarks bar is.
static const int kNewtabBarRoundness = 5;
+
+// The maximum width of the big title shown for extension app windows.
+static const int kExtensionAppTitleMaxWidth = 150;
+
// ------------
// Returned from BrowserView::GetClassName.
@@ -384,6 +388,8 @@ BrowserView::BrowserView(Browser* browser)
frame_(NULL),
browser_(browser),
active_bookmark_bar_(NULL),
+ extension_app_icon_(NULL),
+ extension_app_title_(NULL),
tabstrip_(NULL),
toolbar_(NULL),
infobar_container_(NULL),
@@ -398,7 +404,8 @@ BrowserView::BrowserView(Browser* browser)
#endif
extension_shelf_(NULL),
last_focused_view_storage_id_(
- views::ViewStorage::GetSharedInstance()->CreateStorageID()) {
+ views::ViewStorage::GetSharedInstance()->CreateStorageID()),
+ extension_app_icon_loader_(this) {
browser_->tabstrip_model()->AddObserver(this);
}
@@ -1639,8 +1646,42 @@ void BrowserView::Init() {
LoadAccelerators();
SetAccessibleName(l10n_util::GetString(IDS_PRODUCT_NAME));
+ if (browser_->extension_app()) {
+ extension_app_icon_ = new views::ImageView();
+ extension_app_icon_->SetID(VIEW_ID_EXTENSION_APP_ICON);
+ AddChildView(extension_app_icon_);
+
+ extension_app_title_ = new views::Label();
+ extension_app_title_->SetFont(
+ extension_app_title_->font().DeriveFont(1, gfx::Font::BOLD));
+ extension_app_title_->SetColor(SK_ColorWHITE);
+ extension_app_title_->SetID(VIEW_ID_EXTENSION_APP_TITLE);
+ AddChildView(extension_app_title_);
+
+ extension_app_icon_loader_.LoadImage(
+ browser_->extension_app(),
+ browser_->extension_app()->GetIconPath(
+ Extension::EXTENSION_ICON_MEDIUM),
+ gfx::Size(Extension::EXTENSION_ICON_SMALL,
+ Extension::EXTENSION_ICON_SMALL),
+ ImageLoadingTracker::CACHE);
+
+ extension_app_title_->SetText(
+ UTF8ToWide(browser_->extension_app()->name()));
+ extension_app_title_->SizeToPreferredSize();
+
+ if (extension_app_title_->width() > kExtensionAppTitleMaxWidth) {
+ extension_app_title_->SetBounds(extension_app_title_->x(),
+ extension_app_title_->y(),
+ kExtensionAppTitleMaxWidth,
+ extension_app_title_->height());
+ }
+ }
+
tabstrip_ = CreateTabStrip(browser_->tabstrip_model());
tabstrip_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_TABSTRIP));
+ if (browser_->extension_app() && tabstrip_->AsTabStrip())
+ tabstrip_->AsTabStrip()->set_new_tab_button_enabled(false);
AddChildView(tabstrip_);
frame_->TabStripCreated(tabstrip_);
@@ -1719,6 +1760,12 @@ void BrowserView::InitSystemMenu() {
}
#endif
+void BrowserView::OnImageLoaded(SkBitmap* image, ExtensionResource resource,
+ int index) {
+ if (image)
+ extension_app_icon_->SetImage(*image);
+}
+
BrowserViewLayout* BrowserView::GetBrowserViewLayout() const {
return static_cast<BrowserViewLayout*>(GetLayoutManager());
}
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index 79f9858..10292bf 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -15,6 +15,7 @@
#include "build/build_config.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
+#include "chrome/browser/extensions/image_loading_tracker.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/views/frame/browser_bubble_host.h"
#include "chrome/browser/views/frame/browser_frame.h"
@@ -23,6 +24,8 @@
#include "chrome/browser/views/tabs/base_tab_strip.h"
#include "chrome/browser/views/unhandled_keyboard_event_handler.h"
#include "gfx/native_widget_types.h"
+#include "views/controls/image_view.h"
+#include "views/controls/label.h"
#include "views/window/client_view.h"
#include "views/window/window_delegate.h"
@@ -81,7 +84,8 @@ class BrowserView : public BrowserBubbleHost,
public menus::SimpleMenuModel::Delegate,
public views::WindowDelegate,
public views::ClientView,
- public InfoBarContainer::Delegate {
+ public InfoBarContainer::Delegate,
+ public ImageLoadingTracker::Observer {
public:
// The browser view's class name.
static const char kViewClassName[];
@@ -145,6 +149,14 @@ class BrowserView : public BrowserBubbleHost,
// offset of IDR_THEME_TOOLBAR.
gfx::Rect GetTabStripBounds() const;
+ // Accessor for the big icon used with TYPE_EXTENSION_APP, or NULL if this
+ // browser isn't TYPE_EXTENSION_APP.
+ views::ImageView* extension_app_icon() const { return extension_app_icon_; }
+
+ // Accessor for the big title used with TYPE_EXTENSION_APP, or NULL if this
+ // browser isn't TYPE_EXTENSION_APP.
+ views::Label* extension_app_title() const { return extension_app_title_; }
+
// Accessor for the TabStrip.
BaseTabStrip* tabstrip() const { return tabstrip_; }
@@ -241,6 +253,10 @@ class BrowserView : public BrowserBubbleHost,
BrowserExtender* browser_extender() const { return browser_extender_.get(); }
+ // Overriden from ImageLoadingTracker::Observer.
+ virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
+ int index);
+
// Overridden from BrowserWindow:
virtual void Show();
virtual void SetBounds(const gfx::Rect& bounds);
@@ -486,6 +502,14 @@ class BrowserView : public BrowserBubbleHost,
// or is bookmark_bar_view_ if the bookmark bar is showing.
views::View* active_bookmark_bar_;
+ // The big icon in the top-left if this browser is TYPE_EXTENSION_APP, or
+ // NULL otherwise.
+ views::ImageView* extension_app_icon_;
+
+ // The big title text in the top-left if this browser is TYPE_EXTENSION_APP,
+ // or NULL otherwise.
+ views::Label* extension_app_title_;
+
// The TabStrip.
BaseTabStrip* tabstrip_;
@@ -576,6 +600,9 @@ class BrowserView : public BrowserBubbleHost,
scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_;
#endif
+ // Loads extension_app_icon_ asynchronously on the file thread.
+ ImageLoadingTracker extension_app_icon_loader_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserView);
};
diff --git a/chrome/browser/views/frame/browser_view_layout.cc b/chrome/browser/views/frame/browser_view_layout.cc
index 2b0f2e0..505a913 100644
--- a/chrome/browser/views/frame/browser_view_layout.cc
+++ b/chrome/browser/views/frame/browser_view_layout.cc
@@ -36,6 +36,11 @@ const int kBrowserViewTabStripHorizontalOverlap = 4;
// An offset distance between certain toolbars and the toolbar that preceded
// them in layout.
const int kSeparationLineHeight = 1;
+// Spacing between extension app icon and title.
+const int kExtensionAppIconTitleSpacing = 4;
+// We don't actually display the toolbar in extension app mode, but this is the
+// height of the spacing where it usually goes.
+const int kExtensionAppToolbarHeight = 7;
} // namespace
@@ -43,7 +48,9 @@ const int kSeparationLineHeight = 1;
// BrowserViewLayout, public:
BrowserViewLayout::BrowserViewLayout()
- : tabstrip_(NULL),
+ : extension_app_icon_(NULL),
+ extension_app_title_(NULL),
+ tabstrip_(NULL),
toolbar_(NULL),
contents_split_(NULL),
contents_container_(NULL),
@@ -206,6 +213,8 @@ void BrowserViewLayout::Installed(views::View* host) {
extension_shelf_ = NULL;
active_bookmark_bar_ = NULL;
tabstrip_ = NULL;
+ extension_app_icon_ = NULL;
+ extension_app_title_ = NULL;
browser_view_ = static_cast<BrowserView*>(host);
}
@@ -235,6 +244,12 @@ void BrowserViewLayout::ViewAdded(views::View* host, views::View* view) {
case VIEW_ID_TAB_STRIP:
tabstrip_ = static_cast<BaseTabStrip*>(view);
break;
+ case VIEW_ID_EXTENSION_APP_ICON:
+ extension_app_icon_ = static_cast<views::ImageView*>(view);
+ break;
+ case VIEW_ID_EXTENSION_APP_TITLE:
+ extension_app_title_ = static_cast<views::Label*>(view);
+ break;
}
}
@@ -248,6 +263,7 @@ void BrowserViewLayout::ViewRemoved(views::View* host, views::View* view) {
void BrowserViewLayout::Layout(views::View* host) {
vertical_layout_rect_ = browser_view_->GetLocalBounds(true);
+ LayoutExtensionAppIconAndTitle();
int top = LayoutTabStrip();
top = LayoutToolbar(top);
top = LayoutBookmarkAndInfoBars(top);
@@ -276,6 +292,26 @@ gfx::Size BrowserViewLayout::GetPreferredSize(views::View* host) {
//////////////////////////////////////////////////////////////////////////////
// BrowserViewLayout, private:
+void BrowserViewLayout::LayoutExtensionAppIconAndTitle() {
+ if (browser_view_->browser()->type() != Browser::TYPE_EXTENSION_APP)
+ return;
+
+ extension_app_icon_->SetVisible(true);
+ extension_app_icon_->SetBounds(0, 0, Extension::EXTENSION_ICON_SMALL,
+ Extension::EXTENSION_ICON_SMALL);
+
+ extension_app_title_->SetVisible(true);
+
+ // Position the title vertically centered with the icon and slightly to its
+ // right.
+ extension_app_title_->SetX(
+ extension_app_icon_->x() + extension_app_icon_->width() +
+ kExtensionAppIconTitleSpacing);
+ extension_app_title_->SetY(
+ extension_app_icon_->y() +
+ ((extension_app_icon_->height() - extension_app_title_->height()) / 2));
+}
+
int BrowserViewLayout::LayoutTabStrip() {
if (!browser_view_->IsTabStripVisible()) {
tabstrip_->SetVisible(false);
@@ -314,8 +350,22 @@ int BrowserViewLayout::LayoutToolbar(int top) {
((visible && browser_view_->IsTabStripVisible())
? kToolbarTabStripVerticalOverlap : 0);
}
- int height = visible ? toolbar_->GetPreferredSize().height() : 0;
- toolbar_->SetVisible(visible);
+ int height = 0;
+ if (visible) {
+ if (browser_view_->browser()->type() == Browser::TYPE_EXTENSION_APP) {
+ // TODO(aa): Find a more sensible way to handle this. We want
+ // OpaqueBroserFrame to continue to paint the area where the toolstrip
+ // would be, but we don't actually want a toolbar in this case.
+ toolbar_->SetVisible(false);
+ height = kExtensionAppToolbarHeight;
+ } else {
+ toolbar_->SetVisible(true);
+ height = toolbar_->GetPreferredSize().height();
+ }
+ } else {
+ toolbar_->SetVisible(false);
+ }
+
toolbar_->SetBounds(vertical_layout_rect_.x(), y, browser_view_width, height);
return y + height;
}
diff --git a/chrome/browser/views/frame/browser_view_layout.h b/chrome/browser/views/frame/browser_view_layout.h
index 068d8302..6dc3624 100644
--- a/chrome/browser/views/frame/browser_view_layout.h
+++ b/chrome/browser/views/frame/browser_view_layout.h
@@ -47,6 +47,9 @@ class BrowserViewLayout : public views::LayoutManager {
// for laying out subsequent controls.
virtual int LayoutTabStrip();
+ // Layout the big icon and title in the top left of extension app windows.
+ void LayoutExtensionAppIconAndTitle();
+
// Layout the following controls, starting at |top|, returns the coordinate
// of the bottom of the control, for laying out the next control.
int LayoutToolbar(int top);
@@ -68,6 +71,8 @@ class BrowserViewLayout : public views::LayoutManager {
int LayoutExtensionShelf(int bottom);
// Child views that the layout manager manages.
+ views::ImageView* extension_app_icon_;
+ views::Label* extension_app_title_;
BaseTabStrip* tabstrip_;
ToolbarView* toolbar_;
views::View* contents_split_;
diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.cc b/chrome/browser/views/frame/opaque_browser_frame_view.cc
index c91cb51..af74018 100644
--- a/chrome/browser/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/views/frame/opaque_browser_frame_view.cc
@@ -95,6 +95,8 @@ const int kNewTabCaptionMaximizedSpacing = 16;
// How far to indent the tabstrip from the left side of the screen when there
// is no OTR icon.
const int kTabStripIndent = 1;
+// Spacing between extension app icon/title and tab strip.
+const int kExtensionAppTabStripLeftSpacing = 10;
}
///////////////////////////////////////////////////////////////////////////////
@@ -195,10 +197,27 @@ gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip(
int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ?
(otr_avatar_icon_->bounds().right() + kOTRSideSpacing) :
NonClientBorderThickness() + kTabStripIndent;
+
+ int tabstrip_y = NonClientTopBorderHeight();
+ if (!frame_->GetWindow()->IsMaximized() &&
+ !frame_->GetWindow()->IsFullscreen()) {
+ tabstrip_y += kNonClientRestoredExtraThickness;
+ }
+
int tabstrip_width = minimize_button_->x() - tabstrip_x -
(frame_->GetWindow()->IsMaximized() ?
kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing);
- return gfx::Rect(tabstrip_x, NonClientTopBorderHeight(),
+
+ if (browser_view_->browser()->type() == Browser::TYPE_EXTENSION_APP) {
+ int tabstrip_offset = browser_view_->extension_app_title()->x() +
+ browser_view_->extension_app_title()->width() +
+ kExtensionAppTabStripLeftSpacing;
+
+ tabstrip_x += tabstrip_offset;
+ tabstrip_width -= tabstrip_offset;
+ }
+
+ return gfx::Rect(tabstrip_x, tabstrip_y,
std::max(0, tabstrip_width),
tabstrip->GetPreferredHeight());
}
@@ -431,9 +450,7 @@ int OpaqueBrowserFrameView::NonClientTopBorderHeight() const {
if (browser_view_->IsTabStripVisible() && window->IsMaximized())
return FrameBorderThickness() - kTabstripTopShadowThickness;
- return FrameBorderThickness() +
- ((window->IsMaximized() || window->IsFullscreen()) ?
- 0 : kNonClientRestoredExtraThickness);
+ return FrameBorderThickness();
}
int OpaqueBrowserFrameView::CaptionButtonY() const {
@@ -815,7 +832,7 @@ void OpaqueBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) {
client_area_top += browser_view_->GetToolbarBounds().y() +
std::min(tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER)->height(),
toolbar_bounds.height());
- } else {
+ } else if (!browser_view_->IsTabStripVisible()) {
// The toolbar isn't going to draw a client edge for us, so draw one
// ourselves.
SkBitmap* top_left = tp->GetBitmapNamed(IDR_APP_TOP_LEFT);
diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc
index 3521a88..262154f 100644
--- a/chrome/browser/views/tabs/dragged_tab_controller.cc
+++ b/chrome/browser/views/tabs/dragged_tab_controller.cc
@@ -716,7 +716,8 @@ TabStrip* DraggedTabController::GetTabStripForPoint(
BrowserView* browser =
BrowserView::GetBrowserViewForNativeWindow(local_window);
// We don't allow drops on windows that don't have tabstrips.
- if (!browser || !browser->IsBrowserTypeNormal())
+ if (!browser ||
+ !browser->browser()->SupportsWindowFeature(Browser::FEATURE_TABSTRIP))
return NULL;
TabStrip* other_tabstrip = browser->tabstrip()->AsTabStrip();
diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc
index e9ccb09..26011b4 100644
--- a/chrome/browser/views/tabs/tab_strip.cc
+++ b/chrome/browser/views/tabs/tab_strip.cc
@@ -248,7 +248,8 @@ TabStrip::TabStrip(TabStripModel* model)
available_width_for_tabs_(-1),
animation_container_(new AnimationContainer()),
ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)),
- animation_type_(ANIMATION_DEFAULT) {
+ animation_type_(ANIMATION_DEFAULT),
+ new_tab_button_enabled_(true) {
Init();
}
@@ -521,7 +522,12 @@ void TabStrip::Layout() {
for (int i = 0, tab_count = GetTabCount(); i < tab_count; ++i)
tab_data_[i].tab->SetBounds(tab_data_[i].ideal_bounds);
- newtab_button_->SetBounds(newtab_button_bounds_);
+ if (new_tab_button_enabled_) {
+ newtab_button_->SetBounds(newtab_button_bounds_);
+ newtab_button_->SetVisible(true);
+ } else {
+ newtab_button_->SetVisible(false);
+ }
SchedulePaint();
}
diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h
index 57724ce..79a3af3 100644
--- a/chrome/browser/views/tabs/tab_strip.h
+++ b/chrome/browser/views/tabs/tab_strip.h
@@ -61,6 +61,16 @@ class TabStrip : public BaseTabStrip,
// Accessors for the model and individual Tabs.
TabStripModel* model() const { return model_; }
+ // Set whether the new tab button is enabled.
+ void set_new_tab_button_enabled(bool enabled) {
+ new_tab_button_enabled_ = enabled;
+ }
+
+ // Returns whether the new tab button is enabled.
+ bool new_tab_button_enabled() {
+ return new_tab_button_enabled_;
+ }
+
// Destroys the active drag controller.
void DestroyDragController();
@@ -458,6 +468,9 @@ class TabStrip : public BaseTabStrip,
// Set for special animations.
AnimationType animation_type_;
+ // Whether the new tab button is being displayed.
+ bool new_tab_button_enabled_;
+
DISALLOW_COPY_AND_ASSIGN(TabStrip);
};
diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc
index 43d4430..3b2ce98 100644
--- a/chrome/browser/views/toolbar_view.cc
+++ b/chrome/browser/views/toolbar_view.cc
@@ -75,7 +75,8 @@ ToolbarView::ToolbarView(Browser* browser)
browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this);
browser_->command_updater()->AddCommandObserver(IDC_HOME, this);
browser_->command_updater()->AddCommandObserver(IDC_RELOAD, this);
- if (browser->type() == Browser::TYPE_NORMAL)
+
+ if (browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP))
display_mode_ = DISPLAYMODE_NORMAL;
else
display_mode_ = DISPLAYMODE_LOCATION;