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.
4
5#include "chrome/browser/extensions/chrome_extension_function.h"
6
7#include "chrome/browser/extensions/window_controller.h"
8#include "chrome/browser/extensions/window_controller_list.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/ui/browser.h"
11#include "chrome/browser/ui/browser_finder.h"
12#include "chrome/browser/ui/tabs/tab_strip_model.h"
13#include "content/public/browser/render_process_host.h"
14#include "content/public/browser/render_view_host.h"
15#include "extensions/browser/extension_function_dispatcher.h"
16
17using content::RenderViewHost;
18using content::WebContents;
19
20ChromeUIThreadExtensionFunction::ChromeUIThreadExtensionFunction() {
21}
22
23Profile* ChromeUIThreadExtensionFunction::GetProfile() const {
24  return Profile::FromBrowserContext(context_);
25}
26
27bool ChromeUIThreadExtensionFunction::CanOperateOnWindow(
28    const extensions::WindowController* window_controller) const {
29  const extensions::Extension* extension = GetExtension();
30  // |extension| is NULL for unit tests only.
31  if (extension != NULL && !window_controller->IsVisibleToExtension(extension))
32    return false;
33
34  if (GetProfile() == window_controller->profile())
35    return true;
36
37  if (!include_incognito())
38    return false;
39
40  return GetProfile()->HasOffTheRecordProfile() &&
41         GetProfile()->GetOffTheRecordProfile() == window_controller->profile();
42}
43
44// TODO(stevenjb): Replace this with GetExtensionWindowController().
45Browser* ChromeUIThreadExtensionFunction::GetCurrentBrowser() {
46  // If the delegate has an associated browser, return it.
47  if (dispatcher()) {
48    extensions::WindowController* window_controller =
49        dispatcher()->delegate()->GetExtensionWindowController();
50    if (window_controller) {
51      Browser* browser = window_controller->GetBrowser();
52      if (browser)
53        return browser;
54    }
55  }
56
57  // Otherwise, try to default to a reasonable browser. If |include_incognito_|
58  // is true, we will also search browsers in the incognito version of this
59  // profile. Note that the profile may already be incognito, in which case
60  // we will search the incognito version only, regardless of the value of
61  // |include_incognito|. Look only for browsers on the active desktop as it is
62  // preferable to pretend no browser is open then to return a browser on
63  // another desktop.
64  if (render_view_host_) {
65    Profile* profile = Profile::FromBrowserContext(
66        render_view_host_->GetProcess()->GetBrowserContext());
67    Browser* browser = chrome::FindAnyBrowser(
68        profile, include_incognito_, chrome::GetActiveDesktop());
69    if (browser)
70      return browser;
71  }
72
73  // NOTE(rafaelw): This can return NULL in some circumstances. In particular,
74  // a background_page onload chrome.tabs api call can make it into here
75  // before the browser is sufficiently initialized to return here, or
76  // all of this profile's browser windows may have been closed.
77  // A similar situation may arise during shutdown.
78  // TODO(rafaelw): Delay creation of background_page until the browser
79  // is available. http://code.google.com/p/chromium/issues/detail?id=13284
80  return NULL;
81}
82
83extensions::WindowController*
84ChromeUIThreadExtensionFunction::GetExtensionWindowController() {
85  // If the delegate has an associated window controller, return it.
86  if (dispatcher()) {
87    extensions::WindowController* window_controller =
88        dispatcher()->delegate()->GetExtensionWindowController();
89    if (window_controller)
90      return window_controller;
91  }
92
93  return extensions::WindowControllerList::GetInstance()
94      ->CurrentWindowForFunction(this);
95}
96
97content::WebContents*
98ChromeUIThreadExtensionFunction::GetAssociatedWebContents() {
99  content::WebContents* web_contents =
100      UIThreadExtensionFunction::GetAssociatedWebContents();
101  if (web_contents)
102    return web_contents;
103
104  Browser* browser = GetCurrentBrowser();
105  if (!browser)
106    return NULL;
107  return browser->tab_strip_model()->GetActiveWebContents();
108}
109
110ChromeUIThreadExtensionFunction::~ChromeUIThreadExtensionFunction() {
111}
112
113ChromeAsyncExtensionFunction::ChromeAsyncExtensionFunction() {
114}
115
116ChromeAsyncExtensionFunction::~ChromeAsyncExtensionFunction() {}
117
118ExtensionFunction::ResponseAction ChromeAsyncExtensionFunction::Run() {
119  return RunAsync() ? RespondLater() : RespondNow(Error(error_));
120}
121
122// static
123bool ChromeAsyncExtensionFunction::ValidationFailure(
124    ChromeAsyncExtensionFunction* function) {
125  return false;
126}
127
128ChromeSyncExtensionFunction::ChromeSyncExtensionFunction() {
129}
130
131ChromeSyncExtensionFunction::~ChromeSyncExtensionFunction() {}
132
133ExtensionFunction::ResponseAction ChromeSyncExtensionFunction::Run() {
134  return RespondNow(RunSync() ? ArgumentList(results_.Pass()) : Error(error_));
135}
136
137// static
138bool ChromeSyncExtensionFunction::ValidationFailure(
139    ChromeSyncExtensionFunction* function) {
140  return false;
141}
142