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