Home | History | Annotate | Download | only in views
      1 // Copyright (c) 2012 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.
      4 
      5 #include "base/bind.h"
      6 #include "base/bind_helpers.h"
      7 #include "base/files/file_path.h"
      8 #include "base/memory/singleton.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "chrome/browser/profiles/profile.h"
     12 #include "chrome/browser/ui/browser.h"
     13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     14 #include "chrome/browser/ui/webui/chrome_web_contents_handler.h"
     15 #include "chrome/common/url_constants.h"
     16 #include "chrome/test/base/in_process_browser_test.h"
     17 #include "chrome/test/base/ui_test_utils.h"
     18 #include "content/public/browser/browser_context.h"
     19 #include "content/public/browser/render_widget_host_view.h"
     20 #include "content/public/browser/web_contents.h"
     21 #include "testing/gmock/include/gmock/gmock.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 #include "ui/views/controls/webview/web_dialog_view.h"
     24 #include "ui/views/widget/widget.h"
     25 #include "ui/web_dialogs/test/test_web_dialog_delegate.h"
     26 
     27 using content::BrowserContext;
     28 using content::WebContents;
     29 using testing::Eq;
     30 using ui::WebDialogDelegate;
     31 
     32 namespace {
     33 
     34 // Initial size of WebDialog for SizeWindow test case.
     35 const int kInitialWidth = 40;
     36 const int kInitialHeight = 40;
     37 
     38 class TestWebDialogView : public views::WebDialogView {
     39  public:
     40   TestWebDialogView(content::BrowserContext* context,
     41                     WebDialogDelegate* delegate)
     42       : views::WebDialogView(context, delegate, new ChromeWebContentsHandler),
     43         should_quit_on_size_change_(false) {
     44     delegate->GetDialogSize(&last_size_);
     45   }
     46 
     47   void set_should_quit_on_size_change(bool should_quit) {
     48     should_quit_on_size_change_ = should_quit;
     49   }
     50 
     51  private:
     52   // TODO(xiyuan): Update this when WidgetDelegate has bounds change hook.
     53   virtual void SaveWindowPlacement(const gfx::Rect& bounds,
     54                                    ui::WindowShowState show_state) OVERRIDE {
     55     if (should_quit_on_size_change_ && last_size_ != bounds.size()) {
     56       // Schedule message loop quit because we could be called while
     57       // the bounds change call is on the stack and not in the nested message
     58       // loop.
     59       base::MessageLoop::current()->PostTask(
     60           FROM_HERE,
     61           base::Bind(&base::MessageLoop::Quit,
     62                      base::Unretained(base::MessageLoop::current())));
     63     }
     64 
     65     last_size_ = bounds.size();
     66   }
     67 
     68   virtual void OnDialogClosed(const std::string& json_retval) OVERRIDE {
     69     should_quit_on_size_change_ = false;  // No quit when we are closing.
     70     views::WebDialogView::OnDialogClosed(json_retval);
     71   }
     72 
     73   // Whether we should quit message loop when size change is detected.
     74   bool should_quit_on_size_change_;
     75   gfx::Size last_size_;
     76 
     77   DISALLOW_COPY_AND_ASSIGN(TestWebDialogView);
     78 };
     79 
     80 }  // namespace
     81 
     82 class WebDialogBrowserTest : public InProcessBrowserTest {
     83  public:
     84   WebDialogBrowserTest() {}
     85 };
     86 
     87 // Windows has some issues resizing windows. An off by one problem, and a
     88 // minimum size that seems too big. See http://crbug.com/52602.
     89 #if defined(OS_WIN)
     90 #define MAYBE_SizeWindow DISABLED_SizeWindow
     91 #else
     92 #define MAYBE_SizeWindow SizeWindow
     93 #endif
     94 IN_PROC_BROWSER_TEST_F(WebDialogBrowserTest, MAYBE_SizeWindow) {
     95   ui::test::TestWebDialogDelegate delegate(
     96       (GURL(chrome::kChromeUIChromeURLsURL)));
     97   delegate.set_size(kInitialWidth, kInitialHeight);
     98 
     99   TestWebDialogView* view =
    100       new TestWebDialogView(browser()->profile(), &delegate);
    101   WebContents* web_contents =
    102       browser()->tab_strip_model()->GetActiveWebContents();
    103   ASSERT_TRUE(web_contents != NULL);
    104   views::Widget::CreateWindowWithParent(view, web_contents->GetNativeView());
    105   view->GetWidget()->Show();
    106 
    107   // TestWebDialogView should quit current message loop on size change.
    108   view->set_should_quit_on_size_change(true);
    109 
    110   gfx::Rect bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    111 
    112   gfx::Rect set_bounds = bounds;
    113   gfx::Rect actual_bounds, rwhv_bounds;
    114 
    115   // Bigger than the default in both dimensions.
    116   set_bounds.set_width(400);
    117   set_bounds.set_height(300);
    118 
    119   view->MoveContents(web_contents, set_bounds);
    120   content::RunMessageLoop();  // TestWebDialogView will quit.
    121   actual_bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    122   EXPECT_EQ(set_bounds, actual_bounds);
    123 
    124   rwhv_bounds =
    125       view->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
    126   EXPECT_LT(0, rwhv_bounds.width());
    127   EXPECT_LT(0, rwhv_bounds.height());
    128   EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
    129   EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
    130 
    131   // Larger in one dimension and smaller in the other.
    132   set_bounds.set_width(550);
    133   set_bounds.set_height(250);
    134 
    135   view->MoveContents(web_contents, set_bounds);
    136   content::RunMessageLoop();  // TestWebDialogView will quit.
    137   actual_bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    138   EXPECT_EQ(set_bounds, actual_bounds);
    139 
    140   rwhv_bounds =
    141       view->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
    142   EXPECT_LT(0, rwhv_bounds.width());
    143   EXPECT_LT(0, rwhv_bounds.height());
    144   EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
    145   EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
    146 
    147   // Get very small.
    148   const gfx::Size min_size = view->GetWidget()->GetMinimumSize();
    149   EXPECT_LT(0, min_size.width());
    150   EXPECT_LT(0, min_size.height());
    151 
    152   set_bounds.set_size(min_size);
    153 
    154   view->MoveContents(web_contents, set_bounds);
    155   content::RunMessageLoop();  // TestWebDialogView will quit.
    156   actual_bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    157   EXPECT_EQ(set_bounds, actual_bounds);
    158 
    159   rwhv_bounds =
    160       view->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
    161   EXPECT_LT(0, rwhv_bounds.width());
    162   EXPECT_LT(0, rwhv_bounds.height());
    163   EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
    164   EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
    165 
    166   // Check to make sure we can't get to 0x0. First expand beyond the minimum
    167   // size that was set above so that TestWebDialogView has a change to pick up.
    168   set_bounds.set_height(250);
    169   view->MoveContents(web_contents, set_bounds);
    170   content::RunMessageLoop();  // TestWebDialogView will quit.
    171   actual_bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    172   EXPECT_EQ(set_bounds, actual_bounds);
    173 
    174   // Now verify that attempts to re-size to 0x0 enforces the minimum size.
    175   set_bounds.set_width(0);
    176   set_bounds.set_height(0);
    177 
    178   view->MoveContents(web_contents, set_bounds);
    179   content::RunMessageLoop();  // TestWebDialogView will quit.
    180   actual_bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    181   EXPECT_EQ(min_size, actual_bounds.size());
    182 
    183   // And that the render view is also non-zero.
    184   rwhv_bounds =
    185       view->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
    186   EXPECT_LT(0, rwhv_bounds.width());
    187   EXPECT_LT(0, rwhv_bounds.height());
    188 
    189   view->GetWidget()->CloseNow();
    190 }
    191