| Index: chrome/browser/ui/views/frame/browser_view.cc
 | 
| diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
 | 
| index 9823d93ee2fb1ab78bd643f04c977fb4b1747170..634a4aa846ba38f670145748df81f19703fb58e6 100644
 | 
| --- a/chrome/browser/ui/views/frame/browser_view.cc
 | 
| +++ b/chrome/browser/ui/views/frame/browser_view.cc
 | 
| @@ -135,10 +135,13 @@
 | 
|  #include "ui/gfx/screen.h"
 | 
|  #include "ui/strings/grit/ui_strings.h"
 | 
|  #include "ui/views/controls/button/menu_button.h"
 | 
| +#include "ui/views/controls/single_split_view.h"
 | 
| +#include "ui/views/controls/single_split_view_listener.h"
 | 
|  #include "ui/views/controls/textfield/textfield.h"
 | 
|  #include "ui/views/controls/webview/webview.h"
 | 
|  #include "ui/views/focus/external_focus_tracker.h"
 | 
|  #include "ui/views/focus/view_storage.h"
 | 
| +#include "ui/views/layout/box_layout.h"
 | 
|  #include "ui/views/layout/grid_layout.h"
 | 
|  #include "ui/views/widget/native_widget.h"
 | 
|  #include "ui/views/widget/root_view.h"
 | 
| @@ -568,6 +571,14 @@ void BrowserView::InitStatusBubble() {
 | 
|    contents_web_view_->SetStatusBubble(status_bubble_.get());
 | 
|  }
 | 
|  
 | 
| +bool BrowserView::SplitHandleMoved(views::SingleSplitView* sender) {
 | 
| +  for (int i = 0; i < sender->child_count(); ++i)
 | 
| +    sender->child_at(i)->InvalidateLayout();
 | 
| +  SchedulePaint();
 | 
| +  Layout();
 | 
| +  return false;
 | 
| +}
 | 
| +
 | 
