Home | History | Annotate | Download | only in printing
      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/memory/scoped_ptr.h"
      6 #include "base/run_loop.h"
      7 #include "chrome/browser/printing/print_preview_dialog_controller.h"
      8 #include "chrome/browser/ui/browser.h"
      9 #include "chrome/browser/ui/browser_commands.h"
     10 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     11 #include "chrome/common/print_messages.h"
     12 #include "chrome/common/url_constants.h"
     13 #include "chrome/test/base/in_process_browser_test.h"
     14 #include "chrome/test/base/ui_test_utils.h"
     15 #include "content/public/browser/web_contents_observer.h"
     16 #include "content/public/test/browser_test_utils.h"
     17 #include "url/gurl.h"
     18 #include "ipc/ipc_message_macros.h"
     19 
     20 using content::WebContents;
     21 using content::WebContentsObserver;
     22 
     23 class RequestPrintPreviewObserver : public WebContentsObserver {
     24  public:
     25   explicit RequestPrintPreviewObserver(WebContents* dialog)
     26       : WebContentsObserver(dialog) {
     27   }
     28   virtual ~RequestPrintPreviewObserver() {}
     29 
     30   void set_quit_closure(const base::Closure& quit_closure) {
     31     quit_closure_ = quit_closure;
     32   }
     33 
     34  private:
     35   // content::WebContentsObserver implementation.
     36   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
     37     IPC_BEGIN_MESSAGE_MAP(RequestPrintPreviewObserver, message)
     38       IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
     39                           OnRequestPrintPreview)
     40       IPC_MESSAGE_UNHANDLED(break;)
     41     IPC_END_MESSAGE_MAP();
     42     return false;  // Report not handled so the real handler receives it.
     43   }
     44 
     45   void OnRequestPrintPreview(
     46       const PrintHostMsg_RequestPrintPreview_Params& /* params */) {
     47     base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure_);
     48   }
     49 
     50   base::Closure quit_closure_;
     51 
     52   DISALLOW_COPY_AND_ASSIGN(RequestPrintPreviewObserver);
     53 };
     54 
     55 class PrintPreviewDialogClonedObserver : public WebContentsObserver {
     56  public:
     57   explicit PrintPreviewDialogClonedObserver(WebContents* dialog)
     58       : WebContentsObserver(dialog) {
     59   }
     60   virtual ~PrintPreviewDialogClonedObserver() {}
     61 
     62   RequestPrintPreviewObserver* request_preview_dialog_observer() {
     63     return request_preview_dialog_observer_.get();
     64   }
     65 
     66  private:
     67   // content::WebContentsObserver implementation.
     68   virtual void DidCloneToNewWebContents(
     69       WebContents* old_web_contents,
     70       WebContents* new_web_contents) OVERRIDE {
     71     request_preview_dialog_observer_.reset(
     72         new RequestPrintPreviewObserver(new_web_contents));
     73   }
     74 
     75   scoped_ptr<RequestPrintPreviewObserver> request_preview_dialog_observer_;
     76 
     77   DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogClonedObserver);
     78 };
     79 
     80 class PrintPreviewDialogDestroyedObserver : public WebContentsObserver {
     81  public:
     82   explicit PrintPreviewDialogDestroyedObserver(WebContents* dialog)
     83       : WebContentsObserver(dialog),
     84         dialog_destroyed_(false) {
     85   }
     86   virtual ~PrintPreviewDialogDestroyedObserver() {}
     87 
     88   bool dialog_destroyed() const { return dialog_destroyed_; }
     89 
     90  private:
     91   // content::WebContentsObserver implementation.
     92   virtual void WebContentsDestroyed() OVERRIDE {
     93     dialog_destroyed_ = true;
     94   }
     95 
     96   bool dialog_destroyed_;
     97 
     98   DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogDestroyedObserver);
     99 };
    100 
    101 class PrintPreviewDialogControllerBrowserTest : public InProcessBrowserTest {
    102  public:
    103   PrintPreviewDialogControllerBrowserTest() : initiator_(NULL) {}
    104   virtual ~PrintPreviewDialogControllerBrowserTest() {}
    105 
    106   WebContents* initiator() {
    107     return initiator_;
    108   }
    109 
    110   void PrintPreview() {
    111     base::RunLoop run_loop;
    112     request_preview_dialog_observer()->set_quit_closure(run_loop.QuitClosure());
    113     chrome::Print(browser());
    114     run_loop.Run();
    115   }
    116 
    117   WebContents* GetPrintPreviewDialog() {
    118     printing::PrintPreviewDialogController* dialog_controller =
    119         printing::PrintPreviewDialogController::GetInstance();
    120     return dialog_controller->GetPrintPreviewForContents(initiator_);
    121   }
    122 
    123  private:
    124   virtual void SetUpOnMainThread() OVERRIDE {
    125     WebContents* first_tab =
    126         browser()->tab_strip_model()->GetActiveWebContents();
    127     ASSERT_TRUE(first_tab);
    128 
    129     // Open a new tab so |cloned_tab_observer_| can see it first and attach a
    130     // RequestPrintPreviewObserver to it before the real
    131     // PrintPreviewMessageHandler gets created. Thus enabling
    132     // RequestPrintPreviewObserver to get messages first for the purposes of
    133     // this test.
    134     cloned_tab_observer_.reset(new PrintPreviewDialogClonedObserver(first_tab));
    135     chrome::DuplicateTab(browser());
    136 
    137     initiator_ = browser()->tab_strip_model()->GetActiveWebContents();
    138     ASSERT_TRUE(initiator_);
    139     ASSERT_NE(first_tab, initiator_);
    140   }
    141 
    142   virtual void CleanUpOnMainThread() OVERRIDE {
    143     cloned_tab_observer_.reset();
    144     initiator_ = NULL;
    145   }
    146 
    147   RequestPrintPreviewObserver* request_preview_dialog_observer() {
    148     return cloned_tab_observer_->request_preview_dialog_observer();
    149   }
    150 
    151   scoped_ptr<PrintPreviewDialogClonedObserver> cloned_tab_observer_;
    152   WebContents* initiator_;
    153 
    154   DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogControllerBrowserTest);
    155 };
    156 
    157 // Test to verify that when a initiator navigates, we can create a new preview
    158 // dialog for the new tab contents.
    159 // http://crbug.com/377337
    160 #if defined(OS_WIN)
    161 #define MAYBE_NavigateFromInitiatorTab DISABLED_NavigateFromInitiatorTab
    162 #else
    163 #define MAYBE_NavigateFromInitiatorTab NavigateFromInitiatorTab
    164 #endif
    165 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
    166                        MAYBE_NavigateFromInitiatorTab) {
    167   // print for the first time.
    168   PrintPreview();
    169 
    170   // Get the preview dialog for the initiator tab.
    171   WebContents* preview_dialog = GetPrintPreviewDialog();
    172 
    173   // Check a new print preview dialog got created.
    174   ASSERT_TRUE(preview_dialog);
    175   ASSERT_NE(initiator(), preview_dialog);
    176 
    177   // Navigate in the initiator tab. Make sure navigating destroys the print
    178   // preview dialog.
    179   PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
    180   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
    181   ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());
    182 
    183   // Try printing again.
    184   PrintPreview();
    185 
    186   // Get the print preview dialog for the initiator tab.
    187   WebContents* new_preview_dialog = GetPrintPreviewDialog();
    188 
    189   // Check a new preview dialog got created.
    190   EXPECT_TRUE(new_preview_dialog);
    191 }
    192 
    193 // Test to verify that after reloading the initiator, it creates a new print
    194 // preview dialog.
    195 // http://crbug.com/377337
    196 #if defined(OS_WIN)
    197 #define MAYBE_ReloadInitiatorTab DISABLED_ReloadInitiatorTab
    198 #else
    199 #define MAYBE_ReloadInitiatorTab ReloadInitiatorTab
    200 #endif
    201 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
    202                        MAYBE_ReloadInitiatorTab) {
    203   // print for the first time.
    204   PrintPreview();
    205 
    206   WebContents* preview_dialog = GetPrintPreviewDialog();
    207 
    208   // Check a new print preview dialog got created.
    209   ASSERT_TRUE(preview_dialog);
    210   ASSERT_NE(initiator(), preview_dialog);
    211 
    212   // Reload the initiator. Make sure reloading destroys the print preview
    213   // dialog.
    214   PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
    215   chrome::Reload(browser(), CURRENT_TAB);
    216   content::WaitForLoadStop(
    217       browser()->tab_strip_model()->GetActiveWebContents());
    218   ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());
    219 
    220   // Try printing again.
    221   PrintPreview();
    222 
    223   // Create a preview dialog for the initiator tab.
    224   WebContents* new_preview_dialog = GetPrintPreviewDialog();
    225   EXPECT_TRUE(new_preview_dialog);
    226 }
    227