| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" | 5 #include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/prefs/pref_service.h" | 11 #include "base/prefs/pref_service.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/synchronization/lock.h" | 13 #include "base/synchronization/lock.h" |
| 14 #include "base/threading/thread_restrictions.h" | 14 #include "base/threading/thread_restrictions.h" |
| 15 #include "chrome/browser/browser_process.h" | 15 #include "chrome/browser/browser_process.h" |
| 16 #include "chrome/browser/profiles/profile_manager.h" | 16 #include "chrome/browser/profiles/profile_manager.h" |
| 17 #include "chrome/browser/tab_contents/tab_util.h" | 17 #include "chrome/browser/tab_contents/tab_util.h" |
| 18 #include "chrome/common/pref_names.h" | 18 #include "chrome/common/pref_names.h" |
| 19 #include "chrome/common/url_constants.h" | 19 #include "chrome/common/url_constants.h" |
| 20 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
| 21 #include "content/public/browser/notification_registrar.h" | |
| 22 #include "content/public/browser/notification_source.h" | |
| 23 #include "content/public/browser/notification_types.h" | |
| 24 #include "content/public/browser/render_process_host.h" | 21 #include "content/public/browser/render_process_host.h" |
| 25 #include "content/public/browser/render_view_host.h" | 22 #include "content/public/browser/render_view_host.h" |
| 26 #include "content/public/browser/resource_context.h" | 23 #include "content/public/browser/resource_context.h" |
| 27 #include "content/public/browser/speech_recognition_manager.h" | 24 #include "content/public/browser/speech_recognition_manager.h" |
| 28 #include "content/public/browser/speech_recognition_session_config.h" | 25 #include "content/public/browser/speech_recognition_session_config.h" |
| 29 #include "content/public/browser/speech_recognition_session_context.h" | 26 #include "content/public/browser/speech_recognition_session_context.h" |
| 30 #include "content/public/browser/web_contents.h" | 27 #include "content/public/browser/web_contents.h" |
| 28 #include "content/public/browser/web_contents_observer.h" |
| 31 #include "content/public/common/speech_recognition_error.h" | 29 #include "content/public/common/speech_recognition_error.h" |
| 32 #include "content/public/common/speech_recognition_result.h" | 30 #include "content/public/common/speech_recognition_result.h" |
| 33 #include "net/url_request/url_request_context_getter.h" | 31 #include "net/url_request/url_request_context_getter.h" |
| 34 | 32 |
| 35 #if defined(OS_WIN) | 33 #if defined(OS_WIN) |
| 36 #include "chrome/installer/util/wmi.h" | 34 #include "chrome/installer/util/wmi.h" |
| 37 #endif | 35 #endif |
| 38 | 36 |
| 39 #if defined(ENABLE_EXTENSIONS) | 37 #if defined(ENABLE_EXTENSIONS) |
| 40 #include "chrome/browser/extensions/extension_service.h" | 38 #include "chrome/browser/extensions/extension_service.h" |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 | 128 |
| 131 DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo); | 129 DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo); |
| 132 }; | 130 }; |
| 133 | 131 |
| 134 // Simple utility to get notified when a WebContent (a tab or an extension's | 132 // Simple utility to get notified when a WebContent (a tab or an extension's |
| 135 // background page) is closed or crashes. The callback will always be called on | 133 // background page) is closed or crashes. The callback will always be called on |
| 136 // the UI thread. | 134 // the UI thread. |
| 137 // There is no restriction on the constructor, however this class must be | 135 // There is no restriction on the constructor, however this class must be |
| 138 // destroyed on the UI thread, due to the NotificationRegistrar dependency. | 136 // destroyed on the UI thread, due to the NotificationRegistrar dependency. |
| 139 class ChromeSpeechRecognitionManagerDelegate::TabWatcher | 137 class ChromeSpeechRecognitionManagerDelegate::TabWatcher |
| 140 : public base::RefCountedThreadSafe<TabWatcher>, | 138 : public base::RefCountedThreadSafe<TabWatcher> { |
| 141 public content::NotificationObserver { | |
| 142 public: | 139 public: |
| 143 typedef base::Callback<void(int render_process_id, int render_view_id)> | 140 typedef base::Callback<void(int render_process_id, int render_view_id)> |
| 144 TabClosedCallback; | 141 TabClosedCallback; |
| 145 | 142 |
| 146 explicit TabWatcher(TabClosedCallback tab_closed_callback) | 143 explicit TabWatcher(TabClosedCallback tab_closed_callback) |
| 147 : tab_closed_callback_(tab_closed_callback) { | 144 : tab_closed_callback_(tab_closed_callback) { |
| 148 } | 145 } |
| 149 | 146 |
| 150 // Starts monitoring the WebContents corresponding to the given | 147 // Starts monitoring the WebContents corresponding to the given |
| 151 // |render_process_id|, |render_view_id| pair, invoking |tab_closed_callback_| | 148 // |render_process_id|, |render_view_id| pair, invoking |tab_closed_callback_| |
| 152 // if closed/unloaded. | 149 // if closed/unloaded. |
| 153 void Watch(int render_process_id, int render_view_id) { | 150 void Watch(int render_process_id, int render_view_id) { |
| 154 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 151 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 155 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | 152 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
| 156 &TabWatcher::Watch, this, render_process_id, render_view_id)); | 153 &TabWatcher::Watch, this, render_process_id, render_view_id)); |
| 157 return; | 154 return; |
| 158 } | 155 } |
| 159 | 156 |
| 160 WebContents* web_contents = tab_util::GetWebContentsByID(render_process_id, | 157 WebContents* web_contents = tab_util::GetWebContentsByID(render_process_id, |
| 161 render_view_id); | 158 render_view_id); |
| 162 // Sessions initiated by speech input extension APIs will end up in a NULL | 159 // Sessions initiated by speech input extension APIs will end up in a NULL |
| 163 // WebContent here, but they are properly managed by the | 160 // WebContent here, but they are properly managed by the |
| 164 // chrome::SpeechInputExtensionManager. However, sessions initiated within a | 161 // chrome::SpeechInputExtensionManager. However, sessions initiated within a |
| 165 // extension using the (new) speech JS APIs, will be properly handled here. | 162 // extension using the (new) speech JS APIs, will be properly handled here. |
| 166 // TODO(primiano) turn this line into a DCHECK once speech input extension | 163 // TODO(primiano) turn this line into a DCHECK once speech input extension |
| 167 // API is deprecated. | 164 // API is deprecated. |
| 168 if (!web_contents) | 165 if (!web_contents) |
| 169 return; | 166 return; |
| 170 | 167 |
| 171 // Avoid multiple registrations on |registrar_| for the same |web_contents|. | 168 // Avoid multiple registrations for the same |web_contents|. |
| 172 if (FindWebContents(web_contents) != registered_web_contents_.end()) { | 169 if (FindWebContents(web_contents) != registered_web_contents_.end()) { |
| 173 return; | 170 return; |
| 174 } | 171 } |
| 175 registered_web_contents_.push_back( | 172 registered_web_contents_.push_back(new WebContentsTracker( |
| 176 WebContentsInfo(web_contents, render_process_id, render_view_id)); | 173 web_contents, base::Bind(&TabWatcher::OnTabClosed, |
| 177 | 174 // |this| outlives WebContentsTracker. |
| 178 // Lazy initialize the registrar. | 175 base::Unretained(this), web_contents), |
| 179 if (!registrar_.get()) | 176 render_process_id, render_view_id)); |
| 180 registrar_.reset(new content::NotificationRegistrar()); | |
| 181 | |
| 182 registrar_->Add(this, | |
| 183 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, | |
| 184 content::Source<WebContents>(web_contents)); | |
| 185 registrar_->Add(this, | |
| 186 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, | |
| 187 content::Source<WebContents>(web_contents)); | |
| 188 } | 177 } |
| 189 | 178 |
| 190 // content::NotificationObserver implementation. | 179 void OnTabClosed(content::WebContents* web_contents) { |
| 191 void Observe(int type, | 180 ScopedVector<WebContentsTracker>::iterator iter = |
| 192 const content::NotificationSource& source, | 181 FindWebContents(web_contents); |
| 193 const content::NotificationDetails& details) override { | |
| 194 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 195 DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED || | |
| 196 type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED); | |
| 197 | |
| 198 WebContents* web_contents = content::Source<WebContents>(source).ptr(); | |
| 199 std::vector<WebContentsInfo>::iterator iter = FindWebContents(web_contents); | |
| 200 DCHECK(iter != registered_web_contents_.end()); | 182 DCHECK(iter != registered_web_contents_.end()); |
| 201 int render_process_id = iter->render_process_id; | 183 int render_process_id = (*iter)->render_process_id(); |
| 202 int render_view_id = iter->render_view_id; | 184 int render_view_id = (*iter)->render_view_id(); |
| 203 registered_web_contents_.erase(iter); | 185 registered_web_contents_.erase(iter); |
| 204 | 186 |
| 205 registrar_->Remove(this, | |
| 206 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, | |
| 207 content::Source<WebContents>(web_contents)); | |
| 208 registrar_->Remove(this, | |
| 209 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, | |
| 210 content::Source<WebContents>(web_contents)); | |
| 211 | |
| 212 tab_closed_callback_.Run(render_process_id, render_view_id); | 187 tab_closed_callback_.Run(render_process_id, render_view_id); |
| 213 } | 188 } |
| 214 | 189 |
| 215 private: | 190 private: |
| 216 struct WebContentsInfo { | 191 class WebContentsTracker : public content::WebContentsObserver { |
| 217 WebContentsInfo(content::WebContents* web_contents, | 192 public: |
| 218 int render_process_id, | 193 WebContentsTracker(content::WebContents* web_contents, |
| 219 int render_view_id) | 194 const base::Closure& finished_callback, |
| 220 : web_contents(web_contents), | 195 int render_process_id, |
| 221 render_process_id(render_process_id), | 196 int render_view_id) |
| 222 render_view_id(render_view_id) {} | 197 : content::WebContentsObserver(web_contents), |
| 198 finished_callback_(finished_callback), |
| 199 render_process_id_(render_process_id), |
| 200 render_view_id_(render_view_id) {} |
| 223 | 201 |
| 224 ~WebContentsInfo() {} | 202 ~WebContentsTracker() override {} |
| 225 | 203 |
| 226 content::WebContents* web_contents; | 204 int render_process_id() const { return render_process_id_; } |
| 227 int render_process_id; | 205 int render_view_id() const { return render_view_id_; } |
| 228 int render_view_id; | 206 |
| 207 private: |
| 208 // content::WebContentsObserver overrides. |
| 209 void WebContentsDestroyed() override { |
| 210 Observe(nullptr); |
| 211 finished_callback_.Run(); |
| 212 // NOTE: We are deleted now. |
| 213 } |
| 214 void RenderViewHostChanged(content::RenderViewHost* old_host, |
| 215 content::RenderViewHost* new_host) override { |
| 216 Observe(nullptr); |
| 217 finished_callback_.Run(); |
| 218 // NOTE: We are deleted now. |
| 219 } |
| 220 |
| 221 const base::Closure finished_callback_; |
| 222 const int render_process_id_; |
| 223 const int render_view_id_; |
| 229 }; | 224 }; |
| 230 | 225 |
| 231 friend class base::RefCountedThreadSafe<TabWatcher>; | 226 friend class base::RefCountedThreadSafe<TabWatcher>; |
| 232 | 227 |
| 233 ~TabWatcher() override { | 228 ~TabWatcher() { |
| 234 // Must be destroyed on the UI thread due to |registrar_| non thread-safety. | 229 // Must be destroyed on the UI thread due to |registrar_| non thread-safety. |
| 230 // TODO(lazyboy): Do we still need this? |
| 235 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 231 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 236 } | 232 } |
| 237 | 233 |
| 238 // Helper function to find the iterator in |registered_web_contents_| which | 234 // Helper function to find the iterator in |registered_web_contents_| which |
| 239 // contains |web_contents|. | 235 // contains |web_contents|. |
| 240 std::vector<WebContentsInfo>::iterator FindWebContents( | 236 ScopedVector<WebContentsTracker>::iterator FindWebContents( |
| 241 content::WebContents* web_contents) { | 237 content::WebContents* web_contents) { |
| 242 for (std::vector<WebContentsInfo>::iterator i( | 238 for (ScopedVector<WebContentsTracker>::iterator i( |
| 243 registered_web_contents_.begin()); | 239 registered_web_contents_.begin()); |
| 244 i != registered_web_contents_.end(); ++i) { | 240 i != registered_web_contents_.end(); ++i) { |
| 245 if (i->web_contents == web_contents) | 241 if ((*i)->web_contents() == web_contents) |
| 246 return i; | 242 return i; |
| 247 } | 243 } |
| 248 | 244 |
| 249 return registered_web_contents_.end(); | 245 return registered_web_contents_.end(); |
| 250 } | 246 } |
| 251 | 247 |
| 252 // Lazy-initialized and used on the UI thread to handle web contents | |
| 253 // notifications (tab closing). | |
| 254 scoped_ptr<content::NotificationRegistrar> registrar_; | |
| 255 | |
| 256 // Keeps track of which WebContent(s) have been registered, in order to avoid | 248 // Keeps track of which WebContent(s) have been registered, in order to avoid |
| 257 // double registrations on |registrar_| and to pass the correct render | 249 // double registrations on WebContentsObserver and to pass the correct render |
| 258 // process id and render view id to |tab_closed_callback_| after the process | 250 // process id and render view id to |tab_closed_callback_| after the process |
| 259 // has gone away. | 251 // has gone away. |
| 260 std::vector<WebContentsInfo> registered_web_contents_; | 252 ScopedVector<WebContentsTracker> registered_web_contents_; |
| 261 | 253 |
| 262 // Callback used to notify, on the thread specified by |callback_thread_| the | 254 // Callback used to notify, on the thread specified by |callback_thread_| the |
| 263 // closure of a registered tab. | 255 // closure of a registered tab. |
| 264 TabClosedCallback tab_closed_callback_; | 256 TabClosedCallback tab_closed_callback_; |
| 265 | 257 |
| 266 DISALLOW_COPY_AND_ASSIGN(TabWatcher); | 258 DISALLOW_COPY_AND_ASSIGN(TabWatcher); |
| 267 }; | 259 }; |
| 268 | 260 |
| 269 ChromeSpeechRecognitionManagerDelegate | 261 ChromeSpeechRecognitionManagerDelegate |
| 270 ::ChromeSpeechRecognitionManagerDelegate() { | 262 ::ChromeSpeechRecognitionManagerDelegate() { |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 // Otherwise this should be a regular tab contents. | 426 // Otherwise this should be a regular tab contents. |
| 435 allowed = true; | 427 allowed = true; |
| 436 check_permission = true; | 428 check_permission = true; |
| 437 #endif | 429 #endif |
| 438 | 430 |
| 439 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 431 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 440 base::Bind(callback, check_permission, allowed)); | 432 base::Bind(callback, check_permission, allowed)); |
| 441 } | 433 } |
| 442 | 434 |
| 443 } // namespace speech | 435 } // namespace speech |
| OLD | NEW |