Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / extension_view_host.cc
blobf739d46c14c6993ab7884a5ebc1cc34ea1585eb6
1 // Copyright 2013 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.
5 #include "chrome/browser/extensions/extension_view_host.h"
7 #include "base/strings/string_piece.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/extension_view.h"
11 #include "chrome/browser/extensions/window_controller.h"
12 #include "chrome/browser/file_select_helper.h"
13 #include "chrome/browser/platform_util.h"
14 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_dialogs.h"
17 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
18 #include "components/autofill/core/browser/autofill_manager.h"
19 #include "components/web_modal/web_contents_modal_dialog_manager.h"
20 #include "content/public/browser/notification_source.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/web_contents.h"
23 #include "extensions/browser/extension_system.h"
24 #include "extensions/browser/runtime_data.h"
25 #include "grit/browser_resources.h"
26 #include "third_party/WebKit/public/web/WebInputEvent.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/events/keycodes/keyboard_codes.h"
30 using content::NativeWebKeyboardEvent;
31 using content::OpenURLParams;
32 using content::RenderViewHost;
33 using content::WebContents;
34 using content::WebContentsObserver;
35 using web_modal::WebContentsModalDialogManager;
37 namespace extensions {
39 // Notifies an ExtensionViewHost when a WebContents is destroyed.
40 class ExtensionViewHost::AssociatedWebContentsObserver
41 : public WebContentsObserver {
42 public:
43 AssociatedWebContentsObserver(ExtensionViewHost* host,
44 WebContents* web_contents)
45 : WebContentsObserver(web_contents), host_(host) {}
46 ~AssociatedWebContentsObserver() override {}
48 // content::WebContentsObserver:
49 void WebContentsDestroyed() override {
50 // Deleting |this| from here is safe.
51 host_->SetAssociatedWebContents(NULL);
54 private:
55 ExtensionViewHost* host_;
57 DISALLOW_COPY_AND_ASSIGN(AssociatedWebContentsObserver);
60 ExtensionViewHost::ExtensionViewHost(
61 const Extension* extension,
62 content::SiteInstance* site_instance,
63 const GURL& url,
64 ViewType host_type)
65 : ExtensionHost(extension, site_instance, url, host_type),
66 associated_web_contents_(NULL) {
67 // Not used for panels, see PanelHost.
68 DCHECK(host_type == VIEW_TYPE_EXTENSION_DIALOG ||
69 host_type == VIEW_TYPE_EXTENSION_POPUP);
71 // Attach WebContents helpers. Extension tabs automatically get them attached
72 // in TabHelpers::AttachTabHelpers, but popups don't.
73 // TODO(kalman): How much of TabHelpers::AttachTabHelpers should be here?
74 autofill::ChromeAutofillClient::CreateForWebContents(host_contents());
75 autofill::ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
76 host_contents(),
77 autofill::ChromeAutofillClient::FromWebContents(host_contents()),
78 g_browser_process->GetApplicationLocale(),
79 autofill::AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
82 ExtensionViewHost::~ExtensionViewHost() {
83 // The hosting WebContents will be deleted in the base class, so unregister
84 // this object before it deletes the attached WebContentsModalDialogManager.
85 WebContentsModalDialogManager* manager =
86 WebContentsModalDialogManager::FromWebContents(host_contents());
87 if (manager)
88 manager->SetDelegate(NULL);
91 void ExtensionViewHost::CreateView(Browser* browser) {
92 view_ = CreateExtensionView(this, browser);
95 void ExtensionViewHost::SetAssociatedWebContents(WebContents* web_contents) {
96 associated_web_contents_ = web_contents;
97 if (associated_web_contents_) {
98 // Observe the new WebContents for deletion.
99 associated_web_contents_observer_.reset(
100 new AssociatedWebContentsObserver(this, associated_web_contents_));
101 } else {
102 associated_web_contents_observer_.reset();
106 void ExtensionViewHost::UnhandledKeyboardEvent(
107 WebContents* source,
108 const content::NativeWebKeyboardEvent& event) {
109 view_->HandleKeyboardEvent(source, event);
112 // ExtensionHost overrides:
114 void ExtensionViewHost::OnDidStopFirstLoad() {
115 view_->DidStopLoading();
118 void ExtensionViewHost::LoadInitialURL() {
119 if (!ExtensionSystem::Get(browser_context())->
120 runtime_data()->IsBackgroundPageReady(extension())) {
121 // Make sure the background page loads before any others.
122 registrar_.Add(this,
123 extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
124 content::Source<Extension>(extension()));
125 return;
128 // Popups may spawn modal dialogs, which need positioning information.
129 if (extension_host_type() == VIEW_TYPE_EXTENSION_POPUP) {
130 WebContentsModalDialogManager::CreateForWebContents(host_contents());
131 WebContentsModalDialogManager::FromWebContents(
132 host_contents())->SetDelegate(this);
133 if (!popup_manager_.get())
134 popup_manager_.reset(new web_modal::PopupManager(this));
135 popup_manager_->RegisterWith(host_contents());
138 ExtensionHost::LoadInitialURL();
141 bool ExtensionViewHost::IsBackgroundPage() const {
142 DCHECK(view_);
143 return false;
146 // content::WebContentsDelegate overrides:
148 WebContents* ExtensionViewHost::OpenURLFromTab(
149 WebContents* source,
150 const OpenURLParams& params) {
151 // Whitelist the dispositions we will allow to be opened.
152 switch (params.disposition) {
153 case SINGLETON_TAB:
154 case NEW_FOREGROUND_TAB:
155 case NEW_BACKGROUND_TAB:
156 case NEW_POPUP:
157 case NEW_WINDOW:
158 case SAVE_TO_DISK:
159 case OFF_THE_RECORD: {
160 // Only allow these from hosts that are bound to a browser (e.g. popups).
161 // Otherwise they are not driven by a user gesture.
162 Browser* browser = view_->GetBrowser();
163 return browser ? browser->OpenURL(params) : NULL;
165 default:
166 return NULL;
170 bool ExtensionViewHost::PreHandleKeyboardEvent(
171 WebContents* source,
172 const NativeWebKeyboardEvent& event,
173 bool* is_keyboard_shortcut) {
174 if (extension_host_type() == VIEW_TYPE_EXTENSION_POPUP &&
175 event.type == NativeWebKeyboardEvent::RawKeyDown &&
176 event.windowsKeyCode == ui::VKEY_ESCAPE) {
177 DCHECK(is_keyboard_shortcut != NULL);
178 *is_keyboard_shortcut = true;
179 return false;
182 // Handle higher priority browser shortcuts such as Ctrl-w.
183 Browser* browser = view_->GetBrowser();
184 if (browser)
185 return browser->PreHandleKeyboardEvent(source, event, is_keyboard_shortcut);
187 *is_keyboard_shortcut = false;
188 return false;
191 void ExtensionViewHost::HandleKeyboardEvent(
192 WebContents* source,
193 const NativeWebKeyboardEvent& event) {
194 if (extension_host_type() == VIEW_TYPE_EXTENSION_POPUP) {
195 if (event.type == NativeWebKeyboardEvent::RawKeyDown &&
196 event.windowsKeyCode == ui::VKEY_ESCAPE) {
197 Close();
198 return;
201 UnhandledKeyboardEvent(source, event);
204 bool ExtensionViewHost::PreHandleGestureEvent(
205 content::WebContents* source,
206 const blink::WebGestureEvent& event) {
207 // Disable pinch zooming.
208 return event.type == blink::WebGestureEvent::GesturePinchBegin ||
209 event.type == blink::WebGestureEvent::GesturePinchUpdate ||
210 event.type == blink::WebGestureEvent::GesturePinchEnd;
213 content::ColorChooser* ExtensionViewHost::OpenColorChooser(
214 WebContents* web_contents,
215 SkColor initial_color,
216 const std::vector<content::ColorSuggestion>& suggestions) {
217 // Similar to the file chooser below, opening a color chooser requires a
218 // visible <input> element to click on. Therefore this code only exists for
219 // extensions with a view.
220 return chrome::ShowColorChooser(web_contents, initial_color);
223 void ExtensionViewHost::RunFileChooser(
224 WebContents* tab,
225 const content::FileChooserParams& params) {
226 // For security reasons opening a file picker requires a visible <input>
227 // element to click on, so this code only exists for extensions with a view.
228 FileSelectHelper::RunFileChooser(tab, params);
232 void ExtensionViewHost::ResizeDueToAutoResize(WebContents* source,
233 const gfx::Size& new_size) {
234 view_->ResizeDueToAutoResize(new_size);
237 // content::WebContentsObserver overrides:
239 void ExtensionViewHost::RenderViewCreated(RenderViewHost* render_view_host) {
240 ExtensionHost::RenderViewCreated(render_view_host);
241 view_->RenderViewCreated();
244 // web_modal::WebContentsModalDialogManagerDelegate overrides:
246 web_modal::WebContentsModalDialogHost*
247 ExtensionViewHost::GetWebContentsModalDialogHost() {
248 return this;
251 bool ExtensionViewHost::IsWebContentsVisible(WebContents* web_contents) {
252 return platform_util::IsVisible(web_contents->GetNativeView());
255 gfx::NativeView ExtensionViewHost::GetHostView() const {
256 return view_->GetNativeView();
259 gfx::Point ExtensionViewHost::GetDialogPosition(const gfx::Size& size) {
260 if (!GetVisibleWebContents())
261 return gfx::Point();
262 gfx::Rect bounds = GetVisibleWebContents()->GetViewBounds();
263 return gfx::Point(
264 std::max(0, (bounds.width() - size.width()) / 2),
265 std::max(0, (bounds.height() - size.height()) / 2));
268 gfx::Size ExtensionViewHost::GetMaximumDialogSize() {
269 if (!GetVisibleWebContents())
270 return gfx::Size();
271 return GetVisibleWebContents()->GetViewBounds().size();
274 void ExtensionViewHost::AddObserver(
275 web_modal::ModalDialogHostObserver* observer) {
278 void ExtensionViewHost::RemoveObserver(
279 web_modal::ModalDialogHostObserver* observer) {
282 WindowController* ExtensionViewHost::GetExtensionWindowController() const {
283 Browser* browser = view_->GetBrowser();
284 return browser ? browser->extension_window_controller() : NULL;
287 WebContents* ExtensionViewHost::GetAssociatedWebContents() const {
288 return associated_web_contents_;
291 WebContents* ExtensionViewHost::GetVisibleWebContents() const {
292 if (associated_web_contents_)
293 return associated_web_contents_;
294 if (extension_host_type() == VIEW_TYPE_EXTENSION_POPUP)
295 return host_contents();
296 return NULL;
299 void ExtensionViewHost::Observe(int type,
300 const content::NotificationSource& source,
301 const content::NotificationDetails& details) {
302 DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY);
303 DCHECK(ExtensionSystem::Get(browser_context())
304 ->runtime_data()
305 ->IsBackgroundPageReady(extension()));
306 LoadInitialURL();
309 } // namespace extensions