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/extensions/navigation_observer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_install_ui.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NavigationObserver::NavigationObserver(Profile* profile) : profile_(profile) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisterForNotifications();
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NavigationObserver::~NavigationObserver() {}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NavigationObserver::Observe(int type,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationSource& source,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationDetails& details) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type != content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigationController* controller =
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<NavigationController>(source).ptr();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile_->IsSameProfile(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Profile::FromBrowserContext(controller->GetBrowserContext())))
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PromptToEnableExtensionIfNecessary(controller);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NavigationObserver::RegisterForNotifications() {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NavigationObserver::PromptToEnableExtensionIfNecessary(
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NavigationController* nav_controller) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Bail out if we're already running a prompt.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!in_progress_prompt_extension_id_.empty())
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NavigationEntry* nav_entry = nav_controller->GetVisibleEntry();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nav_entry)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionRegistry* registry = extensions::ExtensionRegistry::Get(profile_);
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const Extension* extension =
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      registry->disabled_extensions().GetExtensionOrAppByURL(
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          nav_entry->GetURL());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try not to repeatedly prompt the user about the same extension.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prompted_extensions_.find(extension->id()) != prompted_extensions_.end())
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prompted_extensions_.insert(extension->id());
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension_prefs->DidExtensionEscalatePermissions(extension->id())) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Keep track of the extension id and nav controller we're prompting for.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // These must be reset in InstallUIProceed and InstallUIAbort.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    in_progress_prompt_extension_id_ = extension->id();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    in_progress_prompt_navigation_controller_ = nav_controller;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_install_prompt_.reset(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new ExtensionInstallPrompt(nav_controller->GetWebContents()));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_install_prompt_->ConfirmReEnable(this, extension);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NavigationObserver::InstallUIProceed() {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionService* extension_service =
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile_)->extension_service();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension = extension_service->GetExtensionById(
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      in_progress_prompt_extension_id_, true);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigationController* nav_controller =
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      in_progress_prompt_navigation_controller_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(extension);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(nav_controller);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in_progress_prompt_extension_id_ = "";
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in_progress_prompt_navigation_controller_ = NULL;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_install_prompt_.reset();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Grant permissions, re-enable the extension, and then reload the tab.
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension_service->GrantPermissionsAndEnableExtension(extension);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nav_controller->Reload(true);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NavigationObserver::InstallUIAbort(bool user_initiated) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionService* extension_service =
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile_)->extension_service();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension = extension_service->GetExtensionById(
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      in_progress_prompt_extension_id_, true);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in_progress_prompt_extension_id_ = "";
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in_progress_prompt_navigation_controller_ = NULL;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_install_prompt_.reset();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::string histogram_name = user_initiated
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                   ? "Extensions.Permissions_ReEnableCancel2"
11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                   : "Extensions.Permissions_ReEnableAbort2";
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionService::RecordPermissionMessagesHistogram(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension, histogram_name.c_str());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
123