15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_message_filter.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <algorithm>
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <functional>
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/utf_string_conversions.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_factory.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_host_metrics.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_service.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/spellchecker/spelling_service_client.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/spellcheck_marker.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/spellcheck_messages.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpellCheckMessageFilter::SpellCheckMessageFilter(int render_process_id)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : render_process_id_(render_process_id),
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_(new SpellingServiceClient) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OverrideThreadForMessage(
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& message, BrowserThread::ID* thread) {
33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // IPC messages arrive on IO thread, but spellcheck data lives on UI thread.
34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // The message filter overrides the thread for these messages because they
35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // access spellcheck data.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message.type() == SpellCheckHostMsg_RequestDictionary::ID ||
37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      message.type() == SpellCheckHostMsg_NotifyChecked::ID ||
38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      message.type() == SpellCheckHostMsg_RespondDocumentMarkers::ID)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *thread = BrowserThread::UI;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message.type() == SpellCheckHostMsg_CallSpellingService::ID)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *thread = BrowserThread::UI;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpellCheckMessageFilter::OnMessageReceived(const IPC::Message& message,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                bool* message_was_ok) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP_EX(SpellCheckMessageFilter, message, *message_was_ok)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestDictionary,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnSpellCheckerRequestDictionary)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(SpellCheckHostMsg_NotifyChecked,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnNotifyChecked)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RespondDocumentMarkers,
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        OnRespondDocumentMarkers)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(SpellCheckHostMsg_CallSpellingService,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnCallSpellingService)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpellCheckMessageFilter::~SpellCheckMessageFilter() {}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OnSpellCheckerRequestDictionary() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RenderProcessHost* host =
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost::FromID(render_process_id_);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!host)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Teardown.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The renderer has requested that we initialize its spellchecker. This should
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // generally only be called once per session, as after the first call, all
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // future renderers will be passed the initialization information on startup
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (or when the dictionary changes in some way).
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SpellcheckServiceFactory::GetForProfile(profile);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(spellcheck_service);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The spellchecker initialization already started and finished; just send
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it to the renderer.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  spellcheck_service->InitForRenderer(host);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(rlp): Ensure that we do not initialize the hunspell dictionary more
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // than once if we get requests from different renderers.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OnNotifyChecked(const string16& word,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              bool misspelled) {
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpellcheckService* spellcheck = GetSpellcheckService();
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Spellcheck service may not be available for a renderer process that is
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // shutting down.
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!spellcheck)
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (spellcheck->GetMetrics())
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spellcheck->GetMetrics()->RecordCheckedWordStats(word, misspelled);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpellCheckMessageFilter::OnRespondDocumentMarkers(
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<uint32>& markers) {
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpellcheckService* spellcheck = GetSpellcheckService();
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Spellcheck service may not be available for a renderer process that is
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // shutting down.
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!spellcheck)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  spellcheck->GetFeedbackSender()->OnReceiveDocumentMarkers(
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      render_process_id_, markers);
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OnCallSpellingService(
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int identifier,
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const string16& text,
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::vector<SpellCheckMarker> markers) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!text.empty());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Erase invalid markers (with offsets out of boundaries of text length).
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  markers.erase(
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      std::remove_if(
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          markers.begin(),
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          markers.end(),
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          std::not1(SpellCheckMarker::IsValidPredicate(text.length()))),
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      markers.end());
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CallSpellingService(text, route_id, identifier, markers);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpellCheckMessageFilter::OnTextCheckComplete(
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int route_id,
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int identifier,
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::vector<SpellCheckMarker>& markers,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& text,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<SpellCheckResult>& results) {
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpellcheckService* spellcheck = GetSpellcheckService();
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Spellcheck service may not be available for a renderer process that is
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // shutting down.
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!spellcheck)
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<SpellCheckResult> results_copy = results;
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  spellcheck->GetFeedbackSender()->OnSpellcheckResults(
143bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      render_process_id_, text, markers, &results_copy);
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Erase custom dictionary words from the spellcheck results and record
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // in-dictionary feedback.
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<SpellCheckResult>::iterator write_iter;
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<SpellCheckResult>::iterator iter;
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string text_copy = UTF16ToUTF8(text);
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (iter = write_iter = results_copy.begin();
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       iter != results_copy.end();
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++iter) {
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (spellcheck->GetCustomDictionary()->HasWord(
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            text_copy.substr(iter->location, iter->length))) {
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spellcheck->GetFeedbackSender()->RecordInDictionary(iter->hash);
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else {
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (write_iter != iter)
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        *write_iter = *iter;
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ++write_iter;
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  results_copy.erase(write_iter, results_copy.end());
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Send(new SpellCheckMsg_RespondSpellingService(
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      route_id, identifier, success, text, results_copy));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CallSpellingService always executes the callback OnTextCheckComplete.
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (Which, in turn, sends a SpellCheckMsg_RespondSpellingService)
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SpellCheckMessageFilter::CallSpellingService(
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const string16& text,
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int route_id,
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int identifier,
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::vector<SpellCheckMarker>& markers) {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Profile* profile = NULL;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RenderProcessHost* host =
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost::FromID(render_process_id_);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (host)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    profile = Profile::FromBrowserContext(host->GetBrowserContext());
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_->RequestTextCheck(
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    profile,
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SpellingServiceClient::SPELLCHECK,
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    text,
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Bind(&SpellCheckMessageFilter::OnTextCheckComplete,
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               base::Unretained(this),
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               route_id,
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               identifier,
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               markers));
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpellcheckService* SpellCheckMessageFilter::GetSpellcheckService() const {
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_);
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
196