| Index: chrome/browser/printing/print_preview_dialog_controller.cc
|
| diff --git a/chrome/browser/printing/print_preview_dialog_controller.cc b/chrome/browser/printing/print_preview_dialog_controller.cc
|
| index 6694af39666b622e31dfe77c4254730310c47bf7..27d365fb4fffb31f2eb155d8ddd25a582cfd4322 100644
|
| --- a/chrome/browser/printing/print_preview_dialog_controller.cc
|
| +++ b/chrome/browser/printing/print_preview_dialog_controller.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include <algorithm>
|
| #include <string>
|
| +#include <vector>
|
|
|
| #include "base/auto_reset.h"
|
| #include "base/path_service.h"
|
| @@ -31,14 +32,14 @@
|
| #include "content/public/browser/navigation_controller.h"
|
| #include "content/public/browser/navigation_details.h"
|
| #include "content/public/browser/navigation_entry.h"
|
| +#include "content/public/browser/notification_details.h"
|
| +#include "content/public/browser/notification_source.h"
|
| #include "content/public/browser/plugin_service.h"
|
| #include "content/public/browser/render_frame_host.h"
|
| #include "content/public/browser/render_process_host.h"
|
| -#include "content/public/browser/render_process_host_observer.h"
|
| #include "content/public/browser/render_view_host.h"
|
| #include "content/public/browser/web_contents.h"
|
| #include "content/public/browser/web_contents_delegate.h"
|
| -#include "content/public/browser/web_contents_observer.h"
|
| #include "content/public/browser/web_contents_view.h"
|
| #include "content/public/common/webplugininfo.h"
|
| #include "ui/web_dialogs/web_dialog_delegate.h"
|
| @@ -46,7 +47,6 @@
|
|
|
| using content::NativeWebKeyboardEvent;
|
| using content::NavigationController;
|
| -using content::RenderProcessHost;
|
| using content::WebContents;
|
| using content::WebUIMessageHandler;
|
| using ui::WebDialogDelegate;
|
| @@ -210,97 +210,6 @@ void PrintPreviewWebContentDelegate::HandleKeyboardEvent(
|
|
|
| namespace printing {
|
|
|
| -struct PrintPreviewDialogController::Operation {
|
| - class Observer : public content::WebContentsObserver,
|
| - public content::RenderProcessHostObserver {
|
| - public:
|
| - Observer();
|
| - virtual ~Observer();
|
| -
|
| - void StartObserving(PrintPreviewDialogController* owner,
|
| - WebContents* web_contents);
|
| - void StopObserving();
|
| -
|
| - private:
|
| - // content::WebContentsObserver
|
| - virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
|
| - virtual void NavigationEntryCommitted(
|
| - const content::LoadCommittedDetails& load_details) OVERRIDE;
|
| - // content::RenderProcessHostObserver
|
| - virtual void RenderProcessExited(RenderProcessHost* host,
|
| - base::ProcessHandle handle,
|
| - base::TerminationStatus status,
|
| - int exit_code) OVERRIDE;
|
| - virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE;
|
| -
|
| - PrintPreviewDialogController* owner_;
|
| - RenderProcessHost* host_;
|
| - };
|
| -
|
| - Operation();
|
| -
|
| - WebContents* preview_dialog;
|
| - WebContents* initiator;
|
| - Observer preview_dialog_observer;
|
| - Observer initiator_observer;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(Operation);
|
| -};
|
| -
|
| -PrintPreviewDialogController::Operation::Operation() : preview_dialog(NULL),
|
| - initiator(NULL) {
|
| -}
|
| -
|
| -PrintPreviewDialogController::Operation::Observer::Observer() : owner_(NULL),
|
| - host_(NULL) {
|
| -}
|
| -
|
| -PrintPreviewDialogController::Operation::Observer::~Observer() {
|
| - StopObserving();
|
| -}
|
| -
|
| -void PrintPreviewDialogController::Operation::Observer::StartObserving(
|
| - PrintPreviewDialogController* owner,
|
| - WebContents* web_contents) {
|
| - owner_ = owner;
|
| - Observe(web_contents);
|
| - host_ = web_contents->GetRenderProcessHost();
|
| - host_->AddObserver(this);
|
| -}
|
| -
|
| -void PrintPreviewDialogController::Operation::Observer::StopObserving() {
|
| - Observe(NULL);
|
| - if (host_) {
|
| - host_->RemoveObserver(this);
|
| - host_ = NULL;
|
| - }
|
| -}
|
| -
|
| -void PrintPreviewDialogController::Operation::Observer::WebContentsDestroyed(
|
| - WebContents* web_contents) {
|
| - owner_->OnWebContentsDestroyed(web_contents);
|
| -}
|
| -
|
| -void
|
| -PrintPreviewDialogController::Operation::Observer::NavigationEntryCommitted(
|
| - const content::LoadCommittedDetails& load_details) {
|
| - owner_->OnNavigationEntryCommitted(web_contents(), &load_details);
|
| -}
|
| -
|
| -void PrintPreviewDialogController::Operation::Observer::RenderProcessExited(
|
| - RenderProcessHost* host,
|
| - base::ProcessHandle handle,
|
| - base::TerminationStatus status,
|
| - int exit_code) {
|
| - owner_->OnRenderProcessExited(host);
|
| -}
|
| -
|
| -void
|
| -PrintPreviewDialogController::Operation::Observer::RenderProcessHostDestroyed(
|
| - RenderProcessHost* host) {
|
| - host_ = NULL;
|
| -}
|
| -
|
| PrintPreviewDialogController::PrintPreviewDialogController()
|
| : waiting_for_new_preview_page_(false),
|
| is_creating_print_preview_dialog_(false) {
|
| @@ -341,11 +250,19 @@ WebContents* PrintPreviewDialogController::GetOrCreatePreviewDialog(
|
|
|
| WebContents* PrintPreviewDialogController::GetPrintPreviewForContents(
|
| WebContents* contents) const {
|
| - for (size_t i = 0; i < preview_operations_.size(); ++i) {
|
| - Operation* operation = preview_operations_[i];
|
| - if (operation->preview_dialog == contents ||
|
| - operation->initiator == contents) {
|
| - return operation->preview_dialog;
|
| + // |preview_dialog_map_| is keyed by the preview dialog, so if find()
|
| + // succeeds, then |contents| is the preview dialog.
|
| + PrintPreviewDialogMap::const_iterator it = preview_dialog_map_.find(contents);
|
| + if (it != preview_dialog_map_.end())
|
| + return contents;
|
| +
|
| + for (it = preview_dialog_map_.begin();
|
| + it != preview_dialog_map_.end();
|
| + ++it) {
|
| + // If |contents| is an initiator.
|
| + if (contents == it->second) {
|
| + // Return the associated preview dialog.
|
| + return it->first;
|
| }
|
| }
|
| return NULL;
|
| @@ -353,18 +270,35 @@ WebContents* PrintPreviewDialogController::GetPrintPreviewForContents(
|
|
|
| WebContents* PrintPreviewDialogController::GetInitiator(
|
| WebContents* preview_dialog) {
|
| - for (size_t i = 0; i < preview_operations_.size(); ++i) {
|
| - Operation* operation = preview_operations_[i];
|
| - if (operation->preview_dialog == preview_dialog)
|
| - return operation->initiator;
|
| + PrintPreviewDialogMap::iterator it = preview_dialog_map_.find(preview_dialog);
|
| + return (it != preview_dialog_map_.end()) ? it->second : NULL;
|
| +}
|
| +
|
| +void PrintPreviewDialogController::Observe(
|
| + int type,
|
| + const content::NotificationSource& source,
|
| + const content::NotificationDetails& details) {
|
| + if (type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED) {
|
| + OnRendererProcessClosed(
|
| + content::Source<content::RenderProcessHost>(source).ptr());
|
| + } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
|
| + OnWebContentsDestroyed(content::Source<WebContents>(source).ptr());
|
| + } else {
|
| + DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type);
|
| + WebContents* contents =
|
| + content::Source<NavigationController>(source)->GetWebContents();
|
| + OnNavEntryCommitted(
|
| + contents,
|
| + content::Details<content::LoadCommittedDetails>(details).ptr());
|
| }
|
| - return NULL;
|
| }
|
|
|
| void PrintPreviewDialogController::ForEachPreviewDialog(
|
| base::Callback<void(content::WebContents*)> callback) {
|
| - for (size_t i = 0; i < preview_operations_.size(); ++i) {
|
| - callback.Run(preview_operations_[i]->preview_dialog);
|
| + for (PrintPreviewDialogMap::const_iterator it = preview_dialog_map_.begin();
|
| + it != preview_dialog_map_.end();
|
| + ++it) {
|
| + callback.Run(it->first);
|
| }
|
| }
|
|
|
| @@ -381,30 +315,26 @@ bool PrintPreviewDialogController::IsPrintPreviewURL(const GURL& url) {
|
|
|
| void PrintPreviewDialogController::EraseInitiatorInfo(
|
| WebContents* preview_dialog) {
|
| - for (size_t i = 0; i < preview_operations_.size(); ++i) {
|
| - Operation* operation = preview_operations_[i];
|
| - if (operation->preview_dialog == preview_dialog) {
|
| - operation->initiator_observer.StopObserving();
|
| - operation->initiator = NULL;
|
| - return;
|
| - }
|
| - }
|
| -}
|
| + PrintPreviewDialogMap::iterator it = preview_dialog_map_.find(preview_dialog);
|
| + if (it == preview_dialog_map_.end())
|
| + return;
|
|
|
| -PrintPreviewDialogController::~PrintPreviewDialogController() {
|
| - DCHECK_EQ(0U, preview_operations_.size());
|
| + RemoveObservers(it->second);
|
| + preview_dialog_map_[preview_dialog] = NULL;
|
| }
|
|
|
| -void PrintPreviewDialogController::OnRenderProcessExited(
|
| - RenderProcessHost* rph) {
|
| +PrintPreviewDialogController::~PrintPreviewDialogController() {}
|
| +
|
| +void PrintPreviewDialogController::OnRendererProcessClosed(
|
| + content::RenderProcessHost* rph) {
|
| // Store contents in a vector and deal with them after iterating through
|
| - // |preview_operations_| because RemoveFoo() can change |preview_operations_|.
|
| + // |preview_dialog_map_| because RemoveFoo() can change |preview_dialog_map_|.
|
| std::vector<WebContents*> closed_initiators;
|
| std::vector<WebContents*> closed_preview_dialogs;
|
| - for (size_t i = 0; i < preview_operations_.size(); ++i) {
|
| - Operation* operation = preview_operations_[i];
|
| - WebContents* preview_dialog = operation->preview_dialog;
|
| - WebContents* initiator = operation->initiator;
|
| + for (PrintPreviewDialogMap::iterator iter = preview_dialog_map_.begin();
|
| + iter != preview_dialog_map_.end(); ++iter) {
|
| + WebContents* preview_dialog = iter->first;
|
| + WebContents* initiator = iter->second;
|
| if (preview_dialog->GetRenderProcessHost() == rph) {
|
| closed_preview_dialogs.push_back(preview_dialog);
|
| } else if (initiator &&
|
| @@ -441,8 +371,8 @@ void PrintPreviewDialogController::OnWebContentsDestroyed(
|
| RemoveInitiator(contents);
|
| }
|
|
|
| -void PrintPreviewDialogController::OnNavigationEntryCommitted(
|
| - WebContents* contents, const content::LoadCommittedDetails* details) {
|
| +void PrintPreviewDialogController::OnNavEntryCommitted(
|
| + WebContents* contents, content::LoadCommittedDetails* details) {
|
| WebContents* preview_dialog = GetPrintPreviewForContents(contents);
|
| if (!preview_dialog) {
|
| NOTREACHED();
|
| @@ -504,15 +434,12 @@ WebContents* PrintPreviewDialogController::CreatePrintPreviewDialog(
|
| extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
|
| preview_dialog);
|
|
|
| + // Add an entry to the map.
|
| + preview_dialog_map_[preview_dialog] = initiator;
|
| waiting_for_new_preview_page_ = true;
|
|
|
| - // Add an entry to the map.
|
| - Operation* operation = new Operation;
|
| - operation->preview_dialog = preview_dialog;
|
| - operation->initiator = initiator;
|
| - operation->preview_dialog_observer.StartObserving(this, preview_dialog);
|
| - operation->initiator_observer.StartObserving(this, initiator);
|
| - preview_operations_.push_back(operation);
|
| + AddObservers(initiator);
|
| + AddObservers(preview_dialog);
|
|
|
| return preview_dialog;
|
| }
|
| @@ -528,15 +455,49 @@ void PrintPreviewDialogController::SaveInitiatorTitle(
|
| }
|
| }
|
|
|
| +void PrintPreviewDialogController::AddObservers(WebContents* contents) {
|
| + registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
|
| + content::Source<WebContents>(contents));
|
| + registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
|
| + content::Source<NavigationController>(&contents->GetController()));
|
| +
|
| + // Multiple sites may share the same RenderProcessHost, so check if this
|
| + // notification has already been added.
|
| + content::Source<content::RenderProcessHost> rph_source(
|
| + contents->GetRenderProcessHost());
|
| + if (!registrar_.IsRegistered(this,
|
| + content::NOTIFICATION_RENDERER_PROCESS_CLOSED, rph_source)) {
|
| + registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
|
| + rph_source);
|
| + }
|
| +}
|
| +
|
| +void PrintPreviewDialogController::RemoveObservers(WebContents* contents) {
|
| + registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
|
| + content::Source<WebContents>(contents));
|
| + registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
|
| + content::Source<NavigationController>(&contents->GetController()));
|
| +
|
| + // Multiple sites may share the same RenderProcessHost, so check if this
|
| + // notification has already been added.
|
| + content::Source<content::RenderProcessHost> rph_source(
|
| + contents->GetRenderProcessHost());
|
| + if (registrar_.IsRegistered(this,
|
| + content::NOTIFICATION_RENDERER_PROCESS_CLOSED, rph_source)) {
|
| + registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
|
| + rph_source);
|
| + }
|
| +}
|
| +
|
| void PrintPreviewDialogController::RemoveInitiator(
|
| WebContents* initiator) {
|
| WebContents* preview_dialog = GetPrintPreviewForContents(initiator);
|
| DCHECK(preview_dialog);
|
| -
|
| // Update the map entry first, so when the print preview dialog gets destroyed
|
| // and reaches RemovePreviewDialog(), it does not attempt to also remove the
|
| // initiator's observers.
|
| - EraseInitiatorInfo(preview_dialog);
|
| + preview_dialog_map_[preview_dialog] = NULL;
|
| + RemoveObservers(initiator);
|
|
|
| PrintViewManager::FromWebContents(initiator)->PrintPreviewDone();
|
|
|
| @@ -551,32 +512,24 @@ void PrintPreviewDialogController::RemoveInitiator(
|
|
|
| void PrintPreviewDialogController::RemovePreviewDialog(
|
| WebContents* preview_dialog) {
|
| - for (size_t i = 0; i < preview_operations_.size(); ++i) {
|
| - Operation* operation = preview_operations_[i];
|
| - if (operation->preview_dialog == preview_dialog) {
|
| - // Remove the initiator's observers before erasing the mapping.
|
| - if (operation->initiator) {
|
| - operation->initiator_observer.StopObserving();
|
| - PrintViewManager::FromWebContents(operation->initiator)->
|
| - PrintPreviewDone();
|
| - }
|
| -
|
| - // Print preview WebContents is destroyed. Notify |PrintPreviewUI| to
|
| - // abort the initiator preview request.
|
| - if (content::WebUI* web_ui = preview_dialog->GetWebUI()) {
|
| - PrintPreviewUI* print_preview_ui =
|
| - static_cast<PrintPreviewUI*>(web_ui->GetController());
|
| - if (print_preview_ui)
|
| - print_preview_ui->OnPrintPreviewDialogDestroyed();
|
| - }
|
| -
|
| - preview_operations_.erase(preview_operations_.begin() + i);
|
| - delete operation;
|
| + // Remove the initiator's observers before erasing the mapping.
|
| + WebContents* initiator = GetInitiator(preview_dialog);
|
| + if (initiator) {
|
| + RemoveObservers(initiator);
|
| + PrintViewManager::FromWebContents(initiator)->PrintPreviewDone();
|
| + }
|
|
|
| - return;
|
| - }
|
| + // Print preview WebContents is destroyed. Notify |PrintPreviewUI| to abort
|
| + // the initiator preview request.
|
| + if (content::WebUI* web_ui = preview_dialog->GetWebUI()) {
|
| + PrintPreviewUI* print_preview_ui =
|
| + static_cast<PrintPreviewUI*>(web_ui->GetController());
|
| + if (print_preview_ui)
|
| + print_preview_ui->OnPrintPreviewDialogDestroyed();
|
| }
|
| - NOTREACHED();
|
| +
|
| + preview_dialog_map_.erase(preview_dialog);
|
| + RemoveObservers(preview_dialog);
|
| }
|
|
|
| } // namespace printing
|
|
|