| OLD | NEW | 
 | (Empty) | 
|    1 // Copyright 2015 The Chromium Authors. All rights reserved. |  | 
|    2 // Use of this source code is governed by a BSD-style license that can be |  | 
|    3 // found in the LICENSE file. |  | 
|    4  |  | 
|    5 #include "ui/display/chromeos/apply_content_protection_task.h" |  | 
|    6  |  | 
|    7 #include "ui/display/chromeos/display_layout_manager.h" |  | 
|    8 #include "ui/display/types/display_snapshot.h" |  | 
|    9 #include "ui/display/types/native_display_delegate.h" |  | 
|   10  |  | 
|   11 namespace ui { |  | 
|   12  |  | 
|   13 namespace { |  | 
|   14  |  | 
|   15 bool GetHDCPCapableDisplays( |  | 
|   16     const DisplayLayoutManager& layout_manager, |  | 
|   17     std::vector<DisplaySnapshot*>* hdcp_capable_displays) { |  | 
|   18   for (DisplaySnapshot* display : layout_manager.GetDisplayStates()) { |  | 
|   19     switch (display->type()) { |  | 
|   20       case DISPLAY_CONNECTION_TYPE_UNKNOWN: |  | 
|   21         return false; |  | 
|   22       // DisplayPort, DVI, and HDMI all support HDCP. |  | 
|   23       case DISPLAY_CONNECTION_TYPE_DISPLAYPORT: |  | 
|   24       case DISPLAY_CONNECTION_TYPE_DVI: |  | 
|   25       case DISPLAY_CONNECTION_TYPE_HDMI: |  | 
|   26         hdcp_capable_displays->push_back(display); |  | 
|   27         break; |  | 
|   28       case DISPLAY_CONNECTION_TYPE_INTERNAL: |  | 
|   29       case DISPLAY_CONNECTION_TYPE_VGA: |  | 
|   30       case DISPLAY_CONNECTION_TYPE_NETWORK: |  | 
|   31       case DISPLAY_CONNECTION_TYPE_VIRTUAL: |  | 
|   32         // No protections for these types. Do nothing. |  | 
|   33         break; |  | 
|   34       case DISPLAY_CONNECTION_TYPE_NONE: |  | 
|   35         NOTREACHED(); |  | 
|   36         break; |  | 
|   37     } |  | 
|   38   } |  | 
|   39  |  | 
|   40   return true; |  | 
|   41 } |  | 
|   42  |  | 
|   43 }  // namespace |  | 
|   44  |  | 
|   45 ApplyContentProtectionTask::ApplyContentProtectionTask( |  | 
|   46     DisplayLayoutManager* layout_manager, |  | 
|   47     NativeDisplayDelegate* native_display_delegate, |  | 
|   48     const DisplayConfigurator::ContentProtections& requests, |  | 
|   49     const ResponseCallback& callback) |  | 
|   50     : layout_manager_(layout_manager), |  | 
|   51       native_display_delegate_(native_display_delegate), |  | 
|   52       requests_(requests), |  | 
|   53       callback_(callback), |  | 
|   54       query_status_(true), |  | 
|   55       pending_requests_(0), |  | 
|   56       weak_ptr_factory_(this) { |  | 
|   57 } |  | 
|   58  |  | 
|   59 ApplyContentProtectionTask::~ApplyContentProtectionTask() { |  | 
|   60 } |  | 
|   61  |  | 
|   62 void ApplyContentProtectionTask::Run() { |  | 
|   63   std::vector<DisplaySnapshot*> hdcp_capable_displays; |  | 
|   64   if (!GetHDCPCapableDisplays(*layout_manager_, &hdcp_capable_displays)) { |  | 
|   65     callback_.Run(false); |  | 
|   66     return; |  | 
|   67   } |  | 
|   68  |  | 
|   69   pending_requests_ = hdcp_capable_displays.size(); |  | 
|   70   if (pending_requests_ == 0) { |  | 
|   71     callback_.Run(true); |  | 
|   72     return; |  | 
|   73   } |  | 
|   74  |  | 
|   75   // Need to poll the driver for updates since other applications may have |  | 
|   76   // updated the state. |  | 
|   77   for (DisplaySnapshot* display : hdcp_capable_displays) { |  | 
|   78     native_display_delegate_->GetHDCPState( |  | 
|   79         *display, |  | 
|   80         base::Bind(&ApplyContentProtectionTask::OnHDCPStateUpdate, |  | 
|   81                    weak_ptr_factory_.GetWeakPtr(), display->display_id())); |  | 
|   82   } |  | 
|   83 } |  | 
|   84  |  | 
|   85 void ApplyContentProtectionTask::OnHDCPStateUpdate(int64_t display_id, |  | 
|   86                                                    bool success, |  | 
|   87                                                    HDCPState state) { |  | 
|   88   query_status_ &= success; |  | 
|   89   display_hdcp_state_map_[display_id] = state; |  | 
|   90   pending_requests_--; |  | 
|   91  |  | 
|   92   // Wait for all the requests before continuing. |  | 
|   93   if (pending_requests_ != 0) |  | 
|   94     return; |  | 
|   95  |  | 
|   96   if (!query_status_) { |  | 
|   97     callback_.Run(false); |  | 
|   98     return; |  | 
|   99   } |  | 
|  100  |  | 
|  101   ApplyProtections(); |  | 
|  102 } |  | 
|  103  |  | 
|  104 void ApplyContentProtectionTask::ApplyProtections() { |  | 
|  105   std::vector<DisplaySnapshot*> hdcp_capable_displays; |  | 
|  106   if (!GetHDCPCapableDisplays(*layout_manager_, &hdcp_capable_displays)) { |  | 
|  107     callback_.Run(false); |  | 
|  108     return; |  | 
|  109   } |  | 
|  110  |  | 
|  111   std::vector<std::pair<DisplaySnapshot*, HDCPState>> hdcp_requests; |  | 
|  112   // Figure out which displays need to have their HDCP state changed. |  | 
|  113   for (DisplaySnapshot* display : hdcp_capable_displays) { |  | 
|  114     uint32_t desired_mask = GetDesiredProtectionMask(display->display_id()); |  | 
|  115  |  | 
|  116     auto it = display_hdcp_state_map_.find(display->display_id()); |  | 
|  117     // If the display can't be found, the display configuration changed. |  | 
|  118     if (it == display_hdcp_state_map_.end()) { |  | 
|  119       callback_.Run(false); |  | 
|  120       return; |  | 
|  121     } |  | 
|  122  |  | 
|  123     bool hdcp_enabled = it->second != HDCP_STATE_UNDESIRED; |  | 
|  124     bool hdcp_requested = desired_mask & CONTENT_PROTECTION_METHOD_HDCP; |  | 
|  125     if (hdcp_enabled != hdcp_requested) { |  | 
|  126       hdcp_requests.push_back(std::make_pair( |  | 
|  127           display, hdcp_requested ? HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED)); |  | 
|  128     } |  | 
|  129   } |  | 
|  130  |  | 
|  131   pending_requests_ = hdcp_requests.size(); |  | 
|  132   // All the requested changes are the same as the current HDCP state. Nothing |  | 
|  133   // to do anymore, just ack the content protection change. |  | 
|  134   if (pending_requests_ == 0) { |  | 
|  135     callback_.Run(true); |  | 
|  136     return; |  | 
|  137   } |  | 
|  138  |  | 
|  139   for (const auto& pair : hdcp_requests) { |  | 
|  140     native_display_delegate_->SetHDCPState( |  | 
|  141         *pair.first, pair.second, |  | 
|  142         base::Bind(&ApplyContentProtectionTask::OnHDCPStateApplied, |  | 
|  143                    weak_ptr_factory_.GetWeakPtr())); |  | 
|  144   } |  | 
|  145 } |  | 
|  146  |  | 
|  147 void ApplyContentProtectionTask::OnHDCPStateApplied(bool success) { |  | 
|  148   query_status_ &= success; |  | 
|  149   pending_requests_--; |  | 
|  150  |  | 
|  151   if (pending_requests_ == 0) |  | 
|  152     callback_.Run(query_status_); |  | 
|  153 } |  | 
|  154  |  | 
|  155 uint32_t ApplyContentProtectionTask::GetDesiredProtectionMask( |  | 
|  156     int64_t display_id) const { |  | 
|  157   uint32_t desired_mask = 0; |  | 
|  158   // In mirror mode, protection request of all displays need to be fulfilled. |  | 
|  159   // In non-mirror mode, only request of client's display needs to be |  | 
|  160   // fulfilled. |  | 
|  161   if (layout_manager_->IsMirroring()) { |  | 
|  162     for (auto pair : requests_) |  | 
|  163       desired_mask |= pair.second; |  | 
|  164   } else { |  | 
|  165     auto it = requests_.find(display_id); |  | 
|  166     if (it != requests_.end()) |  | 
|  167       desired_mask = it->second; |  | 
|  168   } |  | 
|  169  |  | 
|  170   return desired_mask; |  | 
|  171 } |  | 
|  172  |  | 
|  173 }  // namespace ui |  | 
| OLD | NEW |