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