/**
   * Constructs a new ContentViewRenderView that should be can to a view hierarchy. Native code
   * should add/remove the layers to be rendered through the ContentViewLayerRenderer.
   *
   * @param context The context used to create this.
   */
  public ContentViewRenderView(Context context, WindowAndroid rootWindow) {
    super(context);
    assert rootWindow != null;
    mNativeContentViewRenderView = nativeInit(rootWindow.getNativePointer());
    assert mNativeContentViewRenderView != 0;

    mSurfaceView = createSurfaceView(getContext());
    mSurfaceView.setZOrderMediaOverlay(true);
    mSurfaceCallback =
        new SurfaceHolder.Callback() {
          @Override
          public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            assert mNativeContentViewRenderView != 0;
            nativeSurfaceChanged(
                mNativeContentViewRenderView, format, width, height, holder.getSurface());
            if (mCurrentContentView != null) {
              mCurrentContentView.getContentViewCore().onPhysicalBackingSizeChanged(width, height);
            }
          }

          @Override
          public void surfaceCreated(SurfaceHolder holder) {
            setSurfaceViewBackgroundColor(Color.WHITE);

            assert mNativeContentViewRenderView != 0;
            nativeSurfaceCreated(mNativeContentViewRenderView);

            mPendingSwapBuffers = 0;
            mPendingRenders = 0;

            onReadyToRender();
          }

          @Override
          public void surfaceDestroyed(SurfaceHolder holder) {
            assert mNativeContentViewRenderView != 0;
            nativeSurfaceDestroyed(mNativeContentViewRenderView);
          }
        };
    mSurfaceView.getHolder().addCallback(mSurfaceCallback);

    mVSyncAdapter = new VSyncAdapter(getContext());
    addView(
        mSurfaceView,
        new FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
  }
 /**
  * For certain download types(OMA for example), android DownloadManager should handle them. Call
  * this function to intercept those downloads.
  *
  * @param url URL to be downloaded.
  * @return whether the DownloadManager should intercept the download.
  */
 public boolean shouldInterceptContextMenuDownload(String url) {
   Uri uri = Uri.parse(url);
   String scheme = uri.normalizeScheme().getScheme();
   if (!"http".equals(scheme) && !"https".equals(scheme)) return false;
   String path = uri.getPath();
   // OMA downloads have extension "dm" or "dd". For the latter, it
   // can be handled when native download completes.
   if (path != null && (path.endsWith(".dm"))) {
     final DownloadInfo downloadInfo = new DownloadInfo.Builder().setUrl(url).build();
     if (mTab == null) return true;
     WindowAndroid window = mTab.getWindowAndroid();
     if (window.hasPermission(permission.WRITE_EXTERNAL_STORAGE)) {
       onDownloadStartNoStream(downloadInfo);
     } else if (window.canRequestPermission(permission.WRITE_EXTERNAL_STORAGE)) {
       PermissionCallback permissionCallback =
           new PermissionCallback() {
             @Override
             public void onRequestPermissionsResult(String[] permissions, int[] grantResults) {
               if (grantResults.length > 0
                   && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                 onDownloadStartNoStream(downloadInfo);
               }
             }
           };
       window.requestPermissions(
           new String[] {permission.WRITE_EXTERNAL_STORAGE}, permissionCallback);
     }
     return true;
   }
   return false;
 }
  @CalledByNative
  void showJavascriptAppModalDialog(WindowAndroid window, long nativeDialogPointer) {
    assert window != null;
    Context context = window.getActivity().get();
    // If the activity has gone away, then just clean up the native pointer.
    if (context == null) {
      nativeDidCancelAppModalDialog(nativeDialogPointer, false);
      return;
    }

    // Cache the native dialog pointer so that we can use it to return the response.
    mNativeDialogPointer = nativeDialogPointer;

    LayoutInflater inflater =
        (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.js_modal_dialog, null);
    mSuppressCheckBox = (CheckBox) layout.findViewById(R.id.suppress_js_modal_dialogs);
    mPromptTextView = (TextView) layout.findViewById(R.id.js_modal_dialog_prompt);

    prepare(layout);

    AlertDialog.Builder builder =
        new AlertDialog.Builder(context, R.style.AlertDialogTheme)
            .setView(layout)
            .setTitle(mTitle)
            .setOnCancelListener(
                new DialogInterface.OnCancelListener() {
                  @Override
                  public void onCancel(DialogInterface dialog) {
                    cancel(false);
                  }
                });
    if (hasPositiveButton()) {
      builder.setPositiveButton(getPositiveButtonText(), this);
    }
    if (hasNegativeButton()) {
      builder.setNegativeButton(getNegativeButtonText(), this);
    }

    mDialog = builder.create();
    mDialog.setCanceledOnTouchOutside(false);
    mDialog.getDelegate().setHandleNativeActionModesEnabled(false);
    mDialog.show();
  }