tab_helper.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Use of this source code is governed by a BSD-style license that can be
3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// found in the LICENSE file.
4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/tab_helper.h"
6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/chrome_notification_types.h"
8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/activity_log/activity_log.h"
9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/api/declarative/rules_registry_service.h"
10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/api/declarative_content/content_rules_registry.h"
11e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/crx_installer.h"
12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/extension_action.h"
13e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/extension_action_manager.h"
14e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/extension_service.h"
15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/extension_system.h"
16e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/extension_tab_util.h"
17c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "chrome/browser/extensions/image_loader.h"
18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/page_action_controller.h"
19e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/script_badge_controller.h"
20e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/script_bubble_controller.h"
21c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "chrome/browser/extensions/script_executor.h"
22e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/extensions/webstore_inline_installer.h"
23e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/profiles/profile.h"
24a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "chrome/browser/sessions/session_id.h"
25a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "chrome/browser/sessions/session_tab_helper.h"
26e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/ui/browser_dialogs.h"
27e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/ui/web_applications/web_app_ui.h"
28e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/browser/web_applications/web_app.h"
29a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "chrome/common/extensions/extension.h"
30e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/common/extensions/extension_constants.h"
31e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/common/extensions/extension_icon_set.h"
32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/common/extensions/extension_messages.h"
33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/common/extensions/feature_switch.h"
34e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
35e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
36c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "content/public/browser/invalidate_type.h"
37c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "content/public/browser/navigation_controller.h"
38e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "content/public/browser/navigation_details.h"
39c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "content/public/browser/navigation_entry.h"
40c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "content/public/browser/notification_service.h"
41c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "content/public/browser/notification_source.h"
42c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "content/public/browser/notification_types.h"
43c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "content/public/browser/render_process_host.h"
44e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "content/public/browser/render_view_host.h"
45e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "content/public/browser/render_widget_host_view.h"
46e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "content/public/browser/web_contents.h"
47e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "content/public/browser/web_contents_view.h"
48e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "extensions/common/extension_resource.h"
49e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "ui/gfx/image/image.h"
50c55a96383497a772a307b346368133960b02ad03Eric Laurent
51c55a96383497a772a307b346368133960b02ad03Eric Laurentusing content::NavigationController;
52c55a96383497a772a307b346368133960b02ad03Eric Laurentusing content::NavigationEntry;
53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentusing content::RenderViewHost;
54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentusing content::WebContents;
55e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
56e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentDEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::TabHelper);
57c55a96383497a772a307b346368133960b02ad03Eric Laurent
58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentnamespace {
59e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
60c55a96383497a772a307b346368133960b02ad03Eric Laurentconst char kPermissionError[] = "permission_error";
61e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
62e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}  // namespace
63e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
64e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentnamespace extensions {
65c55a96383497a772a307b346368133960b02ad03Eric Laurent
66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentTabHelper::ScriptExecutionObserver::ScriptExecutionObserver(
67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    TabHelper* tab_helper)
68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    : tab_helper_(tab_helper) {
69e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  tab_helper_->AddScriptExecutionObserver(this);
70c55a96383497a772a307b346368133960b02ad03Eric Laurent}
71e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
72e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentTabHelper::ScriptExecutionObserver::ScriptExecutionObserver()
73e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    : tab_helper_(NULL) {
74e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
75e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentTabHelper::ScriptExecutionObserver::~ScriptExecutionObserver() {
77e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (tab_helper_)
78c55a96383497a772a307b346368133960b02ad03Eric Laurent    tab_helper_->RemoveScriptExecutionObserver(this);
79e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
80e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
81e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentTabHelper::TabHelper(content::WebContents* web_contents)
82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    : content::WebContentsObserver(web_contents),
83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      extension_app_(NULL),
84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      extension_function_dispatcher_(
85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          Profile::FromBrowserContext(web_contents->GetBrowserContext()), this),
86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      pending_web_app_action_(NONE),
87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      script_executor_(new ScriptExecutor(web_contents,
88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                          &script_execution_observers_)),
89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      image_loader_ptr_factory_(this) {
90e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // The ActiveTabPermissionManager requires a session ID; ensure this
91e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // WebContents has one.
92e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  SessionTabHelper::CreateForWebContents(web_contents);
93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (web_contents->GetRenderViewHost())
94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    SetTabId(web_contents->GetRenderViewHost());
95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  active_tab_permission_granter_.reset(new ActiveTabPermissionGranter(
96a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      web_contents,
97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      SessionID::IdForTab(web_contents),
98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      Profile::FromBrowserContext(web_contents->GetBrowserContext())));
99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (FeatureSwitch::script_badges()->IsEnabled()) {
100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    location_bar_controller_.reset(
101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        new ScriptBadgeController(web_contents, this));
102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  } else {
103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    location_bar_controller_.reset(
104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        new PageActionController(web_contents));
105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (FeatureSwitch::script_bubble()->IsEnabled()) {
108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    script_bubble_controller_.reset(
109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        new ScriptBubbleController(web_contents, this));
110a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  }
111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // If more classes need to listen to global content script activity, then
114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // a separate routing class with an observer interface should be written.
115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  AddScriptExecutionObserver(ActivityLog::GetInstance(profile_));
117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  registrar_.Add(this,
119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                 content::NOTIFICATION_LOAD_STOP,
120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                 content::Source<NavigationController>(
121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                     &web_contents->GetController()));
122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  registrar_.Add(this,
124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                 chrome::NOTIFICATION_EXTENSION_UNLOADED,
125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                 content::NotificationService::AllSources());
126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
127e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentTabHelper::~TabHelper() {
129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  RemoveScriptExecutionObserver(ActivityLog::GetInstance(profile_));
130c55a96383497a772a307b346368133960b02ad03Eric Laurent}
131c55a96383497a772a307b346368133960b02ad03Eric Laurent
132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::CreateApplicationShortcuts() {
133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  DCHECK(CanCreateApplicationShortcuts());
134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  NavigationEntry* entry =
135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      web_contents()->GetController().GetLastCommittedEntry();
136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (!entry)
137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return;
138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  pending_web_app_action_ = CREATE_SHORTCUT;
140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // Start fetching web app info for CreateApplicationShortcut dialog and show
142a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  // the dialog when the data is available in OnDidGetApplicationInfo.
143a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  GetApplicationInfo(entry->GetPageID());
144a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
145a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
146a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool TabHelper::CanCreateApplicationShortcuts() const {
147a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#if defined(OS_MACOSX)
148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return false;
149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#else
150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return web_app::IsValidUrl(web_contents()->GetURL()) &&
151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      pending_web_app_action_ == NONE;
152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif
153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::SetExtensionApp(const Extension* extension) {
156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  DCHECK(!extension || AppLaunchInfo::GetFullLaunchURL(extension).is_valid());
157e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  extension_app_ = extension;
158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  UpdateExtensionAppIcon(extension_app_);
160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  content::NotificationService::current()->Notify(
162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      content::Source<TabHelper>(this),
164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      content::NotificationService::NoDetails());
165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::SetExtensionAppById(const std::string& extension_app_id) {
168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  const Extension* extension = GetExtension(extension_app_id);
169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (extension)
170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    SetExtensionApp(extension);
171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
173e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::SetExtensionAppIconById(const std::string& extension_app_id) {
174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  const Extension* extension = GetExtension(extension_app_id);
175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (extension)
176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    UpdateExtensionAppIcon(extension);
177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
179e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentSkBitmap* TabHelper::GetExtensionAppIcon() {
180e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (extension_app_icon_.empty())
181e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return NULL;
182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return &extension_app_icon_;
184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::RenderViewCreated(RenderViewHost* render_view_host) {
187e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  SetTabId(render_view_host);
188e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
189e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
190e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::DidNavigateMainFrame(
191e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const content::LoadCommittedDetails& details,
192e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const content::FrameNavigateParams& params) {
193e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#if defined(ENABLE_EXTENSIONS)
194e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (ExtensionSystem::Get(profile_)->extension_service() &&
195e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      RulesRegistryService::Get(profile_)) {
196e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    RulesRegistryService::Get(profile_)->content_rules_registry()->
197e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        DidNavigateMainFrame(web_contents(), details, params);
198e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
199e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif  // defined(ENABLE_EXTENSIONS)
200e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
201e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (details.is_in_page)
202e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return;
203e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
204e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  Profile* profile =
205e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
206e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  ExtensionService* service = profile->GetExtensionService();
207e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (!service)
208e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return;
209e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
210e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  ExtensionActionManager* extension_action_manager =
211e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      ExtensionActionManager::Get(profile);
212e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  for (ExtensionSet::const_iterator it = service->extensions()->begin();
213e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent       it != service->extensions()->end(); ++it) {
214e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ExtensionAction* browser_action =
215e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        extension_action_manager->GetBrowserAction(*it->get());
216e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (browser_action) {
217e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      browser_action->ClearAllValuesForTab(SessionID::IdForTab(web_contents()));
218e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      content::NotificationService::current()->Notify(
219e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED,
220e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          content::Source<ExtensionAction>(browser_action),
221e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          content::NotificationService::NoDetails());
222e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
223e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
224e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
225e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
226e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool TabHelper::OnMessageReceived(const IPC::Message& message) {
227e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  bool handled = true;
228e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  IPC_BEGIN_MESSAGE_MAP(TabHelper, message)
229e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    IPC_MESSAGE_HANDLER(ExtensionHostMsg_DidGetApplicationInfo,
230e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                        OnDidGetApplicationInfo)
231e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    IPC_MESSAGE_HANDLER(ExtensionHostMsg_InlineWebstoreInstall,
232e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                        OnInlineWebstoreInstall)
233e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    IPC_MESSAGE_HANDLER(ExtensionHostMsg_GetAppInstallState,
234e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                        OnGetAppInstallState);
235e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
236e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    IPC_MESSAGE_HANDLER(ExtensionHostMsg_ContentScriptsExecuting,
237e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                        OnContentScriptsExecuting)
238e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    IPC_MESSAGE_HANDLER(ExtensionHostMsg_OnWatchedPageChange,
239e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                        OnWatchedPageChange)
240e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    IPC_MESSAGE_UNHANDLED(handled = false)
241e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  IPC_END_MESSAGE_MAP()
242e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return handled;
243e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::DidCloneToNewWebContents(WebContents* old_web_contents,
246e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                         WebContents* new_web_contents) {
247e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // When the WebContents that this is attached to is cloned, give the new clone
248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // a TabHelper and copy state over.
249e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CreateForWebContents(new_web_contents);
250e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  TabHelper* new_helper = FromWebContents(new_web_contents);
251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
252e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  new_helper->SetExtensionApp(extension_app());
253e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  new_helper->extension_app_icon_ = extension_app_icon_;
254e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
256e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
257e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::OnDidGetApplicationInfo(int32 page_id,
258e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                        const WebApplicationInfo& info) {
259e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // Android does not implement BrowserWindow.
260e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  web_app_info_ = info;
262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
263e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  NavigationEntry* entry =
264e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      web_contents()->GetController().GetLastCommittedEntry();
265e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (!entry || (entry->GetPageID() != page_id))
266e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return;
267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
268e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  switch (pending_web_app_action_) {
269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    case CREATE_SHORTCUT: {
270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      chrome::ShowCreateWebAppShortcutsDialog(
271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          web_contents()->GetView()->GetTopLevelNativeWindow(),
272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          web_contents());
273e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      break;
274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    case UPDATE_SHORTCUT: {
276e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      web_app::UpdateShortcutForTabContents(web_contents());
277e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      break;
278e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
279e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    default:
280e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      NOTREACHED();
281e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      break;
282e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
283e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
284e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  pending_web_app_action_ = NONE;
285e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif
286e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
287e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
288e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::OnInlineWebstoreInstall(
289e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int install_id,
290e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int return_route_id,
291e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const std::string& webstore_item_id,
292e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const GURL& requestor_url) {
293e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  WebstoreStandaloneInstaller::Callback callback =
294e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      base::Bind(&TabHelper::OnInlineInstallComplete, base::Unretained(this),
295e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                 install_id, return_route_id);
296e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  scoped_refptr<WebstoreInlineInstaller> installer(
297e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      new WebstoreInlineInstaller(
298e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          web_contents(),
299e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          webstore_item_id,
300e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          requestor_url,
301e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          callback));
302e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  installer->BeginInstall();
303e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
304e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
305e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::OnGetAppInstallState(const GURL& requestor_url,
306e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                     int return_route_id,
307e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                     int callback_id) {
308e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  Profile* profile =
309e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
310e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  ExtensionService* extension_service = profile->GetExtensionService();
311e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  const ExtensionSet* extensions = extension_service->extensions();
312e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  const ExtensionSet* disabled = extension_service->disabled_extensions();
313e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
314e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  ExtensionURLInfo url(requestor_url);
315e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  std::string state;
316e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (extensions->GetHostedAppByURL(url))
317e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    state = extension_misc::kAppStateInstalled;
318e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  else if (disabled->GetHostedAppByURL(url))
319e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    state = extension_misc::kAppStateDisabled;
320e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  else
321e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    state = extension_misc::kAppStateNotInstalled;
322e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
323e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  Send(new ExtensionMsg_GetAppInstallStateResponse(
324e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return_route_id, state, callback_id));
325e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
326e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
327e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::OnRequest(const ExtensionHostMsg_Request_Params& request) {
328e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  extension_function_dispatcher_.Dispatch(request,
329e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                          web_contents()->GetRenderViewHost());
330e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
331e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
332e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::OnContentScriptsExecuting(
333e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const ScriptExecutionObserver::ExecutingScriptsMap& executing_scripts_map,
334e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int32 on_page_id,
335e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const GURL& on_url) {
336e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  FOR_EACH_OBSERVER(ScriptExecutionObserver, script_execution_observers_,
337e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                    OnScriptsExecuted(web_contents(),
338e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                      executing_scripts_map,
339a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                      on_page_id,
340e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                      on_url));
341e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
342e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
343e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::OnWatchedPageChange(
344e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const std::vector<std::string>& css_selectors) {
345e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#if defined(ENABLE_EXTENSIONS)
346e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (ExtensionSystem::Get(profile_)->extension_service() &&
347e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      RulesRegistryService::Get(profile_)) {
348e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    RulesRegistryService::Get(profile_)->content_rules_registry()->Apply(
349e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        web_contents(), css_selectors);
350e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
351e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif  // defined(ENABLE_EXTENSIONS)
352e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
353a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
354e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentconst Extension* TabHelper::GetExtension(const std::string& extension_app_id) {
355e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (extension_app_id.empty())
356e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return NULL;
357e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
358e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  Profile* profile =
359e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
360e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  ExtensionService* extension_service = profile->GetExtensionService();
361e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (!extension_service || !extension_service->is_ready())
362e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return NULL;
363e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
364e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  const Extension* extension =
365e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      extension_service->GetExtensionById(extension_app_id, false);
366e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return extension;
367e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
368e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
369e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::UpdateExtensionAppIcon(const Extension* extension) {
370e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  extension_app_icon_.reset();
371e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // Ensure previously enqueued callbacks are ignored.
372e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  image_loader_ptr_factory_.InvalidateWeakPtrs();
373e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
374a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  // Enqueue OnImageLoaded callback.
375e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (extension) {
376e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    Profile* profile =
377e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        Profile::FromBrowserContext(web_contents()->GetBrowserContext());
378e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile);
379e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    loader->LoadImageAsync(
380e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        extension,
381e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        IconsInfo::GetIconResource(extension,
382e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                   extension_misc::EXTENSION_ICON_SMALLISH,
383e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                   ExtensionIconSet::MATCH_EXACTLY),
384e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        gfx::Size(extension_misc::EXTENSION_ICON_SMALLISH,
385e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                  extension_misc::EXTENSION_ICON_SMALLISH),
386e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        base::Bind(&TabHelper::OnImageLoaded,
387e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                   image_loader_ptr_factory_.GetWeakPtr()));
388e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
389e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
390e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
391e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::SetAppIcon(const SkBitmap& app_icon) {
392e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  extension_app_icon_ = app_icon;
393e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TITLE);
394e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
395e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
396e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::OnImageLoaded(const gfx::Image& image) {
397e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (!image.IsEmpty()) {
398e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    extension_app_icon_ = *image.ToSkBitmap();
399e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB);
400e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
401e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
402e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
403e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWindowController* TabHelper::GetExtensionWindowController() const  {
404e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return ExtensionTabUtil::GetWindowControllerOfTab(web_contents());
405e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
406e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
407e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::OnInlineInstallComplete(int install_id,
408e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                        int return_route_id,
409e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                        bool success,
410e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                        const std::string& error) {
411e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  Send(new ExtensionMsg_InlineWebstoreInstallResponse(
412e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return_route_id, install_id, success, success ? std::string() : error));
413e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
414e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
415e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebContents* TabHelper::GetAssociatedWebContents() const {
416e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return web_contents();
417e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
418e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
419e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::GetApplicationInfo(int32 page_id) {
420e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  Send(new ExtensionMsg_GetApplicationInfo(routing_id(), page_id));
421e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
422e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
423e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::Observe(int type,
424a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                        const content::NotificationSource& source,
425a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                        const content::NotificationDetails& details) {
426a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  switch (type) {
427a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    case content::NOTIFICATION_LOAD_STOP: {
428a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      const NavigationController& controller =
429a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin          *content::Source<NavigationController>(source).ptr();
430a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      DCHECK_EQ(controller.GetWebContents(), web_contents());
431a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
432e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      if (pending_web_app_action_ == UPDATE_SHORTCUT) {
433e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // Schedule a shortcut update when web application info is available if
434e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // last committed entry is not NULL. Last committed entry could be NULL
435e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // when an interstitial page is injected (e.g. bad https certificate,
436e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // malware site etc). When this happens, we abort the shortcut update.
437e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        NavigationEntry* entry = controller.GetLastCommittedEntry();
438e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        if (entry)
439e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          GetApplicationInfo(entry->GetPageID());
440e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        else
441e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          pending_web_app_action_ = NONE;
442e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      }
443e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      break;
444e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
445e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
446e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
447e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      if (script_bubble_controller_) {
448e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        script_bubble_controller_->OnExtensionUnloaded(
449e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            content::Details<extensions::UnloadedExtensionInfo>(
450e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                details)->extension->id());
451e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        break;
452e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      }
453e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
454e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
455e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
456e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
457e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid TabHelper::SetTabId(RenderViewHost* render_view_host) {
458e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  render_view_host->Send(
459e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      new ExtensionMsg_SetTabId(render_view_host->GetRoutingID(),
460e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                SessionID::IdForTab(web_contents())));
461e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
462e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
463e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}  // namespace extensions
464e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent