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 "content/public/browser/web_contents_view.h"
     22 #include "testing/gmock/include/gmock/gmock.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 #include "ui/views/controls/webview/web_dialog_view.h"
     25 #include "ui/views/widget/widget.h"
     26 #include "ui/web_dialogs/test/test_web_dialog_delegate.h"
     27 
     28 using content::BrowserContext;
     29 using content::WebContents;
     30 using testing::Eq;
     31 using ui::WebDialogDelegate;
     32 
     33 namespace {
     34 
     35 // Initial size of WebDialog for SizeWindow test case.
     36 const int kInitialWidth = 40;
     37 const int kInitialHeight = 40;
     38 
     39 class TestWebDialogView : public views::WebDialogView {
     40  public:
     41   TestWebDialogView(content::BrowserContext* context,
     42                     WebDialogDelegate* delegate)
     43       : views::WebDialogView(context, delegate, new ChromeWebContentsHandler),
     44         should_quit_on_size_change_(false) {
     45     delegate->GetDialogSize(&last_size_);
     46   }
     47 
     48   void set_should_quit_on_size_change(bool should_quit) {
     49     should_quit_on_size_change_ = should_quit;
     50   }
     51 
     52  private:
     53   // TODO(xiyuan): Update this when WidgetDelegate has bounds change hook.
     54   virtual void SaveWindowPlacement(const gfx::Rect& bounds,
     55                                    ui::WindowShowState show_state) OVERRIDE {
     56     if (should_quit_on_size_change_ && last_size_ != bounds.size()) {
     57       // Schedule message loop quit because we could be called while
     58       // the bounds change call is on the stack and not in the nested message
     59       // loop.
     60       base::MessageLoop::current()->PostTask(
     61           FROM_HERE,
     62           base::Bind(&base::MessageLoop::Quit,
     63                      base::Unretained(base::MessageLoop::current())));
     64     }
     65 
     66     last_size_ = bounds.size();
     67   }
     68 
     69   virtual void OnDialogClosed(const std::string& json_retval) OVERRIDE {
     70     should_quit_on_size_change_ = false;  // No quit when we are closing.
     71     views::WebDialogView::OnDialogClosed(json_retval);
     72   }
     73 
     74   // Whether we should quit message loop when size change is detected.
     75   bool should_quit_on_size_change_;
     76   gfx::Size last_size_;
     77 
     78   DISALLOW_COPY_AND_ASSIGN(TestWebDialogView);
     79 };
     80 
     81 }  // namespace
     82 
     83 class WebDialogBrowserTest : public InProcessBrowserTest {
     84  public:
     85   WebDialogBrowserTest() {}
     86 };
     87 
     88 // TODO(linux_aura) http://crbug.com/163931
     89 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(USE_AURA)
     90 #define MAYBE_SizeWindow SizeWindow
     91 #else
     92 // http://code.google.com/p/chromium/issues/detail?id=52602
     93 // Windows has some issues resizing windows- an off by one problem,
     94 // and a minimum size that seems too big.  This file isn't included in
     95 // Mac builds yet. On Chrome OS, this test doesn't apply since ChromeOS
     96 // doesn't allow resizing of windows.
     97 #define MAYBE_SizeWindow DISABLED_SizeWindow
     98 #endif
     99 
    100 IN_PROC_BROWSER_TEST_F(WebDialogBrowserTest, MAYBE_SizeWindow) {
    101   ui::test::TestWebDialogDelegate* delegate =
    102       new ui::test::TestWebDialogDelegate(
    103           GURL(chrome::kChromeUIChromeURLsURL));
    104   delegate->set_size(kInitialWidth, kInitialHeight);
    105 
    106   TestWebDialogView* view =
    107       new TestWebDialogView(browser()->profile(), delegate);
    108   WebContents* web_contents =
    109       browser()->tab_strip_model()->GetActiveWebContents();
    110   ASSERT_TRUE(web_contents != NULL);
    111   views::Widget::CreateWindowWithParent(
    112       view, web_contents->GetView()->GetTopLevelNativeWindow());
    113   view->GetWidget()->Show();
    114 
    115   // TestWebDialogView should quit current message loop on size change.
    116   view->set_should_quit_on_size_change(true);
    117 
    118   gfx::Rect bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    119 
    120   gfx::Rect set_bounds = bounds;
    121   gfx::Rect actual_bounds, rwhv_bounds;
    122 
    123   // Bigger than the default in both dimensions.
    124   set_bounds.set_width(400);
    125   set_bounds.set_height(300);
    126 
    127   view->MoveContents(web_contents, set_bounds);
    128   content::RunMessageLoop();  // TestWebDialogView will quit.
    129   actual_bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    130   EXPECT_EQ(set_bounds, actual_bounds);
    131 
    132   rwhv_bounds =
    133       view->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
    134   EXPECT_LT(0, rwhv_bounds.width());
    135   EXPECT_LT(0, rwhv_bounds.height());
    136   EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
    137   EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
    138 
    139   // Larger in one dimension and smaller in the other.
    140   set_bounds.set_width(550);
    141   set_bounds.set_height(250);
    142 
    143   view->MoveContents(web_contents, set_bounds);
    144   content::RunMessageLoop();  // TestWebDialogView will quit.
    145   actual_bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    146   EXPECT_EQ(set_bounds, actual_bounds);
    147 
    148   rwhv_bounds =
    149       view->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
    150   EXPECT_LT(0, rwhv_bounds.width());
    151   EXPECT_LT(0, rwhv_bounds.height());
    152   EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
    153   EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
    154 
    155   // Get very small.
    156   gfx::Size min_size = view->GetWidget()->GetMinimumSize();
    157   set_bounds.set_size(min_size);
    158 
    159   view->MoveContents(web_contents, set_bounds);
    160   content::RunMessageLoop();  // TestWebDialogView will quit.
    161   actual_bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    162   EXPECT_EQ(set_bounds, actual_bounds);
    163 
    164   rwhv_bounds =
    165       view->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
    166   EXPECT_LT(0, rwhv_bounds.width());
    167   EXPECT_LT(0, rwhv_bounds.height());
    168   EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
    169   EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
    170 
    171   // Check to make sure we can't get to 0x0
    172   set_bounds.set_width(0);
    173   set_bounds.set_height(0);
    174 
    175   view->MoveContents(web_contents, set_bounds);
    176   content::RunMessageLoop();  // TestWebDialogView will quit.
    177   actual_bounds = view->GetWidget()->GetClientAreaBoundsInScreen();
    178   EXPECT_LT(0, actual_bounds.width());
    179   EXPECT_LT(0, actual_bounds.height());
    180 }
    181