| Index: chrome/browser/speech/tab_watcher.cc
|
| diff --git a/chrome/browser/speech/tab_watcher.cc b/chrome/browser/speech/tab_watcher.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d9827037faa7db1b1afeeb6eb486a7623f1cf47a
|
| --- /dev/null
|
| +++ b/chrome/browser/speech/tab_watcher.cc
|
| @@ -0,0 +1,87 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/speech/tab_watcher.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "chrome/browser/tab_contents/tab_util.h"
|
| +#include "content/public/browser/notification_registrar.h"
|
| +#include "content/public/browser/notification_source.h"
|
| +#include "content/public/browser/notification_types.h"
|
| +#include "content/public/browser/render_process_host.h"
|
| +#include "content/public/browser/render_view_host.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +
|
| +using content::BrowserThread;
|
| +using content::WebContents;
|
| +
|
| +namespace {
|
| +const int kNotificationType = content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED;
|
| +}
|
| +
|
| +TabWatcher::TabWatcher(
|
| + TabClosedCallback tab_closed_callback, BrowserThread::ID callback_thread)
|
| + : tab_closed_callback_(tab_closed_callback),
|
| + callback_thread_(callback_thread) {
|
| +}
|
| +
|
| +TabWatcher::~TabWatcher() {
|
| + // Must be destroyed on the UI thread due to |registrar_| non thread-safety.
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +}
|
| +
|
| +void TabWatcher::Watch(int render_process_id, int render_view_id) {
|
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
|
| + &TabWatcher::Watch, this, render_process_id, render_view_id));
|
| + return;
|
| + }
|
| +
|
| + WebContents* web_contents = tab_util::GetWebContentsByID(render_process_id,
|
| + render_view_id);
|
| + // Sessions initiated by speech input extension APIs will end up in a NULL
|
| + // WebContent here, but they are properly managed by the
|
| + // chrome::SpeechInputExtensionManager. However, sessions initiated within an
|
| + // extension using the (new) speech JS APIs, will be properly handled here.
|
| + // TODO(primiano) turn this line into a DCHECK once speech input extension
|
| + // API is deprecated.
|
| + if (!web_contents)
|
| + return;
|
| +
|
| + // Avoid multiple registrations on |registrar_| for the same |web_contents|.
|
| + if (registered_web_contents_.find(web_contents) !=
|
| + registered_web_contents_.end()) {
|
| + return;
|
| + }
|
| + registered_web_contents_.insert(web_contents);
|
| +
|
| + // Lazy initialize the registrar.
|
| + if (!registrar_.get())
|
| + registrar_.reset(new content::NotificationRegistrar());
|
| +
|
| + registrar_->Add(this,
|
| + kNotificationType,
|
| + content::Source<WebContents>(web_contents));
|
| +}
|
| +
|
| +void TabWatcher::Observe(
|
| + int type,
|
| + const content::NotificationSource& source,
|
| + const content::NotificationDetails& details) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + DCHECK_EQ(kNotificationType, type);
|
| +
|
| + WebContents* web_contents = content::Source<WebContents>(source).ptr();
|
| + DCHECK(web_contents);
|
| + const int render_process_id = web_contents->GetRenderProcessHost()->GetID();
|
| + const int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
|
| +
|
| + registrar_->Remove(this,
|
| + kNotificationType,
|
| + content::Source<WebContents>(web_contents));
|
| + registered_web_contents_.erase(web_contents);
|
| +
|
| + BrowserThread::PostTask(callback_thread_, FROM_HERE, base::Bind(
|
| + tab_closed_callback_, render_process_id, render_view_id));
|
| +}
|
|
|