From def7f263c1ba336d4d15fde5487956e490f3fc69 Mon Sep 17 00:00:00 2001 From: bridiver Date: Mon, 27 Mar 2017 18:33:20 -0700 Subject: [PATCH] add tab manager --- atom/browser/api/atom_api_app.cc | 99 ++++--- atom/browser/api/atom_api_web_contents.cc | 46 +++- atom/browser/api/atom_api_web_contents.h | 7 + atom/browser/api/atom_api_window.cc | 2 +- atom/browser/common_web_contents_delegate.cc | 8 + atom/browser/extensions/tab_helper.cc | 88 +++++- atom/browser/extensions/tab_helper.h | 31 ++- atom/browser/window_list.cc | 18 ++ brave/browser/brave_browser_context.h | 4 +- chromium_src/BUILD.gn | 171 +++++++++--- .../chrome/browser/browser_process_impl.cc | 16 +- .../chrome/browser/browser_process_impl.h | 8 + .../engagement/site_engagement_service.cc | 15 ++ .../media_capture_devices_dispatcher.cc | 13 +- .../webrtc/media_capture_devices_dispatcher.h | 5 +- .../webrtc/media_stream_capture_indicator.cc | 21 ++ .../webrtc/media_stream_capture_indicator.h | 30 +++ .../chrome/browser/profiles/profile.h | 1 + chromium_src/chrome/browser/ui/browser.cc | 128 +++++++++ chromium_src/chrome/browser/ui/browser.h | 252 +++++++++++++++++ .../chrome/browser/ui/browser_finder.h | 11 - .../chrome/browser/ui/tabs/tab_strip_model.cc | 253 ++++++++++++++++++ .../media/media_capture_devices_dispatcher.cc | 16 +- .../media/media_capture_devices_dispatcher.h | 9 + 24 files changed, 1115 insertions(+), 137 deletions(-) create mode 100644 chromium_src/chrome/browser/engagement/site_engagement_service.cc create mode 100644 chromium_src/chrome/browser/media/webrtc/media_stream_capture_indicator.cc create mode 100644 chromium_src/chrome/browser/media/webrtc/media_stream_capture_indicator.h create mode 100644 chromium_src/chrome/browser/ui/browser.cc create mode 100644 chromium_src/chrome/browser/ui/browser.h delete mode 100644 chromium_src/chrome/browser/ui/browser_finder.h create mode 100644 chromium_src/chrome/browser/ui/tabs/tab_strip_model.cc diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index e980f03d3d..31fca948e4 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -71,16 +71,15 @@ #include "content/public/browser/notification_types.h" #endif -using atom::Browser; using content::CertificateRequestResultType; namespace mate { #if defined(OS_WIN) template<> -struct Converter { +struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Local val, - Browser::UserTask* out) { + atom::Browser::UserTask* out) { mate::Dictionary dict; if (!ConvertFromV8(isolate, val, &dict)) return false; @@ -312,9 +311,9 @@ struct Converter { #endif template<> -struct Converter { +struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Local val, - Browser::LoginItemSettings* out) { + atom::Browser::LoginItemSettings* out) { mate::Dictionary dict; if (!ConvertFromV8(isolate, val, &dict)) return false; @@ -325,7 +324,7 @@ struct Converter { } static v8::Local ToV8(v8::Isolate* isolate, - Browser::LoginItemSettings val) { + atom::Browser::LoginItemSettings val) { mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); dict.Set("openAtLogin", val.open_at_login); dict.Set("openAsHidden", val.open_as_hidden); @@ -432,7 +431,7 @@ bool NotificationCallbackWrapper( const base::CommandLine::StringVector& cmd, const base::FilePath& cwd) { // Make sure the callback is called after app gets ready. - if (Browser::Get()->is_ready()) { + if (atom::Browser::Get()->is_ready()) { callback.Run(cmd, cwd); } else { scoped_refptr task_runner( @@ -441,7 +440,7 @@ bool NotificationCallbackWrapper( FROM_HERE, base::Bind(base::IgnoreResult(callback), cmd, cwd)); } // ProcessSingleton needs to know whether current process is quiting. - return !Browser::Get()->is_shutting_down(); + return !atom::Browser::Get()->is_shutting_down(); } void OnClientCertificateSelected( @@ -510,7 +509,7 @@ int ImportIntoCertStore( App::App(v8::Isolate* isolate) { static_cast( brave::BraveContentBrowserClient::Get())->set_delegate(this); - Browser::Get()->AddObserver(this); + atom::Browser::Get()->AddObserver(this); content::GpuDataManager::GetInstance()->AddObserver(this); Init(isolate); static_cast(g_browser_process)->set_app(this); @@ -558,7 +557,7 @@ void App::Observe( App::~App() { static_cast( brave::BraveContentBrowserClient::Get())->set_delegate(nullptr); - Browser::Get()->RemoveObserver(this); + atom::Browser::Get()->RemoveObserver(this); net::NetworkChangeNotifier::RemoveMaxBandwidthObserver(this); content::GpuDataManager::GetInstance()->RemoveObserver(this); } @@ -813,7 +812,7 @@ bool App::Relaunch(mate::Arguments* js_args) { } void App::DisableHardwareAcceleration(mate::Arguments* args) { - if (Browser::Get()->is_ready()) { + if (atom::Browser::Get()->is_ready()) { args->ThrowError("app.disableHardwareAcceleration() can only be called " "before app is ready"); return; @@ -895,7 +894,7 @@ void App::OnCertificateManagerModelCreated( #if defined(OS_WIN) v8::Local App::GetJumpListSettings() { - JumpList jump_list(Browser::Get()->GetAppUserModelID()); + JumpList jump_list(atom::Browser::Get()->GetAppUserModelID()); int min_items = 10; std::vector removed_items; @@ -922,7 +921,7 @@ JumpListResult App::SetJumpList(v8::Local val, return JumpListResult::ARGUMENT_ERROR; } - JumpList jump_list(Browser::Get()->GetAppUserModelID()); + JumpList jump_list(atom::Browser::Get()->GetAppUserModelID()); if (delete_jump_list) { return jump_list.Delete() @@ -959,50 +958,50 @@ mate::Handle App::Create(v8::Isolate* isolate) { void App::BuildPrototype( v8::Isolate* isolate, v8::Local prototype) { prototype->SetClassName(mate::StringToV8(isolate, "App")); - auto browser = base::Unretained(Browser::Get()); + auto browser = base::Unretained(atom::Browser::Get()); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) - .SetMethod("quit", base::Bind(&Browser::Quit, browser)) - .SetMethod("exit", base::Bind(&Browser::Exit, browser)) - .SetMethod("focus", base::Bind(&Browser::Focus, browser)) - .SetMethod("getVersion", base::Bind(&Browser::GetVersion, browser)) - .SetMethod("setVersion", base::Bind(&Browser::SetVersion, browser)) - .SetMethod("getName", base::Bind(&Browser::GetName, browser)) - .SetMethod("setName", base::Bind(&Browser::SetName, browser)) - .SetMethod("isReady", base::Bind(&Browser::is_ready, browser)) + .SetMethod("quit", base::Bind(&atom::Browser::Quit, browser)) + .SetMethod("exit", base::Bind(&atom::Browser::Exit, browser)) + .SetMethod("focus", base::Bind(&atom::Browser::Focus, browser)) + .SetMethod("getVersion", base::Bind(&atom::Browser::GetVersion, browser)) + .SetMethod("setVersion", base::Bind(&atom::Browser::SetVersion, browser)) + .SetMethod("getName", base::Bind(&atom::Browser::GetName, browser)) + .SetMethod("setName", base::Bind(&atom::Browser::SetName, browser)) + .SetMethod("isReady", base::Bind(&atom::Browser::is_ready, browser)) .SetMethod("addRecentDocument", - base::Bind(&Browser::AddRecentDocument, browser)) + base::Bind(&atom::Browser::AddRecentDocument, browser)) .SetMethod("clearRecentDocuments", - base::Bind(&Browser::ClearRecentDocuments, browser)) + base::Bind(&atom::Browser::ClearRecentDocuments, browser)) .SetMethod("setAppUserModelId", - base::Bind(&Browser::SetAppUserModelID, browser)) + base::Bind(&atom::Browser::SetAppUserModelID, browser)) .SetMethod("isDefaultProtocolClient", - base::Bind(&Browser::IsDefaultProtocolClient, browser)) + base::Bind(&atom::Browser::IsDefaultProtocolClient, browser)) .SetMethod("setAsDefaultProtocolClient", - base::Bind(&Browser::SetAsDefaultProtocolClient, browser)) + base::Bind(&atom::Browser::SetAsDefaultProtocolClient, browser)) .SetMethod("removeAsDefaultProtocolClient", - base::Bind(&Browser::RemoveAsDefaultProtocolClient, browser)) - .SetMethod("setBadgeCount", base::Bind(&Browser::SetBadgeCount, browser)) - .SetMethod("getBadgeCount", base::Bind(&Browser::GetBadgeCount, browser)) + base::Bind(&atom::Browser::RemoveAsDefaultProtocolClient, browser)) + .SetMethod("setBadgeCount", base::Bind(&atom::Browser::SetBadgeCount, browser)) + .SetMethod("getBadgeCount", base::Bind(&atom::Browser::GetBadgeCount, browser)) .SetMethod("getLoginItemSettings", - base::Bind(&Browser::GetLoginItemSettings, browser)) + base::Bind(&atom::Browser::GetLoginItemSettings, browser)) .SetMethod("setLoginItemSettings", - base::Bind(&Browser::SetLoginItemSettings, browser)) + base::Bind(&atom::Browser::SetLoginItemSettings, browser)) #if defined(OS_MACOSX) - .SetMethod("hide", base::Bind(&Browser::Hide, browser)) - .SetMethod("show", base::Bind(&Browser::Show, browser)) + .SetMethod("hide", base::Bind(&atom::Browser::Hide, browser)) + .SetMethod("show", base::Bind(&atom::Browser::Show, browser)) .SetMethod("setUserActivity", - base::Bind(&Browser::SetUserActivity, browser)) + base::Bind(&atom::Browser::SetUserActivity, browser)) .SetMethod("getCurrentActivityType", - base::Bind(&Browser::GetCurrentActivityType, browser)) + base::Bind(&atom::Browser::GetCurrentActivityType, browser)) #endif #if defined(OS_WIN) - .SetMethod("setUserTasks", base::Bind(&Browser::SetUserTasks, browser)) + .SetMethod("setUserTasks", base::Bind(&atom::Browser::SetUserTasks, browser)) .SetMethod("getJumpListSettings", &App::GetJumpListSettings) .SetMethod("setJumpList", &App::SetJumpList) #endif #if defined(OS_LINUX) .SetMethod("isUnityRunning", - base::Bind(&Browser::IsUnityRunning, browser)) + base::Bind(&atom::Browser::IsUnityRunning, browser)) #endif .SetMethod("setPath", &App::SetPath) .SetMethod("getPath", &App::GetPath) @@ -1069,14 +1068,14 @@ void AppendSwitch(const std::string& switch_string, mate::Arguments* args) { int DockBounce(const std::string& type) { int request_id = -1; if (type == "critical") - request_id = Browser::Get()->DockBounce(Browser::BOUNCE_CRITICAL); + request_id = atom::Browser::Get()->DockBounce(atom::Browser::BOUNCE_CRITICAL); else if (type == "informational") - request_id = Browser::Get()->DockBounce(Browser::BOUNCE_INFORMATIONAL); + request_id = atom::Browser::Get()->DockBounce(atom::Browser::BOUNCE_INFORMATIONAL); return request_id; } void DockSetMenu(atom::api::Menu* menu) { - Browser::Get()->DockSetMenu(menu->model()); + atom::Browser::Get()->DockSetMenu(menu->model()); } #endif @@ -1093,21 +1092,21 @@ void Initialize(v8::Local exports, v8::Local unused, base::Bind(&base::CommandLine::AppendArg, base::Unretained(command_line))); #if defined(OS_MACOSX) - auto browser = base::Unretained(Browser::Get()); + auto browser = base::Unretained(atom::Browser::Get()); dict.SetMethod("dockBounce", &DockBounce); dict.SetMethod("dockCancelBounce", - base::Bind(&Browser::DockCancelBounce, browser)); + base::Bind(&atom::Browser::DockCancelBounce, browser)); dict.SetMethod("dockDownloadFinished", - base::Bind(&Browser::DockDownloadFinished, browser)); + base::Bind(&atom::Browser::DockDownloadFinished, browser)); dict.SetMethod("dockSetBadgeText", - base::Bind(&Browser::DockSetBadgeText, browser)); + base::Bind(&atom::Browser::DockSetBadgeText, browser)); dict.SetMethod("dockGetBadgeText", - base::Bind(&Browser::DockGetBadgeText, browser)); - dict.SetMethod("dockHide", base::Bind(&Browser::DockHide, browser)); - dict.SetMethod("dockShow", base::Bind(&Browser::DockShow, browser)); - dict.SetMethod("dockIsVisible", base::Bind(&Browser::DockIsVisible, browser)); + base::Bind(&atom::Browser::DockGetBadgeText, browser)); + dict.SetMethod("dockHide", base::Bind(&atom::Browser::DockHide, browser)); + dict.SetMethod("dockShow", base::Bind(&atom::Browser::DockShow, browser)); + dict.SetMethod("dockIsVisible", base::Bind(&atom::Browser::DockIsVisible, browser)); dict.SetMethod("dockSetMenu", &DockSetMenu); - dict.SetMethod("dockSetIcon", base::Bind(&Browser::DockSetIcon, browser)); + dict.SetMethod("dockSetIcon", base::Bind(&atom::Browser::DockSetIcon, browser)); #endif } diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 23679ae6e3..0a75cbae52 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -55,6 +55,8 @@ #include "chrome/browser/printing/print_view_manager_basic.h" #include "chrome/browser/printing/print_view_manager_common.h" #include "chrome/browser/ssl/security_state_tab_helper.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/custom_handlers/protocol_handler.h" #include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/autofill/core/browser/autofill_manager.h" @@ -1782,17 +1784,27 @@ void WebContents::Clone(mate::Arguments* args) { options, callback))); } +::Browser* WebContents::browser() const { +#if BUILDFLAG(ENABLE_EXTENSIONS) + auto tab_helper = extensions::TabHelper::FromWebContents(web_contents()); + if (tab_helper) + return tab_helper->browser(); +#endif + return nullptr; +} + void WebContents::SetActive(bool active) { if (active) web_contents()->WasShown(); else web_contents()->WasHidden(); -#if BUILDFLAG(ENABLE_EXTENSIONS) - auto tab_helper = extensions::TabHelper::FromWebContents(web_contents()); - if (tab_helper) - tab_helper->SetActive(active); -#endif + if (active && browser()) { + int index = + browser()->tab_strip_model()->GetIndexOfWebContents(web_contents()); + if (index != TabStripModel::kNoTab) + browser()->tab_strip_model()->ActivateTabAt(index, true); + } Emit("set-active", active); } @@ -1807,6 +1819,30 @@ void WebContents::SetTabIndex(int index) { Emit("set-tab-index", index); } +void WebContents::SetPinned(bool pinned) { + auto tab_helper = extensions::TabHelper::FromWebContents(web_contents()); + if (tab_helper) + tab_helper->SetPinned(pinned); + + Emit("set-pinned", pinned); +} + +void WebContents::SetAutoDiscardable(bool auto_discardable) { + auto tab_helper = extensions::TabHelper::FromWebContents(web_contents()); + if (tab_helper) + tab_helper->SetAutoDiscardable(auto_discardable); + + Emit("set-auto-discardable", auto_discardable); +} + +void WebContents::Discard() { + auto tab_helper = extensions::TabHelper::FromWebContents(web_contents()); + if (tab_helper) { + if (!Emit("will-discard") && tab_helper->Discard()) + Emit("discarded"); + } +} + #if BUILDFLAG(ENABLE_EXTENSIONS) bool WebContents::ExecuteScriptInTab(mate::Arguments* args) { auto tab_helper = extensions::TabHelper::FromWebContents(web_contents()); diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 603d0fec5d..10e11d161d 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -22,6 +22,7 @@ #include "native_mate/handle.h" #include "ui/gfx/image/image.h" +class Browser; class ProtocolHandler; namespace autofill { @@ -216,8 +217,14 @@ class WebContents : public mate::TrackableObject, // Focus. void Focus(); bool IsFocused() const; + + // Tab state + ::Browser* browser() const; void SetActive(bool active); void SetTabIndex(int index); + void SetPinned(bool pinned); + void SetAutoDiscardable(bool auto_discardable); + void Discard(); // Zoom void SetZoomLevel(double zoom); diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 7fbb80c686..01afff6ff4 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "atom/browser/api/atom_api_window.h" -#include "atom/common/native_mate_converters/value_converter.h" #include "atom/browser/api/atom_api_menu.h" #include "atom/browser/api/atom_api_web_contents.h" @@ -14,6 +13,7 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/options_switches.h" #include "base/command_line.h" #include "content/public/browser/render_frame_host.h" diff --git a/atom/browser/common_web_contents_delegate.cc b/atom/browser/common_web_contents_delegate.cc index 00b6c362d2..d0662355e7 100644 --- a/atom/browser/common_web_contents_delegate.cc +++ b/atom/browser/common_web_contents_delegate.cc @@ -23,7 +23,9 @@ #include "chrome/browser/printing/print_preview_message_handler.h" #include "chrome/browser/printing/print_view_manager_basic.h" #include "chrome/browser/ssl/security_state_tab_helper.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/pref_registry/pref_registry_syncable.h" @@ -213,6 +215,12 @@ void CommonWebContentsDelegate::SetOwnerWindow( sessionID.set_id(id); tab_helper->SetWindowId(id); + for (auto* browser : *BrowserList::GetInstance()) { + if (browser->window() == owner_window) { + tab_helper->SetBrowser(browser); + } + } + content::NotificationService::current()->Notify( chrome::NOTIFICATION_TAB_PARENTED, content::Source(web_contents), diff --git a/atom/browser/extensions/tab_helper.cc b/atom/browser/extensions/tab_helper.cc index 1e9c84be11..4ac46a1c07 100644 --- a/atom/browser/extensions/tab_helper.cc +++ b/atom/browser/extensions/tab_helper.cc @@ -12,7 +12,12 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/value_converter.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/memory/tab_manager.h" #include "chrome/browser/sessions/session_tab_helper.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "components/sessions/core/session_id.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/navigation_entry.h" @@ -30,6 +35,8 @@ #include "net/base/filename_util.h" #include "ui/base/resource/resource_bundle.h" +using memory::TabManager; + DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::TabHelper); namespace keys { @@ -50,7 +57,6 @@ const char kSelectedKey[] = "selected"; } // namespace keys static std::map> render_view_map_; -static std::map active_tab_map_; namespace extensions { @@ -58,16 +64,42 @@ TabHelper::TabHelper(content::WebContents* contents) : content::WebContentsObserver(contents), values_(new base::DictionaryValue), script_executor_( - new ScriptExecutor(contents, &script_execution_observers_)) { + new ScriptExecutor(contents, &script_execution_observers_)), + index_(TabStripModel::kNoTab), + pinned_(false), + browser_(nullptr) { SessionTabHelper::CreateForWebContents(contents); RenderViewCreated(contents->GetRenderViewHost()); contents->ForEachFrame( base::Bind(&TabHelper::SetTabId, base::Unretained(this))); AtomExtensionWebContentsObserver::CreateForWebContents(contents); + BrowserList::AddObserver(this); } TabHelper::~TabHelper() { + BrowserList::RemoveObserver(this); +} + +void TabHelper::OnBrowserRemoved(Browser* browser) { + if (browser_ == browser) + browser_ = nullptr; +} + +void TabHelper::SetBrowser(Browser* browser) { + if (browser == browser_) + return; + + if (browser_) { + if (index_ != TabStripModel::kNoTab) + browser_->tab_strip_model()->DetachWebContentsAt(index_); + } + + if (!browser) + return; + + browser_ = browser; + browser_->tab_strip_model()->AppendWebContents(web_contents(), false); } void TabHelper::SetWindowId(const int32_t& id) { @@ -80,17 +112,36 @@ int32_t TabHelper::window_id() const { return SessionTabHelper::FromWebContents(web_contents())->window_id().id(); } -void TabHelper::SetActive(bool active) { - if (active) - active_tab_map_[window_id()] = session_id(); - else if (active_tab_map_[window_id()] == session_id()) - active_tab_map_.erase(window_id()); +void TabHelper::SetAutoDiscardable(bool auto_discardable) { + g_browser_process->GetTabManager()->SetTabAutoDiscardableState( + web_contents(), auto_discardable); +} + +bool TabHelper::Discard() { + int64_t web_contents_id = TabManager::IdFromWebContents(web_contents()); + if (g_browser_process->GetTabManager()->DiscardTabById(web_contents_id)) + return true; + + return false; +} + +void TabHelper::SetPinned(bool pinned) { + pinned_ = pinned; } void TabHelper::SetTabIndex(int index) { index_ = index; } +bool TabHelper::is_active() const { + if (browser()) { + return browser()->tab_strip_model()-> + GetActiveWebContents() == web_contents(); + } else { + return false; + } +} + void TabHelper::SetTabValues(const base::DictionaryValue& values) { values_->MergeDictionary(&values); } @@ -106,6 +157,9 @@ void TabHelper::RenderFrameCreated(content::RenderFrameHost* host) { } void TabHelper::WebContentsDestroyed() { + if (browser()) + SetBrowser(nullptr); + render_view_map_.erase(session_id()); } @@ -303,8 +357,20 @@ base::DictionaryValue* TabHelper::CreateTabValue( auto tab_id = IdForTab(contents); auto window_id = IdForWindowContainingTab(contents); auto tab_helper = TabHelper::FromWebContents(contents); + auto browser = tab_helper->browser(); + + bool pinned = false; + if (browser) { + int index = + browser->tab_strip_model()->GetIndexOfWebContents(contents); + pinned = browser->tab_strip_model()->IsTabPinned(index); + } - bool active = (active_tab_map_[window_id] == tab_id); + bool discarded = + g_browser_process->GetTabManager()->IsTabDiscarded(contents); + bool auto_discardable = + g_browser_process->GetTabManager()->IsTabAutoDiscardable(contents); + bool active = tab_helper->is_active(); std::unique_ptr result( tab_helper->getTabValues()->CreateDeepCopy()); @@ -321,12 +387,12 @@ base::DictionaryValue* TabHelper::CreateTabValue( result->SetString(keys::kStatusKey, contents->IsLoading() ? "loading" : "complete"); result->SetBoolean(keys::kAudibleKey, contents->WasRecentlyAudible()); - result->SetBoolean(keys::kDiscardedKey, false); - result->SetBoolean(keys::kAutoDiscardableKey, false); + result->SetBoolean(keys::kDiscardedKey, discarded); + result->SetBoolean(keys::kAutoDiscardableKey, auto_discardable); result->SetBoolean(keys::kHighlightedKey, active); result->SetInteger(keys::kIndexKey, tab_helper->index_); // TODO(bridiver) - set pinned value - result->SetBoolean(keys::kPinnedKey, false); + result->SetBoolean(keys::kPinnedKey, pinned); result->SetBoolean(keys::kSelectedKey, active); return result.release(); diff --git a/atom/browser/extensions/tab_helper.h b/atom/browser/extensions/tab_helper.h index 9c607ca5d0..a49dfb5ebb 100644 --- a/atom/browser/extensions/tab_helper.h +++ b/atom/browser/extensions/tab_helper.h @@ -9,12 +9,15 @@ #include #include "base/macros.h" +#include "chrome/browser/ui/browser_list_observer.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "extensions/browser/extension_function_dispatcher.h" #include "extensions/browser/script_execution_observer.h" #include "extensions/browser/script_executor.h" +class Browser; + namespace base { class DictionaryValue; } @@ -46,7 +49,8 @@ class Extension; // This class keeps the extension API's windowID up-to-date with the current // window of the tab. class TabHelper : public content::WebContentsObserver, - public content::WebContentsUserData { + public content::WebContentsUserData, + public chrome::BrowserListObserver { public: ~TabHelper() override; @@ -58,11 +62,16 @@ class TabHelper : public content::WebContentsObserver, void SetWindowId(const int32_t& id); int32_t window_id() const; - // Set this tab as the active tab in its window - void SetActive(bool active); + void SetBrowser(Browser* browser); // Set the tab's index in its window void SetTabIndex(int index); + void SetAutoDiscardable(bool auto_discardable); + + void SetPinned(bool pinned); + + bool Discard(); + void SetTabValues(const base::DictionaryValue& values); base::DictionaryValue* getTabValues() { return values_.get(); @@ -70,10 +79,18 @@ class TabHelper : public content::WebContentsObserver, bool ExecuteScriptInTab(mate::Arguments* args); - ScriptExecutor* script_executor() { + ScriptExecutor* script_executor() const { return script_executor_.get(); } + Browser* browser() const { + return browser_; + } + + int get_index() const { return index_; } + bool is_pinned() const { return pinned_; } + bool is_active() const; + // If the specified WebContents has a TabHelper (probably because it // was used as the contents of a tab), returns a tab id. This value is // immutable for a given tab. It will be unique across Chrome within the @@ -95,6 +112,7 @@ class TabHelper : public content::WebContentsObserver, explicit TabHelper(content::WebContents* contents); friend class content::WebContentsUserData; + void OnBrowserRemoved(Browser* browser); void ExecuteScript( std::string extension_id, std::unique_ptr options, @@ -120,7 +138,10 @@ class TabHelper : public content::WebContentsObserver, std::unique_ptr script_executor_; // Index of the tab within the window - int index_ = -1; + int index_; + bool pinned_; + + Browser* browser_; DISALLOW_COPY_AND_ASSIGN(TabHelper); }; diff --git a/atom/browser/window_list.cc b/atom/browser/window_list.cc index acd5a26e85..9a29ebe5b1 100644 --- a/atom/browser/window_list.cc +++ b/atom/browser/window_list.cc @@ -9,6 +9,10 @@ #include "atom/browser/native_window.h" #include "atom/browser/window_list_observer.h" #include "base/logging.h" +#include "browser/inspectable_web_contents.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" namespace atom { @@ -29,6 +33,14 @@ WindowList* WindowList::GetInstance() { // static void WindowList::AddWindow(NativeWindow* window) { DCHECK(window); + + // add to browser list + ::Browser::CreateParams create_params(::Browser::Type::TYPE_TABBED, + Profile::FromBrowserContext(window->inspectable_web_contents() + ->GetWebContents()->GetBrowserContext())); + create_params.window = window; + new ::Browser(create_params); + // Push |window| on the appropriate list instance. WindowVector& windows = GetInstance()->windows_; windows.push_back(window); @@ -49,6 +61,12 @@ void WindowList::RemoveWindow(NativeWindow* window) { if (windows.size() == 0) for (WindowListObserver& observer : observers_.Get()) observer.OnWindowAllClosed(); + + for (auto* browser : *BrowserList::GetInstance()) { + if (browser->window() == window) { + delete browser; + } + } } // static diff --git a/brave/browser/brave_browser_context.h b/brave/browser/brave_browser_context.h index 61e61cc13d..b915990a16 100644 --- a/brave/browser/brave_browser_context.h +++ b/brave/browser/brave_browser_context.h @@ -88,7 +88,9 @@ class BraveBrowserContext : public Profile { sync_preferences::PrefServiceSyncable* GetPrefs() { return user_prefs_.get(); } - // const PrefService* GetPrefs() const override; + const sync_preferences::PrefServiceSyncable* GetPrefs() const override { + return static_cast(this)->GetPrefs(); + } PrefChangeRegistrar* user_prefs_change_registrar() const override { return user_prefs_registrar_.get(); } diff --git a/chromium_src/BUILD.gn b/chromium_src/BUILD.gn index e6212b69b3..b065c35075 100644 --- a/chromium_src/BUILD.gn +++ b/chromium_src/BUILD.gn @@ -128,15 +128,17 @@ source_set("browser") { public_deps = [] deps = [ + ":devtools", + ":importer", ":sessions", - "//electron/atom/browser", - "//chrome/browser/devtools:devtools_protocol_constants", + ":tab_manager", "//chrome/common", "//chrome/utility", "//components/certificate_transparency", "//components/data_usage/core", "//components/prefs", "//components/ssl_config", + "//electron/atom/browser", ] sources = [ @@ -148,27 +150,7 @@ source_set("browser") { "chrome/browser/chrome_notification_types.h", "chrome/browser/custom_handlers/protocol_handler_registry.cc", "chrome/browser/custom_handlers/protocol_handler_registry_factory.cc", - # devtools - "//chrome/browser/devtools/devtools_network_conditions.cc", - "//chrome/browser/devtools/devtools_network_conditions.h", - "//chrome/browser/devtools/devtools_network_controller.cc", - "//chrome/browser/devtools/devtools_network_controller.h", - "//chrome/browser/devtools/devtools_network_controller_handle.cc", - "//chrome/browser/devtools/devtools_network_controller_handle.h", - "//chrome/browser/devtools/devtools_network_interceptor.cc", - "//chrome/browser/devtools/devtools_network_interceptor.h", - "//chrome/browser/devtools/devtools_network_protocol_handler.cc", - "//chrome/browser/devtools/devtools_network_protocol_handler.h", - "//chrome/browser/devtools/devtools_network_transaction_factory.cc", - "//chrome/browser/devtools/devtools_network_transaction_factory.h", - "//chrome/browser/devtools/devtools_network_transaction.cc", - "//chrome/browser/devtools/devtools_network_transaction.h", - "//chrome/browser/devtools/devtools_network_upload_data_stream.cc", - "//chrome/browser/devtools/devtools_network_upload_data_stream.h", - "//chrome/browser/devtools/devtools_protocol.cc", - "//chrome/browser/devtools/devtools_protocol.h", - "$root_gen_dir/chrome/browser/devtools/devtools_protocol_constants.cc", - "$root_gen_dir/chrome/browser/devtools/devtools_protocol_constants.h", + # extensions "//chrome/browser/extensions/global_shortcut_listener.cc", "//chrome/browser/extensions/global_shortcut_listener.h", @@ -176,30 +158,32 @@ source_set("browser") { "//chrome/browser/extensions/global_shortcut_listener_mac.mm", "//chrome/browser/extensions/global_shortcut_listener_win.cc", "//chrome/browser/extensions/global_shortcut_listener_win.h", + + "//chrome/browser/lifetime/keep_alive_registry.cc", + "//chrome/browser/lifetime/keep_alive_registry.h", + "//chrome/browser/lifetime/keep_alive_types.cc", + "//chrome/browser/lifetime/keep_alive_types.h", + "//chrome/browser/lifetime/scoped_keep_alive.cc", + "//chrome/browser/lifetime/scoped_keep_alive.h", + + "chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc", + "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h", + "chrome/browser/media/webrtc/media_stream_capture_indicator.cc", + "chrome/browser/media/webrtc/media_stream_capture_indicator.h", + + "//chrome/browser/site_details.cc", + "//chrome/browser/site_details.h", + "//chrome/browser/ui/browser_finder.cc", + "//chrome/browser/ui/browser_finder.h", + "//chrome/browser/ui/browser_list.cc", + "//chrome/browser/ui/browser_list.h", + "chrome/browser/ui/browser.cc", + "chrome/browser/ui/browser.h", "chrome/browser/ui/browser_otr_state.cc", + "chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc", "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h", - # TODO(bridiver) - maybe use chrome? - # "chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc", - # "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h", - "chrome/browser/importer/external_process_importer_client.cc", - "chrome/browser/importer/external_process_importer_client.h", - "chrome/browser/importer/external_process_importer_host.cc", - "chrome/browser/importer/external_process_importer_host.h", - "//chrome/browser/importer/firefox_profile_lock.cc", - "//chrome/browser/importer/firefox_profile_lock.h", - "//chrome/browser/importer/firefox_profile_lock_posix.cc", - "//chrome/browser/importer/firefox_profile_lock_win.cc", - "chrome/browser/importer/importer_list.cc", - "//chrome/browser/importer/importer_list.h", - "//chrome/browser/importer/importer_lock_dialog.h", - "//chrome/browser/importer/importer_progress_observer.h", - "chrome/browser/importer/importer_uma.cc", - "//chrome/browser/importer/importer_uma.h", - "chrome/browser/importer/in_process_importer_bridge.cc", - "chrome/browser/importer/in_process_importer_bridge.h", - "chrome/browser/importer/profile_writer.h", "chrome/browser/process_singleton_posix.cc", "chrome/browser/process_singleton_win.cc", "chrome/browser/process_singleton.h", @@ -410,6 +394,107 @@ source_set("browser") { ] } } + +source_set("devtools") { + configs += [ ":chromium_src_config" ] + include_dirs = [ "." ] # force this to appear before the chromium src dir + sources = [ + # devtools + "//chrome/browser/devtools/devtools_network_conditions.cc", + "//chrome/browser/devtools/devtools_network_conditions.h", + "//chrome/browser/devtools/devtools_network_controller.cc", + "//chrome/browser/devtools/devtools_network_controller.h", + "//chrome/browser/devtools/devtools_network_controller_handle.cc", + "//chrome/browser/devtools/devtools_network_controller_handle.h", + "//chrome/browser/devtools/devtools_network_interceptor.cc", + "//chrome/browser/devtools/devtools_network_interceptor.h", + "//chrome/browser/devtools/devtools_network_protocol_handler.cc", + "//chrome/browser/devtools/devtools_network_protocol_handler.h", + "//chrome/browser/devtools/devtools_network_transaction_factory.cc", + "//chrome/browser/devtools/devtools_network_transaction_factory.h", + "//chrome/browser/devtools/devtools_network_transaction.cc", + "//chrome/browser/devtools/devtools_network_transaction.h", + "//chrome/browser/devtools/devtools_network_upload_data_stream.cc", + "//chrome/browser/devtools/devtools_network_upload_data_stream.h", + "//chrome/browser/devtools/devtools_protocol.cc", + "//chrome/browser/devtools/devtools_protocol.h", + "$root_gen_dir/chrome/browser/devtools/devtools_protocol_constants.cc", + "$root_gen_dir/chrome/browser/devtools/devtools_protocol_constants.h", + ] + + configs += [ + "//build/config/compiler:no_size_t_to_int_warning", + "//build/config/compiler:wexit_time_destructors", + "//build/config:precompiled_headers", + ] + + deps = [ + "//base", + "//content/public/browser", + "//net", + "//third_party/WebKit/public:features", + "//ui/events:dom_keycode_converter", + "//chrome/browser/devtools:devtools_protocol_constants", + ] +} + +source_set("importer") { + configs += [ ":chromium_src_config" ] + include_dirs = [ "." ] # force this to appear before the chromium src dir + sources = [ + "chrome/browser/importer/external_process_importer_client.cc", + "chrome/browser/importer/external_process_importer_client.h", + "chrome/browser/importer/external_process_importer_host.cc", + "chrome/browser/importer/external_process_importer_host.h", + "//chrome/browser/importer/firefox_profile_lock.cc", + "//chrome/browser/importer/firefox_profile_lock.h", + "//chrome/browser/importer/firefox_profile_lock_posix.cc", + "//chrome/browser/importer/firefox_profile_lock_win.cc", + "chrome/browser/importer/importer_list.cc", + "//chrome/browser/importer/importer_list.h", + "//chrome/browser/importer/importer_lock_dialog.h", + "//chrome/browser/importer/importer_progress_observer.h", + "chrome/browser/importer/importer_uma.cc", + "//chrome/browser/importer/importer_uma.h", + "chrome/browser/importer/in_process_importer_bridge.cc", + "chrome/browser/importer/in_process_importer_bridge.h", + "chrome/browser/importer/profile_writer.h", + ] + + deps = [ + "//electron/atom/browser", + ] +} + +source_set("tab_manager") { + configs += [ ":chromium_src_config" ] + include_dirs = [ "." ] # force this to appear before the chromium src dir + sources = [ + "chrome/browser/engagement/site_engagement_service.cc", + "chrome/browser/lifetime/application_lifetime.cc", + "//chrome/browser/memory/oom_memory_details.cc", + "//chrome/browser/memory/oom_memory_details.h", + "//chrome/browser/memory/tab_manager.cc", + "//chrome/browser/memory/tab_manager.h", + "//chrome/browser/memory/tab_manager_web_contents_data.cc", + "//chrome/browser/memory/tab_manager_web_contents_data.h", + "//chrome/browser/memory/tab_stats.cc", + "//chrome/browser/memory/tab_stats.h", + "//chrome/browser/memory_details.cc", + "//chrome/browser/memory_details.h", + "//chrome/browser/memory_details_linux.cc", + "//chrome/browser/memory_details_mac.cc", + "//chrome/browser/memory_details_win.cc", + "//chrome/browser/ui/browser_tab_strip_tracker.cc", + "//chrome/browser/ui/browser_tab_strip_tracker.h", + "chrome/browser/ui/tabs/tab_strip_model.cc", + "//chrome/browser/ui/tabs/tab_strip_model_observer.cc", + "//chrome/browser/ui/tabs/tab_strip_model_observer.h", + "//chrome/browser/ui/tab_contents/tab_contents_iterator.cc", + "//chrome/browser/ui/tab_contents/tab_contents_iterator.h", + ] +} + source_set("sessions") { configs += [ ":chromium_src_config" ] include_dirs = [ "." ] # force this to appear before the chromium src dir diff --git a/chromium_src/chrome/browser/browser_process_impl.cc b/chromium_src/chrome/browser/browser_process_impl.cc index 8d9dc01546..d56c29e704 100644 --- a/chromium_src/chrome/browser/browser_process_impl.cc +++ b/chromium_src/chrome/browser/browser_process_impl.cc @@ -248,6 +248,17 @@ void BrowserProcessImpl::PreMainMessageLoopRun() { #endif // BUILDFLAG(ENABLE_PLUGINS) } +memory::TabManager* BrowserProcessImpl::GetTabManager() { + DCHECK(thread_checker_.CalledOnValidThread()); +#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) + if (!tab_manager_.get()) + tab_manager_.reset(new memory::TabManager()); + return tab_manager_.get(); +#else + return nullptr; +#endif +} + // NOTIMPLEMENTED void BrowserProcessImpl::EndSession() { NOTIMPLEMENTED(); @@ -432,11 +443,6 @@ StatusTray* BrowserProcessImpl::status_tray() { return nullptr; } -memory::TabManager* BrowserProcessImpl::GetTabManager() { - NOTIMPLEMENTED(); - return nullptr; -} - shell_integration::DefaultWebClientState BrowserProcessImpl::CachedDefaultWebClientState() { NOTIMPLEMENTED(); diff --git a/chromium_src/chrome/browser/browser_process_impl.h b/chromium_src/chrome/browser/browser_process_impl.h index ff7acf8667..e5475036fa 100644 --- a/chromium_src/chrome/browser/browser_process_impl.h +++ b/chromium_src/chrome/browser/browser_process_impl.h @@ -24,6 +24,8 @@ #include "extensions/features/features.h" #include "net/log/net_log.h" +class TabManager; + namespace atom { class AtomResourceDispatcherHostDelegate; @@ -172,6 +174,12 @@ class BrowserProcessImpl : public BrowserProcess { std::unique_ptr &, bool use_brave_server); +#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) + // Any change to this #ifdef must be reflected as well in + // chrome/browser/memory/tab_manager_browsertest.cc + std::unique_ptr tab_manager_; +#endif + std::unique_ptr local_state_; DISALLOW_COPY_AND_ASSIGN(BrowserProcessImpl); diff --git a/chromium_src/chrome/browser/engagement/site_engagement_service.cc b/chromium_src/chrome/browser/engagement/site_engagement_service.cc new file mode 100644 index 0000000000..132ac9a33a --- /dev/null +++ b/chromium_src/chrome/browser/engagement/site_engagement_service.cc @@ -0,0 +1,15 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/engagement/site_engagement_service.h" + +// static +bool SiteEngagementService::IsEnabled() { + return false; +} + +// static +SiteEngagementService* SiteEngagementService::Get(Profile* profile) { + return nullptr; +} diff --git a/chromium_src/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc b/chromium_src/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc index d1432ef54c..c946405dc2 100644 --- a/chromium_src/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc +++ b/chromium_src/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc @@ -4,6 +4,9 @@ #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" +#include "browser/media/media_capture_devices_dispatcher.h" +#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" + MediaCaptureDevicesDispatcher* MediaCaptureDevicesDispatcher::GetInstance() { return base::Singleton::get(); } @@ -15,5 +18,13 @@ MediaCaptureDevicesDispatcher::~MediaCaptureDevicesDispatcher() {} bool MediaCaptureDevicesDispatcher::IsInsecureCapturingInProgress( int render_process_id, int render_frame_id) { - return false; + return brightray::MediaCaptureDevicesDispatcher::GetInstance()-> + IsInsecureCapturingInProgress(render_process_id, render_frame_id); +} + + +scoped_refptr +MediaCaptureDevicesDispatcher::GetMediaStreamCaptureIndicator() { + return brightray::MediaCaptureDevicesDispatcher::GetInstance()-> + GetMediaStreamCaptureIndicator(); } diff --git a/chromium_src/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h b/chromium_src/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h index f352ed977f..6e2ddebbc1 100644 --- a/chromium_src/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h +++ b/chromium_src/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h @@ -15,10 +15,8 @@ #include "base/memory/scoped_vector.h" #include "base/memory/singleton.h" #include "base/observer_list.h" -// #include "content/public/browser/media_observer.h" -// #include "content/public/browser/web_contents_delegate.h" -// #include "content/public/common/media_stream_request.h" +class MediaStreamCaptureIndicator; // This singleton is used to receive updates about media events from the content // layer. @@ -32,6 +30,7 @@ class MediaCaptureDevicesDispatcher { bool IsInsecureCapturingInProgress(int render_process_id, int render_frame_id); + scoped_refptr GetMediaStreamCaptureIndicator(); private: friend struct base::DefaultSingletonTraits; diff --git a/chromium_src/chrome/browser/media/webrtc/media_stream_capture_indicator.cc b/chromium_src/chrome/browser/media/webrtc/media_stream_capture_indicator.cc new file mode 100644 index 0000000000..d4302b06af --- /dev/null +++ b/chromium_src/chrome/browser/media/webrtc/media_stream_capture_indicator.cc @@ -0,0 +1,21 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" + +MediaStreamCaptureIndicator::MediaStreamCaptureIndicator() { +} + +MediaStreamCaptureIndicator::~MediaStreamCaptureIndicator() { +} + +bool MediaStreamCaptureIndicator::IsCapturingUserMedia( + content::WebContents* web_contents) const { + return false; +} + +bool MediaStreamCaptureIndicator::IsBeingMirrored( + content::WebContents* web_contents) const { + return false; +} diff --git a/chromium_src/chrome/browser/media/webrtc/media_stream_capture_indicator.h b/chromium_src/chrome/browser/media/webrtc/media_stream_capture_indicator.h new file mode 100644 index 0000000000..bf0d455c5f --- /dev/null +++ b/chromium_src/chrome/browser/media/webrtc/media_stream_capture_indicator.h @@ -0,0 +1,30 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEDIA_WEBRTC_MEDIA_STREAM_CAPTURE_INDICATOR_H_ +#define CHROME_BROWSER_MEDIA_WEBRTC_MEDIA_STREAM_CAPTURE_INDICATOR_H_ + +#include "base/callback_forward.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" + +namespace content { +class WebContents; +} // namespace content + +class MediaStreamCaptureIndicator + : public base::RefCountedThreadSafe { + public: + MediaStreamCaptureIndicator(); + + bool IsCapturingUserMedia(content::WebContents* web_contents) const; + bool IsBeingMirrored(content::WebContents* web_contents) const; + private: + friend class base::RefCountedThreadSafe; + ~MediaStreamCaptureIndicator(); + + DISALLOW_COPY_AND_ASSIGN(MediaStreamCaptureIndicator); +}; + +#endif // CHROME_BROWSER_MEDIA_WEBRTC_MEDIA_STREAM_CAPTURE_INDICATOR_H_ diff --git a/chromium_src/chrome/browser/profiles/profile.h b/chromium_src/chrome/browser/profiles/profile.h index 7daf1845d9..66e4f374d8 100644 --- a/chromium_src/chrome/browser/profiles/profile.h +++ b/chromium_src/chrome/browser/profiles/profile.h @@ -94,6 +94,7 @@ class Profile : public atom::AtomBrowserContext { double GetDefaultZoomLevelForProfile(); virtual sync_preferences::PrefServiceSyncable* GetPrefs() = 0; + virtual const sync_preferences::PrefServiceSyncable* GetPrefs() const = 0; virtual user_prefs::PrefRegistrySyncable* pref_registry() const = 0; diff --git a/chromium_src/chrome/browser/ui/browser.cc b/chromium_src/chrome/browser/ui/browser.cc new file mode 100644 index 0000000000..6c48de1c0b --- /dev/null +++ b/chromium_src/chrome/browser/ui/browser.cc @@ -0,0 +1,128 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/browser.h" + +#include + +#include +#include +#include + +#include "atom/browser/native_window.h" +#include "build/build_config.h" +#include "chrome/browser/devtools/devtools_window.h" +#include "chrome/browser/lifetime/keep_alive_registry.h" +#include "chrome/browser/lifetime/keep_alive_types.h" +#include "chrome/browser/lifetime/scoped_keep_alive.h" +#include "chrome/browser/ui/browser_list.h" +// #include "chrome/browser/ui/browser_tab_strip_model_delegate.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" + +Browser::CreateParams::CreateParams(Profile* profile) + : type(TYPE_TABBED), + profile(profile), + trusted_source(false), + initial_show_state(ui::SHOW_STATE_DEFAULT), + is_session_restore(false), + window(NULL) {} + +Browser::CreateParams::CreateParams(Type type, Profile* profile) + : type(type), + profile(profile), + trusted_source(false), + initial_show_state(ui::SHOW_STATE_DEFAULT), + is_session_restore(false), + window(NULL) {} + +Browser::CreateParams::CreateParams(const CreateParams& other) = default; + +// TODO(bridiver) - atom_api_web_contents should be tab strip model delegate +Browser::Browser(const CreateParams& params) + : type_(params.type), + profile_(params.profile), + window_(params.window), + // tab_strip_model_delegate_(new chrome::BrowserTabStripModelDelegate(this)), + tab_strip_model_( + new TabStripModel(nullptr, params.profile)), + app_name_(params.app_name), + is_trusted_source_(params.trusted_source), + initial_show_state_(params.initial_show_state), + is_session_restore_(params.is_session_restore), + weak_factory_(this) { + BrowserList::AddBrowser(this); + // content::NotificationService::current()->Notify( + // chrome::NOTIFICATION_BROWSER_WINDOW_READY, content::Source(this), + // content::NotificationService::NoDetails()); +} + +Browser::~Browser() { + BrowserList::RemoveBrowser(this); +} + +bool Browser::is_app() const { + return !app_name_.empty(); +} + +bool Browser::ShouldRunUnloadListenerBeforeClosing( + content::WebContents* web_contents) { + return false; +} + +bool Browser::RunUnloadListenerBeforeClosing( + content::WebContents* web_contents) { + return false; +} + +void Browser::RegisterKeepAlive() { + keep_alive_.reset(new ScopedKeepAlive(KeepAliveOrigin::BROWSER, + KeepAliveRestartOption::DISABLED)); +} +void Browser::UnregisterKeepAlive() { + keep_alive_.reset(); +} + +bool Browser::SupportsWindowFeature(WindowFeature feature) const { + return SupportsWindowFeatureImpl(feature, true); +} + +bool Browser::CanSupportWindowFeature(WindowFeature feature) const { + return SupportsWindowFeatureImpl(feature, false); +} + +bool Browser::CallBeforeUnloadHandlers( + const base::Callback& on_close_confirmed) { + on_close_confirmed.Run(true); +} + +void Browser::ResetBeforeUnloadHandlers() { +} + +bool Browser::SupportsWindowFeatureImpl(WindowFeature feature, + bool check_fullscreen) const { +// bool hide_ui_for_fullscreen = check_fullscreen && ShouldHideUIForFullscreen(); + + unsigned int features = FEATURE_NONE; + +// if (is_type_tabbed()) +// features |= FEATURE_BOOKMARKBAR; + +// if (!hide_ui_for_fullscreen) { +// if (!is_type_tabbed()) +// features |= FEATURE_TITLEBAR; + + if (is_type_tabbed()) + features |= FEATURE_TABSTRIP; + +// if (is_type_tabbed()) +// features |= FEATURE_TOOLBAR; + + // if (SupportsLocationBar()) + // features |= FEATURE_LOCATIONBAR; + +// if (ShouldUseWebAppFrame()) +// features |= FEATURE_WEBAPPFRAME; +// } + return !!(features & feature); +} diff --git a/chromium_src/chrome/browser/ui/browser.h b/chromium_src/chrome/browser/ui/browser.h new file mode 100644 index 0000000000..b28a298eb9 --- /dev/null +++ b/chromium_src/chrome/browser/ui/browser.h @@ -0,0 +1,252 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_BROWSER_H_ +#define CHROME_BROWSER_UI_BROWSER_H_ + +#include + +#include +#include +#include +#include +#include + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/scoped_observer.h" +#include "base/strings/string16.h" +#include "build/build_config.h" +#include "components/sessions/core/session_id.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" +#include "ui/base/ui_base_types.h" +#include "ui/base/window_open_disposition.h" +#include "ui/gfx/geometry/rect.h" + +class BrowserWindow; +class Profile; +class ScopedKeepAlive; +class TabStripModel; +class TabStripModelDelegate; + +class Browser : public content::WebContentsDelegate { + public: + // SessionService::WindowType mirrors these values. If you add to this + // enum, look at SessionService::WindowType to see if it needs to be + // updated. + enum Type { + // If you add a new type, consider updating the test + // BrowserTest.StartMaximized. + TYPE_TABBED = 1, + TYPE_POPUP = 2 + }; + + // Possible elements of the Browser window. + enum WindowFeature { + FEATURE_NONE = 0, + FEATURE_TITLEBAR = 1, + FEATURE_TABSTRIP = 2, + FEATURE_TOOLBAR = 4, + FEATURE_LOCATIONBAR = 8, + FEATURE_BOOKMARKBAR = 16, + FEATURE_INFOBAR = 32, + FEATURE_DOWNLOADSHELF = 64, + FEATURE_WEBAPPFRAME = 128 + }; + + struct CreateParams { + explicit CreateParams(Profile* profile); + CreateParams(Type type, Profile* profile); + CreateParams(const CreateParams& other); + + // The browser type. + Type type; + + // The associated profile. + Profile* profile; + + // Specifies the browser is_trusted_source_ value. + bool trusted_source; + + // The bounds of the window to open. + gfx::Rect initial_bounds; + + // The workspace the window should open in, if the platform supports it. + std::string initial_workspace; + + ui::WindowShowState initial_show_state; + + bool is_session_restore; + + // Supply a custom BrowserWindow implementation, to be used instead of the + // default. Intended for testing. + BrowserWindow* window; + + private: + friend class Browser; + + // The application name that is also the name of the window to the shell. + // Do not set this value directly, use CreateForApp. + // This name will be set for: + // 1) v1 applications launched via an application shortcut or extension API. + // 2) undocked devtool windows. + // 3) popup windows spawned from v1 applications. + std::string app_name; + }; + + // Constructors, Creation, Showing ////////////////////////////////////////// + + explicit Browser(const CreateParams& params); + ~Browser(); + + // void WillDestroyNativeObject(); + + // ui::WindowShowState initial_show_state() const { return initial_show_state_; } + // void set_initial_show_state(ui::WindowShowState initial_show_state) { + // initial_show_state_ = initial_show_state; + // } + + // // Set indicator that this browser is being created via session restore. + // // This is used on the Mac (only) to determine animation style when the + // // browser window is shown. + // void set_is_session_restore(bool is_session_restore) { + // is_session_restore_ = is_session_restore; + // } + // bool is_session_restore() const { + // return is_session_restore_; + // } + + // Accessors //////////////////////////////////////////////////////////////// + + // Type type() const { return type_; } + // const std::string& app_name() const { return app_name_; } + // bool is_trusted_source() const { return is_trusted_source_; } + Profile* profile() const { return profile_; } + + BrowserWindow* window() const { return window_; } + TabStripModel* tab_strip_model() const { return tab_strip_model_.get(); } + const SessionID& session_id() const { return session_id_; } + + // OnBeforeUnload handling ////////////////////////////////////////////////// + + // Gives beforeunload handlers the chance to cancel the close. Returns whether + // to proceed with the close. If called while the process begun by + // CallBeforeUnloadHandlers is in progress, returns false without taking + // action. + // bool ShouldCloseWindow(); + + // Begins the process of confirming whether the associated browser can be + // closed. If there are no tabs with beforeunload handlers it will immediately + // return false. Otherwise, it starts prompting the user, returns true and + // will call |on_close_confirmed| with the result of the user's decision. + // After calling this function, if the window will not be closed, call + // ResetBeforeUnloadHandlers() to reset all beforeunload handlers; calling + // this function multiple times without an intervening call to + // ResetBeforeUnloadHandlers() will run only the beforeunload handlers + // registered since the previous call. + bool CallBeforeUnloadHandlers( + const base::Callback& on_close_confirmed); + + // Clears the results of any beforeunload confirmation dialogs triggered by a + // CallBeforeUnloadHandlers call. + void ResetBeforeUnloadHandlers(); + + // Assorted browser commands //////////////////////////////////////////////// + + // NOTE: Within each of the following sections, the IDs are ordered roughly by + // how they appear in the GUI/menus (left to right, top to bottom, etc.). + + // See the description of + // FullscreenController::ToggleFullscreenModeWithExtension. + // void ToggleFullscreenModeWithExtension(const GURL& extension_url); + + // Returns true if the Browser supports the specified feature. The value of + // this varies during the lifetime of the browser. For example, if the window + // is fullscreen this may return a different value. If you only care about + // whether or not it's possible for the browser to support a particular + // feature use |CanSupportWindowFeature|. + bool SupportsWindowFeature(WindowFeature feature) const; + + // Returns true if the Browser can support the specified feature. See comment + // in |SupportsWindowFeature| for details on this. + bool CanSupportWindowFeature(WindowFeature feature) const; + + // Used to register a KeepAlive to affect the Chrome lifetime. The KeepAlive + // is registered when the browser is added to the browser list, and unregisted + // when it is removed from it. + void RegisterKeepAlive(); + void UnregisterKeepAlive(); + + bool is_type_tabbed() const { return type_ == TYPE_TABBED; } + // bool is_type_popup() const { return type_ == TYPE_POPUP; } + + bool is_app() const; + // bool is_devtools() const; + + bool ShouldRunUnloadListenerBeforeClosing(content::WebContents* web_contents); + bool RunUnloadListenerBeforeClosing(content::WebContents* web_contents); + + private: + + // Implementation of SupportsWindowFeature and CanSupportWindowFeature. If + // |check_fullscreen| is true, the set of features reflect the actual state of + // the browser, otherwise the set of features reflect the possible state of + // the browser. + bool SupportsWindowFeatureImpl(WindowFeature feature, + bool check_fullscreen) const; + + // This Browser's type. + const Type type_; + + // This Browser's profile. + Profile* const profile_; + + // This Browser's window. + BrowserWindow* window_; + + // std::unique_ptr tab_strip_model_delegate_; + std::unique_ptr tab_strip_model_; + + // The application name that is also the name of the window to the shell. + // This name should be set when: + // 1) we launch an application via an application shortcut or extension API. + // 2) we launch an undocked devtool window. + std::string app_name_; + + // True if the source is trusted (i.e. we do not need to show the URL in a + // a popup window). Also used to determine which app windows to save and + // restore on Chrome OS. + bool is_trusted_source_; + + // Unique identifier of this browser for session restore. This id is only + // unique within the current session, and is not guaranteed to be unique + // across sessions. + const SessionID session_id_; + + // ///////////////////////////////////////////////////////////////////////////// + + // // Override values for the bounds of the window and its maximized or minimized + // // state. + // // These are supplied by callers that don't want to use the default values. + // // The default values are typically loaded from local state (last session), + // // obtained from the last window of the same type, or obtained from the + // // shell shortcut's startup info. + // gfx::Rect override_bounds_; + ui::WindowShowState initial_show_state_; + // const std::string initial_workspace_; + + // Tracks when this browser is being created by session restore. + bool is_session_restore_; + + std::unique_ptr keep_alive_; + + // The following factory is used to close the frame at a later time. + base::WeakPtrFactory weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(Browser); +}; + +#endif // CHROME_BROWSER_UI_BROWSER_H_ diff --git a/chromium_src/chrome/browser/ui/browser_finder.h b/chromium_src/chrome/browser/ui/browser_finder.h deleted file mode 100644 index d032921555..0000000000 --- a/chromium_src/chrome/browser/ui/browser_finder.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_BROWSER_FINDER_H_ -#define CHROME_BROWSER_UI_BROWSER_FINDER_H_ - -namespace chrome { -} // namespace chrome - -#endif // CHROME_BROWSER_UI_BROWSER_FINDER_H_ diff --git a/chromium_src/chrome/browser/ui/tabs/tab_strip_model.cc b/chromium_src/chrome/browser/ui/tabs/tab_strip_model.cc new file mode 100644 index 0000000000..a631b0496b --- /dev/null +++ b/chromium_src/chrome/browser/ui/tabs/tab_strip_model.cc @@ -0,0 +1,253 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "chrome/browser/ui/tabs/tab_strip_model.h" + +#include "atom/browser/extensions/tab_helper.h" +#include "base/memory/ptr_util.h" +#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" +#include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" +#include "ui/base/models/list_selection_model.h" + +using content::WebContents; +using extensions::TabHelper; + +/////////////////////////////////////////////////////////////////////////////// +// WebContentsData + +// An object to hold a reference to a WebContents that is in a tabstrip, as +// well as other various properties it has. +class TabStripModel::WebContentsData : public content::WebContentsObserver { + public: + WebContentsData(WebContents* a_contents); + + // Changes the WebContents that this WebContentsData tracks. + void SetWebContents(WebContents* contents); + TabHelper* tab_helper(); + + private: + DISALLOW_COPY_AND_ASSIGN(WebContentsData); +}; + +TabStripModel::WebContentsData::WebContentsData(WebContents* contents) + : content::WebContentsObserver(contents) {} + +void TabStripModel::WebContentsData::SetWebContents(WebContents* contents) { + Observe(contents); +} + +TabHelper* TabStripModel::WebContentsData::tab_helper() { + return TabHelper::FromWebContents(web_contents()); +} + +/////////////////////////////////////////////////////////////////////////////// +// TabStripModel, public: +TabStripModel::TabStripModel(TabStripModelDelegate* delegate, Profile* profile) + : delegate_(delegate), + profile_(profile), + closing_all_(false), + in_notify_(false), + weak_factory_(this) { + DCHECK(!delegate_); +} + +TabStripModel::~TabStripModel() { + contents_data_.clear(); +} + +void TabStripModel::AddObserver(TabStripModelObserver* observer) { + observers_.AddObserver(observer); +} + +void TabStripModel::RemoveObserver(TabStripModelObserver* observer) { + observers_.RemoveObserver(observer); +} + +bool TabStripModel::ContainsIndex(int index) const { + return !!GetWebContentsAt(index); +} + +void TabStripModel::AppendWebContents(WebContents* contents, + bool foreground) { + TabHelper* tab_helper = TabHelper::FromWebContents(contents); + DCHECK(tab_helper); + + // delegate_->WillAddWebContents(contents); + std::unique_ptr data = + base::MakeUnique(contents); + + // the TabHelper tracks the actual index for now + int index = tab_helper->get_index() || contents_data_.size() - 1; + contents_data_.push_back(std::move(data)); + for (auto& observer : observers_) + observer.TabInsertedAt(this, contents, index, foreground); +} + +WebContents* TabStripModel::ReplaceWebContentsAt(int index, + WebContents* new_contents) { + // delegate_->WillAddWebContents(new_contents); + + DCHECK(ContainsIndex(index)); + WebContents* old_contents = GetWebContentsAt(index); + + for (size_t i = 0; i < contents_data_.size(); ++i) { + if (contents_data_[i]->tab_helper()->get_index() == index) { + contents_data_[i]->SetWebContents(new_contents); + break; + } + } + + for (auto& observer : observers_) + observer.TabReplacedAt(this, old_contents, new_contents, index); + + // When the active WebContents is replaced send out a selection notification + // too. We do this as nearly all observers need to treat a replacement of the + // selected contents as the selection changing. + // TODO(bridiver) - listen for this event and actually swap them + if (active_index() == index) { + for (auto& observer : observers_) + observer.ActiveTabChanged(old_contents, new_contents, active_index(), + TabStripModelObserver::CHANGE_REASON_REPLACED); + } + return old_contents; +} + +WebContents* TabStripModel::DetachWebContentsAt(int index) { + CHECK(!in_notify_); + if (contents_data_.empty()) + return nullptr; + DCHECK(ContainsIndex(index)); + + WebContents* removed_contents = GetWebContentsAt(index); + + for (size_t i = 0; i < contents_data_.size(); ++i) { + if (contents_data_[i]->tab_helper()->get_index() == index) { + contents_data_.erase(contents_data_.begin() + index); + break; + } + } + + for (auto& observer : observers_) + observer.TabDetachedAt(removed_contents, index); + + if (empty()) { + selection_model_.Clear(); + // TabDetachedAt() might unregister observers, so send |TabStripEmpty()| in + // a second pass. + for (auto& observer : observers_) + observer.TabStripEmpty(); + } + return removed_contents; +} + +void TabStripModel::ActivateTabAt(int index, bool user_gesture) { + DCHECK(ContainsIndex(index)); + ui::ListSelectionModel new_model; + new_model.Copy(selection_model_); + new_model.SetSelectedIndex(index); + SetSelection(new_model, user_gesture ? NOTIFY_USER_GESTURE : NOTIFY_DEFAULT); +} + +WebContents* TabStripModel::GetActiveWebContents() const { + return GetWebContentsAt(active_index()); +} + +WebContents* TabStripModel::GetWebContentsAt(int index) const { + for (size_t i = 0; i < contents_data_.size(); ++i) { + if (contents_data_[i]->tab_helper()->get_index() == index) + return contents_data_[i]->web_contents(); + } + return nullptr; +} + +int TabStripModel::GetIndexOfWebContents(const WebContents* contents) const { + auto tab_helper = TabHelper::FromWebContents(contents); + if (tab_helper) + return tab_helper->get_index(); + + return kNoTab; +} + +void TabStripModel::SetTabPinned(int index, bool pinned) { + DCHECK(ContainsIndex(index)); + + auto tab_helper = TabHelper::FromWebContents(GetWebContentsAt(index)); + DCHECK(tab_helper); + + if (pinned != tab_helper->is_pinned()) + tab_helper->SetPinned(pinned); + + for (auto& observer : observers_) + observer.TabPinnedStateChanged(this, tab_helper->web_contents(), + index); +} + +bool TabStripModel::IsTabPinned(int index) const { + if (!ContainsIndex(index)) + return false; + + auto tab_helper = TabHelper::FromWebContents(GetWebContentsAt(index)); + DCHECK(tab_helper); + + return tab_helper->is_pinned(); +} + +bool TabStripModel::IsTabSelected(int index) const { + if (!ContainsIndex(index)) + return false; + + return selection_model_.IsSelected(index); +} + +void TabStripModel::NotifyIfTabDeactivated(WebContents* contents) { + if (contents) { + for (auto& observer : observers_) + observer.TabDeactivated(contents); + } +} + +void TabStripModel::NotifyIfActiveTabChanged(WebContents* old_contents, + NotifyTypes notify_types) { + WebContents* new_contents = GetWebContentsAt(active_index()); + if (old_contents != new_contents) { + int reason = notify_types == NOTIFY_USER_GESTURE + ? TabStripModelObserver::CHANGE_REASON_USER_GESTURE + : TabStripModelObserver::CHANGE_REASON_NONE; + CHECK(!in_notify_); + in_notify_ = true; + for (auto& observer : observers_) + observer.ActiveTabChanged(old_contents, new_contents, active_index(), + reason); + in_notify_ = false; + } +} + +void TabStripModel::NotifyIfActiveOrSelectionChanged( + WebContents* old_contents, + NotifyTypes notify_types, + const ui::ListSelectionModel& old_model) { + NotifyIfActiveTabChanged(old_contents, notify_types); + + if (!selection_model().Equals(old_model)) { + for (auto& observer : observers_) + observer.TabSelectionChanged(this, old_model); + } +} + +void TabStripModel::SetSelection( + const ui::ListSelectionModel& new_model, + NotifyTypes notify_types) { + WebContents* old_contents = GetActiveWebContents(); + ui::ListSelectionModel old_model; + old_model.Copy(selection_model_); + if (new_model.active() != selection_model_.active()) + NotifyIfTabDeactivated(old_contents); + selection_model_.Copy(new_model); + NotifyIfActiveOrSelectionChanged(old_contents, notify_types, old_model); +} + diff --git a/vendor/brightray/browser/media/media_capture_devices_dispatcher.cc b/vendor/brightray/browser/media/media_capture_devices_dispatcher.cc index 93ec53557d..33ce9c3eea 100644 --- a/vendor/brightray/browser/media/media_capture_devices_dispatcher.cc +++ b/vendor/brightray/browser/media/media_capture_devices_dispatcher.cc @@ -5,6 +5,7 @@ #include "browser/media/media_capture_devices_dispatcher.h" #include "base/logging.h" +#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/media_capture_devices.h" #include "content/public/common/media_stream_request.h" @@ -41,7 +42,8 @@ MediaCaptureDevicesDispatcher* MediaCaptureDevicesDispatcher::GetInstance() { } MediaCaptureDevicesDispatcher::MediaCaptureDevicesDispatcher() - : is_device_enumeration_disabled_(false) { + : is_device_enumeration_disabled_(false), + media_stream_capture_indicator_(new MediaStreamCaptureIndicator()) { // MediaCaptureDevicesDispatcher is a singleton. It should be created on // UI thread. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -65,6 +67,11 @@ MediaCaptureDevicesDispatcher::GetVideoCaptureDevices() { return content::MediaCaptureDevices::GetInstance()->GetVideoCaptureDevices(); } +scoped_refptr +MediaCaptureDevicesDispatcher::GetMediaStreamCaptureIndicator() { + return media_stream_capture_indicator_; +} + void MediaCaptureDevicesDispatcher::GetDefaultDevices( bool audio, bool video, @@ -123,6 +130,13 @@ MediaCaptureDevicesDispatcher::GetFirstAvailableVideoDevice() { return &(*video_devices.begin()); } +bool MediaCaptureDevicesDispatcher::IsInsecureCapturingInProgress( + int render_process_id, + int render_frame_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return false; +} + void MediaCaptureDevicesDispatcher::DisableDeviceEnumerationForTesting() { is_device_enumeration_disabled_ = true; } diff --git a/vendor/brightray/browser/media/media_capture_devices_dispatcher.h b/vendor/brightray/browser/media/media_capture_devices_dispatcher.h index dbbd66d258..1eade79509 100644 --- a/vendor/brightray/browser/media/media_capture_devices_dispatcher.h +++ b/vendor/brightray/browser/media/media_capture_devices_dispatcher.h @@ -11,6 +11,8 @@ #include "content/public/browser/web_contents_delegate.h" #include "content/public/common/media_stream_request.h" +class MediaStreamCaptureIndicator; + namespace brightray { // This singleton is used to receive updates about media events from the content @@ -49,6 +51,11 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver { // signleton. void DisableDeviceEnumerationForTesting(); + bool IsInsecureCapturingInProgress(int render_process_id, + int render_frame_id); + + scoped_refptr GetMediaStreamCaptureIndicator(); + // Overridden from content::MediaObserver: void OnAudioCaptureDevicesChanged() override; void OnVideoCaptureDevicesChanged() override; @@ -76,6 +83,8 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver { // Flag used by unittests to disable device enumeration. bool is_device_enumeration_disabled_; + scoped_refptr media_stream_capture_indicator_; + DISALLOW_COPY_AND_ASSIGN(MediaCaptureDevicesDispatcher); };