1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/extension_tab_helper.h"
6
7 #include "chrome/browser/extensions/extension_service.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
10 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h"
11 #include "chrome/common/extensions/extension_action.h"
12 #include "chrome/common/extensions/extension_icon_set.h"
13 #include "chrome/common/extensions/extension_messages.h"
14 #include "chrome/common/extensions/extension_resource.h"
15 #include "content/browser/tab_contents/tab_contents.h"
16 #include "content/browser/tab_contents/navigation_controller.h"
17 #include "content/common/notification_service.h"
18
ExtensionTabHelper(TabContentsWrapper * wrapper)19 ExtensionTabHelper::ExtensionTabHelper(TabContentsWrapper* wrapper)
20 : TabContentsObserver(wrapper->tab_contents()),
21 extension_app_(NULL),
22 wrapper_(wrapper) {
23 }
24
~ExtensionTabHelper()25 ExtensionTabHelper::~ExtensionTabHelper() {
26 }
27
CopyStateFrom(const ExtensionTabHelper & source)28 void ExtensionTabHelper::CopyStateFrom(const ExtensionTabHelper& source) {
29 SetExtensionApp(source.extension_app());
30 extension_app_icon_ = source.extension_app_icon_;
31 }
32
PageActionStateChanged()33 void ExtensionTabHelper::PageActionStateChanged() {
34 tab_contents()->NotifyNavigationStateChanged(
35 TabContents::INVALIDATE_PAGE_ACTIONS);
36 }
37
GetApplicationInfo(int32 page_id)38 void ExtensionTabHelper::GetApplicationInfo(int32 page_id) {
39 Send(new ExtensionMsg_GetApplicationInfo(routing_id(), page_id));
40 }
41
SetExtensionApp(const Extension * extension)42 void ExtensionTabHelper::SetExtensionApp(const Extension* extension) {
43 DCHECK(!extension || extension->GetFullLaunchURL().is_valid());
44 extension_app_ = extension;
45
46 UpdateExtensionAppIcon(extension_app_);
47
48 NotificationService::current()->Notify(
49 NotificationType::TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
50 Source<ExtensionTabHelper>(this),
51 NotificationService::NoDetails());
52 }
53
SetExtensionAppById(const std::string & extension_app_id)54 void ExtensionTabHelper::SetExtensionAppById(
55 const std::string& extension_app_id) {
56 if (extension_app_id.empty())
57 return;
58
59 ExtensionService* extension_service =
60 tab_contents()->profile()->GetExtensionService();
61 if (!extension_service || !extension_service->is_ready())
62 return;
63
64 const Extension* extension =
65 extension_service->GetExtensionById(extension_app_id, false);
66 if (extension)
67 SetExtensionApp(extension);
68 }
69
GetExtensionAppIcon()70 SkBitmap* ExtensionTabHelper::GetExtensionAppIcon() {
71 if (extension_app_icon_.empty())
72 return NULL;
73
74 return &extension_app_icon_;
75 }
76
DidNavigateMainFramePostCommit(const NavigationController::LoadCommittedDetails & details,const ViewHostMsg_FrameNavigate_Params & params)77 void ExtensionTabHelper::DidNavigateMainFramePostCommit(
78 const NavigationController::LoadCommittedDetails& details,
79 const ViewHostMsg_FrameNavigate_Params& params) {
80 if (details.is_in_page)
81 return;
82
83 ExtensionService* service = tab_contents()->profile()->GetExtensionService();
84 if (!service)
85 return;
86
87 for (size_t i = 0; i < service->extensions()->size(); ++i) {
88 ExtensionAction* browser_action =
89 service->extensions()->at(i)->browser_action();
90 if (browser_action) {
91 browser_action->ClearAllValuesForTab(
92 tab_contents()->controller().session_id().id());
93 NotificationService::current()->Notify(
94 NotificationType::EXTENSION_BROWSER_ACTION_UPDATED,
95 Source<ExtensionAction>(browser_action),
96 NotificationService::NoDetails());
97 }
98
99 ExtensionAction* page_action =
100 service->extensions()->at(i)->page_action();
101 if (page_action) {
102 page_action->ClearAllValuesForTab(
103 tab_contents()->controller().session_id().id());
104 PageActionStateChanged();
105 }
106 }
107 }
108
OnMessageReceived(const IPC::Message & message)109 bool ExtensionTabHelper::OnMessageReceived(const IPC::Message& message) {
110 bool handled = true;
111 IPC_BEGIN_MESSAGE_MAP(ExtensionTabHelper, message)
112 IPC_MESSAGE_HANDLER(ExtensionHostMsg_DidGetApplicationInfo,
113 OnDidGetApplicationInfo)
114 IPC_MESSAGE_HANDLER(ExtensionHostMsg_InstallApplication,
115 OnInstallApplication)
116 IPC_MESSAGE_UNHANDLED(handled = false)
117 IPC_END_MESSAGE_MAP()
118 return handled;
119 }
120
OnDidGetApplicationInfo(int32 page_id,const WebApplicationInfo & info)121 void ExtensionTabHelper::OnDidGetApplicationInfo(
122 int32 page_id, const WebApplicationInfo& info) {
123 web_app_info_ = info;
124
125 if (wrapper_->delegate())
126 wrapper_->delegate()->OnDidGetApplicationInfo(wrapper_, page_id);
127 }
128
OnInstallApplication(const WebApplicationInfo & info)129 void ExtensionTabHelper::OnInstallApplication(const WebApplicationInfo& info) {
130 if (wrapper_->delegate())
131 wrapper_->delegate()->OnInstallApplication(wrapper_, info);
132 }
133
UpdateExtensionAppIcon(const Extension * extension)134 void ExtensionTabHelper::UpdateExtensionAppIcon(const Extension* extension) {
135 extension_app_icon_.reset();
136
137 if (extension) {
138 extension_app_image_loader_.reset(new ImageLoadingTracker(this));
139 extension_app_image_loader_->LoadImage(
140 extension,
141 extension->GetIconResource(Extension::EXTENSION_ICON_SMALLISH,
142 ExtensionIconSet::MATCH_EXACTLY),
143 gfx::Size(Extension::EXTENSION_ICON_SMALLISH,
144 Extension::EXTENSION_ICON_SMALLISH),
145 ImageLoadingTracker::CACHE);
146 } else {
147 extension_app_image_loader_.reset(NULL);
148 }
149 }
150
SetAppIcon(const SkBitmap & app_icon)151 void ExtensionTabHelper::SetAppIcon(const SkBitmap& app_icon) {
152 extension_app_icon_ = app_icon;
153 tab_contents()->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE);
154 }
155
OnImageLoaded(SkBitmap * image,const ExtensionResource & resource,int index)156 void ExtensionTabHelper::OnImageLoaded(SkBitmap* image,
157 const ExtensionResource& resource,
158 int index) {
159 if (image) {
160 extension_app_icon_ = *image;
161 tab_contents()->NotifyNavigationStateChanged(TabContents::INVALIDATE_TAB);
162 }
163 }
164