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 20using content::WebContents; 21using content::WebContentsObserver; 22 23class 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 55class 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 80class 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 101class 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 TearDownOnMainThread() 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 165IN_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 201IN_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