| // Copyright 2020 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package camera |
| |
| import ( |
| "context" |
| "strings" |
| "time" |
| |
| "chromiumos/tast/common/media/caps" |
| "chromiumos/tast/common/policy" |
| "chromiumos/tast/common/policy/fakedms" |
| "chromiumos/tast/errors" |
| "chromiumos/tast/local/apps" |
| "chromiumos/tast/local/camera/cca" |
| "chromiumos/tast/local/camera/testutil" |
| "chromiumos/tast/local/chrome" |
| "chromiumos/tast/local/chrome/uiauto" |
| "chromiumos/tast/local/chrome/uiauto/launcher" |
| "chromiumos/tast/local/chrome/uiauto/nodewith" |
| "chromiumos/tast/local/chrome/uiauto/role" |
| "chromiumos/tast/local/input" |
| "chromiumos/tast/local/policyutil" |
| "chromiumos/tast/local/policyutil/fixtures" |
| "chromiumos/tast/testing" |
| ) |
| |
| func init() { |
| testing.AddTest(&testing.Test{ |
| Func: CCAUIPolicy, |
| Desc: "Verifies if CCA is unusable when the camera app is disabled by the Adenterprise policy", |
| Contacts: []string{"wtlee@chromium.org", "chromeos-camera-eng@google.com"}, |
| Attr: []string{"group:mainline", "informational", "group:camera-libcamera"}, |
| SoftwareDeps: []string{"camera_app", "chrome", caps.BuiltinOrVividCamera}, |
| Data: []string{"cca_ui.js"}, |
| Fixture: "chromePolicyLoggedIn", |
| }) |
| } |
| |
| func CCAUIPolicy(ctx context.Context, s *testing.State) { |
| cr := s.FixtValue().(*fixtures.FixtData).Chrome |
| fdms := s.FixtValue().(*fixtures.FixtData).FakeDMS |
| |
| scripts := []string{s.DataPath("cca_ui.js")} |
| outDir := s.OutDir() |
| |
| subTestTimeout := 30 * time.Second |
| for _, tst := range []struct { |
| name string |
| testFunc func(context.Context, *chrome.Chrome, []string, string) error |
| policy []policy.Policy |
| }{{ |
| "testNoPolicy", |
| testNoPolicy, |
| []policy.Policy{}, |
| }, { |
| "testBlockCameraFeature", |
| testBlockCameraFeature, |
| []policy.Policy{&policy.SystemFeaturesDisableList{Val: []string{"camera"}}}, |
| }, { |
| "testBlockVideoCapture", |
| testBlockVideoCapture, |
| []policy.Policy{&policy.VideoCaptureAllowed{Val: false}}, |
| }} { |
| subTestCtx, cancel := context.WithTimeout(ctx, subTestTimeout) |
| s.Run(subTestCtx, tst.name, func(ctx context.Context, s *testing.State) { |
| if err := cca.ClearSavedDir(ctx, cr); err != nil { |
| s.Fatal("Failed to clear saved directory: ", err) |
| } |
| |
| if err := servePolicy(ctx, fdms, cr, tst.policy); err != nil { |
| s.Fatal("Failed to serve policy: ", err) |
| } |
| |
| if err := tst.testFunc(ctx, cr, scripts, outDir); err != nil { |
| s.Fatalf("Failed to run subtest %v: %v", tst.name, err) |
| } |
| }) |
| cancel() |
| } |
| } |
| |
| func servePolicy(ctx context.Context, fdms *fakedms.FakeDMS, cr *chrome.Chrome, ps []policy.Policy) (retErr error) { |
| if err := policyutil.ResetChrome(ctx, fdms, cr); err != nil { |
| return errors.Wrap(err, "failed to reset Chrome") |
| } |
| |
| if err := policyutil.ServeAndVerify(ctx, fdms, cr, ps); err != nil { |
| return errors.Wrap(err, "failed to serve policy") |
| } |
| return nil |
| } |
| |
| // testNoPolicy tests without any policy and expects CCA works fine. |
| func testNoPolicy(ctx context.Context, cr *chrome.Chrome, scripts []string, outDir string) error { |
| tb, err := testutil.NewTestBridge(ctx, cr, testutil.UseRealCamera) |
| if err != nil { |
| return errors.Wrap(err, "failed to construct test bridge") |
| } |
| defer tb.TearDown(ctx) |
| |
| app, err := cca.New(ctx, cr, scripts, outDir, tb) |
| if err != nil { |
| return errors.Wrap(err, "failed to start CCA with no policy") |
| } |
| return app.Close(ctx) |
| } |
| |
| // testBlockCameraFeature tries to block camera feature and expects a message |
| // box "Camera is blocked" will show when launching CCA through the launcher. |
| func testBlockCameraFeature(ctx context.Context, cr *chrome.Chrome, scripts []string, outDir string) error { |
| tconn, err := cr.TestAPIConn(ctx) |
| if err != nil { |
| return errors.Wrap(err, "failed to get test extension connection") |
| } |
| kb, err := input.Keyboard(ctx) |
| if err != nil { |
| return errors.Wrap(err, "failed to find keyboard") |
| } |
| defer kb.Close() |
| if err := launcher.SearchAndLaunch(tconn, kb, apps.Camera.Name)(ctx); err != nil { |
| return errors.Wrap(err, "failed to find camera app in the launcher") |
| } |
| |
| ui := uiauto.New(tconn).WithTimeout(10 * time.Second) |
| blockedWindowFinder := nodewith.Role(role.Window).Name("Camera is blocked") |
| okButtonFinder := nodewith.Role(role.Button).Name("OK") |
| err = uiauto.Combine("Check and close blocked window", |
| ui.WaitUntilExists(blockedWindowFinder), |
| ui.LeftClick(okButtonFinder))(ctx) |
| if err != nil { |
| return errors.Wrap(err, "failed to check and close blocked window") |
| } |
| return nil |
| } |
| |
| // testBlockVideoCapture tries to block video capture and expects CCA fails to |
| // initialize since the preview won't show. |
| func testBlockVideoCapture(ctx context.Context, cr *chrome.Chrome, scripts []string, outDir string) error { |
| tb, err := testutil.NewTestBridge(ctx, cr, testutil.UseRealCamera) |
| if err != nil { |
| return errors.Wrap(err, "failed to construct test bridge") |
| } |
| defer tb.TearDown(ctx) |
| |
| app, err := cca.New(ctx, cr, scripts, outDir, tb) |
| if err == nil { |
| var errJS *cca.ErrJS |
| if err := app.Close(ctx); err != nil && !errors.As(err, &errJS) { |
| // It is acceptable that there are errors in CCA since the video |
| // capture is blocked. Reports if the error is not JS error. |
| testing.ContextLog(ctx, "Failed to close app: ", err) |
| } |
| return errors.New("failed to block video capture by policy") |
| } else if !strings.Contains(err.Error(), cca.ErrVideoNotActive) { |
| return errors.Wrap(err, "unexpected error when blocking video capture") |
| } |
| return nil |
| } |