Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Represents the browser side of the browser <--> renderer communication | 5 // Represents the browser side of the browser <--> renderer communication |
| 6 // channel. There will be one RenderProcessHost per renderer process. | 6 // channel. There will be one RenderProcessHost per renderer process. |
| 7 | 7 |
| 8 #include "content/browser/renderer_host/render_process_host_impl.h" | 8 #include "content/browser/renderer_host/render_process_host_impl.h" |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 #include "content/public/common/url_constants.h" | 157 #include "content/public/common/url_constants.h" |
| 158 #include "device/battery/battery_monitor_impl.h" | 158 #include "device/battery/battery_monitor_impl.h" |
| 159 #include "gpu/GLES2/gl2extchromium.h" | 159 #include "gpu/GLES2/gl2extchromium.h" |
| 160 #include "gpu/command_buffer/client/gpu_switches.h" | 160 #include "gpu/command_buffer/client/gpu_switches.h" |
| 161 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 161 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| 162 #include "gpu/command_buffer/service/gpu_switches.h" | 162 #include "gpu/command_buffer/service/gpu_switches.h" |
| 163 #include "ipc/attachment_broker.h" | 163 #include "ipc/attachment_broker.h" |
| 164 #include "ipc/attachment_broker_privileged.h" | 164 #include "ipc/attachment_broker_privileged.h" |
| 165 #include "ipc/ipc_channel.h" | 165 #include "ipc/ipc_channel.h" |
| 166 #include "ipc/ipc_logging.h" | 166 #include "ipc/ipc_logging.h" |
| 167 #include "ipc/ipc_sender.h" | |
| 167 #include "ipc/ipc_switches.h" | 168 #include "ipc/ipc_switches.h" |
| 168 #include "ipc/mojo/ipc_channel_mojo.h" | 169 #include "ipc/mojo/ipc_channel_mojo.h" |
| 169 #include "media/base/media_switches.h" | 170 #include "media/base/media_switches.h" |
| 170 #include "mojo/edk/embedder/embedder.h" | 171 #include "mojo/edk/embedder/embedder.h" |
| 171 #include "net/url_request/url_request_context_getter.h" | 172 #include "net/url_request/url_request_context_getter.h" |
| 172 #include "ppapi/shared_impl/ppapi_switches.h" | 173 #include "ppapi/shared_impl/ppapi_switches.h" |
| 173 #include "services/shell/runner/common/switches.h" | 174 #include "services/shell/runner/common/switches.h" |
| 174 #include "storage/browser/fileapi/sandbox_file_system_backend.h" | 175 #include "storage/browser/fileapi/sandbox_file_system_backend.h" |
| 175 #include "third_party/skia/include/core/SkBitmap.h" | 176 #include "third_party/skia/include/core/SkBitmap.h" |
| 176 #include "ui/base/ui_base_switches.h" | 177 #include "ui/base/ui_base_switches.h" |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 440 for (auto it : vector) { | 441 for (auto it : vector) { |
| 441 if (!str.empty()) | 442 if (!str.empty()) |
| 442 str += ","; | 443 str += ","; |
| 443 str += base::UintToString(it); | 444 str += base::UintToString(it); |
| 444 } | 445 } |
| 445 return str; | 446 return str; |
| 446 } | 447 } |
| 447 | 448 |
| 448 } // namespace | 449 } // namespace |
| 449 | 450 |
| 451 // SafeSenderProxy owns two IPC::Sender implementations which proxy to the | |
| 452 // RPH's own ChannelProxy. One enables immediate sends while the other enables | |
| 453 // IO-thread sends. These are both implemented via RPHI's SendImpl which safely | |
| 454 // avoids dereferencing the underlying ChannelProxy if it's been reset (e.g. | |
| 455 // after process death.) | |
| 456 class RenderProcessHostImpl::SafeSenderProxy { | |
| 457 public: | |
| 458 // |process| must outlive this object. | |
| 459 explicit SafeSenderProxy(RenderProcessHostImpl* process) | |
| 460 : process_(process), | |
| 461 immediate_sender_(process_, true /* send_now */), | |
| 462 io_thread_sender_(process_, false /* send_now */) {} | |
| 463 ~SafeSenderProxy() {} | |
| 464 | |
| 465 IPC::Sender* immediate_sender() { return &immediate_sender_; } | |
| 466 IPC::Sender* io_thread_sender() { return &io_thread_sender_; } | |
| 467 | |
| 468 bool SendImpl(std::unique_ptr<IPC::Message> message, bool send_now) { | |
| 469 return process_->SendImpl(std::move(message), send_now); | |
| 470 } | |
|
piman
2016/05/24 17:24:51
nit: this is not needed any more, I think.
Ken Rockot(use gerrit already)
2016/05/24 18:00:08
Removed
| |
| 471 | |
| 472 private: | |
| 473 class SenderProxy : public IPC::Sender { | |
| 474 public: | |
| 475 SenderProxy(RenderProcessHostImpl* process, bool send_now) | |
| 476 : process_(process), send_now_(send_now) {} | |
| 477 ~SenderProxy() override {} | |
| 478 | |
| 479 // IPC::Sender: | |
| 480 bool Send(IPC::Message* message) override { | |
| 481 return process_->SendImpl(base::WrapUnique(message), send_now_); | |
| 482 } | |
| 483 | |
| 484 private: | |
| 485 RenderProcessHostImpl* const process_; | |
| 486 const bool send_now_; | |
| 487 | |
| 488 DISALLOW_COPY_AND_ASSIGN(SenderProxy); | |
| 489 }; | |
| 490 | |
| 491 RenderProcessHostImpl* const process_; | |
|
piman
2016/05/24 17:24:51
nit: neither is this.
Ken Rockot(use gerrit already)
2016/05/24 18:00:08
Ditto
| |
| 492 SenderProxy immediate_sender_; | |
| 493 SenderProxy io_thread_sender_; | |
| 494 | |
| 495 DISALLOW_COPY_AND_ASSIGN(SafeSenderProxy); | |
| 496 }; | |
| 497 | |
| 450 RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; | 498 RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; |
| 451 | 499 |
| 452 base::MessageLoop* g_in_process_thread; | 500 base::MessageLoop* g_in_process_thread; |
| 453 | 501 |
| 454 base::MessageLoop* | 502 base::MessageLoop* |
| 455 RenderProcessHostImpl::GetInProcessRendererThreadForTesting() { | 503 RenderProcessHostImpl::GetInProcessRendererThreadForTesting() { |
| 456 return g_in_process_thread; | 504 return g_in_process_thread; |
| 457 } | 505 } |
| 458 | 506 |
| 459 // Stores the maximum number of renderer processes the content module can | 507 // Stores the maximum number of renderer processes the content module can |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 RenderProcessHostImpl::RenderProcessHostImpl( | 577 RenderProcessHostImpl::RenderProcessHostImpl( |
| 530 BrowserContext* browser_context, | 578 BrowserContext* browser_context, |
| 531 StoragePartitionImpl* storage_partition_impl, | 579 StoragePartitionImpl* storage_partition_impl, |
| 532 bool is_for_guests_only) | 580 bool is_for_guests_only) |
| 533 : fast_shutdown_started_(false), | 581 : fast_shutdown_started_(false), |
| 534 deleting_soon_(false), | 582 deleting_soon_(false), |
| 535 #ifndef NDEBUG | 583 #ifndef NDEBUG |
| 536 is_self_deleted_(false), | 584 is_self_deleted_(false), |
| 537 #endif | 585 #endif |
| 538 pending_views_(0), | 586 pending_views_(0), |
| 587 safe_sender_(new SafeSenderProxy(this)), | |
| 539 mojo_application_host_(new MojoApplicationHost), | 588 mojo_application_host_(new MojoApplicationHost), |
| 540 visible_widgets_(0), | 589 visible_widgets_(0), |
| 541 is_process_backgrounded_(false), | 590 is_process_backgrounded_(false), |
| 542 is_initialized_(false), | 591 is_initialized_(false), |
| 543 id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), | 592 id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), |
| 544 browser_context_(browser_context), | 593 browser_context_(browser_context), |
| 545 storage_partition_impl_(storage_partition_impl), | 594 storage_partition_impl_(storage_partition_impl), |
| 546 sudden_termination_allowed_(true), | 595 sudden_termination_allowed_(true), |
| 547 ignore_input_events_(false), | 596 ignore_input_events_(false), |
| 548 is_for_guests_only_(is_for_guests_only), | 597 is_for_guests_only_(is_for_guests_only), |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 641 ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this); | 690 ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this); |
| 642 gpu_observer_registered_ = false; | 691 gpu_observer_registered_ = false; |
| 643 } | 692 } |
| 644 | 693 |
| 645 #if USE_ATTACHMENT_BROKER | 694 #if USE_ATTACHMENT_BROKER |
| 646 IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel( | 695 IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel( |
| 647 channel_.get()); | 696 channel_.get()); |
| 648 #endif | 697 #endif |
| 649 // We may have some unsent messages at this point, but that's OK. | 698 // We may have some unsent messages at this point, but that's OK. |
| 650 channel_.reset(); | 699 channel_.reset(); |
| 651 while (!queued_messages_.empty()) { | 700 while (!queued_messages_.empty()) |
| 652 delete queued_messages_.front(); | |
| 653 queued_messages_.pop(); | 701 queued_messages_.pop(); |
| 654 } | |
| 655 | 702 |
| 656 UnregisterHost(GetID()); | 703 UnregisterHost(GetID()); |
| 657 | 704 |
| 658 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 705 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 659 switches::kDisableGpuShaderDiskCache)) { | 706 switches::kDisableGpuShaderDiskCache)) { |
| 660 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 707 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 661 base::Bind(&RemoveShaderInfo, GetID())); | 708 base::Bind(&RemoveShaderInfo, GetID())); |
| 662 } | 709 } |
| 663 } | 710 } |
| 664 | 711 |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1008 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) | 1055 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
| 1009 enable_web_bluetooth = true; | 1056 enable_web_bluetooth = true; |
| 1010 #endif | 1057 #endif |
| 1011 | 1058 |
| 1012 if (enable_web_bluetooth) { | 1059 if (enable_web_bluetooth) { |
| 1013 bluetooth_dispatcher_host_ = new BluetoothDispatcherHost(GetID()); | 1060 bluetooth_dispatcher_host_ = new BluetoothDispatcherHost(GetID()); |
| 1014 AddFilter(bluetooth_dispatcher_host_.get()); | 1061 AddFilter(bluetooth_dispatcher_host_.get()); |
| 1015 } | 1062 } |
| 1016 } | 1063 } |
| 1017 | 1064 |
| 1065 bool RenderProcessHostImpl::SendImpl(std::unique_ptr<IPC::Message> msg, | |
| 1066 bool send_now) { | |
| 1067 TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::SendImpl"); | |
| 1068 #if !defined(OS_ANDROID) | |
| 1069 DCHECK(!msg->is_sync()); | |
| 1070 #endif | |
| 1071 | |
| 1072 if (!channel_) { | |
| 1073 #if defined(OS_ANDROID) | |
| 1074 if (msg->is_sync()) | |
| 1075 return false; | |
| 1076 #endif | |
| 1077 if (!is_initialized_) { | |
| 1078 queued_messages_.emplace(std::move(msg)); | |
| 1079 return true; | |
| 1080 } else { | |
| 1081 return false; | |
| 1082 } | |
| 1083 } | |
| 1084 | |
| 1085 if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { | |
| 1086 #if defined(OS_ANDROID) | |
| 1087 if (msg->is_sync()) | |
| 1088 return false; | |
| 1089 #endif | |
| 1090 queued_messages_.emplace(std::move(msg)); | |
| 1091 return true; | |
| 1092 } | |
| 1093 | |
| 1094 if (send_now) | |
| 1095 return channel_->SendNow(std::move(msg)); | |
| 1096 | |
| 1097 return channel_->SendOnIPCThread(std::move(msg)); | |
| 1098 } | |
| 1099 | |
| 1018 void RenderProcessHostImpl::RegisterMojoServices() { | 1100 void RenderProcessHostImpl::RegisterMojoServices() { |
| 1019 #if !defined(OS_ANDROID) | 1101 #if !defined(OS_ANDROID) |
| 1020 mojo_application_host_->service_registry()->AddService( | 1102 mojo_application_host_->service_registry()->AddService( |
| 1021 base::Bind(&device::BatteryMonitorImpl::Create)); | 1103 base::Bind(&device::BatteryMonitorImpl::Create)); |
| 1022 #endif | 1104 #endif |
| 1023 | 1105 |
| 1024 mojo_application_host_->service_registry()->AddService( | 1106 mojo_application_host_->service_registry()->AddService( |
| 1025 base::Bind(&PermissionServiceContext::CreateService, | 1107 base::Bind(&PermissionServiceContext::CreateService, |
| 1026 base::Unretained(permission_service_context_.get()))); | 1108 base::Unretained(permission_service_context_.get()))); |
| 1027 | 1109 |
| (...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1636 | 1718 |
| 1637 // Set this before ProcessDied() so observers can tell if the render process | 1719 // Set this before ProcessDied() so observers can tell if the render process |
| 1638 // died due to fast shutdown versus another cause. | 1720 // died due to fast shutdown versus another cause. |
| 1639 fast_shutdown_started_ = true; | 1721 fast_shutdown_started_ = true; |
| 1640 | 1722 |
| 1641 ProcessDied(false /* already_dead */, nullptr); | 1723 ProcessDied(false /* already_dead */, nullptr); |
| 1642 return true; | 1724 return true; |
| 1643 } | 1725 } |
| 1644 | 1726 |
| 1645 bool RenderProcessHostImpl::Send(IPC::Message* msg) { | 1727 bool RenderProcessHostImpl::Send(IPC::Message* msg) { |
| 1646 TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send"); | 1728 return SendImpl(base::WrapUnique(msg), false /* send_now */); |
| 1647 #if !defined(OS_ANDROID) | |
| 1648 DCHECK(!msg->is_sync()); | |
| 1649 #endif | |
| 1650 | |
| 1651 if (!channel_) { | |
| 1652 #if defined(OS_ANDROID) | |
| 1653 if (msg->is_sync()) { | |
| 1654 delete msg; | |
| 1655 return false; | |
| 1656 } | |
| 1657 #endif | |
| 1658 if (!is_initialized_) { | |
| 1659 queued_messages_.push(msg); | |
| 1660 return true; | |
| 1661 } else { | |
| 1662 delete msg; | |
| 1663 return false; | |
| 1664 } | |
| 1665 } | |
| 1666 | |
| 1667 if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { | |
| 1668 #if defined(OS_ANDROID) | |
| 1669 if (msg->is_sync()) { | |
| 1670 delete msg; | |
| 1671 return false; | |
| 1672 } | |
| 1673 #endif | |
| 1674 queued_messages_.push(msg); | |
| 1675 return true; | |
| 1676 } | |
| 1677 | |
| 1678 return channel_->Send(msg); | |
| 1679 } | 1729 } |
| 1680 | 1730 |
| 1681 bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { | 1731 bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { |
| 1682 // If we're about to be deleted, or have initiated the fast shutdown sequence, | 1732 // If we're about to be deleted, or have initiated the fast shutdown sequence, |
| 1683 // we ignore incoming messages. | 1733 // we ignore incoming messages. |
| 1684 | 1734 |
| 1685 if (deleting_soon_ || fast_shutdown_started_) | 1735 if (deleting_soon_ || fast_shutdown_started_) |
| 1686 return false; | 1736 return false; |
| 1687 | 1737 |
| 1688 mark_child_process_activity_time(); | 1738 mark_child_process_activity_time(); |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2024 p2p_socket_dispatcher_host_); | 2074 p2p_socket_dispatcher_host_); |
| 2025 } | 2075 } |
| 2026 return stop_rtp_dump_callback_; | 2076 return stop_rtp_dump_callback_; |
| 2027 } | 2077 } |
| 2028 #endif | 2078 #endif |
| 2029 | 2079 |
| 2030 IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() { | 2080 IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() { |
| 2031 return channel_.get(); | 2081 return channel_.get(); |
| 2032 } | 2082 } |
| 2033 | 2083 |
| 2084 IPC::Sender* RenderProcessHostImpl::GetImmediateSender() { | |
| 2085 return safe_sender_->immediate_sender(); | |
| 2086 } | |
| 2087 | |
| 2088 IPC::Sender* RenderProcessHostImpl::GetIOThreadSender() { | |
| 2089 return safe_sender_->io_thread_sender(); | |
| 2090 } | |
| 2091 | |
| 2034 void RenderProcessHostImpl::AddFilter(BrowserMessageFilter* filter) { | 2092 void RenderProcessHostImpl::AddFilter(BrowserMessageFilter* filter) { |
| 2035 channel_->AddFilter(filter->GetFilter()); | 2093 channel_->AddFilter(filter->GetFilter()); |
| 2036 } | 2094 } |
| 2037 | 2095 |
| 2038 bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) { | 2096 bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) { |
| 2039 if (GetActiveViewCount() == count) | 2097 if (GetActiveViewCount() == count) |
| 2040 return FastShutdownIfPossible(); | 2098 return FastShutdownIfPossible(); |
| 2041 return false; | 2099 return false; |
| 2042 } | 2100 } |
| 2043 | 2101 |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2369 } | 2427 } |
| 2370 | 2428 |
| 2371 RendererClosedDetails details(status, exit_code); | 2429 RendererClosedDetails details(status, exit_code); |
| 2372 | 2430 |
| 2373 child_process_launcher_.reset(); | 2431 child_process_launcher_.reset(); |
| 2374 #if USE_ATTACHMENT_BROKER | 2432 #if USE_ATTACHMENT_BROKER |
| 2375 IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel( | 2433 IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel( |
| 2376 channel_.get()); | 2434 channel_.get()); |
| 2377 #endif | 2435 #endif |
| 2378 channel_.reset(); | 2436 channel_.reset(); |
| 2379 while (!queued_messages_.empty()) { | 2437 while (!queued_messages_.empty()) |
| 2380 delete queued_messages_.front(); | |
| 2381 queued_messages_.pop(); | 2438 queued_messages_.pop(); |
| 2382 } | |
| 2383 UpdateProcessPriority(); | 2439 UpdateProcessPriority(); |
| 2384 DCHECK(!is_process_backgrounded_); | 2440 DCHECK(!is_process_backgrounded_); |
| 2385 | 2441 |
| 2386 // RenderProcessExited observers and RenderProcessGone handlers might | 2442 // RenderProcessExited observers and RenderProcessGone handlers might |
| 2387 // navigate or perform other actions that require a connection. Ensure that | 2443 // navigate or perform other actions that require a connection. Ensure that |
| 2388 // there is one before calling them. | 2444 // there is one before calling them. |
| 2389 mojo_application_host_.reset(new MojoApplicationHost); | 2445 mojo_application_host_.reset(new MojoApplicationHost); |
| 2390 | 2446 |
| 2391 within_process_died_observer_ = true; | 2447 within_process_died_observer_ = true; |
| 2392 NotificationService::current()->Notify( | 2448 NotificationService::current()->Notify( |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2549 // with state that must be there before any JavaScript executes. | 2605 // with state that must be there before any JavaScript executes. |
| 2550 // | 2606 // |
| 2551 // The queued messages contain such things as "navigate". If this notification | 2607 // The queued messages contain such things as "navigate". If this notification |
| 2552 // was after, we can end up executing JavaScript before the initialization | 2608 // was after, we can end up executing JavaScript before the initialization |
| 2553 // happens. | 2609 // happens. |
| 2554 NotificationService::current()->Notify(NOTIFICATION_RENDERER_PROCESS_CREATED, | 2610 NotificationService::current()->Notify(NOTIFICATION_RENDERER_PROCESS_CREATED, |
| 2555 Source<RenderProcessHost>(this), | 2611 Source<RenderProcessHost>(this), |
| 2556 NotificationService::NoDetails()); | 2612 NotificationService::NoDetails()); |
| 2557 | 2613 |
| 2558 while (!queued_messages_.empty()) { | 2614 while (!queued_messages_.empty()) { |
| 2559 Send(queued_messages_.front()); | 2615 Send(queued_messages_.front().release()); |
| 2560 queued_messages_.pop(); | 2616 queued_messages_.pop(); |
| 2561 } | 2617 } |
| 2562 | 2618 |
| 2563 if (IsReady()) { | 2619 if (IsReady()) { |
| 2564 DCHECK(!sent_render_process_ready_); | 2620 DCHECK(!sent_render_process_ready_); |
| 2565 sent_render_process_ready_ = true; | 2621 sent_render_process_ready_ = true; |
| 2566 // Send RenderProcessReady only if the channel is already connected. | 2622 // Send RenderProcessReady only if the channel is already connected. |
| 2567 FOR_EACH_OBSERVER(RenderProcessHostObserver, | 2623 FOR_EACH_OBSERVER(RenderProcessHostObserver, |
| 2568 observers_, | 2624 observers_, |
| 2569 RenderProcessReady(this)); | 2625 RenderProcessReady(this)); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2761 | 2817 |
| 2762 // Skip widgets in other processes. | 2818 // Skip widgets in other processes. |
| 2763 if (rvh->GetProcess()->GetID() != GetID()) | 2819 if (rvh->GetProcess()->GetID() != GetID()) |
| 2764 continue; | 2820 continue; |
| 2765 | 2821 |
| 2766 rvh->OnWebkitPreferencesChanged(); | 2822 rvh->OnWebkitPreferencesChanged(); |
| 2767 } | 2823 } |
| 2768 } | 2824 } |
| 2769 | 2825 |
| 2770 } // namespace content | 2826 } // namespace content |
| OLD | NEW |