• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/printing/print_preview_tab_controller.h"
6 
7 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/tabs/tab_strip_model.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_list.h"
11 #include "chrome/browser/ui/browser_navigator.h"
12 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
13 #include "chrome/common/url_constants.h"
14 #include "content/browser/tab_contents/tab_contents.h"
15 #include "content/common/notification_details.h"
16 #include "content/common/notification_source.h"
17 
18 namespace printing {
19 
PrintPreviewTabController()20 PrintPreviewTabController::PrintPreviewTabController()
21     : waiting_for_new_preview_page_(false) {
22 }
23 
~PrintPreviewTabController()24 PrintPreviewTabController::~PrintPreviewTabController() {}
25 
26 // static
GetInstance()27 PrintPreviewTabController* PrintPreviewTabController::GetInstance() {
28   if (!g_browser_process)
29     return NULL;
30   return g_browser_process->print_preview_tab_controller();
31 }
32 
33 // static
PrintPreview(TabContents * tab)34 void PrintPreviewTabController::PrintPreview(TabContents* tab) {
35   if (tab->showing_interstitial_page())
36     return;
37 
38   printing::PrintPreviewTabController* tab_controller =
39       printing::PrintPreviewTabController::GetInstance();
40   if (!tab_controller)
41     return;
42   tab_controller->GetOrCreatePreviewTab(tab);
43 }
44 
GetOrCreatePreviewTab(TabContents * initiator_tab)45 TabContents* PrintPreviewTabController::GetOrCreatePreviewTab(
46     TabContents* initiator_tab) {
47   DCHECK(initiator_tab);
48 
49   // Get the print preview tab for |initiator_tab|.
50   TabContents* preview_tab = GetPrintPreviewForTab(initiator_tab);
51   if (preview_tab) {
52     // Show current preview tab.
53     preview_tab->Activate();
54     return preview_tab;
55   }
56   return CreatePrintPreviewTab(initiator_tab);
57 }
58 
GetPrintPreviewForTab(TabContents * tab) const59 TabContents* PrintPreviewTabController::GetPrintPreviewForTab(
60     TabContents* tab) const {
61   PrintPreviewTabMap::const_iterator it = preview_tab_map_.find(tab);
62   if (it != preview_tab_map_.end())
63     return tab;
64 
65   for (it = preview_tab_map_.begin(); it != preview_tab_map_.end(); ++it) {
66     // If |tab| is an initiator tab.
67     if (tab == it->second) {
68       // Return the associated preview tab.
69       return it->first;
70     }
71   }
72   return NULL;
73 }
74 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)75 void PrintPreviewTabController::Observe(NotificationType type,
76                                         const NotificationSource& source,
77                                         const NotificationDetails& details) {
78   TabContents* source_tab = NULL;
79   NavigationController::LoadCommittedDetails* detail_info = NULL;
80 
81   switch (type.value) {
82     case NotificationType::TAB_CONTENTS_DESTROYED: {
83       source_tab = Source<TabContents>(source).ptr();
84       break;
85     }
86     case NotificationType::NAV_ENTRY_COMMITTED: {
87       NavigationController* controller =
88           Source<NavigationController>(source).ptr();
89       source_tab = controller->tab_contents();
90       detail_info =
91           Details<NavigationController::LoadCommittedDetails>(details).ptr();
92       break;
93     }
94     default: {
95       NOTREACHED();
96       break;
97     }
98   }
99 
100   DCHECK(source_tab);
101 
102   TabContents* preview_tab = GetPrintPreviewForTab(source_tab);
103   bool source_tab_is_preview_tab = (source_tab == preview_tab);
104 
105   if (detail_info) {
106     PageTransition::Type transition_type =
107         detail_info->entry->transition_type();
108     NavigationType::Type nav_type = detail_info->type;
109 
110     // Don't update/erase the map entry if the page has not changed.
111     if (transition_type == PageTransition::RELOAD ||
112         nav_type == NavigationType::SAME_PAGE) {
113       return;
114     }
115 
116     // New |preview_tab| is created. Don't update/erase map entry.
117     if (waiting_for_new_preview_page_ &&
118         transition_type == PageTransition::LINK &&
119         nav_type == NavigationType::NEW_PAGE &&
120         source_tab_is_preview_tab) {
121       waiting_for_new_preview_page_ = false;
122       return;
123     }
124 
125     // User navigated to a preview tab using forward/back button.
126     if (source_tab_is_preview_tab &&
127         transition_type == PageTransition::FORWARD_BACK &&
128         nav_type == NavigationType::EXISTING_PAGE) {
129       return;
130     }
131   }
132 
133   if (source_tab_is_preview_tab) {
134     // Remove the initiator tab's observers before erasing the mapping.
135     TabContents* initiator_tab = GetInitiatorTab(source_tab);
136     if (initiator_tab)
137       RemoveObservers(initiator_tab);
138 
139     // Erase the map entry.
140     preview_tab_map_.erase(source_tab);
141   } else {
142     // |source_tab| is an initiator tab, update the map entry.
143     preview_tab_map_[preview_tab] = NULL;
144   }
145   RemoveObservers(source_tab);
146 }
147 
148 // static
IsPrintPreviewTab(TabContents * tab)149 bool PrintPreviewTabController::IsPrintPreviewTab(TabContents* tab) {
150   const GURL& url = tab->GetURL();
151   return (url.SchemeIs(chrome::kChromeUIScheme) &&
152           url.host() == chrome::kChromeUIPrintHost);
153 }
154 
GetInitiatorTab(TabContents * preview_tab)155 TabContents* PrintPreviewTabController::GetInitiatorTab(
156     TabContents* preview_tab) {
157   PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab);
158   if (it != preview_tab_map_.end())
159     return preview_tab_map_[preview_tab];
160   return NULL;
161 }
162 
CreatePrintPreviewTab(TabContents * initiator_tab)163 TabContents* PrintPreviewTabController::CreatePrintPreviewTab(
164     TabContents* initiator_tab) {
165   Browser* current_browser = BrowserList::FindBrowserWithID(
166       initiator_tab->controller().window_id().id());
167   // Add a new tab next to initiator tab.
168   browser::NavigateParams params(current_browser,
169                                  GURL(chrome::kChromeUIPrintURL),
170                                  PageTransition::LINK);
171   params.disposition = NEW_FOREGROUND_TAB;
172   params.tabstrip_index = current_browser->tabstrip_model()->
173       GetWrapperIndex(initiator_tab) + 1;
174   browser::Navigate(&params);
175   TabContentsWrapper* preview_tab = params.target_contents;
176   preview_tab->tab_contents()->Activate();
177 
178   // Add an entry to the map.
179   preview_tab_map_[preview_tab->tab_contents()] = initiator_tab;
180   waiting_for_new_preview_page_ = true;
181 
182   AddObservers(initiator_tab);
183   AddObservers(preview_tab->tab_contents());
184 
185   return preview_tab->tab_contents();
186 }
187 
AddObservers(TabContents * tab)188 void PrintPreviewTabController::AddObservers(TabContents* tab) {
189   registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
190                  Source<TabContents>(tab));
191   registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
192                  Source<NavigationController>(&tab->controller()));
193 }
194 
RemoveObservers(TabContents * tab)195 void PrintPreviewTabController::RemoveObservers(TabContents* tab) {
196   registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
197                     Source<TabContents>(tab));
198   registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED,
199                     Source<NavigationController>(&tab->controller()));
200 }
201 
202 }  // namespace printing
203