1 // Copyright 2018 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/devtools/protocol/target_handler.h"
6
7 #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
8 #include "chrome/browser/devtools/devtools_browser_context_manager.h"
9 #include "chrome/browser/profiles/profile_manager.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/browser_list.h"
12 #include "chrome/browser/ui/browser_navigator.h"
13 #include "content/public/browser/devtools_agent_host.h"
14
15 namespace {
CreateNavigateParams(Profile * profile,const GURL & url,ui::PageTransition transition,bool new_window,bool background,Browser * browser)16 NavigateParams CreateNavigateParams(Profile* profile,
17 const GURL& url,
18 ui::PageTransition transition,
19 bool new_window,
20 bool background,
21 Browser* browser) {
22 DCHECK(new_window || browser);
23 NavigateParams params(profile, url, transition);
24 if (new_window) {
25 params.disposition = WindowOpenDisposition::NEW_WINDOW;
26 if (background)
27 params.window_action = NavigateParams::WindowAction::SHOW_WINDOW_INACTIVE;
28 } else {
29 params.disposition = (background)
30 ? WindowOpenDisposition::NEW_BACKGROUND_TAB
31 : WindowOpenDisposition::NEW_FOREGROUND_TAB;
32 params.browser = browser;
33 }
34 return params;
35 }
36 } // namespace
37
TargetHandler(protocol::UberDispatcher * dispatcher)38 TargetHandler::TargetHandler(protocol::UberDispatcher* dispatcher) {
39 protocol::Target::Dispatcher::wire(dispatcher, this);
40 }
41
~TargetHandler()42 TargetHandler::~TargetHandler() {
43 ChromeDevToolsManagerDelegate* delegate =
44 ChromeDevToolsManagerDelegate::GetInstance();
45 if (delegate)
46 delegate->UpdateDeviceDiscovery();
47 }
48
SetRemoteLocations(std::unique_ptr<protocol::Array<protocol::Target::RemoteLocation>> locations)49 protocol::Response TargetHandler::SetRemoteLocations(
50 std::unique_ptr<protocol::Array<protocol::Target::RemoteLocation>>
51 locations) {
52 remote_locations_.clear();
53 if (!locations)
54 return protocol::Response::Success();
55
56 for (const auto& location : *locations) {
57 remote_locations_.insert(
58 net::HostPortPair(location->GetHost(), location->GetPort()));
59 }
60
61 ChromeDevToolsManagerDelegate* delegate =
62 ChromeDevToolsManagerDelegate::GetInstance();
63 if (delegate)
64 delegate->UpdateDeviceDiscovery();
65 return protocol::Response::Success();
66 }
67
CreateTarget(const std::string & url,protocol::Maybe<int> width,protocol::Maybe<int> height,protocol::Maybe<std::string> browser_context_id,protocol::Maybe<bool> enable_begin_frame_control,protocol::Maybe<bool> new_window,protocol::Maybe<bool> background,std::string * out_target_id)68 protocol::Response TargetHandler::CreateTarget(
69 const std::string& url,
70 protocol::Maybe<int> width,
71 protocol::Maybe<int> height,
72 protocol::Maybe<std::string> browser_context_id,
73 protocol::Maybe<bool> enable_begin_frame_control,
74 protocol::Maybe<bool> new_window,
75 protocol::Maybe<bool> background,
76 std::string* out_target_id) {
77 Profile* profile = ProfileManager::GetActiveUserProfile();
78 if (browser_context_id.isJust()) {
79 std::string profile_id = browser_context_id.fromJust();
80 profile =
81 DevToolsBrowserContextManager::GetInstance().GetProfileById(profile_id);
82 if (!profile) {
83 return protocol::Response::ServerError(
84 "Failed to find browser context with id " + profile_id);
85 }
86 }
87 bool create_new_window = new_window.fromMaybe(false);
88 bool create_in_background = background.fromMaybe(false);
89 Browser* target_browser = nullptr;
90
91 // Must find target_browser if new_window not explicitly true.
92 if (!create_new_window) {
93 // Find a browser to open a new tab.
94 // We shouldn't use browser that is scheduled to close.
95 for (auto* browser : *BrowserList::GetInstance()) {
96 if (browser->profile() == profile &&
97 !browser->IsAttemptingToCloseBrowser()) {
98 target_browser = browser;
99 break;
100 }
101 }
102 }
103
104 bool explicit_old_window = !new_window.fromMaybe(true);
105 if (explicit_old_window && !target_browser) {
106 return protocol::Response::ServerError(
107 "Failed to open new tab - "
108 "no browser is open");
109 }
110
111 create_new_window = !target_browser;
112 NavigateParams params = CreateNavigateParams(
113 profile, GURL(url), ui::PAGE_TRANSITION_AUTO_TOPLEVEL, create_new_window,
114 create_in_background, target_browser);
115 Navigate(¶ms);
116 if (!params.navigated_or_inserted_contents)
117 return protocol::Response::ServerError("Failed to open a new tab");
118
119 *out_target_id = content::DevToolsAgentHost::GetOrCreateFor(
120 params.navigated_or_inserted_contents)
121 ->GetId();
122 return protocol::Response::Success();
123 }
124