common_web_contents_delegate.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. // Copyright (c) 2015 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/common_web_contents_delegate.h"
  5. #include <memory>
  6. #include <set>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/files/file_util.h"
  11. #include "base/json/json_reader.h"
  12. #include "base/task/post_task.h"
  13. #include "base/task/thread_pool.h"
  14. #include "base/threading/scoped_blocking_call.h"
  15. #include "base/threading/sequenced_task_runner_handle.h"
  16. #include "chrome/browser/ssl/security_state_tab_helper.h"
  17. #include "chrome/common/pref_names.h"
  18. #include "components/prefs/pref_service.h"
  19. #include "components/prefs/scoped_user_pref_update.h"
  20. #include "components/security_state/content/content_utils.h"
  21. #include "components/security_state/core/security_state.h"
  22. #include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
  23. #include "content/public/browser/browser_thread.h"
  24. #include "content/public/browser/child_process_security_policy.h"
  25. #include "content/public/browser/file_select_listener.h"
  26. #include "content/public/browser/render_process_host.h"
  27. #include "content/public/browser/render_view_host.h"
  28. #include "content/public/browser/render_widget_host.h"
  29. #include "content/public/browser/security_style_explanation.h"
  30. #include "content/public/browser/security_style_explanations.h"
  31. #include "printing/buildflags/buildflags.h"
  32. #include "shell/browser/electron_browser_client.h"
  33. #include "shell/browser/electron_browser_context.h"
  34. #include "shell/browser/native_window.h"
  35. #include "shell/browser/ui/file_dialog.h"
  36. #include "shell/browser/web_contents_preferences.h"
  37. #include "shell/browser/web_dialog_helper.h"
  38. #include "shell/common/electron_constants.h"
  39. #include "shell/common/options_switches.h"
  40. #include "storage/browser/file_system/isolated_context.h"
  41. #if BUILDFLAG(ENABLE_COLOR_CHOOSER)
  42. #include "chrome/browser/ui/color_chooser.h"
  43. #endif
  44. #if BUILDFLAG(ENABLE_OSR)
  45. #include "shell/browser/osr/osr_web_contents_view.h"
  46. #endif
  47. #if BUILDFLAG(ENABLE_PRINTING)
  48. #include "chrome/browser/printing/print_view_manager_basic.h"
  49. #include "components/printing/browser/print_manager_utils.h"
  50. #include "shell/browser/printing/print_preview_message_handler.h"
  51. #endif
  52. #if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
  53. #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
  54. #endif
  55. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  56. #include "components/pdf/browser/pdf_web_contents_helper.h" // nogncheck
  57. #include "shell/browser/electron_pdf_web_contents_helper_client.h"
  58. #endif
  59. using content::BrowserThread;
  60. namespace electron {
  61. namespace {
  62. const char kRootName[] = "<root>";
  63. struct FileSystem {
  64. FileSystem() = default;
  65. FileSystem(const std::string& type,
  66. const std::string& file_system_name,
  67. const std::string& root_url,
  68. const std::string& file_system_path)
  69. : type(type),
  70. file_system_name(file_system_name),
  71. root_url(root_url),
  72. file_system_path(file_system_path) {}
  73. std::string type;
  74. std::string file_system_name;
  75. std::string root_url;
  76. std::string file_system_path;
  77. };
  78. std::string RegisterFileSystem(content::WebContents* web_contents,
  79. const base::FilePath& path) {
  80. auto* isolated_context = storage::IsolatedContext::GetInstance();
  81. std::string root_name(kRootName);
  82. storage::IsolatedContext::ScopedFSHandle file_system =
  83. isolated_context->RegisterFileSystemForPath(
  84. storage::kFileSystemTypeNativeLocal, std::string(), path, &root_name);
  85. content::ChildProcessSecurityPolicy* policy =
  86. content::ChildProcessSecurityPolicy::GetInstance();
  87. content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
  88. int renderer_id = render_view_host->GetProcess()->GetID();
  89. policy->GrantReadFileSystem(renderer_id, file_system.id());
  90. policy->GrantWriteFileSystem(renderer_id, file_system.id());
  91. policy->GrantCreateFileForFileSystem(renderer_id, file_system.id());
  92. policy->GrantDeleteFromFileSystem(renderer_id, file_system.id());
  93. if (!policy->CanReadFile(renderer_id, path))
  94. policy->GrantReadFile(renderer_id, path);
  95. return file_system.id();
  96. }
  97. FileSystem CreateFileSystemStruct(content::WebContents* web_contents,
  98. const std::string& file_system_id,
  99. const std::string& file_system_path,
  100. const std::string& type) {
  101. const GURL origin = web_contents->GetURL().GetOrigin();
  102. std::string file_system_name =
  103. storage::GetIsolatedFileSystemName(origin, file_system_id);
  104. std::string root_url = storage::GetIsolatedFileSystemRootURIString(
  105. origin, file_system_id, kRootName);
  106. return FileSystem(type, file_system_name, root_url, file_system_path);
  107. }
  108. std::unique_ptr<base::DictionaryValue> CreateFileSystemValue(
  109. const FileSystem& file_system) {
  110. std::unique_ptr<base::DictionaryValue> file_system_value(
  111. new base::DictionaryValue());
  112. file_system_value->SetString("type", file_system.type);
  113. file_system_value->SetString("fileSystemName", file_system.file_system_name);
  114. file_system_value->SetString("rootURL", file_system.root_url);
  115. file_system_value->SetString("fileSystemPath", file_system.file_system_path);
  116. return file_system_value;
  117. }
  118. void WriteToFile(const base::FilePath& path, const std::string& content) {
  119. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  120. base::BlockingType::WILL_BLOCK);
  121. DCHECK(!path.empty());
  122. base::WriteFile(path, content.data(), content.size());
  123. }
  124. void AppendToFile(const base::FilePath& path, const std::string& content) {
  125. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  126. base::BlockingType::WILL_BLOCK);
  127. DCHECK(!path.empty());
  128. base::AppendToFile(path, content.data(), content.size());
  129. }
  130. PrefService* GetPrefService(content::WebContents* web_contents) {
  131. auto* context = web_contents->GetBrowserContext();
  132. return static_cast<electron::ElectronBrowserContext*>(context)->prefs();
  133. }
  134. std::map<std::string, std::string> GetAddedFileSystemPaths(
  135. content::WebContents* web_contents) {
  136. auto* pref_service = GetPrefService(web_contents);
  137. const base::DictionaryValue* file_system_paths_value =
  138. pref_service->GetDictionary(prefs::kDevToolsFileSystemPaths);
  139. std::map<std::string, std::string> result;
  140. if (file_system_paths_value) {
  141. base::DictionaryValue::Iterator it(*file_system_paths_value);
  142. for (; !it.IsAtEnd(); it.Advance()) {
  143. std::string type =
  144. it.value().is_string() ? it.value().GetString() : std::string();
  145. result[it.key()] = type;
  146. }
  147. }
  148. return result;
  149. }
  150. bool IsDevToolsFileSystemAdded(content::WebContents* web_contents,
  151. const std::string& file_system_path) {
  152. auto file_system_paths = GetAddedFileSystemPaths(web_contents);
  153. return file_system_paths.find(file_system_path) != file_system_paths.end();
  154. }
  155. } // namespace
  156. CommonWebContentsDelegate::CommonWebContentsDelegate()
  157. : devtools_file_system_indexer_(new DevToolsFileSystemIndexer),
  158. file_task_runner_(
  159. base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
  160. weak_factory_(this) {}
  161. CommonWebContentsDelegate::~CommonWebContentsDelegate() = default;
  162. void CommonWebContentsDelegate::InitWithWebContents(
  163. content::WebContents* web_contents,
  164. ElectronBrowserContext* browser_context,
  165. bool is_guest) {
  166. browser_context_ = browser_context;
  167. web_contents->SetDelegate(this);
  168. #if BUILDFLAG(ENABLE_PRINTING)
  169. PrintPreviewMessageHandler::CreateForWebContents(web_contents);
  170. printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
  171. printing::CreateCompositeClientIfNeeded(web_contents,
  172. browser_context->GetUserAgent());
  173. #endif
  174. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  175. pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
  176. web_contents, std::make_unique<ElectronPDFWebContentsHelperClient>());
  177. #endif
  178. // Determine whether the WebContents is offscreen.
  179. auto* web_preferences = WebContentsPreferences::From(web_contents);
  180. offscreen_ =
  181. web_preferences && web_preferences->IsEnabled(options::kOffscreen);
  182. // Create InspectableWebContents.
  183. web_contents_.reset(new InspectableWebContents(
  184. web_contents, browser_context->prefs(), is_guest));
  185. web_contents_->SetDelegate(this);
  186. }
  187. void CommonWebContentsDelegate::SetOwnerWindow(NativeWindow* owner_window) {
  188. SetOwnerWindow(GetWebContents(), owner_window);
  189. }
  190. void CommonWebContentsDelegate::SetOwnerWindow(
  191. content::WebContents* web_contents,
  192. NativeWindow* owner_window) {
  193. if (owner_window) {
  194. owner_window_ = owner_window->GetWeakPtr();
  195. NativeWindowRelay::CreateForWebContents(web_contents,
  196. owner_window->GetWeakPtr());
  197. } else {
  198. owner_window_ = nullptr;
  199. web_contents->RemoveUserData(NativeWindowRelay::UserDataKey());
  200. }
  201. #if BUILDFLAG(ENABLE_OSR)
  202. auto* osr_wcv = GetOffScreenWebContentsView();
  203. if (osr_wcv)
  204. osr_wcv->SetNativeWindow(owner_window);
  205. #endif
  206. }
  207. void CommonWebContentsDelegate::ResetManagedWebContents(bool async) {
  208. if (async) {
  209. // Browser context should be destroyed only after the WebContents,
  210. // this is guaranteed in the sync mode by the order of declaration,
  211. // in the async version we maintain a reference until the WebContents
  212. // is destroyed.
  213. // //electron/patches/chromium/content_browser_main_loop.patch
  214. // is required to get the right quit closure for the main message loop.
  215. base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
  216. web_contents_.release());
  217. } else {
  218. web_contents_.reset();
  219. }
  220. }
  221. content::WebContents* CommonWebContentsDelegate::GetWebContents() const {
  222. if (!web_contents_)
  223. return nullptr;
  224. return web_contents_->GetWebContents();
  225. }
  226. content::WebContents* CommonWebContentsDelegate::GetDevToolsWebContents()
  227. const {
  228. if (!web_contents_)
  229. return nullptr;
  230. return web_contents_->GetDevToolsWebContents();
  231. }
  232. #if BUILDFLAG(ENABLE_OSR)
  233. OffScreenWebContentsView*
  234. CommonWebContentsDelegate::GetOffScreenWebContentsView() const {
  235. return nullptr;
  236. }
  237. #endif
  238. content::WebContents* CommonWebContentsDelegate::OpenURLFromTab(
  239. content::WebContents* source,
  240. const content::OpenURLParams& params) {
  241. content::NavigationController::LoadURLParams load_url_params(params.url);
  242. load_url_params.referrer = params.referrer;
  243. load_url_params.transition_type = params.transition;
  244. load_url_params.extra_headers = params.extra_headers;
  245. load_url_params.should_replace_current_entry =
  246. params.should_replace_current_entry;
  247. load_url_params.is_renderer_initiated = params.is_renderer_initiated;
  248. load_url_params.started_from_context_menu = params.started_from_context_menu;
  249. load_url_params.initiator_origin = params.initiator_origin;
  250. load_url_params.source_site_instance = params.source_site_instance;
  251. load_url_params.frame_tree_node_id = params.frame_tree_node_id;
  252. load_url_params.redirect_chain = params.redirect_chain;
  253. load_url_params.has_user_gesture = params.user_gesture;
  254. load_url_params.blob_url_loader_factory = params.blob_url_loader_factory;
  255. load_url_params.href_translate = params.href_translate;
  256. load_url_params.reload_type = params.reload_type;
  257. if (params.post_data) {
  258. load_url_params.load_type =
  259. content::NavigationController::LOAD_TYPE_HTTP_POST;
  260. load_url_params.post_data = params.post_data;
  261. }
  262. source->GetController().LoadURLWithParams(load_url_params);
  263. return source;
  264. }
  265. bool CommonWebContentsDelegate::CanOverscrollContent() {
  266. return false;
  267. }
  268. content::ColorChooser* CommonWebContentsDelegate::OpenColorChooser(
  269. content::WebContents* web_contents,
  270. SkColor color,
  271. const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions) {
  272. #if BUILDFLAG(ENABLE_COLOR_CHOOSER)
  273. return chrome::ShowColorChooser(web_contents, color);
  274. #else
  275. return nullptr;
  276. #endif
  277. }
  278. void CommonWebContentsDelegate::RunFileChooser(
  279. content::RenderFrameHost* render_frame_host,
  280. scoped_refptr<content::FileSelectListener> listener,
  281. const blink::mojom::FileChooserParams& params) {
  282. if (!web_dialog_helper_)
  283. web_dialog_helper_ =
  284. std::make_unique<WebDialogHelper>(owner_window(), offscreen_);
  285. web_dialog_helper_->RunFileChooser(render_frame_host, std::move(listener),
  286. params);
  287. }
  288. void CommonWebContentsDelegate::EnumerateDirectory(
  289. content::WebContents* guest,
  290. scoped_refptr<content::FileSelectListener> listener,
  291. const base::FilePath& path) {
  292. if (!web_dialog_helper_)
  293. web_dialog_helper_ =
  294. std::make_unique<WebDialogHelper>(owner_window(), offscreen_);
  295. web_dialog_helper_->EnumerateDirectory(guest, std::move(listener), path);
  296. }
  297. void CommonWebContentsDelegate::EnterFullscreenModeForTab(
  298. content::RenderFrameHost* requesting_frame,
  299. const blink::mojom::FullscreenOptions& options) {
  300. if (!owner_window_)
  301. return;
  302. auto* source = content::WebContents::FromRenderFrameHost(requesting_frame);
  303. if (IsFullscreenForTabOrPending(source)) {
  304. DCHECK_EQ(fullscreen_frame_, source->GetFocusedFrame());
  305. return;
  306. }
  307. SetHtmlApiFullscreen(true);
  308. owner_window_->NotifyWindowEnterHtmlFullScreen();
  309. if (native_fullscreen_) {
  310. // Explicitly trigger a view resize, as the size is not actually changing if
  311. // the browser is fullscreened, too.
  312. source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
  313. }
  314. }
  315. void CommonWebContentsDelegate::ExitFullscreenModeForTab(
  316. content::WebContents* source) {
  317. if (!owner_window_)
  318. return;
  319. SetHtmlApiFullscreen(false);
  320. owner_window_->NotifyWindowLeaveHtmlFullScreen();
  321. if (native_fullscreen_) {
  322. // Explicitly trigger a view resize, as the size is not actually changing if
  323. // the browser is fullscreened, too. Chrome does this indirectly from
  324. // `chrome/browser/ui/exclusive_access/fullscreen_controller.cc`.
  325. source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
  326. }
  327. }
  328. bool CommonWebContentsDelegate::IsFullscreenForTabOrPending(
  329. const content::WebContents* source) {
  330. return html_fullscreen_;
  331. }
  332. blink::SecurityStyle CommonWebContentsDelegate::GetSecurityStyle(
  333. content::WebContents* web_contents,
  334. content::SecurityStyleExplanations* security_style_explanations) {
  335. SecurityStateTabHelper* helper =
  336. SecurityStateTabHelper::FromWebContents(web_contents);
  337. DCHECK(helper);
  338. return security_state::GetSecurityStyle(helper->GetSecurityLevel(),
  339. *helper->GetVisibleSecurityState(),
  340. security_style_explanations);
  341. }
  342. bool CommonWebContentsDelegate::TakeFocus(content::WebContents* source,
  343. bool reverse) {
  344. if (source && source->GetOutermostWebContents() == source) {
  345. // If this is the outermost web contents and the user has tabbed or
  346. // shift + tabbed through all the elements, reset the focus back to
  347. // the first or last element so that it doesn't stay in the body.
  348. source->FocusThroughTabTraversal(reverse);
  349. return true;
  350. }
  351. return false;
  352. }
  353. void CommonWebContentsDelegate::DevToolsSaveToFile(const std::string& url,
  354. const std::string& content,
  355. bool save_as) {
  356. base::FilePath path;
  357. auto it = saved_files_.find(url);
  358. if (it != saved_files_.end() && !save_as) {
  359. path = it->second;
  360. } else {
  361. file_dialog::DialogSettings settings;
  362. settings.parent_window = owner_window();
  363. settings.force_detached = offscreen_;
  364. settings.title = url;
  365. settings.default_path = base::FilePath::FromUTF8Unsafe(url);
  366. if (!file_dialog::ShowSaveDialogSync(settings, &path)) {
  367. base::Value url_value(url);
  368. web_contents_->CallClientFunction("DevToolsAPI.canceledSaveURL",
  369. &url_value, nullptr, nullptr);
  370. return;
  371. }
  372. }
  373. saved_files_[url] = path;
  374. // Notify DevTools.
  375. base::Value url_value(url);
  376. base::Value file_system_path_value(path.AsUTF8Unsafe());
  377. web_contents_->CallClientFunction("DevToolsAPI.savedURL", &url_value,
  378. &file_system_path_value, nullptr);
  379. file_task_runner_->PostTask(FROM_HERE,
  380. base::BindOnce(&WriteToFile, path, content));
  381. }
  382. void CommonWebContentsDelegate::DevToolsAppendToFile(
  383. const std::string& url,
  384. const std::string& content) {
  385. auto it = saved_files_.find(url);
  386. if (it == saved_files_.end())
  387. return;
  388. // Notify DevTools.
  389. base::Value url_value(url);
  390. web_contents_->CallClientFunction("DevToolsAPI.appendedToURL", &url_value,
  391. nullptr, nullptr);
  392. file_task_runner_->PostTask(
  393. FROM_HERE, base::BindOnce(&AppendToFile, it->second, content));
  394. }
  395. void CommonWebContentsDelegate::DevToolsRequestFileSystems() {
  396. auto file_system_paths = GetAddedFileSystemPaths(GetDevToolsWebContents());
  397. if (file_system_paths.empty()) {
  398. base::ListValue empty_file_system_value;
  399. web_contents_->CallClientFunction("DevToolsAPI.fileSystemsLoaded",
  400. &empty_file_system_value, nullptr,
  401. nullptr);
  402. return;
  403. }
  404. std::vector<FileSystem> file_systems;
  405. for (const auto& file_system_path : file_system_paths) {
  406. base::FilePath path =
  407. base::FilePath::FromUTF8Unsafe(file_system_path.first);
  408. std::string file_system_id =
  409. RegisterFileSystem(GetDevToolsWebContents(), path);
  410. FileSystem file_system =
  411. CreateFileSystemStruct(GetDevToolsWebContents(), file_system_id,
  412. file_system_path.first, file_system_path.second);
  413. file_systems.push_back(file_system);
  414. }
  415. base::ListValue file_system_value;
  416. for (const auto& file_system : file_systems)
  417. file_system_value.Append(CreateFileSystemValue(file_system));
  418. web_contents_->CallClientFunction("DevToolsAPI.fileSystemsLoaded",
  419. &file_system_value, nullptr, nullptr);
  420. }
  421. void CommonWebContentsDelegate::DevToolsAddFileSystem(
  422. const std::string& type,
  423. const base::FilePath& file_system_path) {
  424. base::FilePath path = file_system_path;
  425. if (path.empty()) {
  426. std::vector<base::FilePath> paths;
  427. file_dialog::DialogSettings settings;
  428. settings.parent_window = owner_window();
  429. settings.force_detached = offscreen_;
  430. settings.properties = file_dialog::OPEN_DIALOG_OPEN_DIRECTORY;
  431. if (!file_dialog::ShowOpenDialogSync(settings, &paths))
  432. return;
  433. path = paths[0];
  434. }
  435. std::string file_system_id =
  436. RegisterFileSystem(GetDevToolsWebContents(), path);
  437. if (IsDevToolsFileSystemAdded(GetDevToolsWebContents(), path.AsUTF8Unsafe()))
  438. return;
  439. FileSystem file_system = CreateFileSystemStruct(
  440. GetDevToolsWebContents(), file_system_id, path.AsUTF8Unsafe(), type);
  441. std::unique_ptr<base::DictionaryValue> file_system_value(
  442. CreateFileSystemValue(file_system));
  443. auto* pref_service = GetPrefService(GetDevToolsWebContents());
  444. DictionaryPrefUpdate update(pref_service, prefs::kDevToolsFileSystemPaths);
  445. update.Get()->SetWithoutPathExpansion(path.AsUTF8Unsafe(),
  446. std::make_unique<base::Value>(type));
  447. web_contents_->CallClientFunction("DevToolsAPI.fileSystemAdded", nullptr,
  448. file_system_value.get(), nullptr);
  449. }
  450. void CommonWebContentsDelegate::DevToolsRemoveFileSystem(
  451. const base::FilePath& file_system_path) {
  452. if (!web_contents_)
  453. return;
  454. std::string path = file_system_path.AsUTF8Unsafe();
  455. storage::IsolatedContext::GetInstance()->RevokeFileSystemByPath(
  456. file_system_path);
  457. auto* pref_service = GetPrefService(GetDevToolsWebContents());
  458. DictionaryPrefUpdate update(pref_service, prefs::kDevToolsFileSystemPaths);
  459. update.Get()->RemoveWithoutPathExpansion(path, nullptr);
  460. base::Value file_system_path_value(path);
  461. web_contents_->CallClientFunction("DevToolsAPI.fileSystemRemoved",
  462. &file_system_path_value, nullptr, nullptr);
  463. }
  464. void CommonWebContentsDelegate::DevToolsIndexPath(
  465. int request_id,
  466. const std::string& file_system_path,
  467. const std::string& excluded_folders_message) {
  468. if (!IsDevToolsFileSystemAdded(GetDevToolsWebContents(), file_system_path)) {
  469. OnDevToolsIndexingDone(request_id, file_system_path);
  470. return;
  471. }
  472. if (devtools_indexing_jobs_.count(request_id) != 0)
  473. return;
  474. std::vector<std::string> excluded_folders;
  475. std::unique_ptr<base::Value> parsed_excluded_folders =
  476. base::JSONReader::ReadDeprecated(excluded_folders_message);
  477. if (parsed_excluded_folders && parsed_excluded_folders->is_list()) {
  478. for (const base::Value& folder_path : parsed_excluded_folders->GetList()) {
  479. if (folder_path.is_string())
  480. excluded_folders.push_back(folder_path.GetString());
  481. }
  482. }
  483. devtools_indexing_jobs_[request_id] =
  484. scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>(
  485. devtools_file_system_indexer_->IndexPath(
  486. file_system_path, excluded_folders,
  487. base::BindRepeating(
  488. &CommonWebContentsDelegate::OnDevToolsIndexingWorkCalculated,
  489. weak_factory_.GetWeakPtr(), request_id, file_system_path),
  490. base::BindRepeating(
  491. &CommonWebContentsDelegate::OnDevToolsIndexingWorked,
  492. weak_factory_.GetWeakPtr(), request_id, file_system_path),
  493. base::BindRepeating(
  494. &CommonWebContentsDelegate::OnDevToolsIndexingDone,
  495. weak_factory_.GetWeakPtr(), request_id, file_system_path)));
  496. }
  497. void CommonWebContentsDelegate::DevToolsStopIndexing(int request_id) {
  498. auto it = devtools_indexing_jobs_.find(request_id);
  499. if (it == devtools_indexing_jobs_.end())
  500. return;
  501. it->second->Stop();
  502. devtools_indexing_jobs_.erase(it);
  503. }
  504. void CommonWebContentsDelegate::DevToolsSearchInPath(
  505. int request_id,
  506. const std::string& file_system_path,
  507. const std::string& query) {
  508. if (!IsDevToolsFileSystemAdded(GetDevToolsWebContents(), file_system_path)) {
  509. OnDevToolsSearchCompleted(request_id, file_system_path,
  510. std::vector<std::string>());
  511. return;
  512. }
  513. devtools_file_system_indexer_->SearchInPath(
  514. file_system_path, query,
  515. base::BindRepeating(&CommonWebContentsDelegate::OnDevToolsSearchCompleted,
  516. weak_factory_.GetWeakPtr(), request_id,
  517. file_system_path));
  518. }
  519. void CommonWebContentsDelegate::OnDevToolsIndexingWorkCalculated(
  520. int request_id,
  521. const std::string& file_system_path,
  522. int total_work) {
  523. base::Value request_id_value(request_id);
  524. base::Value file_system_path_value(file_system_path);
  525. base::Value total_work_value(total_work);
  526. web_contents_->CallClientFunction("DevToolsAPI.indexingTotalWorkCalculated",
  527. &request_id_value, &file_system_path_value,
  528. &total_work_value);
  529. }
  530. void CommonWebContentsDelegate::OnDevToolsIndexingWorked(
  531. int request_id,
  532. const std::string& file_system_path,
  533. int worked) {
  534. base::Value request_id_value(request_id);
  535. base::Value file_system_path_value(file_system_path);
  536. base::Value worked_value(worked);
  537. web_contents_->CallClientFunction("DevToolsAPI.indexingWorked",
  538. &request_id_value, &file_system_path_value,
  539. &worked_value);
  540. }
  541. void CommonWebContentsDelegate::OnDevToolsIndexingDone(
  542. int request_id,
  543. const std::string& file_system_path) {
  544. devtools_indexing_jobs_.erase(request_id);
  545. base::Value request_id_value(request_id);
  546. base::Value file_system_path_value(file_system_path);
  547. web_contents_->CallClientFunction("DevToolsAPI.indexingDone",
  548. &request_id_value, &file_system_path_value,
  549. nullptr);
  550. }
  551. void CommonWebContentsDelegate::OnDevToolsSearchCompleted(
  552. int request_id,
  553. const std::string& file_system_path,
  554. const std::vector<std::string>& file_paths) {
  555. base::ListValue file_paths_value;
  556. for (const auto& file_path : file_paths) {
  557. file_paths_value.AppendString(file_path);
  558. }
  559. base::Value request_id_value(request_id);
  560. base::Value file_system_path_value(file_system_path);
  561. web_contents_->CallClientFunction("DevToolsAPI.searchCompleted",
  562. &request_id_value, &file_system_path_value,
  563. &file_paths_value);
  564. }
  565. void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
  566. // Window is already in fullscreen mode, save the state.
  567. if (enter_fullscreen && owner_window_->IsFullscreen()) {
  568. native_fullscreen_ = true;
  569. html_fullscreen_ = true;
  570. return;
  571. }
  572. // Exit html fullscreen state but not window's fullscreen mode.
  573. if (!enter_fullscreen && native_fullscreen_) {
  574. html_fullscreen_ = false;
  575. return;
  576. }
  577. // Set fullscreen on window if allowed.
  578. auto* web_preferences = WebContentsPreferences::From(GetWebContents());
  579. bool html_fullscreenable =
  580. web_preferences ? !web_preferences->IsEnabled(
  581. options::kDisableHtmlFullscreenWindowResize)
  582. : true;
  583. if (html_fullscreenable) {
  584. owner_window_->SetFullScreen(enter_fullscreen);
  585. }
  586. html_fullscreen_ = enter_fullscreen;
  587. native_fullscreen_ = false;
  588. }
  589. content::PictureInPictureResult
  590. CommonWebContentsDelegate::EnterPictureInPicture(
  591. content::WebContents* web_contents,
  592. const viz::SurfaceId& surface_id,
  593. const gfx::Size& natural_size) {
  594. #if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
  595. return PictureInPictureWindowManager::GetInstance()->EnterPictureInPicture(
  596. web_contents, surface_id, natural_size);
  597. #else
  598. return content::PictureInPictureResult::kNotSupported;
  599. #endif
  600. }
  601. void CommonWebContentsDelegate::ExitPictureInPicture() {
  602. #if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
  603. PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
  604. #endif
  605. }
  606. } // namespace electron