123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// found in the LICENSE file.
423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/extensions/error_console/error_console.h"
823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/chrome_extension_messages.h"
1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/public/browser/browser_context.h"
1123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/public/browser/render_process_host.h"
1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/public/browser/render_view_host.h"
1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_registry.h"
1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_system.h"
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/common/extension_messages.h"
1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/common/extension_urls.h"
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using content::BrowserContext;
1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)DEFINE_WEB_CONTENTS_USER_DATA_KEY(
2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    extensions::ChromeExtensionWebContentsObserver);
2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace extensions {
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ChromeExtensionWebContentsObserver::ChromeExtensionWebContentsObserver(
2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    content::WebContents* web_contents)
2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : ExtensionWebContentsObserver(web_contents) {}
2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ChromeExtensionWebContentsObserver::~ChromeExtensionWebContentsObserver() {}
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ChromeExtensionWebContentsObserver::RenderViewCreated(
3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    content::RenderViewHost* render_view_host) {
3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ReloadIfTerminated(render_view_host);
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ExtensionWebContentsObserver::RenderViewCreated(render_view_host);
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ChromeExtensionWebContentsObserver::OnMessageReceived(
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const IPC::Message& message,
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    content::RenderFrameHost* render_frame_host) {
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool handled = true;
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(ChromeExtensionWebContentsObserver, message)
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ExtensionHostMsg_DetailedConsoleMessageAdded,
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                        OnDetailedConsoleMessageAdded)
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  IPC_END_MESSAGE_MAP()
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return handled;
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ChromeExtensionWebContentsObserver::OnDetailedConsoleMessageAdded(
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const base::string16& message,
5123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const base::string16& source,
5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const StackTrace& stack_trace,
5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    int32 severity_level) {
5423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!IsSourceFromAnExtension(source))
5523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
5623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
5723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  content::RenderViewHost* render_view_host =
5823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      web_contents()->GetRenderViewHost();
5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::string extension_id = GetExtensionId(render_view_host);
6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (extension_id.empty())
6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    extension_id = GURL(source).host();
6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ExtensionSystem::Get(browser_context())->error_console()->ReportError(
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      scoped_ptr<ExtensionError>(
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          new RuntimeError(extension_id,
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           browser_context()->IsOffTheRecord(),
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           source,
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           message,
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           stack_trace,
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           web_contents()->GetLastCommittedURL(),
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           static_cast<logging::LogSeverity>(severity_level),
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           render_view_host->GetRoutingID(),
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           render_view_host->GetProcess()->GetID())));
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ChromeExtensionWebContentsObserver::ReloadIfTerminated(
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    content::RenderViewHost* render_view_host) {
7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::string extension_id = GetExtensionId(render_view_host);
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (extension_id.empty())
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Reload the extension if it has crashed.
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // TODO(yoz): This reload doesn't happen synchronously for unpacked
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  //            extensions. It seems to be fast enough, but there is a race.
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  //            We should delay loading until the extension has reloaded.
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (registry->GetExtensionById(extension_id, ExtensionRegistry::TERMINATED)) {
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ExtensionSystem::Get(browser_context())->
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        extension_service()->ReloadExtension(extension_id);
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}  // namespace extensions
95