|  gfx::Rect BrowserView::GetToolbarBounds() const {
 | 
|    gfx::Rect toolbar_bounds(toolbar_->bounds());
 | 
|    if (toolbar_bounds.IsEmpty())
 | 
| @@ -682,6 +693,14 @@ gfx::ImageSkia BrowserView::GetOTRAvatarIcon() const {
 | 
|    return *GetThemeProvider()->GetImageSkiaNamed(IDR_OTR_ICON);
 | 
|  }
 | 
|  
 | 
| +void BrowserView::ShowSidebar(content::WebContents* sidebar_contents) {
 | 
| +  UpdateSidebarForContents(sidebar_contents);
 | 
| +}
 | 
| +
 | 
| +void BrowserView::HideSidebar() {
 | 
| +  UpdateSidebarForContents(nullptr);
 | 
| +}
 | 
| +
 | 
|  ///////////////////////////////////////////////////////////////////////////////
 | 
|  // BrowserView, BrowserWindow implementation:
 | 
|  
 | 
| @@ -1339,6 +1358,12 @@ void BrowserView::ShowOneClickSigninBubble(
 | 
|  }
 | 
|  #endif
 | 
|  
 | 
| +int BrowserView::GetSidebarWidth() const {
 | 
| +  if (!sidebar_container_ || !sidebar_container_->visible())
 | 
| +    return 0;
 | 
| +  return sidebar_split_->divider_offset();
 | 
| +}
 | 
| +
 | 
|  void BrowserView::SetDownloadShelfVisible(bool visible) {
 | 
|    // This can be called from the superclass destructor, when it destroys our
 | 
|    // child views. At that point, browser_ is already gone.
 | 
| @@ -1600,6 +1625,7 @@ void BrowserView::TabDetachedAt(WebContents* contents, int index) {
 | 
|      contents_web_view_->SetWebContents(nullptr);
 | 
|      infobar_container_->ChangeInfoBarManager(nullptr);
 | 
|      UpdateDevToolsForContents(nullptr, true);
 | 
| +    UpdateSidebarForContents(nullptr);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -2077,8 +2103,27 @@ void BrowserView::InitViews() {
 | 
|    contents_container_->AddChildView(contents_web_view_);
 | 
|    contents_container_->SetLayoutManager(new ContentsLayoutManager(
 | 
|        devtools_web_view_, contents_web_view_));
 | 
| -  AddChildView(contents_container_);
 | 
| -  set_contents_view(contents_container_);
 | 
| +
 | 
| +  sidebar_web_view_ = new views::WebView(browser_->profile());
 | 
| +  sidebar_web_view_->set_id(VIEW_ID_SIDE_BAR_VIEW);
 | 
| +  sidebar_web_view_->SetVisible(false);
 | 
| +
 | 
| +  sidebar_container_ = new views::View();
 | 
| +  sidebar_container_->AddChildView(sidebar_web_view_);
 | 
| +  sidebar_container_->set_id(VIEW_ID_SIDE_BAR_CONTAINER);
 | 
| +  sidebar_container_->SetVisible(false);
 | 
| +
 | 
| +  sidebar_split_ = new views::SingleSplitView(
 | 
| +      contents_container_, sidebar_container_,
 | 
| +      views::SingleSplitView::HORIZONTAL_SPLIT, this);
 | 
| +
 | 
| +  sidebar_split_->set_id(VIEW_ID_SIDE_BAR_SPLIT);
 | 
| +  sidebar_split_->set_background(views::Background::CreateSolidBackground(
 | 
| +      GetWidget()->GetThemeProvider()->GetColor(
 | 
| +          ThemeProperties::COLOR_TOOLBAR)));
 | 
| +  sidebar_split_->set_resize_leading_on_bounds_change(false);
 | 
| +  AddChildView(sidebar_split_);
 | 
| +  set_contents_view(sidebar_split_);
 | 
|  
 | 
|    // Top container holds tab strip and toolbar and lives at the front of the
 | 
|    // view hierarchy.
 | 
| @@ -2107,16 +2152,10 @@ void BrowserView::InitViews() {
 | 
|    immersive_mode_controller_->Init(this);
 | 
|  
 | 
|    BrowserViewLayout* browser_view_layout = new BrowserViewLayout;
 | 
| -  browser_view_layout->Init(new BrowserViewLayoutDelegateImpl(this),
 | 
| -                            browser(),
 | 
| -                            this,
 | 
| -                            top_container_,
 | 
| -                            tabstrip_,
 | 
| -                            toolbar_,
 | 
| -                            infobar_container_,
 | 
| -                            contents_container_,
 | 
| -                            GetContentsLayoutManager(),
 | 
| -                            immersive_mode_controller_.get());
 | 
| +  browser_view_layout->Init(
 | 
| +      new BrowserViewLayoutDelegateImpl(this), browser(), this, top_container_,
 | 
| +      tabstrip_, toolbar_, infobar_container_, sidebar_split_,
 | 
| +      GetContentsLayoutManager(), immersive_mode_controller_.get());
 | 
|    SetLayoutManager(browser_view_layout);
 | 
|  
 | 
|  #if defined(OS_WIN)
 | 
| @@ -2130,6 +2169,50 @@ void BrowserView::InitViews() {
 | 
|    GetLocationBar()->GetOmniboxView()->model()->popup_model()->AddObserver(this);
 | 
|  }
 | 
|  
 | 
| +void BrowserView::UpdateSidebarForContents(
 | 
| +    content::WebContents* sidebar_contents) {
 | 
| +  if (!sidebar_container_)
 | 
| +    return;  // Happens when sidebar is not allowed.
 | 
| +
 | 
| +  bool visible = nullptr != sidebar_contents;
 | 
| +
 | 
| +  bool should_show = visible && !sidebar_container_->visible();
 | 
| +  bool should_hide = !visible && sidebar_container_->visible();
 | 
| +
 | 
| +  sidebar_web_view_->SetWebContents(sidebar_contents);
 | 
| +
 | 
| +  // Update sidebar UI width.
 | 
| +  if (should_show) {
 | 
| +    // Restore split offset.
 | 
| +    int sidebar_width = g_browser_process->local_state()->GetInteger(
 | 
| +        prefs::kExtensionSidebarWidth);
 | 
| +    if (sidebar_width < 0) {
 | 
| +      // By default sidebar width is 1/7th of the current page content width.
 | 
| +      sidebar_width = sidebar_split_->width() / 7;
 | 
| +    }
 | 
| +    int min_sidebar_width = sidebar_split_->GetMinimumSize().width();
 | 
| +    // Not allowed to be wider than 50% of the split-view's frame
 | 
| +    sidebar_width = std::min(sidebar_split_->width() / 2 - min_sidebar_width,
 | 
| +                             std::max(min_sidebar_width, sidebar_width));
 | 
| +    sidebar_split_->set_divider_offset(sidebar_split_->width() - sidebar_width);
 | 
| +
 | 
| +    sidebar_container_->SetVisible(true);
 | 
| +    sidebar_web_view_->SetVisible(true);
 | 
| +    sidebar_split_->InvalidateLayout();
 | 
| +    Layout();
 | 
| +
 | 
| +  } else if (should_hide) {
 | 
| +    // Store split offset when hiding sidebar only.
 | 
| +    g_browser_process->local_state()->SetInteger(
 | 
| +        prefs::kExtensionSidebarWidth,
 | 
| +        sidebar_split_->width() - sidebar_split_->divider_offset());
 | 
| +
 | 
| +    sidebar_container_->SetVisible(false);
 | 
| +    sidebar_split_->InvalidateLayout();
 | 
| +    Layout();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  void BrowserView::LoadingAnimationCallback() {
 | 
|    base::TimeTicks now = base::TimeTicks::Now();
 | 
|    if (!last_animation_time_.is_null()) {
 | 
| 
 |